diff options
Diffstat (limited to 'gr-audio/lib/portaudio')
-rw-r--r-- | gr-audio/lib/portaudio/audio_portaudio_sink.cc | 362 | ||||
-rw-r--r-- | gr-audio/lib/portaudio/audio_portaudio_sink.h | 86 | ||||
-rw-r--r-- | gr-audio/lib/portaudio/audio_portaudio_source.cc | 374 | ||||
-rw-r--r-- | gr-audio/lib/portaudio/audio_portaudio_source.h | 84 | ||||
-rw-r--r-- | gr-audio/lib/portaudio/gr-audio-portaudio.conf | 10 | ||||
-rw-r--r-- | gr-audio/lib/portaudio/gri_portaudio.cc | 111 | ||||
-rw-r--r-- | gr-audio/lib/portaudio/gri_portaudio.h | 32 |
7 files changed, 0 insertions, 1059 deletions
diff --git a/gr-audio/lib/portaudio/audio_portaudio_sink.cc b/gr-audio/lib/portaudio/audio_portaudio_sink.cc deleted file mode 100644 index af7f1e48c..000000000 --- a/gr-audio/lib/portaudio/audio_portaudio_sink.cc +++ /dev/null @@ -1,362 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006-2011 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 he 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 "gr_audio_registry.h" -#include <audio_portaudio_sink.h> -#include <gr_io_signature.h> -#include <gr_prefs.h> -#include <stdio.h> -#include <iostream> -#include <unistd.h> -#include <stdexcept> -#include <gri_portaudio.h> -#include <string.h> - -AUDIO_REGISTER_SINK(REG_PRIO_MED, portaudio)( - int sampling_rate, const std::string &device_name, bool ok_to_block -){ - return audio_sink::sptr(new audio_portaudio_sink(sampling_rate, device_name, ok_to_block)); -} - -//#define LOGGING 0 // define to 0 or 1 - -#define SAMPLE_FORMAT paFloat32 -typedef float sample_t; - -// Number of portaudio buffers in the ringbuffer -static const unsigned int N_BUFFERS = 4; - -static std::string -default_device_name () -{ - return gr_prefs::singleton()->get_string("audio_portaudio", "default_output_device", ""); -} - -void -audio_portaudio_sink::create_ringbuffer(void) -{ - int bufsize_samples = d_portaudio_buffer_size_frames * d_output_parameters.channelCount; - - if (d_verbose) - fprintf(stderr,"ring buffer size = %d frames\n", - N_BUFFERS*bufsize_samples/d_output_parameters.channelCount); - - // FYI, the buffer indicies are in units of samples. - d_writer = gr_make_buffer(N_BUFFERS * bufsize_samples, sizeof(sample_t)); - d_reader = gr_buffer_add_reader(d_writer, 0); -} - -/* - * This routine will be called by the PortAudio engine when audio is needed. - * It may called at interrupt level on some machines so don't do anything - * that could mess up the system like calling malloc() or free(). - * - * Our job is to write framesPerBuffer frames into outputBuffer. - */ -int -portaudio_sink_callback (const void *inputBuffer, - void *outputBuffer, - unsigned long framesPerBuffer, - const PaStreamCallbackTimeInfo* timeInfo, - PaStreamCallbackFlags statusFlags, - void *arg) -{ - audio_portaudio_sink *self = (audio_portaudio_sink *)arg; - int nreqd_samples = - framesPerBuffer * self->d_output_parameters.channelCount; - - int navail_samples = self->d_reader->items_available(); - - if (nreqd_samples <= navail_samples) { // We've got enough data... - { - gruel::scoped_lock guard(self->d_ringbuffer_mutex); - - memcpy(outputBuffer, - self->d_reader->read_pointer(), - nreqd_samples * sizeof(sample_t)); - self->d_reader->update_read_pointer(nreqd_samples); - - self->d_ringbuffer_ready = true; - } - - // Tell the sink thread there is new room in the ringbuffer. - self->d_ringbuffer_cond.notify_one(); - return paContinue; - } - - else { // underrun - self->d_nunderuns++; - ssize_t r = ::write(2, "aU", 2); // FIXME change to non-blocking call - if(r == -1) { - perror("audio_portaudio_source::portaudio_source_callback write error to stderr."); - } - - // FIXME we should transfer what we've got and pad the rest - memset(outputBuffer, 0, nreqd_samples * sizeof(sample_t)); - - self->d_ringbuffer_ready = true; - self->d_ringbuffer_cond.notify_one(); // Tell the sink to get going! - - return paContinue; - } -} - - -// ---------------------------------------------------------------- - -audio_portaudio_sink::audio_portaudio_sink(int sampling_rate, - const std::string device_name, - bool ok_to_block) - : gr_sync_block ("audio_portaudio_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_ok_to_block(ok_to_block), - d_verbose(gr_prefs::singleton()->get_bool("audio_portaudio", "verbose", false)), - d_portaudio_buffer_size_frames(0), - d_stream(0), - d_ringbuffer_mutex(), - d_ringbuffer_cond(), - d_ringbuffer_ready(false), - d_nunderuns(0) -{ - memset(&d_output_parameters, 0, sizeof(d_output_parameters)); - //if (LOGGING) - // d_log = gri_logger::singleton(); - - PaError err; - int i, numDevices; - PaDeviceIndex device = 0; - const PaDeviceInfo *deviceInfo = NULL; - - err = Pa_Initialize(); - if (err != paNoError) { - bail ("Initialize failed", err); - } - - if (d_verbose) - gri_print_devices(); - - numDevices = Pa_GetDeviceCount(); - if (numDevices < 0) - bail("Pa Device count failed", 0); - if (numDevices == 0) - bail("no devices available", 0); - - if (d_device_name.empty()) - { - // FIXME Get smarter about picking something - fprintf(stderr,"\nUsing Default Device\n"); - device = Pa_GetDefaultOutputDevice(); - deviceInfo = Pa_GetDeviceInfo(device); - fprintf(stderr,"%s is the chosen device using %s as the host\n", - deviceInfo->name, Pa_GetHostApiInfo(deviceInfo->hostApi)->name); - } - else - { - bool found = false; - fprintf(stderr,"\nTest Devices\n"); - for (i=0;i<numDevices;i++) { - deviceInfo = Pa_GetDeviceInfo( i ); - fprintf(stderr,"Testing device name: %s",deviceInfo->name); - if (deviceInfo->maxOutputChannels <= 0) { - fprintf(stderr,"\n"); - continue; - } - if (strstr(deviceInfo->name, d_device_name.c_str())){ - fprintf(stderr," Chosen!\n"); - device = i; - fprintf(stderr,"%s using %s as the host\n",d_device_name.c_str(), - Pa_GetHostApiInfo(deviceInfo->hostApi)->name), fflush(stderr); - found = true; - deviceInfo = Pa_GetDeviceInfo(device); - i = numDevices; // force loop exit - } - else - fprintf(stderr,"\n"),fflush(stderr); - } - - if (!found){ - bail("Failed to find specified device name", 0); - exit(1); - } - } - - - d_output_parameters.device = device; - d_output_parameters.channelCount = deviceInfo->maxOutputChannels; - d_output_parameters.sampleFormat = SAMPLE_FORMAT; - d_output_parameters.suggestedLatency = deviceInfo->defaultLowOutputLatency; - d_output_parameters.hostApiSpecificStreamInfo = NULL; - - // We fill in the real channelCount in check_topology when we know - // how many inputs are connected to us. - - // Now that we know the maximum number of channels (allegedly) - // supported by the h/w, we can compute a reasonable input - // signature. The portaudio specs say that they'll accept any - // number of channels from 1 to max. - set_input_signature(gr_make_io_signature(1, deviceInfo->maxOutputChannels, - sizeof (sample_t))); -} - - -bool -audio_portaudio_sink::check_topology (int ninputs, int noutputs) -{ - PaError err; - - if (Pa_IsStreamActive(d_stream)) - { - Pa_CloseStream(d_stream); - d_stream = 0; - d_reader.reset(); // boost::shared_ptr for d_reader = 0 - d_writer.reset(); // boost::shared_ptr for d_write = 0 - } - - d_output_parameters.channelCount = ninputs; // # of channels we're really using - -#if 1 - d_portaudio_buffer_size_frames = (int)(0.0213333333 * d_sampling_rate + 0.5); // Force 1024 frame buffers at 48000 - fprintf(stderr, "Latency = %8.5f, requested sampling_rate = %g\n", // Force latency to 21.3333333.. ms - 0.0213333333, (double)d_sampling_rate); -#endif - err = Pa_OpenStream(&d_stream, - NULL, // No input - &d_output_parameters, - d_sampling_rate, - d_portaudio_buffer_size_frames, - paClipOff, - &portaudio_sink_callback, - (void*)this); - - if (err != paNoError) { - output_error_msg ("OpenStream failed", err); - return false; - } - -#if 0 - const PaStreamInfo *psi = Pa_GetStreamInfo(d_stream); - - d_portaudio_buffer_size_frames = (int)(d_output_parameters.suggestedLatency * psi->sampleRate); - fprintf(stderr, "Latency = %7.4f, psi->sampleRate = %g\n", - d_output_parameters.suggestedLatency, psi->sampleRate); -#endif - - fprintf(stderr, "d_portaudio_buffer_size_frames = %d\n", d_portaudio_buffer_size_frames); - - assert(d_portaudio_buffer_size_frames != 0); - - create_ringbuffer(); - - err = Pa_StartStream(d_stream); - if (err != paNoError) { - output_error_msg ("StartStream failed", err); - return false; - } - - return true; -} - -audio_portaudio_sink::~audio_portaudio_sink () -{ - Pa_StopStream(d_stream); // wait for output to drain - Pa_CloseStream(d_stream); - Pa_Terminate(); -} - -/* - * This version consumes everything sent to it, blocking if required. - * I think this will allow us better control of the total buffering/latency - * in the audio path. - */ -int -audio_portaudio_sink::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const float **in = (const float **) &input_items[0]; - const unsigned nchan = d_output_parameters.channelCount; // # of channels == samples/frame - - int k; - - for (k = 0; k < noutput_items; ){ - int nframes = d_writer->space_available() / nchan; // How much space in ringbuffer - if (nframes == 0){ // no room... - if (d_ok_to_block){ - { - gruel::scoped_lock guard(d_ringbuffer_mutex); - while (!d_ringbuffer_ready) - d_ringbuffer_cond.wait(guard); - } - - continue; - } - else { - // There's no room and we're not allowed to block. - // (A USRP is most likely controlling the pacing through the pipeline.) - // We drop the samples on the ground, and say we processed them all ;) - // - // FIXME, there's probably room for a bit more finesse here. - return noutput_items; - } - } - - // We can write the smaller of the request and the room we've got - { - gruel::scoped_lock guard(d_ringbuffer_mutex); - - int nf = std::min(noutput_items - k, nframes); - float *p = (float *) d_writer->write_pointer(); - - for (int i = 0; i < nf; i++) - for (unsigned int c = 0; c < nchan; c++) - *p++ = in[c][k + i]; - - d_writer->update_write_pointer(nf * nchan); - k += nf; - - d_ringbuffer_ready = false; - } - } - - return k; // tell how many we actually did -} - -void -audio_portaudio_sink::output_error_msg (const char *msg, int err) -{ - fprintf (stderr, "audio_portaudio_sink[%s]: %s: %s\n", - d_device_name.c_str (), msg, Pa_GetErrorText(err)); -} - -void -audio_portaudio_sink::bail (const char *msg, int err) throw (std::runtime_error) -{ - output_error_msg (msg, err); - throw std::runtime_error ("audio_portaudio_sink"); -} diff --git a/gr-audio/lib/portaudio/audio_portaudio_sink.h b/gr-audio/lib/portaudio/audio_portaudio_sink.h deleted file mode 100644 index cf64d3da0..000000000 --- a/gr-audio/lib/portaudio/audio_portaudio_sink.h +++ /dev/null @@ -1,86 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006-2011 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. - */ -#ifndef INCLUDED_AUDIO_PORTAUDIO_SINK_H -#define INCLUDED_AUDIO_PORTAUDIO_SINK_H - -#include <gr_audio_sink.h> -#include <gr_buffer.h> -#include <gruel/thread.h> -#include <string> -#include <portaudio.h> -#include <stdexcept> -//#include <gri_logger.h> - -PaStreamCallback portaudio_sink_callback; - - -/*! - * \brief Audio sink using PORTAUDIO - * \ingroup audio_blk - * - * Input samples must be in the range [-1,1]. - */ -class audio_portaudio_sink : public audio_sink { - - friend PaStreamCallback portaudio_sink_callback; - - - unsigned int d_sampling_rate; - std::string d_device_name; - bool d_ok_to_block; - bool d_verbose; - - unsigned int d_portaudio_buffer_size_frames; // number of frames in a portaudio buffer - - PaStream *d_stream; - PaStreamParameters d_output_parameters; - - gr_buffer_sptr d_writer; // buffer used between work and callback - gr_buffer_reader_sptr d_reader; - - gruel::mutex d_ringbuffer_mutex; - gruel::condition_variable d_ringbuffer_cond; - bool d_ringbuffer_ready; - - // random stats - int d_nunderuns; // count of underruns - //gri_logger_sptr d_log; // handle to non-blocking logging instance - - void output_error_msg (const char *msg, int err); - void bail (const char *msg, int err) throw (std::runtime_error); - void create_ringbuffer(); - - -public: - audio_portaudio_sink (int sampling_rate, const std::string device_name, - bool ok_to_block); - - ~audio_portaudio_sink (); - - bool check_topology (int ninputs, int noutputs); - - int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -#endif /* INCLUDED_AUDIO_PORTAUDIO_SINK_H */ diff --git a/gr-audio/lib/portaudio/audio_portaudio_source.cc b/gr-audio/lib/portaudio/audio_portaudio_source.cc deleted file mode 100644 index ddb1a6fb6..000000000 --- a/gr-audio/lib/portaudio/audio_portaudio_source.cc +++ /dev/null @@ -1,374 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006-2011 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 he 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 "gr_audio_registry.h" -#include <audio_portaudio_source.h> -#include <gr_io_signature.h> -#include <gr_prefs.h> -#include <stdio.h> -#include <iostream> -#include <unistd.h> -#include <stdexcept> -#include <gri_portaudio.h> -#include <string.h> - -AUDIO_REGISTER_SOURCE(REG_PRIO_MED, portaudio)( - int sampling_rate, const std::string &device_name, bool ok_to_block -){ - return audio_source::sptr(new audio_portaudio_source(sampling_rate, device_name, ok_to_block)); -} - -//#define LOGGING 0 // define to 0 or 1 - -#define SAMPLE_FORMAT paFloat32 -typedef float sample_t; - -// Number of portaudio buffers in the ringbuffer -static const unsigned int N_BUFFERS = 4; - -static std::string -default_device_name () -{ - return gr_prefs::singleton()->get_string("audio_portaudio", "default_input_device", ""); -} - -void -audio_portaudio_source::create_ringbuffer(void) -{ - int bufsize_samples = d_portaudio_buffer_size_frames * d_input_parameters.channelCount; - - if (d_verbose) - fprintf(stderr, "ring buffer size = %d frames\n", - N_BUFFERS*bufsize_samples/d_input_parameters.channelCount); - - // FYI, the buffer indicies are in units of samples. - d_writer = gr_make_buffer(N_BUFFERS * bufsize_samples, sizeof(sample_t)); - d_reader = gr_buffer_add_reader(d_writer, 0); -} - -/* - * This routine will be called by the PortAudio engine when audio is needed. - * It may called at interrupt level on some machines so don't do anything - * that could mess up the system like calling malloc() or free(). - * - * Our job is to copy framesPerBuffer frames from inputBuffer. - */ -int -portaudio_source_callback (const void *inputBuffer, - void *outputBuffer, - unsigned long framesPerBuffer, - const PaStreamCallbackTimeInfo* timeInfo, - PaStreamCallbackFlags statusFlags, - void *arg) -{ - audio_portaudio_source *self = (audio_portaudio_source *)arg; - int nchan = self->d_input_parameters.channelCount; - int nframes_to_copy = framesPerBuffer; - int nframes_room = self->d_writer->space_available() / nchan; - - if (nframes_to_copy <= nframes_room){ // We've got room for the data .. - //if (LOGGING) - // self->d_log->printf("PAsrc cb: f/b = %4ld\n", framesPerBuffer); - - // copy from input buffer to ringbuffer - { - gruel::scoped_lock(d_ringbuffer_mutex); - - memcpy(self->d_writer->write_pointer(), - inputBuffer, - nframes_to_copy * nchan * sizeof(sample_t)); - self->d_writer->update_write_pointer(nframes_to_copy * nchan); - - // Tell the source thread there is new data in the ringbuffer. - self->d_ringbuffer_ready = true; - } - - self->d_ringbuffer_cond.notify_one(); - return paContinue; - } - - else { // overrun - self->d_noverruns++; - ssize_t r = ::write(2, "aO", 2); // FIXME change to non-blocking call - if(r == -1) { - perror("audio_portaudio_source::portaudio_source_callback write error to stderr."); - } - - self->d_ringbuffer_ready = false; - self->d_ringbuffer_cond.notify_one(); // Tell the sink to get going! - return paContinue; - } -} - - -// ---------------------------------------------------------------- - -audio_portaudio_source::audio_portaudio_source(int sampling_rate, - const std::string device_name, - bool ok_to_block) - : gr_sync_block ("audio_portaudio_source", - 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_ok_to_block(ok_to_block), - d_verbose(gr_prefs::singleton()->get_bool("audio_portaudio", "verbose", false)), - d_portaudio_buffer_size_frames(0), - d_stream(0), - d_ringbuffer_mutex(), - d_ringbuffer_cond(), - d_ringbuffer_ready(false), - d_noverruns(0) -{ - memset(&d_input_parameters, 0, sizeof(d_input_parameters)); - //if (LOGGING) - // d_log = gri_logger::singleton(); - - PaError err; - int i, numDevices; - PaDeviceIndex device = 0; - const PaDeviceInfo *deviceInfo = NULL; - - - err = Pa_Initialize(); - if (err != paNoError) { - bail ("Initialize failed", err); - } - - if (d_verbose) - gri_print_devices(); - - numDevices = Pa_GetDeviceCount(); - if (numDevices < 0) - bail("Pa Device count failed", 0); - if (numDevices == 0) - bail("no devices available", 0); - - if (d_device_name.empty()) - { - // FIXME Get smarter about picking something - device = Pa_GetDefaultInputDevice(); - deviceInfo = Pa_GetDeviceInfo(device); - fprintf(stderr,"%s is the chosen device using %s as the host\n", - deviceInfo->name, Pa_GetHostApiInfo(deviceInfo->hostApi)->name); - } - else - { - bool found = false; - - for (i=0;i<numDevices;i++) { - deviceInfo = Pa_GetDeviceInfo( i ); - fprintf(stderr,"Testing device name: %s",deviceInfo->name); - if (deviceInfo->maxInputChannels <= 0) { - fprintf(stderr,"\n"); - continue; - } - if (strstr(deviceInfo->name, d_device_name.c_str())){ - fprintf(stderr," Chosen!\n"); - device = i; - fprintf(stderr,"%s using %s as the host\n",d_device_name.c_str(), - Pa_GetHostApiInfo(deviceInfo->hostApi)->name), fflush(stderr); - found = true; - deviceInfo = Pa_GetDeviceInfo(device); - i = numDevices; // force loop exit - } - else - fprintf(stderr,"\n"),fflush(stderr); - } - - if (!found){ - bail("Failed to find specified device name", 0); - } - } - - - d_input_parameters.device = device; - d_input_parameters.channelCount = deviceInfo->maxInputChannels; - d_input_parameters.sampleFormat = SAMPLE_FORMAT; - d_input_parameters.suggestedLatency = deviceInfo->defaultLowInputLatency; - d_input_parameters.hostApiSpecificStreamInfo = NULL; - - // We fill in the real channelCount in check_topology when we know - // how many inputs are connected to us. - - // Now that we know the maximum number of channels (allegedly) - // supported by the h/w, we can compute a reasonable output - // signature. The portaudio specs say that they'll accept any - // number of channels from 1 to max. - set_output_signature(gr_make_io_signature(1, deviceInfo->maxInputChannels, - sizeof (sample_t))); -} - - -bool -audio_portaudio_source::check_topology (int ninputs, int noutputs) -{ - PaError err; - - if (Pa_IsStreamActive(d_stream)) - { - Pa_CloseStream(d_stream); - d_stream = 0; - d_reader.reset(); // boost::shared_ptr for d_reader = 0 - d_writer.reset(); // boost::shared_ptr for d_write = 0 - } - - d_input_parameters.channelCount = noutputs; // # of channels we're really using - -#if 1 - d_portaudio_buffer_size_frames = (int)(0.0213333333 * d_sampling_rate + 0.5); // Force 512 frame buffers at 48000 - fprintf(stderr, "Latency = %8.5f, requested sampling_rate = %g\n", // Force latency to 21.3333333.. ms - 0.0213333333, (double)d_sampling_rate); -#endif - err = Pa_OpenStream(&d_stream, - &d_input_parameters, - NULL, // No output - d_sampling_rate, - d_portaudio_buffer_size_frames, - paClipOff, - &portaudio_source_callback, - (void*)this); - - if (err != paNoError) { - output_error_msg ("OpenStream failed", err); - return false; - } - -#if 0 - const PaStreamInfo *psi = Pa_GetStreamInfo(d_stream); - - d_portaudio_buffer_size_frames = (int)(d_input_parameters.suggestedLatency * psi->sampleRate); - fprintf(stderr, "Latency = %7.4f, psi->sampleRate = %g\n", - d_input_parameters.suggestedLatency, psi->sampleRate); -#endif - - fprintf(stderr, "d_portaudio_buffer_size_frames = %d\n", d_portaudio_buffer_size_frames); - - assert(d_portaudio_buffer_size_frames != 0); - - create_ringbuffer(); - - err = Pa_StartStream(d_stream); - if (err != paNoError) { - output_error_msg ("StartStream failed", err); - return false; - } - - return true; -} - -audio_portaudio_source::~audio_portaudio_source () -{ - Pa_StopStream(d_stream); // wait for output to drain - Pa_CloseStream(d_stream); - Pa_Terminate(); -} - -int -audio_portaudio_source::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - float **out = (float **) &output_items[0]; - const unsigned nchan = d_input_parameters.channelCount; // # of channels == samples/frame - - int k; - for (k = 0; k < noutput_items; ){ - - int nframes = d_reader->items_available() / nchan; // # of frames in ringbuffer - if (nframes == 0){ // no data right now... - if (k > 0) // If we've produced anything so far, return that - return k; - - if (d_ok_to_block) { - gruel:: scoped_lock guard(d_ringbuffer_mutex); - while (d_ringbuffer_ready == false) - d_ringbuffer_cond.wait(guard); // block here, then try again - continue; - } - - assert(k == 0); - - // There's no data and we're not allowed to block. - // (A USRP is most likely controlling the pacing through the pipeline.) - // This is an underun. The scheduler wouldn't have called us if it - // had anything better to do. Thus we really need to produce some amount - // of "fill". - // - // There are lots of options for comfort noise, etc. - // FIXME We'll fill with zeros for now. Yes, it will "click"... - - // Fill with some frames of zeros - { - gruel::scoped_lock guard(d_ringbuffer_mutex); - - int nf = std::min(noutput_items - k, (int) d_portaudio_buffer_size_frames); - for (int i = 0; i < nf; i++){ - for (unsigned int c = 0; c < nchan; c++){ - out[c][k + i] = 0; - } - } - k += nf; - - d_ringbuffer_ready = false; - return k; - } - } - - // We can read the smaller of the request and what's in the buffer. - { - gruel::scoped_lock guard(d_ringbuffer_mutex); - - int nf = std::min(noutput_items - k, nframes); - - const float *p = (const float *) d_reader->read_pointer(); - for (int i = 0; i < nf; i++){ - for (unsigned int c = 0; c < nchan; c++){ - out[c][k + i] = *p++; - } - } - d_reader->update_read_pointer(nf * nchan); - k += nf; - d_ringbuffer_ready = false; - } - } - - return k; // tell how many we actually did -} - -void -audio_portaudio_source::output_error_msg (const char *msg, int err) -{ - fprintf (stderr, "audio_portaudio_source[%s]: %s: %s\n", - d_device_name.c_str (), msg, Pa_GetErrorText(err)); -} - -void -audio_portaudio_source::bail (const char *msg, int err) throw (std::runtime_error) -{ - output_error_msg (msg, err); - throw std::runtime_error ("audio_portaudio_source"); -} diff --git a/gr-audio/lib/portaudio/audio_portaudio_source.h b/gr-audio/lib/portaudio/audio_portaudio_source.h deleted file mode 100644 index e81389a3b..000000000 --- a/gr-audio/lib/portaudio/audio_portaudio_source.h +++ /dev/null @@ -1,84 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006-2011 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. - */ -#ifndef INCLUDED_AUDIO_PORTAUDIO_SOURCE_H -#define INCLUDED_AUDIO_PORTAUDIO_SOURCE_H - -#include <gr_audio_source.h> -#include <gr_buffer.h> -#include <gruel/thread.h> -#include <string> -#include <portaudio.h> -#include <stdexcept> - -PaStreamCallback portaudio_source_callback; - - -/*! - * \brief Audio source using PORTAUDIO - * \ingroup audio_blk - * - * Input samples must be in the range [-1,1]. - */ -class audio_portaudio_source : public audio_source { - - friend PaStreamCallback portaudio_source_callback; - - - unsigned int d_sampling_rate; - std::string d_device_name; - bool d_ok_to_block; - bool d_verbose; - - unsigned int d_portaudio_buffer_size_frames; // number of frames in a portaudio buffer - - PaStream *d_stream; - PaStreamParameters d_input_parameters; - - gr_buffer_sptr d_writer; // buffer used between work and callback - gr_buffer_reader_sptr d_reader; - - gruel::mutex d_ringbuffer_mutex; - gruel::condition_variable d_ringbuffer_cond; - bool d_ringbuffer_ready; - - // random stats - int d_noverruns; // count of overruns - - void output_error_msg (const char *msg, int err); - void bail (const char *msg, int err) throw (std::runtime_error); - void create_ringbuffer(); - - -public: - audio_portaudio_source (int sampling_rate, const std::string device_name, - bool ok_to_block); - - ~audio_portaudio_source (); - - bool check_topology (int ninputs, int noutputs); - - int work (int ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -#endif /* INCLUDED_AUDIO_PORTAUDIO_SOURCE_H */ diff --git a/gr-audio/lib/portaudio/gr-audio-portaudio.conf b/gr-audio/lib/portaudio/gr-audio-portaudio.conf deleted file mode 100644 index 0dd147443..000000000 --- a/gr-audio/lib/portaudio/gr-audio-portaudio.conf +++ /dev/null @@ -1,10 +0,0 @@ -# This file contains system wide configuration data for GNU Radio. -# You may override any setting on a per-user basis by editing -# ~/.gnuradio/config.conf - -[audio_portaudio] - -#default_input_device = hw:0,0 -#default_output_device = hw:0,0 - -verbose = false diff --git a/gr-audio/lib/portaudio/gri_portaudio.cc b/gr-audio/lib/portaudio/gri_portaudio.cc deleted file mode 100644 index 66f3d4647..000000000 --- a/gr-audio/lib/portaudio/gri_portaudio.cc +++ /dev/null @@ -1,111 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006 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 <gri_portaudio.h> -#include <portaudio.h> -#include <string.h> - - -PaDeviceIndex -gri_pa_find_device_by_name(const char *name) -{ - int i; - int numDevices; - const PaDeviceInfo *pdi; - int len = strlen( name ); - PaDeviceIndex result = paNoDevice; - numDevices = Pa_GetDeviceCount(); - for( i=0; i<numDevices; i++ ) - { - pdi = Pa_GetDeviceInfo( i ); - if( strncmp( name, pdi->name, len ) == 0 ) - { - result = i; - break; - } - } - return result; -} - - -void -gri_print_devices() -{ - int numDevices, defaultDisplayed, myDevice=0; - const PaDeviceInfo *deviceInfo; - - numDevices = Pa_GetDeviceCount(); - if (numDevices < 0) - return; - - printf("Number of devices found = %d\n", numDevices); - - for (int i=0; i < numDevices; i++ ) { - deviceInfo = Pa_GetDeviceInfo( i ); - printf( "--------------------------------------- device #%d\n", i ); - /* Mark global and API specific default devices */ - defaultDisplayed = 0; - if( i == Pa_GetDefaultInputDevice() ) - { - myDevice = i; - printf( "[ Default Input" ); - defaultDisplayed = 1; - } - else if( i == Pa_GetHostApiInfo( deviceInfo->hostApi )->defaultInputDevice ) - { - const PaHostApiInfo *hostInfo = Pa_GetHostApiInfo( deviceInfo->hostApi ); - printf( "[ Default %s Input", hostInfo->name ); - defaultDisplayed = 1; - } - - if( i == Pa_GetDefaultOutputDevice() ) - { - printf( (defaultDisplayed ? "," : "[") ); - printf( " Default Output" ); - defaultDisplayed = 1; - } - else if( i == Pa_GetHostApiInfo( deviceInfo->hostApi )->defaultOutputDevice ) - { - const PaHostApiInfo *hostInfo = Pa_GetHostApiInfo( deviceInfo->hostApi ); - printf( (defaultDisplayed ? "," : "[") ); - printf( " Default %s Output", hostInfo->name ); - defaultDisplayed = 1; - } - if( defaultDisplayed ) - printf( " ]\n" ); - - /* print device info fields */ - printf( "Name = %s\n", deviceInfo->name ); - printf( "Host API = %s\n", Pa_GetHostApiInfo( deviceInfo->hostApi )->name ); - printf( "Max inputs = %d", deviceInfo->maxInputChannels ); - printf( ", Max outputs = %d\n", deviceInfo->maxOutputChannels ); - - printf( "Default low input latency = %8.3f\n", deviceInfo->defaultLowInputLatency ); - printf( "Default low output latency = %8.3f\n", deviceInfo->defaultLowOutputLatency ); - printf( "Default high input latency = %8.3f\n", deviceInfo->defaultHighInputLatency ); - printf( "Default high output latency = %8.3f\n", deviceInfo->defaultHighOutputLatency ); - } -} diff --git a/gr-audio/lib/portaudio/gri_portaudio.h b/gr-audio/lib/portaudio/gri_portaudio.h deleted file mode 100644 index c3ea7d064..000000000 --- a/gr-audio/lib/portaudio/gri_portaudio.h +++ /dev/null @@ -1,32 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006 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. - */ - -#ifndef INCLUDED_GRI_PORTAUDIO_H -#define INCLUDED_GRI_PORTAUDIO_H - -#include <stdio.h> -#include <portaudio.h> - -PaDeviceIndex gri_pa_find_device_by_name(const char *name); -void gri_print_devices(); - -#endif /* INCLUDED_GRI_PORTAUDIO_H */ |