⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 audio_alsa_sink.cc

📁 这是用python语言写的一个数字广播的信号处理工具包。利用它
💻 CC
📖 第 1 页 / 共 2 页
字号:
/* -*- c++ -*- *//* * Copyright 2004 Free Software Foundation, Inc. *  * This file is part of GNU Radio *  * GNU Radio is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. *  * GNU Radio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. *  * You should have received a copy of the GNU General Public License * along with GNU Radio; see the file COPYING.  If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <audio_alsa_sink.h>#include <gr_io_signature.h>#include <gr_prefs.h>#include <stdio.h>#include <iostream>#include <stdexcept>#include <gri_alsa.h>static bool CHATTY_DEBUG = false;static snd_pcm_format_t acceptable_formats[] = {  // these are in our preferred order...  SND_PCM_FORMAT_S32,  SND_PCM_FORMAT_S16};#define NELEMS(x) (sizeof(x)/sizeof(x[0]))static std::string default_device_name (){  return gr_prefs::singleton()->get_string("audio_alsa", "default_output_device", "hw:0,0");}static doubledefault_period_time (){  return std::max(0.001, gr_prefs::singleton()->get_double("audio_alsa", "period_time", 0.010));}static intdefault_nperiods (){  return std::max(2L, gr_prefs::singleton()->get_long("audio_alsa", "nperiods", 4));}// ----------------------------------------------------------------audio_alsa_sink_sptraudio_alsa_make_sink (int sampling_rate,		      const std::string dev,		      bool ok_to_block){  return audio_alsa_sink_sptr (new audio_alsa_sink (sampling_rate, dev,						    ok_to_block));}audio_alsa_sink::audio_alsa_sink (int sampling_rate,				  const std::string device_name,				  bool ok_to_block)  : gr_sync_block ("audio_alsa_sink",		   gr_make_io_signature (0, 0, 0),		   gr_make_io_signature (0, 0, 0)),    d_sampling_rate (sampling_rate),    d_device_name (device_name.empty() ? default_device_name() : device_name),    d_pcm_handle (0),    d_hw_params ((snd_pcm_hw_params_t *)(new char[snd_pcm_hw_params_sizeof()])),    d_sw_params ((snd_pcm_sw_params_t *)(new char[snd_pcm_sw_params_sizeof()])),    d_nperiods (default_nperiods()),    d_period_time_us ((unsigned int) (default_period_time() * 1e6)),    d_period_size (0),    d_buffer_size_bytes (0), d_buffer (0),    d_worker (0), d_special_case_mono_to_stereo (false),    d_nunderuns (0), d_nsuspends (0){  CHATTY_DEBUG = gr_prefs::singleton()->get_bool("audio_alsa", "verbose", false);  int  	error;  int	dir;  // open the device for playback  error = snd_pcm_open(&d_pcm_handle, d_device_name.c_str (),		       SND_PCM_STREAM_PLAYBACK, 0);  if (error < 0){    fprintf (stderr, "audio_alsa_sink[%s]: %s\n",	     d_device_name.c_str(), snd_strerror(error));    throw std::runtime_error ("audio_alsa_sink");  }  // Fill params with a full configuration space for a PCM.  error = snd_pcm_hw_params_any(d_pcm_handle, d_hw_params);  if (error < 0)    bail ("broken configuration for playback", error);  if (CHATTY_DEBUG)    gri_alsa_dump_hw_params (d_pcm_handle, d_hw_params, stdout);  // now that we know how many channels the h/w can handle, set input signature  unsigned int umin_chan, umax_chan;  snd_pcm_hw_params_get_channels_min (d_hw_params, &umin_chan);  snd_pcm_hw_params_get_channels_max (d_hw_params, &umax_chan);  int min_chan = std::min (umin_chan, 1000U);  int max_chan = std::min (umax_chan, 1000U);  // As a special case, if the hw's min_chan is two, we'll accept  // a single input and handle the duplication ourselves.  if (min_chan == 2){    min_chan = 1;    d_special_case_mono_to_stereo = true;  }  set_input_signature (gr_make_io_signature (min_chan, max_chan,					     sizeof (float)));    // fill in portions of the d_hw_params that we know now...  // Specify the access methods we implement  // For now, we only handle RW_INTERLEAVED...  snd_pcm_access_mask_t *access_mask;  snd_pcm_access_mask_alloca (&access_mask);  snd_pcm_access_mask_none (access_mask);  snd_pcm_access_mask_set (access_mask, SND_PCM_ACCESS_RW_INTERLEAVED);  // snd_pcm_access_mask_set (access_mask, SND_PCM_ACCESS_RW_NONINTERLEAVED);  if ((error = snd_pcm_hw_params_set_access_mask (d_pcm_handle,						  d_hw_params, access_mask)) < 0)    bail ("failed to set access mask", error);  // set sample format  if (!gri_alsa_pick_acceptable_format (d_pcm_handle, d_hw_params,					acceptable_formats,					NELEMS (acceptable_formats),					&d_format,					"audio_alsa_sink",					CHATTY_DEBUG))    throw std::runtime_error ("audio_alsa_sink");    // sampling rate  unsigned int orig_sampling_rate = d_sampling_rate;  if ((error = snd_pcm_hw_params_set_rate_near (d_pcm_handle, d_hw_params,						&d_sampling_rate, 0)) < 0)    bail ("failed to set rate near", error);    if (orig_sampling_rate != d_sampling_rate){    fprintf (stderr, "audio_alsa_sink[%s]: unable to support sampling rate %d\n",	     snd_pcm_name (d_pcm_handle), orig_sampling_rate);    fprintf (stderr, "  card requested %d instead.\n", d_sampling_rate);  }  /*   * ALSA transfers data in units of "periods".   * We indirectly determine the underlying buffersize by specifying   * the number of periods we want (typically 4) and the length of each   * period in units of time (typically 1ms).   */  unsigned int min_nperiods, max_nperiods;  snd_pcm_hw_params_get_periods_min (d_hw_params, &min_nperiods, &dir);  snd_pcm_hw_params_get_periods_max (d_hw_params, &max_nperiods, &dir);  //fprintf (stderr, "alsa_sink: min_nperiods = %d, max_nperiods = %d\n",  // min_nperiods, max_nperiods);  unsigned int orig_nperiods = d_nperiods;  d_nperiods = std::min (std::max (min_nperiods, d_nperiods), max_nperiods);  // adjust period time so that total buffering remains more-or-less constant  d_period_time_us = (d_period_time_us * orig_nperiods) / d_nperiods;  error = snd_pcm_hw_params_set_periods (d_pcm_handle, d_hw_params,					 d_nperiods, 0);  if (error < 0)    bail ("set_periods failed", error);  dir = 0;  error = snd_pcm_hw_params_set_period_time_near (d_pcm_handle, d_hw_params,						  &d_period_time_us, &dir);  if (error < 0)    bail ("set_period_time_near failed", error);  dir = 0;  error = snd_pcm_hw_params_get_period_size (d_hw_params,					     &d_period_size, &dir);  if (error < 0)    bail ("get_period_size failed", error);    set_output_multiple (d_period_size);}boolaudio_alsa_sink::check_topology (int ninputs, int noutputs){  // ninputs is how many channels the user has connected.  // Now we can finish up setting up the hw params...  int nchan = ninputs;  int err;  // FIXME check_topology may be called more than once.  // Ensure that the pcm is in a state where we can still mess with the hw_params  bool special_case = nchan == 1 && d_special_case_mono_to_stereo;  if (special_case)    nchan = 2;    err = snd_pcm_hw_params_set_channels (d_pcm_handle, d_hw_params, nchan);  if (err < 0){    output_error_msg ("set_channels failed", err);    return false;  }  // set the parameters into the driver...  err = snd_pcm_hw_params(d_pcm_handle, d_hw_params);  if (err < 0){    output_error_msg ("snd_pcm_hw_params failed", err);    return false;  }  // get current s/w params  err = snd_pcm_sw_params_current (d_pcm_handle, d_sw_params);  if (err < 0)    bail ("snd_pcm_sw_params_current", err);    // Tell the PCM device to wait to start until we've filled  // it's buffers half way full.  This helps avoid audio underruns.  err = snd_pcm_sw_params_set_start_threshold(d_pcm_handle,					      d_sw_params,					      d_nperiods * d_period_size / 2);  if (err < 0)    bail ("snd_pcm_sw_params_set_start_threshold", err);  // store the s/w params  err = snd_pcm_sw_params (d_pcm_handle, d_sw_params);  if (err < 0)    bail ("snd_pcm_sw_params", err);  d_buffer_size_bytes =    d_period_size * nchan * snd_pcm_format_size (d_format, 1);  d_buffer = new char [d_buffer_size_bytes];  if (CHATTY_DEBUG)    fprintf (stdout, "audio_alsa_sink[%s]: sample resolution = %d bits\n",	     snd_pcm_name (d_pcm_handle),	     snd_pcm_hw_params_get_sbits (d_hw_params));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -