📄 audio_alsa_sink.cc
字号:
switch (d_format){ case SND_PCM_FORMAT_S16: if (special_case) d_worker = &audio_alsa_sink::work_s16_1x2; else d_worker = &audio_alsa_sink::work_s16; break; case SND_PCM_FORMAT_S32: if (special_case) d_worker = &audio_alsa_sink::work_s32_1x2; else d_worker = &audio_alsa_sink::work_s32; break; default: assert (0); } return true;}audio_alsa_sink::~audio_alsa_sink (){ if (snd_pcm_state (d_pcm_handle) == SND_PCM_STATE_RUNNING) snd_pcm_drop (d_pcm_handle); snd_pcm_close(d_pcm_handle); delete [] ((char *) d_hw_params); delete [] ((char *) d_sw_params); delete [] d_buffer;}intaudio_alsa_sink::work (int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items){ assert ((noutput_items % d_period_size) == 0); // this is a call through a pointer to a method... return (this->*d_worker)(noutput_items, input_items, output_items);}/* * Work function that deals with float to S16 conversion */intaudio_alsa_sink::work_s16 (int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items){ typedef gr_int16 sample_t; // the type of samples we're creating static const int NBITS = 16; // # of bits in a sample unsigned int nchan = input_items.size (); const float **in = (const float **) &input_items[0]; sample_t *buf = (sample_t *) d_buffer; int bi; int n; unsigned int sizeof_frame = nchan * sizeof (sample_t); assert (d_buffer_size_bytes == d_period_size * sizeof_frame); for (n = 0; n < noutput_items; n += d_period_size){ // process one period of data bi = 0; for (unsigned int i = 0; i < d_period_size; i++){ for (unsigned int chan = 0; chan < nchan; chan++){ buf[bi++] = (sample_t) (in[chan][i] * (float) ((1L << (NBITS-1)) - 1)); } } // update src pointers for (unsigned int chan = 0; chan < nchan; chan++) in[chan] += d_period_size; if (!write_buffer (buf, d_period_size, sizeof_frame)) return -1; // No fixing this problem. Say we're done. } return n;}/* * Work function that deals with float to S32 conversion */intaudio_alsa_sink::work_s32 (int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items){ typedef gr_int32 sample_t; // the type of samples we're creating static const int NBITS = 32; // # of bits in a sample unsigned int nchan = input_items.size (); const float **in = (const float **) &input_items[0]; sample_t *buf = (sample_t *) d_buffer; int bi; int n; unsigned int sizeof_frame = nchan * sizeof (sample_t); assert (d_buffer_size_bytes == d_period_size * sizeof_frame); for (n = 0; n < noutput_items; n += d_period_size){ // process one period of data bi = 0; for (unsigned int i = 0; i < d_period_size; i++){ for (unsigned int chan = 0; chan < nchan; chan++){ buf[bi++] = (sample_t) (in[chan][i] * (float) ((1L << (NBITS-1)) - 1)); } } // update src pointers for (unsigned int chan = 0; chan < nchan; chan++) in[chan] += d_period_size; if (!write_buffer (buf, d_period_size, sizeof_frame)) return -1; // No fixing this problem. Say we're done. } return n;}/* * Work function that deals with float to S16 conversion and * mono to stereo kludge. */intaudio_alsa_sink::work_s16_1x2 (int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items){ typedef gr_int16 sample_t; // the type of samples we're creating static const int NBITS = 16; // # of bits in a sample assert (input_items.size () == 1); static const unsigned int nchan = 2; const float **in = (const float **) &input_items[0]; sample_t *buf = (sample_t *) d_buffer; int bi; int n; unsigned int sizeof_frame = nchan * sizeof (sample_t); assert (d_buffer_size_bytes == d_period_size * sizeof_frame); for (n = 0; n < noutput_items; n += d_period_size){ // process one period of data bi = 0; for (unsigned int i = 0; i < d_period_size; i++){ sample_t t = (sample_t) (in[0][i] * (float) ((1L << (NBITS-1)) - 1)); buf[bi++] = t; buf[bi++] = t; } // update src pointers in[0] += d_period_size; if (!write_buffer (buf, d_period_size, sizeof_frame)) return -1; // No fixing this problem. Say we're done. } return n;}/* * Work function that deals with float to S32 conversion and * mono to stereo kludge. */intaudio_alsa_sink::work_s32_1x2 (int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items){ typedef gr_int32 sample_t; // the type of samples we're creating static const int NBITS = 32; // # of bits in a sample assert (input_items.size () == 1); static unsigned int nchan = 2; const float **in = (const float **) &input_items[0]; sample_t *buf = (sample_t *) d_buffer; int bi; int n; unsigned int sizeof_frame = nchan * sizeof (sample_t); assert (d_buffer_size_bytes == d_period_size * sizeof_frame); for (n = 0; n < noutput_items; n += d_period_size){ // process one period of data bi = 0; for (unsigned int i = 0; i < d_period_size; i++){ sample_t t = (sample_t) (in[0][i] * (float) ((1L << (NBITS-1)) - 1)); buf[bi++] = t; buf[bi++] = t; } // update src pointers in[0] += d_period_size; if (!write_buffer (buf, d_period_size, sizeof_frame)) return -1; // No fixing this problem. Say we're done. } return n;}boolaudio_alsa_sink::write_buffer (const void *vbuffer, unsigned nframes, unsigned sizeof_frame){ const unsigned char *buffer = (const unsigned char *) vbuffer; while (nframes > 0){ int r = snd_pcm_writei (d_pcm_handle, buffer, nframes); if (r == -EAGAIN) continue; // try again else if (r == -EPIPE){ // underrun d_nunderuns++; fputs ("aU", stderr); if ((r = snd_pcm_prepare (d_pcm_handle)) < 0){ output_error_msg ("snd_pcm_prepare failed. Can't recover from underrun", r); return false; } continue; // try again } else if (r == -ESTRPIPE){ // h/w is suspended (whatever that means) // This is apparently related to power management d_nsuspends++; if ((r = snd_pcm_resume (d_pcm_handle)) < 0){ output_error_msg ("failed to resume from suspend", r); return false; } continue; // try again } else if (r < 0){ output_error_msg ("snd_pcm_writei failed", r); return false; } nframes -= r; buffer += r * sizeof_frame; } return true;}voidaudio_alsa_sink::output_error_msg (const char *msg, int err){ fprintf (stderr, "audio_alsa_sink[%s]: %s: %s\n", snd_pcm_name (d_pcm_handle), msg, snd_strerror (err));}voidaudio_alsa_sink::bail (const char *msg, int err) throw (std::runtime_error){ output_error_msg (msg, err); throw std::runtime_error ("audio_alsa_sink");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -