3 * Copyright 2004 Free Software Foundation, Inc.
5 * This file is part of GNU Radio
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)
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.
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.
27 #include <audio_oss_source.h>
28 #include <gr_io_signature.h>
30 #include <sys/soundcard.h>
31 #include <sys/ioctl.h>
32 #include <sys/types.h>
42 default_device_name ()
44 return gr_prefs::singleton()->get_string("audio_oss", "default_input_device", "/dev/dsp");
48 audio_oss_make_source (int sampling_rate, const std::string dev, bool ok_to_block)
50 return audio_oss_source_sptr (new audio_oss_source (sampling_rate, dev, ok_to_block));
54 audio_oss_source::audio_oss_source (int sampling_rate,
55 const std::string device_name,
57 : gr_sync_block ("audio_oss_source",
58 gr_make_io_signature (0, 0, 0),
59 gr_make_io_signature (1, 2, sizeof (float))),
60 d_sampling_rate (sampling_rate),
61 d_device_name (device_name.empty() ? default_device_name() : device_name),
62 d_fd (-1), d_buffer (0), d_chunk_size (0)
64 if ((d_fd = open (d_device_name.c_str (), O_RDONLY)) < 0){
65 fprintf (stderr, "audio_oss_source: ");
66 perror (d_device_name.c_str ());
67 throw std::runtime_error ("audio_oss_source");
71 std::max(0.001, gr_prefs::singleton()->get_double("audio_oss", "latency", 0.005));
73 d_chunk_size = (int) (d_sampling_rate * CHUNK_TIME);
74 set_output_multiple (d_chunk_size);
76 d_buffer = new short [d_chunk_size * 2];
78 int format = AFMT_S16_NE;
79 int orig_format = format;
80 if (ioctl (d_fd, SNDCTL_DSP_SETFMT, &format) < 0){
81 std::cerr << "audio_oss_source: " << d_device_name << " ioctl failed\n";
82 perror (d_device_name.c_str ());
83 throw std::runtime_error ("audio_oss_source");
86 if (format != orig_format){
87 fprintf (stderr, "audio_oss_source: unable to support format %d\n", orig_format);
88 fprintf (stderr, " card requested %d instead.\n", format);
91 // set to stereo no matter what. Some hardware only does stereo
93 if (ioctl (d_fd, SNDCTL_DSP_CHANNELS, &channels) < 0 || channels != 2){
94 perror ("audio_oss_source: could not set STEREO mode");
95 throw std::runtime_error ("audio_oss_source");
99 int sf = sampling_rate;
100 if (ioctl (d_fd, SNDCTL_DSP_SPEED, &sf) < 0){
101 std::cerr << "audio_oss_source: "
102 << d_device_name << ": invalid sampling_rate "
103 << sampling_rate << "\n";
104 sampling_rate = 8000;
105 if (ioctl (d_fd, SNDCTL_DSP_SPEED, &sf) < 0){
106 std::cerr << "audio_oss_source: failed to set sampling_rate to 8000\n";
107 throw std::runtime_error ("audio_oss_source");
112 audio_oss_source::~audio_oss_source ()
119 audio_oss_source::work (int noutput_items,
120 gr_vector_const_void_star &input_items,
121 gr_vector_void_star &output_items)
123 float *f0 = (float *) output_items[0];
124 float *f1 = (float *) output_items[1]; // will be invalid if this is mono output
126 const int shorts_per_item = 2; // L + R
127 const int bytes_per_item = shorts_per_item * sizeof (short);
129 // To minimize latency, never return more than CHUNK_TIME
130 // worth of samples per call to work.
132 noutput_items = std::min (noutput_items, d_chunk_size);
135 int ntogo = noutput_items;
138 int nbytes = std::min (ntogo, d_chunk_size) * bytes_per_item;
139 int result_nbytes = read (d_fd, d_buffer, nbytes);
141 if (result_nbytes < 0){
142 perror ("audio_oss_source");
143 return -1; // say we're done
146 if ((result_nbytes & (bytes_per_item - 1)) != 0){
147 fprintf (stderr, "audio_oss_source: internal error.\n");
148 throw std::runtime_error ("internal error");
151 int result_nitems = result_nbytes / bytes_per_item;
153 // now unpack samples into output streams
155 switch (output_items.size ()){
156 case 1: // mono output
157 for (int i = 0; i < result_nitems; i++){
158 f0[base+i] = d_buffer[2*i+0] * (1.0 / 32767);
162 case 2: // stereo output
163 for (int i = 0; i < result_nitems; i++){
164 f0[base+i] = d_buffer[2*i+0] * (1.0 / 32767);
165 f1[base+i] = d_buffer[2*i+1] * (1.0 / 32767);
173 ntogo -= result_nitems;
174 base += result_nitems;
177 return noutput_items - ntogo;