Imported Upstream version 3.2.2
[debian/gnuradio] / gr-audio-alsa / src / audio_alsa_source.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2004,2006 Free Software Foundation, Inc.
4  * 
5  * This file is part of GNU Radio
6  * 
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  * 
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with GNU Radio; see the file COPYING.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <audio_alsa_source.h>
28 #include <gr_io_signature.h>
29 #include <gr_prefs.h>
30 #include <stdio.h>
31 #include <iostream>
32 #include <stdexcept>
33 #include <gri_alsa.h>
34
35
36 static bool CHATTY_DEBUG = false;
37
38 static snd_pcm_format_t acceptable_formats[] = {
39   // these are in our preferred order...
40   SND_PCM_FORMAT_S32,
41   SND_PCM_FORMAT_S16
42 };
43
44 #define NELEMS(x) (sizeof(x)/sizeof(x[0]))
45
46
47 static std::string 
48 default_device_name ()
49 {
50   return gr_prefs::singleton()->get_string("audio_alsa", "default_input_device", "hw:0,0");
51 }
52
53 static double
54 default_period_time ()
55 {
56   return std::max(0.001, gr_prefs::singleton()->get_double("audio_alsa", "period_time", 0.010));
57 }
58
59 static int
60 default_nperiods ()
61 {
62   return std::max(2L, gr_prefs::singleton()->get_long("audio_alsa", "nperiods", 4));
63 }
64
65 // ----------------------------------------------------------------
66
67 audio_alsa_source_sptr
68 audio_alsa_make_source (int sampling_rate, const std::string dev,
69                         bool ok_to_block)
70 {
71   return audio_alsa_source_sptr (new audio_alsa_source (sampling_rate, dev,
72                                                         ok_to_block));
73 }
74
75 audio_alsa_source::audio_alsa_source (int sampling_rate,
76                                       const std::string device_name,
77                                       bool ok_to_block)
78   : gr_sync_block ("audio_alsa_source",
79                    gr_make_io_signature (0, 0, 0),
80                    gr_make_io_signature (0, 0, 0)),
81     d_sampling_rate (sampling_rate),
82     d_device_name (device_name.empty() ? default_device_name() : device_name),
83     d_pcm_handle (0),
84     d_hw_params ((snd_pcm_hw_params_t *)(new char[snd_pcm_hw_params_sizeof()])),
85     d_sw_params ((snd_pcm_sw_params_t *)(new char[snd_pcm_sw_params_sizeof()])),
86     d_nperiods (default_nperiods()),
87     d_period_time_us ((unsigned int) (default_period_time() * 1e6)),
88     d_period_size (0),
89     d_buffer_size_bytes (0), d_buffer (0),
90     d_worker (0), d_hw_nchan (0),
91     d_special_case_stereo_to_mono (false),
92     d_noverruns (0), d_nsuspends (0)
93 {
94
95   CHATTY_DEBUG = gr_prefs::singleton()->get_bool("audio_alsa", "verbose", false);
96
97   int   error;
98   int   dir;
99
100   // open the device for capture
101   error = snd_pcm_open(&d_pcm_handle, d_device_name.c_str (),
102                        SND_PCM_STREAM_CAPTURE, 0);
103   if (error < 0){
104     fprintf (stderr, "audio_alsa_source[%s]: %s\n",
105              d_device_name.c_str(), snd_strerror(error));
106     throw std::runtime_error ("audio_alsa_source");
107   }
108
109   // Fill params with a full configuration space for a PCM.
110   error = snd_pcm_hw_params_any(d_pcm_handle, d_hw_params);
111   if (error < 0)
112     bail ("broken configuration for playback", error);
113
114   if (CHATTY_DEBUG)
115     gri_alsa_dump_hw_params (d_pcm_handle, d_hw_params, stdout);
116
117   // now that we know how many channels the h/w can handle, set output signature
118   unsigned int umax_chan;
119   unsigned int umin_chan;
120   snd_pcm_hw_params_get_channels_min (d_hw_params, &umin_chan);
121   snd_pcm_hw_params_get_channels_max (d_hw_params, &umax_chan);
122   int min_chan = std::min (umin_chan, 1000U);
123   int max_chan = std::min (umax_chan, 1000U);
124
125   // As a special case, if the hw's min_chan is two, we'll accept
126   // a single output and handle the demux ourselves.
127
128   if (min_chan == 2){
129     min_chan = 1;
130     d_special_case_stereo_to_mono = true;
131   }
132   
133   set_output_signature (gr_make_io_signature (min_chan, max_chan,
134                                               sizeof (float)));
135   
136   // fill in portions of the d_hw_params that we know now...
137
138   // Specify the access methods we implement
139   // For now, we only handle RW_INTERLEAVED...
140   snd_pcm_access_mask_t *access_mask;
141   snd_pcm_access_mask_t **access_mask_ptr = &access_mask; // FIXME: workaround for compiler warning
142   snd_pcm_access_mask_alloca (access_mask_ptr);
143   snd_pcm_access_mask_none (access_mask);
144   snd_pcm_access_mask_set (access_mask, SND_PCM_ACCESS_RW_INTERLEAVED);
145   // snd_pcm_access_mask_set (access_mask, SND_PCM_ACCESS_RW_NONINTERLEAVED);
146
147   if ((error = snd_pcm_hw_params_set_access_mask (d_pcm_handle,
148                                                   d_hw_params, access_mask)) < 0)
149     bail ("failed to set access mask", error);
150
151
152   // set sample format
153   if (!gri_alsa_pick_acceptable_format (d_pcm_handle, d_hw_params,
154                                         acceptable_formats,
155                                         NELEMS (acceptable_formats),
156                                         &d_format,
157                                         "audio_alsa_source",
158                                         CHATTY_DEBUG))
159     throw std::runtime_error ("audio_alsa_source");
160   
161
162   // sampling rate
163   unsigned int orig_sampling_rate = d_sampling_rate;
164   if ((error = snd_pcm_hw_params_set_rate_near (d_pcm_handle, d_hw_params,
165                                                 &d_sampling_rate, 0)) < 0)
166     bail ("failed to set rate near", error);
167   
168   if (orig_sampling_rate != d_sampling_rate){
169     fprintf (stderr, "audio_alsa_source[%s]: unable to support sampling rate %d\n",
170              snd_pcm_name (d_pcm_handle), orig_sampling_rate);
171     fprintf (stderr, "  card requested %d instead.\n", d_sampling_rate);
172   }
173
174   /*
175    * ALSA transfers data in units of "periods".
176    * We indirectly determine the underlying buffersize by specifying
177    * the number of periods we want (typically 4) and the length of each
178    * period in units of time (typically 1ms).
179    */
180   unsigned int min_nperiods, max_nperiods;
181   snd_pcm_hw_params_get_periods_min (d_hw_params, &min_nperiods, &dir);
182   snd_pcm_hw_params_get_periods_max (d_hw_params, &max_nperiods, &dir);
183   //fprintf (stderr, "alsa_source: min_nperiods = %d, max_nperiods = %d\n",
184   // min_nperiods, max_nperiods);
185
186
187   unsigned int orig_nperiods = d_nperiods;
188   d_nperiods = std::min (std::max (min_nperiods, d_nperiods), max_nperiods);
189
190   // adjust period time so that total buffering remains more-or-less constant
191   d_period_time_us = (d_period_time_us * orig_nperiods) / d_nperiods;
192
193   error = snd_pcm_hw_params_set_periods (d_pcm_handle, d_hw_params,
194                                          d_nperiods, 0);
195   if (error < 0)
196     bail ("set_periods failed", error);
197
198   dir = 0;
199   error = snd_pcm_hw_params_set_period_time_near (d_pcm_handle, d_hw_params,
200                                                   &d_period_time_us, &dir);
201   if (error < 0)
202     bail ("set_period_time_near failed", error);
203
204   dir = 0;
205   error = snd_pcm_hw_params_get_period_size (d_hw_params,
206                                              &d_period_size, &dir);
207   if (error < 0)
208     bail ("get_period_size failed", error);
209   
210   set_output_multiple (d_period_size);
211 }
212
213 bool
214 audio_alsa_source::check_topology (int ninputs, int noutputs)
215 {
216   // noutputs is how many channels the user has connected.
217   // Now we can finish up setting up the hw params...
218
219   unsigned int nchan = noutputs;
220   int err;
221
222   // FIXME check_topology may be called more than once.
223   // Ensure that the pcm is in a state where we can still mess with the hw_params
224
225   bool special_case = nchan == 1 && d_special_case_stereo_to_mono;
226   if (special_case)
227     nchan = 2;
228
229   d_hw_nchan = nchan;
230   err = snd_pcm_hw_params_set_channels (d_pcm_handle, d_hw_params, d_hw_nchan);
231   if (err < 0){
232     output_error_msg ("set_channels failed", err);
233     return false;
234   }
235
236   // set the parameters into the driver...
237   err = snd_pcm_hw_params(d_pcm_handle, d_hw_params);
238   if (err < 0){
239     output_error_msg ("snd_pcm_hw_params failed", err);
240     return false;
241   }
242
243   d_buffer_size_bytes =
244     d_period_size * d_hw_nchan * snd_pcm_format_size (d_format, 1);
245
246   d_buffer = new char [d_buffer_size_bytes];
247
248   if (CHATTY_DEBUG)
249     fprintf (stdout, "audio_alsa_source[%s]: sample resolution = %d bits\n",
250              snd_pcm_name (d_pcm_handle),
251              snd_pcm_hw_params_get_sbits (d_hw_params));
252
253   switch (d_format){
254   case SND_PCM_FORMAT_S16:
255     if (special_case)
256       d_worker = &audio_alsa_source::work_s16_2x1;
257     else
258       d_worker = &audio_alsa_source::work_s16;
259     break;
260
261   case SND_PCM_FORMAT_S32:
262     if (special_case)
263       d_worker = &audio_alsa_source::work_s32_2x1;
264     else
265       d_worker = &audio_alsa_source::work_s32;
266     break;
267
268   default:
269     assert (0);
270   }
271
272   return true;
273 }
274
275 audio_alsa_source::~audio_alsa_source ()
276 {
277   if (snd_pcm_state (d_pcm_handle) == SND_PCM_STATE_RUNNING)
278     snd_pcm_drop (d_pcm_handle);
279
280   snd_pcm_close(d_pcm_handle);
281   delete [] ((char *) d_hw_params);
282   delete [] ((char *) d_sw_params);
283   delete [] d_buffer;
284 }
285
286 int
287 audio_alsa_source::work (int noutput_items,
288                          gr_vector_const_void_star &input_items,
289                          gr_vector_void_star &output_items)
290 {
291   assert ((noutput_items % d_period_size) == 0);
292   assert (noutput_items != 0);
293
294   // this is a call through a pointer to a method...
295   return (this->*d_worker)(noutput_items, input_items, output_items);
296 }
297
298 /*
299  * Work function that deals with float to S16 conversion
300  */
301 int
302 audio_alsa_source::work_s16 (int noutput_items,
303                              gr_vector_const_void_star &input_items,
304                              gr_vector_void_star &output_items)
305 {
306   typedef gr_int16      sample_t;       // the type of samples we're creating
307   static const int NBITS = 16;          // # of bits in a sample
308   
309   unsigned int nchan = output_items.size ();
310   float **out = (float **) &output_items[0];
311   sample_t *buf = (sample_t *) d_buffer;
312   int bi;
313
314   unsigned int sizeof_frame = d_hw_nchan * sizeof (sample_t);
315   assert (d_buffer_size_bytes == d_period_size * sizeof_frame);
316
317   // To minimize latency, return at most a single period's worth of samples.
318   // [We could also read the first one in a blocking mode and subsequent
319   //  ones in non-blocking mode, but we'll leave that for later (or never).]
320   
321   if (!read_buffer (buf, d_period_size, sizeof_frame))
322     return -1;          // No fixing this problem.  Say we're done.
323
324   // process one period of data
325   bi = 0;
326   for (unsigned int i = 0; i < d_period_size; i++){
327     for (unsigned int chan = 0; chan < nchan; chan++){
328       out[chan][i] = (float) buf[bi++] * (1.0 / (float) ((1L << (NBITS-1)) - 1));
329     }
330   }
331
332   return d_period_size;
333 }
334
335 /*
336  * Work function that deals with float to S16 conversion
337  * and stereo to mono kludge...
338  */
339 int
340 audio_alsa_source::work_s16_2x1 (int noutput_items,
341                                  gr_vector_const_void_star &input_items,
342                                  gr_vector_void_star &output_items)
343 {
344   typedef gr_int16      sample_t;       // the type of samples we're creating
345   static const int NBITS = 16;          // # of bits in a sample
346   
347   unsigned int nchan = output_items.size ();
348   float **out = (float **) &output_items[0];
349   sample_t *buf = (sample_t *) d_buffer;
350   int bi;
351
352   assert (nchan == 1);
353
354   unsigned int sizeof_frame = d_hw_nchan * sizeof (sample_t);
355   assert (d_buffer_size_bytes == d_period_size * sizeof_frame);
356
357   // To minimize latency, return at most a single period's worth of samples.
358   // [We could also read the first one in a blocking mode and subsequent
359   //  ones in non-blocking mode, but we'll leave that for later (or never).]
360   
361   if (!read_buffer (buf, d_period_size, sizeof_frame))
362     return -1;          // No fixing this problem.  Say we're done.
363
364   // process one period of data
365   bi = 0;
366   for (unsigned int i = 0; i < d_period_size; i++){
367     int t = (buf[bi] + buf[bi+1]) / 2;
368     bi += 2;
369     out[0][i] = (float) t * (1.0 / (float) ((1L << (NBITS-1)) - 1));
370   }
371
372   return d_period_size;
373 }
374
375 /*
376  * Work function that deals with float to S32 conversion
377  */
378 int
379 audio_alsa_source::work_s32 (int noutput_items,
380                              gr_vector_const_void_star &input_items,
381                              gr_vector_void_star &output_items)
382 {
383   typedef gr_int32      sample_t;       // the type of samples we're creating
384   static const int NBITS = 32;          // # of bits in a sample
385   
386   unsigned int nchan = output_items.size ();
387   float **out = (float **) &output_items[0];
388   sample_t *buf = (sample_t *) d_buffer;
389   int bi;
390
391   unsigned int sizeof_frame = d_hw_nchan * sizeof (sample_t);
392   assert (d_buffer_size_bytes == d_period_size * sizeof_frame);
393
394   // To minimize latency, return at most a single period's worth of samples.
395   // [We could also read the first one in a blocking mode and subsequent
396   //  ones in non-blocking mode, but we'll leave that for later (or never).]
397   
398   if (!read_buffer (buf, d_period_size, sizeof_frame))
399     return -1;          // No fixing this problem.  Say we're done.
400
401   // process one period of data
402   bi = 0;
403   for (unsigned int i = 0; i < d_period_size; i++){
404     for (unsigned int chan = 0; chan < nchan; chan++){
405       out[chan][i] = (float) buf[bi++] * (1.0 / (float) ((1L << (NBITS-1)) - 1));
406     }
407   }
408
409   return d_period_size;
410 }
411
412 /*
413  * Work function that deals with float to S32 conversion
414  * and stereo to mono kludge...
415  */
416 int
417 audio_alsa_source::work_s32_2x1 (int noutput_items,
418                                  gr_vector_const_void_star &input_items,
419                                  gr_vector_void_star &output_items)
420 {
421   typedef gr_int32      sample_t;       // the type of samples we're creating
422   static const int NBITS = 32;          // # of bits in a sample
423   
424   unsigned int nchan = output_items.size ();
425   float **out = (float **) &output_items[0];
426   sample_t *buf = (sample_t *) d_buffer;
427   int bi;
428
429   assert (nchan == 1);
430
431   unsigned int sizeof_frame = d_hw_nchan * sizeof (sample_t);
432   assert (d_buffer_size_bytes == d_period_size * sizeof_frame);
433
434   // To minimize latency, return at most a single period's worth of samples.
435   // [We could also read the first one in a blocking mode and subsequent
436   //  ones in non-blocking mode, but we'll leave that for later (or never).]
437   
438   if (!read_buffer (buf, d_period_size, sizeof_frame))
439     return -1;          // No fixing this problem.  Say we're done.
440
441   // process one period of data
442   bi = 0;
443   for (unsigned int i = 0; i < d_period_size; i++){
444     int t = (buf[bi] + buf[bi+1]) / 2;
445     bi += 2;
446     out[0][i] = (float) t * (1.0 / (float) ((1L << (NBITS-1)) - 1));
447   }
448
449   return d_period_size;
450 }
451
452 bool
453 audio_alsa_source::read_buffer (void *vbuffer, unsigned nframes, unsigned sizeof_frame)
454 {
455   unsigned char *buffer = (unsigned char *) vbuffer;
456
457   while (nframes > 0){
458     int r = snd_pcm_readi (d_pcm_handle, buffer, nframes);
459     if (r == -EAGAIN)
460       continue;                 // try again
461
462     else if (r == -EPIPE){      // overrun
463       d_noverruns++;
464       fputs ("aO", stderr);
465       if ((r = snd_pcm_prepare (d_pcm_handle)) < 0){
466         output_error_msg ("snd_pcm_prepare failed. Can't recover from overrun", r);
467         return false;
468       }
469       continue;                 // try again
470     }
471
472     else if (r == -ESTRPIPE){   // h/w is suspended (whatever that means)
473                                 // This is apparently related to power management
474       d_nsuspends++;
475       if ((r = snd_pcm_resume (d_pcm_handle)) < 0){
476         output_error_msg ("failed to resume from suspend", r);
477         return false;
478       }
479       continue;                 // try again
480     }
481
482     else if (r < 0){
483       output_error_msg ("snd_pcm_readi failed", r);
484       return false;
485     }
486
487     nframes -= r;
488     buffer += r * sizeof_frame;
489   }
490
491   return true;
492 }
493
494
495 void
496 audio_alsa_source::output_error_msg (const char *msg, int err)
497 {
498   fprintf (stderr, "audio_alsa_source[%s]: %s: %s\n",
499            snd_pcm_name (d_pcm_handle), msg,  snd_strerror (err));
500 }
501
502 void
503 audio_alsa_source::bail (const char *msg, int err) throw (std::runtime_error)
504 {
505   output_error_msg (msg, err);
506   throw std::runtime_error ("audio_alsa_source");
507 }