diff options
Diffstat (limited to 'gr-audio-osx')
-rw-r--r-- | gr-audio-osx/.gitignore | 30 | ||||
-rw-r--r-- | gr-audio-osx/Makefile.am | 25 | ||||
-rw-r--r-- | gr-audio-osx/README_OSX | 61 | ||||
-rw-r--r-- | gr-audio-osx/TODO | 51 | ||||
-rw-r--r-- | gr-audio-osx/src/.gitignore | 16 | ||||
-rw-r--r-- | gr-audio-osx/src/Makefile.am | 80 | ||||
-rw-r--r-- | gr-audio-osx/src/Makefile.swig.gen | 145 | ||||
-rw-r--r-- | gr-audio-osx/src/audio_osx.h | 71 | ||||
-rw-r--r-- | gr-audio-osx/src/audio_osx.i | 100 | ||||
-rw-r--r-- | gr-audio-osx/src/audio_osx_sink.cc | 411 | ||||
-rw-r--r-- | gr-audio-osx/src/audio_osx_sink.h | 96 | ||||
-rw-r--r-- | gr-audio-osx/src/audio_osx_source.cc | 1023 | ||||
-rw-r--r-- | gr-audio-osx/src/audio_osx_source.h | 132 | ||||
-rw-r--r-- | gr-audio-osx/src/circular_buffer.h | 315 | ||||
-rwxr-xr-x | gr-audio-osx/src/qa_osx.py | 40 | ||||
-rw-r--r-- | gr-audio-osx/src/run_tests.in | 10 | ||||
-rwxr-xr-x | gr-audio-osx/src/test_audio_loop.py | 65 |
17 files changed, 0 insertions, 2671 deletions
diff --git a/gr-audio-osx/.gitignore b/gr-audio-osx/.gitignore deleted file mode 100644 index cdcf41b15..000000000 --- a/gr-audio-osx/.gitignore +++ /dev/null @@ -1,30 +0,0 @@ -/*.cache -/*.la -/*.lo -/*.pc -/.deps -/.la -/.libs -/.lo -/Makefile -/Makefile.in -/aclocal.m4 -/autom4te.cache -/config.cache -/config.h -/config.h.in -/config.log -/config.status -/configure -/depcomp -/install-sh -/libtool -/ltmain.sh -/make.log -/missing -/missing -/mkinstalldirs -/py-compile -/stamp-h -/stamp-h.in -/stamp-h1 diff --git a/gr-audio-osx/Makefile.am b/gr-audio-osx/Makefile.am deleted file mode 100644 index 84a4c69b3..000000000 --- a/gr-audio-osx/Makefile.am +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright 2004,2006,2010 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. -# - -include $(top_srcdir)/Makefile.common - -EXTRA_DIST += README_OSX -SUBDIRS = src diff --git a/gr-audio-osx/README_OSX b/gr-audio-osx/README_OSX deleted file mode 100644 index 2a98e96bb..000000000 --- a/gr-audio-osx/README_OSX +++ /dev/null @@ -1,61 +0,0 @@ -Michael Dickens -2006-Apr-30 - -0) This module should compile and install in the same manner as the -other GNURadio modules (e.g. gnuradio-core), with the possible -exception that GNU libtool 1.5.20 or newer should be installed and -used (if not first in the path) via "make LIBTOOL=/..." and so forth. -Version 1.5.10 has failed making, and while picking version 1.5.20 is -somewhat arbitrary, the newer version compiles and installs easily -under OSX. - -1) This module should be automatically loaded by the Python command -"from gr import audio". The audio import script will automatically -select gr.audio_osx if it is available (though it will try to import -ALSA first, then OSS, then OSX, and finally WINDOWS audio modules, in -that order). If that import command doesn't work, try reinstalling -gnuradio-core from scratch followed by gr-audio-osx. - -2) Instantiation arguments for either source or sink are: - -* sample_rate : integer : default == 44100 - OSX converts the integer sample rate to a double internally; it - would be nice to have this input as a double natively, but that - doesn't work with other audio devices. - -* device_name : string : default == "2" - For OSX, the device name should be an integer string. This value is - the maximum number of channels to allocate (for input or output). - In the "source" case (input), the actual number of channels will be - whatever is available on that current system input device. In the - "sink" case (output), OSX will convert the provided channels into - whatever format is required by the current system output device. - For example, "3" would try to setup for 3 input or output channels. - NOTE that this is a very different use than that for other audio - modules (though they can interpret the number of channels from this - argument). - -* do_block : boolean : default == true - If the data transfer buffer between OSX internals and GNURadio gets - full, either block (true) or overwrite (false) depending on this - variable. - -The following are currently non-standard arguments: - -* channel_config : integer : default == -1 - An enum (internally) describing the channel configuration. Not - currently used, but rather reserved for future expansion. - -* max_sample_count : integer : default == -1 - The maximum number of samples to buffer between OSX internals and - GNURadio. The value -1 is mapped to 1 second's worth of data. - -3) When the buffer is full and do_block is false and new data comes -in, the oldest data will be overwritten. The source will print out -"iX" each time this happens; the sink will print out "oX". - -4) In the "src" directory is a python script "test_audio_loop" which -connects the default audio input device to the default audio output -device. This script is very useful in testing that audio is correctly -installed and both the source and sink are functional. This script is -not run by "make check". diff --git a/gr-audio-osx/TODO b/gr-audio-osx/TODO deleted file mode 100644 index e36ed2b25..000000000 --- a/gr-audio-osx/TODO +++ /dev/null @@ -1,51 +0,0 @@ -List as of 2006-Apr-22, by Michael Dickens, primary author - -* Change buffering to use gr_buffer's and necessary related classes. - Currently uses a circular_buffer I wrote myself (in - ./src/circular_buffer.h ), which hides the "circular" part from the - user but otherwise is very fast as well as thread safe. - -* A current limitation of this implementation is that the user cannot - dynamically switch audio devices (input or output) during playback - and use the new device without stopping the current executing GR and - restarting the process. I would like to figure out how to get a - CoreAudio "listener" for when the default hardware input / output - device changes (e.g. when switched by the user in the "Sound" system - preference pane). The code in ./src/audio-osx-source.cc creates - listeners for the AudioUnit being used as well as the Hardware - device, but these for some reason don't do the trick. It's possible - that the Python framework doesn't allow for one to do this. - -* In both the source and sink, move the code which defines the "Audio - Stream Basic Description" (ASBD) to a routine to do this as needed - as start-up as well as in a callback ("listener") if the default - device changes. - -* Tweak the mutex (d_internal) to only where it is truly needed - (around class-specific variables used across all threads) in order - to improve performance. Currently the mutex is used at the - start and end of any function requiring access to the class variables. - -* Change the instantiation arguments ... once those arguments are - finalized. Right now gr.audio.source () takes the sample rate (int - - should be double), the device name (std::string), a boolean for - blocking or not, and 2 completely non-standard ones for channel - configuration and the maximum sample count to buffer. These are - reasonable for OSX, but might not be for other OSs. Nothing to do - right now but wait and discuss. - -* Once the previous issue has been resolved, then the current method - of determining the number of channels needs to be updated. - Currently the "device_name" for OSX should contain a numeric string - for the maximum number of channels to use (e.g. "3" means 3 - channels, generally mapped to 2 channel stereo by OSX). The - "device_name" is generally input via "-O" in Python scripts, so "-O - 3" would allow for 3 incoming output channels (or fewer). In theory - the "channel_config" argument would make more sense for determining - channel usage. Example config strings might be "2.1" for stereo w/ - subwoofer (3 channels), "5.1" or "6.1" for various surround w/ - subwoofer (6 & 7 channels, respectively). OSX can handle all sorts - of channel configurations, but the names for these will be different - than those use for OSS or ALMA or Windows ... thus the need for a - common naming scheme for all cared-about configurations, possibly - with options for other OS-specific options. diff --git a/gr-audio-osx/src/.gitignore b/gr-audio-osx/src/.gitignore deleted file mode 100644 index 7e84b05b3..000000000 --- a/gr-audio-osx/src/.gitignore +++ /dev/null @@ -1,16 +0,0 @@ -/Makefile -/Makefile.in -/.la -/.lo -/.deps -/.libs -/*.la -/*.lo -/usrp.py -/usrp.cc -/audio_osx.cc -/audio_osx.py -/run_tests -/gnuradio -/guile -/python diff --git a/gr-audio-osx/src/Makefile.am b/gr-audio-osx/src/Makefile.am deleted file mode 100644 index fce31c9d2..000000000 --- a/gr-audio-osx/src/Makefile.am +++ /dev/null @@ -1,80 +0,0 @@ -# -# Copyright 2006,2008,2009,2010 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. -# - -include $(top_srcdir)/Makefile.common -include $(top_srcdir)/Makefile.swig - -TESTS = -EXTRA_DIST += run_tests.in -DISTCLEANFILES += run_tests - -AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) $(WITH_INCLUDES) - -# C/C++ headers get installed in ${prefix}/include/gnuradio -grinclude_HEADERS = \ - audio_osx_sink.h \ - audio_osx_source.h - -noinst_HEADERS = \ - audio_osx.h \ - circular_buffer.h - -noinst_PYTHON = \ - qa_osx.py \ - test_audio_loop.py - -lib_LTLIBRARIES = libgnuradio-audio-osx.la - -libgnuradio_audio_osx_la_SOURCES = \ - audio_osx_sink.cc \ - audio_osx_source.cc - -libgnuradio_audio_osx_la_LIBADD = \ - $(GNURADIO_CORE_LA) - -libgnuradio_audio_osx_la_LDFLAGS = \ - -framework AudioUnit \ - -framework CoreAudio \ - -framework AudioToolbox \ - $(NO_UNDEFINED) \ - $(LTVERSIONFLAGS) - -################################### -# SWIG interfaces and libraries - -TOP_SWIG_IFILES = \ - audio_osx.i - -# Install so that they end up available as: -# import gnuradio.audio_osx -# This ends up at: -# ${prefix}/lib/python${python_version}/site-packages/gnuradio -audio_osx_pythondir_category = \ - gnuradio - -# additional libraries for linking with the SWIG-generated library -audio_osx_la_swig_libadd = \ - libgnuradio-audio-osx.la - - -if PYTHON -TESTS += run_tests -endif
\ No newline at end of file diff --git a/gr-audio-osx/src/Makefile.swig.gen b/gr-audio-osx/src/Makefile.swig.gen deleted file mode 100644 index 532433083..000000000 --- a/gr-audio-osx/src/Makefile.swig.gen +++ /dev/null @@ -1,145 +0,0 @@ -# -*- Makefile -*- -# -# Copyright 2009 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. -# - -# Makefile.swig.gen for audio_osx.i - -## Default install locations for these files: -## -## Default location for the Python directory is: -## ${prefix}/lib/python${python_version}/site-packages/[category]/audio_osx -## Default location for the Python exec directory is: -## ${exec_prefix}/lib/python${python_version}/site-packages/[category]/audio_osx -## -## The following can be overloaded to change the install location, but -## this has to be done in the including Makefile.am -before- -## Makefile.swig is included. - -audio_osx_pythondir_category ?= gnuradio/audio_osx -audio_osx_pylibdir_category ?= $(audio_osx_pythondir_category) -audio_osx_pythondir = $(pythondir)/$(audio_osx_pythondir_category) -audio_osx_pylibdir = $(pyexecdir)/$(audio_osx_pylibdir_category) - -# The .so libraries for the guile modules get installed whereever guile -# is installed, usually /usr/lib/guile/gnuradio/ -# FIXME: determince whether these should be installed with gnuradio. -audio_osx_scmlibdir = $(libdir) - -# The scm files for the guile modules get installed where ever guile -# is installed, usually /usr/share/guile/site/audio_osx -# FIXME: determince whether these should be installed with gnuradio. -audio_osx_scmdir = $(guiledir) - -## SWIG headers are always installed into the same directory. - -audio_osx_swigincludedir = $(swigincludedir) - -## This is a template file for a "generated" Makefile addition (in -## this case, "Makefile.swig.gen"). By including the top-level -## Makefile.swig, this file will be used to generate the SWIG -## dependencies. Assign the variable TOP_SWIG_FILES to be the list of -## SWIG .i files to generated wrappings for; there can be more than 1 -## so long as the names are unique (no sorting is done on the -## TOP_SWIG_FILES list). This file explicitly assumes that a SWIG .i -## file will generate .cc, .py, and possibly .h files -- meaning that -## all of these files will have the same base name (that provided for -## the SWIG .i file). -## -## This code is setup to ensure parallel MAKE ("-j" or "-jN") does the -## right thing. For more info, see < -## http://sources.redhat.com/automake/automake.html#Multiple-Outputs > - -## Other cleaned files: dependency files generated by SWIG or this Makefile - -MOSTLYCLEANFILES += $(DEPDIR)/*.S* - -## Various SWIG variables. These can be overloaded in the including -## Makefile.am by setting the variable value there, then including -## Makefile.swig . - -audio_osx_swiginclude_HEADERS = \ - audio_osx.i \ - $(audio_osx_swiginclude_headers) - -if PYTHON -audio_osx_pylib_LTLIBRARIES = \ - _audio_osx.la - -_audio_osx_la_SOURCES = \ - python/audio_osx.cc \ - $(audio_osx_la_swig_sources) - -audio_osx_python_PYTHON = \ - audio_osx.py \ - $(audio_osx_python) - -_audio_osx_la_LIBADD = \ - $(STD_SWIG_LA_LIB_ADD) \ - $(audio_osx_la_swig_libadd) - -_audio_osx_la_LDFLAGS = \ - $(STD_SWIG_LA_LD_FLAGS) \ - $(audio_osx_la_swig_ldflags) - -_audio_osx_la_CXXFLAGS = \ - $(STD_SWIG_CXX_FLAGS) \ - -I$(top_builddir) \ - $(audio_osx_la_swig_cxxflags) - -python/audio_osx.cc: audio_osx.py -audio_osx.py: audio_osx.i - -# Include the python dependencies for this file --include python/audio_osx.d - -endif # end of if python - -if GUILE - -audio_osx_scmlib_LTLIBRARIES = \ - libguile-gnuradio-audio_osx.la -libguile_gnuradio_audio_osx_la_SOURCES = \ - guile/audio_osx.cc \ - $(audio_osx_la_swig_sources) -nobase_audio_osx_scm_DATA = \ - gnuradio/audio_osx.scm \ - gnuradio/audio_osx-primitive.scm -libguile_gnuradio_audio_osx_la_LIBADD = \ - $(STD_SWIG_LA_LIB_ADD) \ - $(audio_osx_la_swig_libadd) -libguile_gnuradio_audio_osx_la_LDFLAGS = \ - $(STD_SWIG_LA_LD_FLAGS) \ - $(audio_osx_la_swig_ldflags) -libguile_gnuradio_audio_osx_la_CXXFLAGS = \ - $(STD_SWIG_CXX_FLAGS) \ - -I$(top_builddir) \ - $(audio_osx_la_swig_cxxflags) - -guile/audio_osx.cc: gnuradio/audio_osx.scm -gnuradio/audio_osx.scm: audio_osx.i -gnuradio/audio_osx-primitive.scm: gnuradio/audio_osx.scm - -# Include the guile dependencies for this file --include guile/audio_osx.d - -endif # end of GUILE - - diff --git a/gr-audio-osx/src/audio_osx.h b/gr-audio-osx/src/audio_osx.h deleted file mode 100644 index 79e79e36c..000000000 --- a/gr-audio-osx/src/audio_osx.h +++ /dev/null @@ -1,71 +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_AUDIO_OSX_H -#define INCLUDED_AUDIO_OSX_H - -#include <iostream> -#include <string.h> - -#define CheckErrorAndThrow(err,what,throw_str) \ - if (err) { \ - OSStatus error = static_cast<OSStatus>(err); \ - char err_str[4]; \ - strncpy (err_str, (char*)(&err), 4); \ - std::cerr << what << std::endl; \ - std::cerr << " Error# " << error << " ('" << err_str \ - << "')" << std::endl; \ - std::cerr << " " << __FILE__ << ":" << __LINE__ << std::endl; \ - fflush (stderr); \ - throw std::runtime_error (throw_str); \ - } - -#define CheckError(err,what) \ - if (err) { \ - OSStatus error = static_cast<OSStatus>(err); \ - char err_str[4]; \ - strncpy (err_str, (char*)(&err), 4); \ - std::cerr << what << std::endl; \ - std::cerr << " Error# " << error << " ('" << err_str \ - << "')" << std::endl; \ - std::cerr << " " << __FILE__ << ":" << __LINE__ << std::endl; \ - fflush (stderr); \ - } - -#ifdef WORDS_BIGENDIAN -#define GR_PCM_ENDIANNESS kLinearPCMFormatFlagIsBigEndian -#else -#define GR_PCM_ENDIANNESS 0 -#endif - -// Check the version of MacOSX being used -#ifdef __APPLE_CC__ -#include <AvailabilityMacros.h> -#ifndef MAC_OS_X_VERSION_10_6 -#define MAC_OS_X_VERSION_10_6 1060 -#endif -#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6 -#define GR_USE_OLD_AUDIO_UNIT -#endif -#endif - -#endif /* INCLUDED_AUDIO_OSX_H */ diff --git a/gr-audio-osx/src/audio_osx.i b/gr-audio-osx/src/audio_osx.i deleted file mode 100644 index a51e9bae0..000000000 --- a/gr-audio-osx/src/audio_osx.i +++ /dev/null @@ -1,100 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006,2009 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. - */ - -%include "gnuradio.i" // the common stuff - -%{ -#include "audio_osx_sink.h" -#include "audio_osx_source.h" -%} - -// ---------------------------------------------------------------- - -GR_SWIG_BLOCK_MAGIC(audio_osx,sink) - -audio_osx_sink_sptr -audio_osx_make_sink (int sample_rate = 44100, - const std::string device_name = "2", - bool do_block = TRUE, - int channel_config = -1, - int max_sample_count = -1 - ) throw (std::runtime_error); - -class audio_osx_sink : public gr_sync_block { - protected: - audio_osx_sink (int sample_rate = 44100, - const std::string device_name = "2", - bool do_block = TRUE, - int channel_config = -1, - int max_sample_count = -1); - - public: - ~audio_osx_sink (); - - bool start (); - bool stop (); - - int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -// ---------------------------------------------------------------- - -GR_SWIG_BLOCK_MAGIC(audio_osx,source) - -audio_osx_source_sptr -audio_osx_make_source (int sample_rate = 44100, - const std::string device_name = "2", - bool do_block = TRUE, - int channel_config = -1, - int max_sample_count = -1 - ) throw (std::runtime_error); - -class audio_osx_source : public gr_sync_block { - protected: - audio_osx_source (int sample_rate = 44100, - const std::string device_name = "2", - bool do_block = TRUE, - int channel_config = -1, - int max_sample_count = -1); - - public: - ~audio_osx_source (); - - bool start (); - bool stop (); - - int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -#if SWIGGUILE -%scheme %{ -(load-extension-global "libguile-gnuradio-audio_osx" "scm_init_gnuradio_audio_osx_module") -%} - -%goops %{ -(use-modules (gnuradio gnuradio_core_runtime)) -%} -#endif diff --git a/gr-audio-osx/src/audio_osx_sink.cc b/gr-audio-osx/src/audio_osx_sink.cc deleted file mode 100644 index ec9b024e8..000000000 --- a/gr-audio-osx/src/audio_osx_sink.cc +++ /dev/null @@ -1,411 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006,2010 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_osx_sink.h> -#include <gr_io_signature.h> -#include <stdexcept> -#include <audio_osx.h> - -#define _OSX_AU_DEBUG_ 0 - -audio_osx_sink::audio_osx_sink (int sample_rate, - const std::string device_name, - bool do_block, - int channel_config, - int max_sample_count) - : gr_sync_block ("audio_osx_sink", - gr_make_io_signature (0, 0, 0), - gr_make_io_signature (0, 0, 0)), - d_sample_rate (0.0), d_channel_config (0), d_n_channels (0), - d_queueSampleCount (0), d_max_sample_count (0), - d_do_block (do_block), d_internal (0), d_cond_data (0), - d_OutputAU (0) -{ - if (sample_rate <= 0) { - std::cerr << "Invalid Sample Rate: " << sample_rate << std::endl; - throw std::invalid_argument ("audio_osx_sink::audio_osx_sink"); - } else - d_sample_rate = (Float64) sample_rate; - - if (channel_config <= 0 & channel_config != -1) { - std::cerr << "Invalid Channel Config: " << channel_config << std::endl; - throw std::invalid_argument ("audio_osx_sink::audio_osx_sink"); - } else if (channel_config == -1) { -// no user input; try "device name" instead - int l_n_channels = (int) strtol (device_name.data(), (char **)NULL, 10); - if (l_n_channels == 0 & errno) { - std::cerr << "Error Converting Device Name: " << errno << std::endl; - throw std::invalid_argument ("audio_osx_sink::audio_osx_sink"); - } - if (l_n_channels <= 0) - channel_config = 2; - else - channel_config = l_n_channels; - } - - d_n_channels = d_channel_config = channel_config; - -// set the input signature - - set_input_signature (gr_make_io_signature (1, d_n_channels, sizeof (float))); - -// check that the max # of samples to store is valid - - if (max_sample_count == -1) - max_sample_count = sample_rate; - else if (max_sample_count <= 0) { - std::cerr << "Invalid Max Sample Count: " << max_sample_count << std::endl; - throw std::invalid_argument ("audio_osx_sink::audio_osx_sink"); - } - - d_max_sample_count = max_sample_count; - -// allocate the output circular buffer(s), one per channel - - d_buffers = (circular_buffer<float>**) new - circular_buffer<float>* [d_n_channels]; - UInt32 n_alloc = (UInt32) ceil ((double) d_max_sample_count); - for (UInt32 n = 0; n < d_n_channels; n++) { - d_buffers[n] = new circular_buffer<float> (n_alloc, false, false); - } - -// create the default AudioUnit for output - OSStatus err = noErr; - -// Open the default output unit -#ifndef GR_USE_OLD_AUDIO_UNIT - AudioComponentDescription desc; -#else - ComponentDescription desc; -#endif - - desc.componentType = kAudioUnitType_Output; - desc.componentSubType = kAudioUnitSubType_DefaultOutput; - desc.componentManufacturer = kAudioUnitManufacturer_Apple; - desc.componentFlags = 0; - desc.componentFlagsMask = 0; - -#ifndef GR_USE_OLD_AUDIO_UNIT - AudioComponent comp = AudioComponentFindNext(NULL, &desc); - if (comp == NULL) { - std::cerr << "AudioComponentFindNext Error" << std::endl; - throw std::runtime_error ("audio_osx_sink::audio_osx_sink"); - } -#else - Component comp = FindNextComponent (NULL, &desc); - if (comp == NULL) { - std::cerr << "FindNextComponent Error" << std::endl; - throw std::runtime_error ("audio_osx_sink::audio_osx_sink"); - } -#endif - -#ifndef GR_USE_OLD_AUDIO_UNIT - err = AudioComponentInstanceNew (comp, &d_OutputAU); - CheckErrorAndThrow (err, "AudioComponentInstanceNew", "audio_osx_sink::audio_osx_sink"); -#else - err = OpenAComponent (comp, &d_OutputAU); - CheckErrorAndThrow (err, "OpenAComponent", "audio_osx_sink::audio_osx_sink"); -#endif - -// Set up a callback function to generate output to the output unit - - AURenderCallbackStruct input; - input.inputProc = (AURenderCallback)(audio_osx_sink::AUOutputCallback); - input.inputProcRefCon = this; - - err = AudioUnitSetProperty (d_OutputAU, - kAudioUnitProperty_SetRenderCallback, - kAudioUnitScope_Input, - 0, - &input, - sizeof (input)); - CheckErrorAndThrow (err, "AudioUnitSetProperty Render Callback", "audio_osx_sink::audio_osx_sink"); - -// tell the Output Unit what format data will be supplied to it -// so that it handles any format conversions - - AudioStreamBasicDescription streamFormat; - streamFormat.mSampleRate = (Float64)(sample_rate); - streamFormat.mFormatID = kAudioFormatLinearPCM; - streamFormat.mFormatFlags = (kLinearPCMFormatFlagIsFloat | - GR_PCM_ENDIANNESS | - kLinearPCMFormatFlagIsPacked | - kAudioFormatFlagIsNonInterleaved); - streamFormat.mBytesPerPacket = 4; - streamFormat.mFramesPerPacket = 1; - streamFormat.mBytesPerFrame = 4; - streamFormat.mChannelsPerFrame = d_n_channels; - streamFormat.mBitsPerChannel = 32; - - err = AudioUnitSetProperty (d_OutputAU, - kAudioUnitProperty_StreamFormat, - kAudioUnitScope_Input, - 0, - &streamFormat, - sizeof (AudioStreamBasicDescription)); - CheckErrorAndThrow (err, "AudioUnitSetProperty StreamFormat", "audio_osx_sink::audio_osx_sink"); - -// create the stuff to regulate I/O - - d_cond_data = new gruel::condition_variable (); - if (d_cond_data == NULL) - CheckErrorAndThrow (errno, "new condition (data)", - "audio_osx_sink::audio_osx_sink"); - - d_internal = new gruel::mutex (); - if (d_internal == NULL) - CheckErrorAndThrow (errno, "new mutex (internal)", - "audio_osx_sink::audio_osx_sink"); - -// initialize the AU for output - - err = AudioUnitInitialize (d_OutputAU); - CheckErrorAndThrow (err, "AudioUnitInitialize", - "audio_osx_sink::audio_osx_sink"); - -#if _OSX_AU_DEBUG_ - std::cerr << "audio_osx_sink Parameters:" << std::endl; - std::cerr << " Sample Rate is " << d_sample_rate << std::endl; - std::cerr << " Number of Channels is " << d_n_channels << std::endl; - std::cerr << " Max # samples to store per channel is " << d_max_sample_count << std::endl; -#endif -} - -bool audio_osx_sink::IsRunning () -{ - UInt32 AURunning = 0, AUSize = sizeof (UInt32); - - OSStatus err = AudioUnitGetProperty (d_OutputAU, - kAudioOutputUnitProperty_IsRunning, - kAudioUnitScope_Global, - 0, - &AURunning, - &AUSize); - CheckErrorAndThrow (err, "AudioUnitGetProperty IsRunning", - "audio_osx_sink::IsRunning"); - - return (AURunning); -} - -bool audio_osx_sink::start () -{ - if (! IsRunning ()) { - OSStatus err = AudioOutputUnitStart (d_OutputAU); - CheckErrorAndThrow (err, "AudioOutputUnitStart", "audio_osx_sink::start"); - } - - return (true); -} - -bool audio_osx_sink::stop () -{ - if (IsRunning ()) { - OSStatus err = AudioOutputUnitStop (d_OutputAU); - CheckErrorAndThrow (err, "AudioOutputUnitStop", "audio_osx_sink::stop"); - - for (UInt32 n = 0; n < d_n_channels; n++) { - d_buffers[n]->abort (); - } - } - - return (true); -} - -audio_osx_sink::~audio_osx_sink () -{ -// stop and close the AudioUnit - stop (); - AudioUnitUninitialize (d_OutputAU); -#ifndef GR_USE_OLD_AUDIO_UNIT - AudioComponentInstanceDispose (d_OutputAU); -#else - CloseComponent (d_OutputAU); -#endif - -// empty and delete the queues - for (UInt32 n = 0; n < d_n_channels; n++) { - delete d_buffers[n]; - d_buffers[n] = 0; - } - delete [] d_buffers; - d_buffers = 0; - -// close and delete control stuff - delete d_cond_data; - d_cond_data = 0; - delete d_internal; - d_internal = 0; -} - -audio_osx_sink_sptr -audio_osx_make_sink (int sampling_freq, - const std::string dev, - bool do_block, - int channel_config, - int max_sample_count) -{ - return gnuradio::get_initial_sptr(new audio_osx_sink (sampling_freq, - dev, - do_block, - channel_config, - max_sample_count)); -} - -int -audio_osx_sink::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - gruel::scoped_lock l (*d_internal); - - /* take the input data, copy it, and push it to the bottom of the queue - mono input are pushed onto queue[0]; - stereo input are pushed onto queue[1]. - Start the AudioUnit if necessary. */ - - UInt32 l_max_count; - int diff_count = d_max_sample_count - noutput_items; - if (diff_count < 0) - l_max_count = 0; - else - l_max_count = (UInt32) diff_count; - -#if 0 - if (l_max_count < d_queueItemLength->back()) { -// allow 2 buffers at a time, regardless of length - l_max_count = d_queueItemLength->back(); - } -#endif - -#if _OSX_AU_DEBUG_ - std::cerr << "work1: qSC = " << d_queueSampleCount << ", lMC = "<< l_max_count - << ", dmSC = " << d_max_sample_count << ", nOI = " << noutput_items << std::endl; -#endif - - if (d_queueSampleCount > l_max_count) { -// data coming in too fast; do_block decides what to do - if (d_do_block == true) { -// block until there is data to return - while (d_queueSampleCount > l_max_count) { -// release control so-as to allow data to be retrieved; -// block until there is data to return - d_cond_data->wait (l); -// the condition's 'notify' was called; acquire control -// to keep thread safe - } - } - } -// not blocking case and overflow is handled by the circular buffer - -// add the input frames to the buffers' queue, checking for overflow - - UInt32 l_counter; - int res = 0; - float* inBuffer = (float*) input_items[0]; - const UInt32 l_size = input_items.size(); - for (l_counter = 0; l_counter < l_size; l_counter++) { - inBuffer = (float*) input_items[l_counter]; - int l_res = d_buffers[l_counter]->enqueue (inBuffer, - noutput_items); - if (l_res == -1) - res = -1; - } - while (l_counter < d_n_channels) { -// for extra channels, copy the last input's data - int l_res = d_buffers[l_counter++]->enqueue (inBuffer, - noutput_items); - if (l_res == -1) - res = -1; - } - - if (res == -1) { -// data coming in too fast -// drop oldest buffer - fputs ("aO", stderr); - fflush (stderr); -// set the local number of samples available to the max - d_queueSampleCount = d_buffers[0]->buffer_length_items (); - } else { -// keep up the local sample count - d_queueSampleCount += noutput_items; - } - -#if _OSX_AU_DEBUG_ - std::cerr << "work2: #OI = " << noutput_items << ", #Cnt = " - << d_queueSampleCount << ", mSC = " << d_max_sample_count << std::endl; -#endif - - return (noutput_items); -} - -OSStatus audio_osx_sink::AUOutputCallback -(void *inRefCon, - AudioUnitRenderActionFlags *ioActionFlags, - const AudioTimeStamp *inTimeStamp, - UInt32 inBusNumber, - UInt32 inNumberFrames, - AudioBufferList *ioData) -{ - audio_osx_sink* This = (audio_osx_sink*) inRefCon; - OSStatus err = noErr; - - gruel::scoped_lock l (*This->d_internal); - -#if _OSX_AU_DEBUG_ - std::cerr << "cb_in: SC = " << This->d_queueSampleCount - << ", in#F = " << inNumberFrames << std::endl; -#endif - - if (This->d_queueSampleCount < inNumberFrames) { -// not enough data to fill request - err = -1; - } else { -// enough data; remove data from our buffers into the AU's buffers - int l_counter = This->d_n_channels; - - while (--l_counter >= 0) { - size_t t_n_output_items = inNumberFrames; - float* outBuffer = (float*) ioData->mBuffers[l_counter].mData; - This->d_buffers[l_counter]->dequeue (outBuffer, &t_n_output_items); - if (t_n_output_items != inNumberFrames) { - throw std::runtime_error ("audio_osx_sink::AUOutputCallback(): " - "number of available items changing " - "unexpectedly.\n"); - } - } - - This->d_queueSampleCount -= inNumberFrames; - } - -#if _OSX_AU_DEBUG_ - std::cerr << "cb_out: SC = " << This->d_queueSampleCount << std::endl; -#endif - -// signal that data is available - This->d_cond_data->notify_one (); - - return (err); -} diff --git a/gr-audio-osx/src/audio_osx_sink.h b/gr-audio-osx/src/audio_osx_sink.h deleted file mode 100644 index a1a56502c..000000000 --- a/gr-audio-osx/src/audio_osx_sink.h +++ /dev/null @@ -1,96 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006,2010 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_OSX_SINK_H -#define INCLUDED_AUDIO_OSX_SINK_H - -#include <gr_sync_block.h> -#include <string> -#include <list> -#include <AudioUnit/AudioUnit.h> -#include <circular_buffer.h> - -class audio_osx_sink; -typedef boost::shared_ptr<audio_osx_sink> audio_osx_sink_sptr; - -audio_osx_sink_sptr -audio_osx_make_sink (int sample_rate = 44100, - const std::string device_name = "2", - bool do_block = true, - int channel_config = -1, - int max_sample_count = -1); - -/*! - * \brief audio sink using OSX - * - * input signature is one or two streams of floats. - * Input samples must be in the range [-1,1]. - */ - -class audio_osx_sink : public gr_sync_block { - friend audio_osx_sink_sptr - audio_osx_make_sink (int sample_rate, - const std::string device_name, - bool do_block, - int channel_config, - int max_sample_count); - - Float64 d_sample_rate; - int d_channel_config; - UInt32 d_n_channels; - UInt32 d_queueSampleCount, d_max_sample_count; - bool d_do_block; - gruel::mutex* d_internal; - gruel::condition_variable* d_cond_data; - circular_buffer<float>** d_buffers; - -// AudioUnits and Such - AudioUnit d_OutputAU; - -protected: - audio_osx_sink (int sample_rate = 44100, - const std::string device_name = "2", - bool do_block = true, - int channel_config = -1, - int max_sample_count = -1); - -public: - ~audio_osx_sink (); - - bool IsRunning (); - bool start (); - bool stop (); - - int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - -private: - static OSStatus AUOutputCallback (void *inRefCon, - AudioUnitRenderActionFlags *ioActionFlags, - const AudioTimeStamp *inTimeStamp, - UInt32 inBusNumber, - UInt32 inNumberFrames, - AudioBufferList *ioData); -}; - -#endif /* INCLUDED_AUDIO_OSX_SINK_H */ diff --git a/gr-audio-osx/src/audio_osx_source.cc b/gr-audio-osx/src/audio_osx_source.cc deleted file mode 100644 index 757e65a9e..000000000 --- a/gr-audio-osx/src/audio_osx_source.cc +++ /dev/null @@ -1,1023 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006,2010 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_osx_source.h> -#include <gr_io_signature.h> -#include <stdexcept> -#include <audio_osx.h> - -#define _OSX_AU_DEBUG_ 0 -#define _OSX_DO_LISTENERS_ 0 - -void PrintStreamDesc (AudioStreamBasicDescription *inDesc) -{ - if (inDesc == NULL) { - std::cerr << "PrintStreamDesc: Can't print a NULL desc!" << std::endl; - return; - } - - std::cerr << " Sample Rate : " << inDesc->mSampleRate << std::endl; - char format_id[4]; - strncpy (format_id, (char*)(&inDesc->mFormatID), 4); - std::cerr << " Format ID : " << format_id << std::endl; - std::cerr << " Format Flags : " << inDesc->mFormatFlags << std::endl; - std::cerr << " Bytes per Packet : " << inDesc->mBytesPerPacket << std::endl; - std::cerr << " Frames per Packet : " << inDesc->mFramesPerPacket << std::endl; - std::cerr << " Bytes per Frame : " << inDesc->mBytesPerFrame << std::endl; - std::cerr << " Channels per Frame : " << inDesc->mChannelsPerFrame << std::endl; - std::cerr << " Bits per Channel : " << inDesc->mBitsPerChannel << std::endl; -} - -// FIXME these should query some kind of user preference - -audio_osx_source::audio_osx_source (int sample_rate, - const std::string device_name, - bool do_block, - int channel_config, - int max_sample_count) - : gr_sync_block ("audio_osx_source", - gr_make_io_signature (0, 0, 0), - gr_make_io_signature (0, 0, 0)), - d_deviceSampleRate (0.0), d_outputSampleRate (0.0), - d_channel_config (0), - d_inputBufferSizeFrames (0), d_inputBufferSizeBytes (0), - d_outputBufferSizeFrames (0), d_outputBufferSizeBytes (0), - d_deviceBufferSizeFrames (0), d_deviceBufferSizeBytes (0), - d_leadSizeFrames (0), d_leadSizeBytes (0), - d_trailSizeFrames (0), d_trailSizeBytes (0), - d_extraBufferSizeFrames (0), d_extraBufferSizeBytes (0), - d_queueSampleCount (0), d_max_sample_count (0), - d_n_AvailableInputFrames (0), d_n_ActualInputFrames (0), - d_n_user_channels (0), d_n_max_channels (0), d_n_deviceChannels (0), - d_do_block (do_block), d_passThrough (false), - d_internal (0), d_cond_data (0), - d_buffers (0), - d_InputAU (0), d_InputBuffer (0), d_OutputBuffer (0), - d_AudioConverter (0) -{ - if (sample_rate <= 0) { - std::cerr << "Invalid Sample Rate: " << sample_rate << std::endl; - throw std::invalid_argument ("audio_osx_source::audio_osx_source"); - } else - d_outputSampleRate = (Float64) sample_rate; - - if (channel_config <= 0 & channel_config != -1) { - std::cerr << "Invalid Channel Config: " << channel_config << std::endl; - throw std::invalid_argument ("audio_osx_source::audio_osx_source"); - } else if (channel_config == -1) { -// no user input; try "device name" instead - int l_n_channels = (int) strtol (device_name.data(), (char **)NULL, 10); - if (l_n_channels == 0 & errno) { - std::cerr << "Error Converting Device Name: " << errno << std::endl; - throw std::invalid_argument ("audio_osx_source::audio_osx_source"); - } - if (l_n_channels <= 0) - channel_config = 2; - else - channel_config = l_n_channels; - } - - d_channel_config = channel_config; - -// check that the max # of samples to store is valid - - if (max_sample_count == -1) - max_sample_count = sample_rate; - else if (max_sample_count <= 0) { - std::cerr << "Invalid Max Sample Count: " << max_sample_count << std::endl; - throw std::invalid_argument ("audio_osx_source::audio_osx_source"); - } - - d_max_sample_count = max_sample_count; - -#if _OSX_AU_DEBUG_ - std::cerr << "source(): max # samples = " << d_max_sample_count << std::endl; -#endif - - OSStatus err = noErr; - -// create the default AudioUnit for input - -// Open the default input unit -#ifndef GR_USE_OLD_AUDIO_UNIT - AudioComponentDescription InputDesc; -#else - ComponentDescription InputDesc; -#endif - - - InputDesc.componentType = kAudioUnitType_Output; - InputDesc.componentSubType = kAudioUnitSubType_HALOutput; - InputDesc.componentManufacturer = kAudioUnitManufacturer_Apple; - InputDesc.componentFlags = 0; - InputDesc.componentFlagsMask = 0; - -#ifndef GR_USE_OLD_AUDIO_UNIT - AudioComponent comp = AudioComponentFindNext (NULL, &InputDesc); -#else - Component comp = FindNextComponent (NULL, &InputDesc); -#endif - - if (comp == NULL) { -#ifndef GR_USE_OLD_AUDIO_UNIT - std::cerr << "AudioComponentFindNext Error" << std::endl; -#else - std::cerr << "FindNextComponent Error" << std::endl; -#endif - throw std::runtime_error ("audio_osx_source::audio_osx_source"); - } - -#ifndef GR_USE_OLD_AUDIO_UNIT - err = AudioComponentInstanceNew (comp, &d_InputAU); - CheckErrorAndThrow (err, "AudioComponentInstanceNew", - "audio_osx_source::audio_osx_source"); -#else - err = OpenAComponent (comp, &d_InputAU); - CheckErrorAndThrow (err, "OpenAComponent", - "audio_osx_source::audio_osx_source"); -#endif - - - UInt32 enableIO; - -// must enable the AUHAL for input and disable output -// before setting the AUHAL's current device - -// Enable input on the AUHAL - enableIO = 1; - err = AudioUnitSetProperty (d_InputAU, - kAudioOutputUnitProperty_EnableIO, - kAudioUnitScope_Input, - 1, // input element - &enableIO, - sizeof (UInt32)); - CheckErrorAndThrow (err, "AudioUnitSetProperty Input Enable", - "audio_osx_source::audio_osx_source"); - -// Disable output on the AUHAL - enableIO = 0; - err = AudioUnitSetProperty (d_InputAU, - kAudioOutputUnitProperty_EnableIO, - kAudioUnitScope_Output, - 0, // output element - &enableIO, - sizeof (UInt32)); - CheckErrorAndThrow (err, "AudioUnitSetProperty Output Disable", - "audio_osx_source::audio_osx_source"); - -// set the default input device for our input AU - - SetDefaultInputDeviceAsCurrent (); - -#if _OSX_DO_LISTENERS_ -// set up a listener if default hardware input device changes - - err = AudioHardwareAddPropertyListener - (kAudioHardwarePropertyDefaultInputDevice, - (AudioHardwarePropertyListenerProc) HardwareListener, - this); - - CheckErrorAndThrow (err, "AudioHardwareAddPropertyListener", - "audio_osx_source::audio_osx_source"); - -// Add a listener for any changes in the input AU's output stream -// the function "UnitListener" will be called if the stream format -// changes for whatever reason - - err = AudioUnitAddPropertyListener - (d_InputAU, - kAudioUnitProperty_StreamFormat, - (AudioUnitPropertyListenerProc) UnitListener, - this); - CheckErrorAndThrow (err, "Adding Unit Property Listener", - "audio_osx_source::audio_osx_source"); -#endif - -// Now find out if it actually can do input. - - UInt32 hasInput = 0; - UInt32 dataSize = sizeof (hasInput); - err = AudioUnitGetProperty (d_InputAU, - kAudioOutputUnitProperty_HasIO, - kAudioUnitScope_Input, - 1, - &hasInput, - &dataSize); - CheckErrorAndThrow (err, "AudioUnitGetProperty HasIO", - "audio_osx_source::audio_osx_source"); - if (hasInput == 0) { - std::cerr << "Selected Audio Device does not support Input." << std::endl; - throw std::runtime_error ("audio_osx_source::audio_osx_source"); - } - -// Set up a callback function to retrieve input from the Audio Device - - AURenderCallbackStruct AUCallBack; - - AUCallBack.inputProc = (AURenderCallback)(audio_osx_source::AUInputCallback); - AUCallBack.inputProcRefCon = this; - - err = AudioUnitSetProperty (d_InputAU, - kAudioOutputUnitProperty_SetInputCallback, - kAudioUnitScope_Global, - 0, - &AUCallBack, - sizeof (AURenderCallbackStruct)); - CheckErrorAndThrow (err, "AudioUnitSetProperty Input Callback", - "audio_osx_source::audio_osx_source"); - - UInt32 propertySize; - AudioStreamBasicDescription asbd_device, asbd_client, asbd_user; - -// asbd_device: ASBD of the device that is creating the input data stream -// asbd_client: ASBD of the client size (output) of the hardware device -// asbd_user: ASBD of the user's arguments - -// Get the Stream Format (device side) - - propertySize = sizeof (asbd_device); - err = AudioUnitGetProperty (d_InputAU, - kAudioUnitProperty_StreamFormat, - kAudioUnitScope_Input, - 1, - &asbd_device, - &propertySize); - CheckErrorAndThrow (err, "AudioUnitGetProperty Device Input Stream Format", - "audio_osx_source::audio_osx_source"); - -#if _OSX_AU_DEBUG_ - std::cerr << std::endl << "---- Device Stream Format ----" << std::endl; - PrintStreamDesc (&asbd_device); -#endif - -// Get the Stream Format (client side) - propertySize = sizeof (asbd_client); - err = AudioUnitGetProperty (d_InputAU, - kAudioUnitProperty_StreamFormat, - kAudioUnitScope_Output, - 1, - &asbd_client, - &propertySize); - CheckErrorAndThrow (err, "AudioUnitGetProperty Device Ouput Stream Format", - "audio_osx_source::audio_osx_source"); - -#if _OSX_AU_DEBUG_ - std::cerr << std::endl << "---- Client Stream Format ----" << std::endl; - PrintStreamDesc (&asbd_client); -#endif - -// Set the format of all the AUs to the input/output devices channel count - -// get the max number of input (& thus output) channels supported by -// this device - d_n_max_channels = asbd_client.mChannelsPerFrame; - -// create the output io signature; -// no input siganture to set (source is hardware) - set_output_signature (gr_make_io_signature (1, - d_n_max_channels, - sizeof (float))); - -// allocate the output circular buffer(s), one per channel - d_buffers = (circular_buffer<float>**) new - circular_buffer<float>* [d_n_max_channels]; - UInt32 n_alloc = (UInt32) ceil ((double) d_max_sample_count); - for (UInt32 n = 0; n < d_n_max_channels; n++) { - d_buffers[n] = new circular_buffer<float> (n_alloc, false, false); - } - - d_deviceSampleRate = asbd_device.mSampleRate; - d_n_deviceChannels = asbd_device.mChannelsPerFrame; - -// create an ASBD for the user's wants - - asbd_user.mSampleRate = d_outputSampleRate; - asbd_user.mFormatID = kAudioFormatLinearPCM; - asbd_user.mFormatFlags = (kLinearPCMFormatFlagIsFloat | - GR_PCM_ENDIANNESS | - kLinearPCMFormatFlagIsPacked | - kAudioFormatFlagIsNonInterleaved); - asbd_user.mBytesPerPacket = 4; - asbd_user.mFramesPerPacket = 1; - asbd_user.mBytesPerFrame = 4; - asbd_user.mChannelsPerFrame = d_n_max_channels; - asbd_user.mBitsPerChannel = 32; - - if (d_deviceSampleRate == d_outputSampleRate) { -// no need to do conversion if asbd_client matches user wants - d_passThrough = true; - d_leadSizeFrames = d_trailSizeFrames = 0L; - } else { - d_passThrough = false; -// Create the audio converter - - err = AudioConverterNew (&asbd_client, &asbd_user, &d_AudioConverter); - CheckErrorAndThrow (err, "AudioConverterNew", - "audio_osx_source::audio_osx_source"); - -// Set the audio converter sample rate quality to "max" ... -// requires more samples, but should sound nicer - - UInt32 ACQuality = kAudioConverterQuality_Max; - propertySize = sizeof (ACQuality); - err = AudioConverterSetProperty (d_AudioConverter, - kAudioConverterSampleRateConverterQuality, - propertySize, - &ACQuality); - CheckErrorAndThrow (err, "AudioConverterSetProperty " - "SampleRateConverterQuality", - "audio_osx_source::audio_osx_source"); - -// set the audio converter's prime method to "pre", -// which uses both leading and trailing frames -// from the "current input". All of this is handled -// internally by the AudioConverter; we just supply -// the frames for conversion. - -// UInt32 ACPrimeMethod = kConverterPrimeMethod_None; - UInt32 ACPrimeMethod = kConverterPrimeMethod_Pre; - propertySize = sizeof (ACPrimeMethod); - err = AudioConverterSetProperty (d_AudioConverter, - kAudioConverterPrimeMethod, - propertySize, - &ACPrimeMethod); - CheckErrorAndThrow (err, "AudioConverterSetProperty PrimeMethod", - "audio_osx_source::audio_osx_source"); - -// Get the size of the I/O buffer(s) to allow for pre-allocated buffers - -// lead frame info (trail frame info is ignored) - - AudioConverterPrimeInfo ACPrimeInfo = {0, 0}; - propertySize = sizeof (ACPrimeInfo); - err = AudioConverterGetProperty (d_AudioConverter, - kAudioConverterPrimeInfo, - &propertySize, - &ACPrimeInfo); - CheckErrorAndThrow (err, "AudioConverterGetProperty PrimeInfo", - "audio_osx_source::audio_osx_source"); - - switch (ACPrimeMethod) { - case (kConverterPrimeMethod_None): - d_leadSizeFrames = - d_trailSizeFrames = 0L; - break; - case (kConverterPrimeMethod_Normal): - d_leadSizeFrames = 0L; - d_trailSizeFrames = ACPrimeInfo.trailingFrames; - break; - default: - d_leadSizeFrames = ACPrimeInfo.leadingFrames; - d_trailSizeFrames = ACPrimeInfo.trailingFrames; - } - } - d_leadSizeBytes = d_leadSizeFrames * sizeof (Float32); - d_trailSizeBytes = d_trailSizeFrames * sizeof (Float32); - - propertySize = sizeof (d_deviceBufferSizeFrames); - err = AudioUnitGetProperty (d_InputAU, - kAudioDevicePropertyBufferFrameSize, - kAudioUnitScope_Global, - 0, - &d_deviceBufferSizeFrames, - &propertySize); - CheckErrorAndThrow (err, "AudioUnitGetProperty Buffer Frame Size", - "audio_osx_source::audio_osx_source"); - - d_deviceBufferSizeBytes = d_deviceBufferSizeFrames * sizeof (Float32); - d_inputBufferSizeBytes = d_deviceBufferSizeBytes + d_leadSizeBytes; - d_inputBufferSizeFrames = d_deviceBufferSizeFrames + d_leadSizeFrames; - -// outBufSizeBytes = floor (inBufSizeBytes * rate_out / rate_in) -// since this is rarely exact, we need another buffer to hold -// "extra" samples not processed at any given sampling period -// this buffer must be at least 4 floats in size, but generally -// follows the rule that -// extraBufSize = ceil (rate_in / rate_out)*sizeof(float) - - d_extraBufferSizeFrames = ((UInt32) ceil (d_deviceSampleRate - / d_outputSampleRate) - * sizeof (float)); - if (d_extraBufferSizeFrames < 4) - d_extraBufferSizeFrames = 4; - d_extraBufferSizeBytes = d_extraBufferSizeFrames * sizeof (float); - - d_outputBufferSizeFrames = (UInt32) ceil (((Float64) d_inputBufferSizeFrames) - * d_outputSampleRate - / d_deviceSampleRate); - d_outputBufferSizeBytes = d_outputBufferSizeFrames * sizeof (float); - d_inputBufferSizeFrames += d_extraBufferSizeFrames; - -// pre-alloc all buffers - - AllocAudioBufferList (&d_InputBuffer, d_n_deviceChannels, - d_inputBufferSizeBytes); - if (d_passThrough == false) { - AllocAudioBufferList (&d_OutputBuffer, d_n_max_channels, - d_outputBufferSizeBytes); - } else { - d_OutputBuffer = d_InputBuffer; - } - -// create the stuff to regulate I/O - - d_cond_data = new gruel::condition_variable (); - if (d_cond_data == NULL) - CheckErrorAndThrow (errno, "new condition (data)", - "audio_osx_source::audio_osx_source"); - - d_internal = new gruel::mutex (); - if (d_internal == NULL) - CheckErrorAndThrow (errno, "new mutex (internal)", - "audio_osx_source::audio_osx_source"); - -// initialize the AU for input - - err = AudioUnitInitialize (d_InputAU); - CheckErrorAndThrow (err, "AudioUnitInitialize", - "audio_osx_source::audio_osx_source"); - -#if _OSX_AU_DEBUG_ - std::cerr << "audio_osx_source Parameters:" << std::endl; - std::cerr << " Device Sample Rate is " << d_deviceSampleRate << std::endl; - std::cerr << " User Sample Rate is " << d_outputSampleRate << std::endl; - std::cerr << " Max Sample Count is " << d_max_sample_count << std::endl; - std::cerr << " # Device Channels is " << d_n_deviceChannels << std::endl; - std::cerr << " # Max Channels is " << d_n_max_channels << std::endl; - std::cerr << " Device Buffer Size is Frames = " << d_deviceBufferSizeFrames << std::endl; - std::cerr << " Lead Size is Frames = " << d_leadSizeFrames << std::endl; - std::cerr << " Trail Size is Frames = " << d_trailSizeFrames << std::endl; - std::cerr << " Input Buffer Size is Frames = " << d_inputBufferSizeFrames << std::endl; - std::cerr << " Output Buffer Size is Frames = " << d_outputBufferSizeFrames << std::endl; -#endif -} - -void -audio_osx_source::AllocAudioBufferList (AudioBufferList** t_ABL, - UInt32 n_channels, - UInt32 bufferSizeBytes) -{ - FreeAudioBufferList (t_ABL); - UInt32 propertySize = (offsetof (AudioBufferList, mBuffers[0]) + - (sizeof (AudioBuffer) * n_channels)); - *t_ABL = (AudioBufferList*) calloc (1, propertySize); - (*t_ABL)->mNumberBuffers = n_channels; - - int counter = n_channels; - - while (--counter >= 0) { - (*t_ABL)->mBuffers[counter].mNumberChannels = 1; - (*t_ABL)->mBuffers[counter].mDataByteSize = bufferSizeBytes; - (*t_ABL)->mBuffers[counter].mData = calloc (1, bufferSizeBytes); - } -} - -void -audio_osx_source::FreeAudioBufferList (AudioBufferList** t_ABL) -{ -// free pre-allocated audio buffer, if it exists - if (*t_ABL != NULL) { - int counter = (*t_ABL)->mNumberBuffers; - while (--counter >= 0) - free ((*t_ABL)->mBuffers[counter].mData); - free (*t_ABL); - (*t_ABL) = 0; - } -} - -bool audio_osx_source::IsRunning () -{ - UInt32 AURunning = 0, AUSize = sizeof (UInt32); - - OSStatus err = AudioUnitGetProperty (d_InputAU, - kAudioOutputUnitProperty_IsRunning, - kAudioUnitScope_Global, - 0, - &AURunning, - &AUSize); - CheckErrorAndThrow (err, "AudioUnitGetProperty IsRunning", - "audio_osx_source::IsRunning"); - - return (AURunning); -} - -bool audio_osx_source::start () -{ - if (! IsRunning ()) { - OSStatus err = AudioOutputUnitStart (d_InputAU); - CheckErrorAndThrow (err, "AudioOutputUnitStart", - "audio_osx_source::start"); - } - - return (true); -} - -bool audio_osx_source::stop () -{ - if (IsRunning ()) { - OSStatus err = AudioOutputUnitStop (d_InputAU); - CheckErrorAndThrow (err, "AudioOutputUnitStart", - "audio_osx_source::stop"); - for (UInt32 n = 0; n < d_n_user_channels; n++) { - d_buffers[n]->abort (); - } - } - - return (true); -} - -audio_osx_source::~audio_osx_source () -{ - OSStatus err = noErr; - -// stop the AudioUnit - stop(); - -#if _OSX_DO_LISTENERS_ -// remove the listeners - - err = AudioUnitRemovePropertyListener - (d_InputAU, - kAudioUnitProperty_StreamFormat, - (AudioUnitPropertyListenerProc) UnitListener); - CheckError (err, "~audio_osx_source: AudioUnitRemovePropertyListener"); - - err = AudioHardwareRemovePropertyListener - (kAudioHardwarePropertyDefaultInputDevice, - (AudioHardwarePropertyListenerProc) HardwareListener); - CheckError (err, "~audio_osx_source: AudioHardwareRemovePropertyListener"); -#endif - -// free pre-allocated audio buffers - FreeAudioBufferList (&d_InputBuffer); - - if (d_passThrough == false) { - err = AudioConverterDispose (d_AudioConverter); - CheckError (err, "~audio_osx_source: AudioConverterDispose"); - FreeAudioBufferList (&d_OutputBuffer); - } - -// remove the audio unit - err = AudioUnitUninitialize (d_InputAU); - CheckError (err, "~audio_osx_source: AudioUnitUninitialize"); - -#ifndef GR_USE_OLD_AUDIO_UNIT - err = AudioComponentInstanceDispose (d_InputAU); - CheckError (err, "~audio_osx_source: AudioComponentInstanceDispose"); -#else - err = CloseComponent (d_InputAU); - CheckError (err, "~audio_osx_source: CloseComponent"); -#endif - -// empty and delete the queues - for (UInt32 n = 0; n < d_n_max_channels; n++) { - delete d_buffers[n]; - d_buffers[n] = 0; - } - delete [] d_buffers; - d_buffers = 0; - -// close and delete the control stuff - delete d_cond_data; - d_cond_data = 0; - delete d_internal; - d_internal = 0; -} - -audio_osx_source_sptr -audio_osx_make_source (int sampling_freq, - const std::string device_name, - bool do_block, - int channel_config, - int max_sample_count) -{ - return gnuradio::get_initial_sptr(new audio_osx_source (sampling_freq, - device_name, - do_block, - channel_config, - max_sample_count)); -} - -bool -audio_osx_source::check_topology (int ninputs, int noutputs) -{ -// check # inputs to make sure it's valid - if (ninputs != 0) { - std::cerr << "audio_osx_source::check_topology(): number of input " - << "streams provided (" << ninputs - << ") should be 0." << std::endl; - throw std::runtime_error ("audio_osx_source::check_topology()"); - } - -// check # outputs to make sure it's valid - if ((noutputs < 1) | (noutputs > (int) d_n_max_channels)) { - std::cerr << "audio_osx_source::check_topology(): number of output " - << "streams provided (" << noutputs << ") should be in [1," - << d_n_max_channels << "] for the selected audio device." - << std::endl; - throw std::runtime_error ("audio_osx_source::check_topology()"); - } - -// save the actual number of output (user) channels - d_n_user_channels = noutputs; - -#if _OSX_AU_DEBUG_ - std::cerr << "chk_topo: Actual # user output channels = " - << noutputs << std::endl; -#endif - - return (true); -} - -int -audio_osx_source::work -(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - // acquire control to do processing here only - gruel::scoped_lock l (*d_internal); - -#if _OSX_AU_DEBUG_ - std::cerr << "work1: SC = " << d_queueSampleCount - << ", #OI = " << noutput_items - << ", #Chan = " << output_items.size() << std::endl; -#endif - - // set the actual # of output items to the 'desired' amount then - // verify that data is available; if not enough data is available, - // either wait until it is (is "do_block" is true), return (0) is no - // data is available and "do_block" is false, or process the actual - // amount of available data. - - UInt32 actual_noutput_items = noutput_items; - - if (d_queueSampleCount < actual_noutput_items) { - if (d_queueSampleCount == 0) { - // no data; do_block decides what to do - if (d_do_block == true) { - while (d_queueSampleCount == 0) { - // release control so-as to allow data to be retrieved; - // block until there is data to return - d_cond_data->wait (l); - // the condition's 'notify' was called; acquire control to - // keep thread safe - } - } else { - // no data & not blocking; return nothing - return (0); - } - } - // use the actual amount of available data - actual_noutput_items = d_queueSampleCount; - } - - // number of channels - int l_counter = (int) output_items.size(); - - // copy the items from the circular buffer(s) to 'work's output buffers - // verify that the number copied out is as expected. - - while (--l_counter >= 0) { - size_t t_n_output_items = actual_noutput_items; - d_buffers[l_counter]->dequeue ((float*) output_items[l_counter], - &t_n_output_items); - if (t_n_output_items != actual_noutput_items) { - std::cerr << "audio_osx_source::work(): ERROR: number of " - << "available items changing unexpectedly; expecting " - << actual_noutput_items << ", got " - << t_n_output_items << "." << std::endl; - throw std::runtime_error ("audio_osx_source::work()"); - } - } - - // subtract the actual number of items removed from the buffer(s) - // from the local accounting of the number of available samples - - d_queueSampleCount -= actual_noutput_items; - -#if _OSX_AU_DEBUG_ - std::cerr << "work2: SC = " << d_queueSampleCount - << ", act#OI = " << actual_noutput_items << std::endl - << "Returning." << std::endl; -#endif - - return (actual_noutput_items); -} - -OSStatus -audio_osx_source::ConverterCallback -(AudioConverterRef inAudioConverter, - UInt32* ioNumberDataPackets, - AudioBufferList* ioData, - AudioStreamPacketDescription** ioASPD, - void* inUserData) -{ - // take current device buffers and copy them to the tail of the - // input buffers the lead buffer is already there in the first - // d_leadSizeFrames slots - - audio_osx_source* This = static_cast<audio_osx_source*>(inUserData); - AudioBufferList* l_inputABL = This->d_InputBuffer; - UInt32 totalInputBufferSizeBytes = ((*ioNumberDataPackets) * sizeof (float)); - int counter = This->d_n_deviceChannels; - ioData->mNumberBuffers = This->d_n_deviceChannels; - This->d_n_ActualInputFrames = (*ioNumberDataPackets); - -#if _OSX_AU_DEBUG_ - std::cerr << "cc1: io#DP = " << (*ioNumberDataPackets) - << ", TIBSB = " << totalInputBufferSizeBytes - << ", #C = " << counter << std::endl; -#endif - - while (--counter >= 0) { - AudioBuffer* l_ioD_AB = &(ioData->mBuffers[counter]); - l_ioD_AB->mNumberChannels = 1; - l_ioD_AB->mData = (float*)(l_inputABL->mBuffers[counter].mData); - l_ioD_AB->mDataByteSize = totalInputBufferSizeBytes; - } - -#if _OSX_AU_DEBUG_ - std::cerr << "cc2: Returning." << std::endl; -#endif - - return (noErr); -} - -OSStatus -audio_osx_source::AUInputCallback (void* inRefCon, - AudioUnitRenderActionFlags* ioActionFlags, - const AudioTimeStamp* inTimeStamp, - UInt32 inBusNumber, - UInt32 inNumberFrames, - AudioBufferList* ioData) -{ - OSStatus err = noErr; - audio_osx_source* This = static_cast<audio_osx_source*>(inRefCon); - - gruel::scoped_lock l (*This->d_internal); - -#if _OSX_AU_DEBUG_ - std::cerr << "cb0: in#F = " << inNumberFrames - << ", inBN = " << inBusNumber - << ", SC = " << This->d_queueSampleCount << std::endl; -#endif - -// Get the new audio data from the input device - - err = AudioUnitRender (This->d_InputAU, - ioActionFlags, - inTimeStamp, - 1, //inBusNumber, - inNumberFrames, - This->d_InputBuffer); - CheckErrorAndThrow (err, "AudioUnitRender", - "audio_osx_source::AUInputCallback"); - - UInt32 AvailableInputFrames = inNumberFrames; - This->d_n_AvailableInputFrames = inNumberFrames; - -// get the number of actual output frames, -// either via converting the buffer or not - - UInt32 ActualOutputFrames; - - if (This->d_passThrough == true) { - ActualOutputFrames = AvailableInputFrames; - } else { - UInt32 AvailableInputBytes = AvailableInputFrames * sizeof (float); - UInt32 AvailableOutputBytes = AvailableInputBytes; - UInt32 AvailableOutputFrames = AvailableOutputBytes / sizeof (float); - UInt32 propertySize = sizeof (AvailableOutputBytes); - err = AudioConverterGetProperty (This->d_AudioConverter, - kAudioConverterPropertyCalculateOutputBufferSize, - &propertySize, - &AvailableOutputBytes); - CheckErrorAndThrow (err, "AudioConverterGetProperty CalculateOutputBufferSize", "audio_osx_source::audio_osx_source"); - - AvailableOutputFrames = AvailableOutputBytes / sizeof (float); - -#if 0 -// when decimating too much, the output sounds warbly due to -// fluctuating # of output frames -// This should not be a surprise, but there's probably some -// clever programming that could lessed the effect ... -// like finding the "ideal" # of output frames, and keeping -// that number constant no matter the # of input frames - UInt32 l_InputBytes = AvailableOutputBytes; - propertySize = sizeof (AvailableOutputBytes); - err = AudioConverterGetProperty (This->d_AudioConverter, - kAudioConverterPropertyCalculateInputBufferSize, - &propertySize, - &l_InputBytes); - CheckErrorAndThrow (err, "AudioConverterGetProperty CalculateInputBufferSize", "audio_osx_source::audio_osx_source"); - - if (l_InputBytes < AvailableInputBytes) { -// OK to zero pad the input a little - AvailableOutputFrames += 1; - AvailableOutputBytes = AvailableOutputFrames * sizeof (float); - } -#endif - -#if _OSX_AU_DEBUG_ - std::cerr << "cb1: avail: #IF = " << AvailableInputFrames - << ", #OF = " << AvailableOutputFrames << std::endl; -#endif - ActualOutputFrames = AvailableOutputFrames; - -// convert the data to the correct rate -// on input, ActualOutputFrames is the number of available output frames - - err = AudioConverterFillComplexBuffer (This->d_AudioConverter, - (AudioConverterComplexInputDataProc)(This->ConverterCallback), - inRefCon, - &ActualOutputFrames, - This->d_OutputBuffer, - NULL); - CheckErrorAndThrow (err, "AudioConverterFillComplexBuffer", - "audio_osx_source::AUInputCallback"); - -// on output, ActualOutputFrames is the actual number of output frames - -#if _OSX_AU_DEBUG_ - std::cerr << "cb2: actual: #IF = " << This->d_n_ActualInputFrames - << ", #OF = " << AvailableOutputFrames << std::endl; - if (This->d_n_ActualInputFrames != AvailableInputFrames) - std::cerr << "cb2.1: avail#IF = " << AvailableInputFrames - << ", actual#IF = " << This->d_n_ActualInputFrames << std::endl; -#endif - } - -// add the output frames to the buffers' queue, checking for overflow - - int l_counter = This->d_n_user_channels; - int res = 0; - - while (--l_counter >= 0) { - float* inBuffer = (float*) This->d_OutputBuffer->mBuffers[l_counter].mData; - -#if _OSX_AU_DEBUG_ - std::cerr << "cb3: enqueuing audio data." << std::endl; -#endif - - int l_res = This->d_buffers[l_counter]->enqueue (inBuffer, ActualOutputFrames); - if (l_res == -1) - res = -1; - } - - if (res == -1) { -// data coming in too fast -// drop oldest buffer - fputs ("aO", stderr); - fflush (stderr); -// set the local number of samples available to the max - This->d_queueSampleCount = This->d_buffers[0]->buffer_length_items (); - } else { -// keep up the local sample count - This->d_queueSampleCount += ActualOutputFrames; - } - -#if _OSX_AU_DEBUG_ - std::cerr << "cb4: #OI = " << ActualOutputFrames - << ", #Cnt = " << This->d_queueSampleCount - << ", mSC = " << This->d_max_sample_count << std::endl; -#endif - -// signal that data is available, if appropraite - This->d_cond_data->notify_one (); - -#if _OSX_AU_DEBUG_ - std::cerr << "cb5: returning." << std::endl; -#endif - - return (err); -} - -void -audio_osx_source::SetDefaultInputDeviceAsCurrent -() -{ -// set the default input device - AudioDeviceID deviceID; - UInt32 dataSize = sizeof (AudioDeviceID); - AudioHardwareGetProperty (kAudioHardwarePropertyDefaultInputDevice, - &dataSize, - &deviceID); - OSStatus err = AudioUnitSetProperty (d_InputAU, - kAudioOutputUnitProperty_CurrentDevice, - kAudioUnitScope_Global, - 0, - &deviceID, - sizeof (AudioDeviceID)); - CheckErrorAndThrow (err, "AudioUnitSetProperty Current Device", - "audio_osx_source::SetDefaultInputDeviceAsCurrent"); -} - -#if _OSX_DO_LISTENERS_ -OSStatus -audio_osx_source::HardwareListener -(AudioHardwarePropertyID inPropertyID, - void *inClientData) -{ - OSStatus err = noErr; - audio_osx_source* This = static_cast<audio_osx_source*>(inClientData); - - std::cerr << "a_o_s::HardwareListener" << std::endl; - -// set the new default hardware input device for use by our AU - - This->SetDefaultInputDeviceAsCurrent (); - -// reset the converter to tell it that the stream has changed - - err = AudioConverterReset (This->d_AudioConverter); - CheckErrorAndThrow (err, "AudioConverterReset", - "audio_osx_source::UnitListener"); - - return (err); -} - -OSStatus -audio_osx_source::UnitListener -(void *inRefCon, - AudioUnit ci, - AudioUnitPropertyID inID, - AudioUnitScope inScope, - AudioUnitElement inElement) -{ - OSStatus err = noErr; - audio_osx_source* This = static_cast<audio_osx_source*>(inRefCon); - AudioStreamBasicDescription asbd; - - std::cerr << "a_o_s::UnitListener" << std::endl; - -// get the converter's input ASBD (for printing) - - UInt32 propertySize = sizeof (asbd); - err = AudioConverterGetProperty (This->d_AudioConverter, - kAudioConverterCurrentInputStreamDescription, - &propertySize, - &asbd); - CheckErrorAndThrow (err, "AudioConverterGetProperty " - "CurrentInputStreamDescription", - "audio_osx_source::UnitListener"); - - std::cerr << "UnitListener: Input Source changed." << std::endl - << "Old Source Output Info:" << std::endl; - PrintStreamDesc (&asbd); - -// get the new input unit's output ASBD - - propertySize = sizeof (asbd); - err = AudioUnitGetProperty (This->d_InputAU, - kAudioUnitProperty_StreamFormat, - kAudioUnitScope_Output, 1, - &asbd, &propertySize); - CheckErrorAndThrow (err, "AudioUnitGetProperty StreamFormat", - "audio_osx_source::UnitListener"); - - std::cerr << "New Source Output Info:" << std::endl; - PrintStreamDesc (&asbd); - -// set the converter's input ASBD to this - - err = AudioConverterSetProperty (This->d_AudioConverter, - kAudioConverterCurrentInputStreamDescription, - propertySize, - &asbd); - CheckErrorAndThrow (err, "AudioConverterSetProperty " - "CurrentInputStreamDescription", - "audio_osx_source::UnitListener"); - -// reset the converter to tell it that the stream has changed - - err = AudioConverterReset (This->d_AudioConverter); - CheckErrorAndThrow (err, "AudioConverterReset", - "audio_osx_source::UnitListener"); - - return (err); -} -#endif diff --git a/gr-audio-osx/src/audio_osx_source.h b/gr-audio-osx/src/audio_osx_source.h deleted file mode 100644 index e8df47b16..000000000 --- a/gr-audio-osx/src/audio_osx_source.h +++ /dev/null @@ -1,132 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006,2010 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_OSX_SOURCE_H -#define INCLUDED_AUDIO_OSX_SOURCE_H - -#include <gr_sync_block.h> -#include <string> -#include <AudioToolbox/AudioToolbox.h> -#include <AudioUnit/AudioUnit.h> -#include <circular_buffer.h> - -class audio_osx_source; -typedef boost::shared_ptr<audio_osx_source> audio_osx_source_sptr; - -audio_osx_source_sptr -audio_osx_make_source (int sample_rate = 44100, - const std::string device_name = "", - bool do_block = true, - int channel_config = -1, - int max_sample_count = -1); - -/*! - * \brief audio source using OSX - * - * Input signature is one or two streams of floats. - * Samples must be in the range [-1,1]. - */ - -class audio_osx_source : public gr_sync_block { - friend audio_osx_source_sptr - audio_osx_make_source (int sample_rate, - const std::string device_name, - bool do_block, - int channel_config, - int max_sample_count); - - Float64 d_deviceSampleRate, d_outputSampleRate; - int d_channel_config; - UInt32 d_inputBufferSizeFrames, d_inputBufferSizeBytes; - UInt32 d_outputBufferSizeFrames, d_outputBufferSizeBytes; - UInt32 d_deviceBufferSizeFrames, d_deviceBufferSizeBytes; - UInt32 d_leadSizeFrames, d_leadSizeBytes; - UInt32 d_trailSizeFrames, d_trailSizeBytes; - UInt32 d_extraBufferSizeFrames, d_extraBufferSizeBytes; - UInt32 d_queueSampleCount, d_max_sample_count; - UInt32 d_n_AvailableInputFrames, d_n_ActualInputFrames; - UInt32 d_n_user_channels, d_n_max_channels, d_n_deviceChannels; - bool d_do_block, d_passThrough, d_waiting_for_data; - gruel::mutex* d_internal; - gruel::condition_variable* d_cond_data; - circular_buffer<float>** d_buffers; - -// AudioUnits and Such - AudioUnit d_InputAU; - AudioBufferList* d_InputBuffer; - AudioBufferList* d_OutputBuffer; - AudioConverterRef d_AudioConverter; - -protected: - audio_osx_source (int sample_rate = 44100, - const std::string device_name = "", - bool do_block = true, - int channel_config = -1, - int max_sample_count = -1); - -public: - ~audio_osx_source (); - - bool start (); - bool stop (); - bool IsRunning (); - - 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); - -private: - void SetDefaultInputDeviceAsCurrent (); - - void AllocAudioBufferList (AudioBufferList** t_ABL, - UInt32 n_channels, - UInt32 inputBufferSizeBytes); - - void FreeAudioBufferList (AudioBufferList** t_ABL); - - static OSStatus ConverterCallback (AudioConverterRef inAudioConverter, - UInt32* ioNumberDataPackets, - AudioBufferList* ioData, - AudioStreamPacketDescription** outASPD, - void* inUserData); - - static OSStatus AUInputCallback (void *inRefCon, - AudioUnitRenderActionFlags *ioActionFlags, - const AudioTimeStamp *inTimeStamp, - UInt32 inBusNumber, - UInt32 inNumberFrames, - AudioBufferList *ioData); -#if _OSX_DO_LISTENERS_ - static OSStatus UnitListener (void *inRefCon, - AudioUnit ci, - AudioUnitPropertyID inID, - AudioUnitScope inScope, - AudioUnitElement inElement); - - static OSStatus HardwareListener (AudioHardwarePropertyID inPropertyID, - void *inClientData); -#endif -}; - -#endif /* INCLUDED_AUDIO_OSX_SOURCE_H */ diff --git a/gr-audio-osx/src/circular_buffer.h b/gr-audio-osx/src/circular_buffer.h deleted file mode 100644 index 48758bf87..000000000 --- a/gr-audio-osx/src/circular_buffer.h +++ /dev/null @@ -1,315 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006,2009,2010 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 _CIRCULAR_BUFFER_H_ -#define _CIRCULAR_BUFFER_H_ - -#include <gruel/thread.h> -#include <iostream> -#include <stdexcept> - -#ifndef DO_DEBUG -#define DO_DEBUG 0 -#endif - -#if DO_DEBUG -#define DEBUG(X) do{X} while(0); -#else -#define DEBUG(X) do{} while(0); -#endif - -template <class T> -class circular_buffer -{ -private: -// the buffer to use - T* d_buffer; - -// the following are in Items (type T) - size_t d_bufLen_I, d_readNdx_I, d_writeNdx_I; - size_t d_n_avail_write_I, d_n_avail_read_I; - -// stuff to control access to class internals - gruel::mutex* d_internal; - gruel::condition_variable* d_readBlock; - gruel::condition_variable* d_writeBlock; - -// booleans to decide how to control reading, writing, and aborting - bool d_doWriteBlock, d_doFullRead, d_doAbort; - - void delete_mutex_cond () { - if (d_internal) { - delete d_internal; - d_internal = NULL; - } - if (d_readBlock) { - delete d_readBlock; - d_readBlock = NULL; - } - if (d_writeBlock) { - delete d_writeBlock; - d_writeBlock = NULL; - } - }; - -public: - circular_buffer (size_t bufLen_I, - bool doWriteBlock = true, bool doFullRead = false) { - if (bufLen_I == 0) - throw std::runtime_error ("circular_buffer(): " - "Number of items to buffer must be > 0.\n"); - d_bufLen_I = bufLen_I; - d_buffer = (T*) new T[d_bufLen_I]; - d_doWriteBlock = doWriteBlock; - d_doFullRead = doFullRead; - d_internal = NULL; - d_readBlock = d_writeBlock = NULL; - reset (); - DEBUG (std::cerr << "c_b(): buf len (items) = " << d_bufLen_ - << ", doWriteBlock = " << (d_doWriteBlock ? "true" : "false") - << ", doFullRead = " << (d_doFullRead ? "true" : "false") - << std::endl); - }; - - ~circular_buffer () { - delete_mutex_cond (); - delete [] d_buffer; - }; - - inline size_t n_avail_write_items () { - gruel::scoped_lock l (*d_internal); - size_t retVal = d_n_avail_write_I; - return (retVal); - }; - - inline size_t n_avail_read_items () { - gruel::scoped_lock l (*d_internal); - size_t retVal = d_n_avail_read_I; - return (retVal); - }; - - inline size_t buffer_length_items () {return (d_bufLen_I);}; - inline bool do_write_block () {return (d_doWriteBlock);}; - inline bool do_full_read () {return (d_doFullRead);}; - - void reset () { - d_doAbort = false; - bzero (d_buffer, d_bufLen_I * sizeof (T)); - d_readNdx_I = d_writeNdx_I = d_n_avail_read_I = 0; - d_n_avail_write_I = d_bufLen_I; - delete_mutex_cond (); - // create a mutex to handle contention of shared resources; - // any routine needed access to shared resources uses lock() - // before doing anything, then unlock() when finished. - d_internal = new gruel::mutex (); - // link the internal mutex to the read and write conditions; - // when wait() is called, the internal mutex will automatically - // be unlock()'ed. Upon return (from a notify_one() to the condition), - // the internal mutex will be lock()'ed. - d_readBlock = new gruel::condition_variable (); - d_writeBlock = new gruel::condition_variable (); - }; - -/* - * enqueue: add the given buffer of item-length to the queue, - * first-in-first-out (FIFO). - * - * inputs: - * buf: a pointer to the buffer holding the data - * - * bufLen_I: the buffer length in items (of the instantiated type) - * - * returns: - * -1: on overflow (write is not blocking, and data is being - * written faster than it is being read) - * 0: if nothing to do (0 length buffer) - * 1: if success - * 2: in the process of aborting, do doing nothing - * - * will throw runtime errors if inputs are improper: - * buffer pointer is NULL - * buffer length is larger than the instantiated buffer length - */ - - int enqueue (T* buf, size_t bufLen_I) { - DEBUG (std::cerr << "enqueue: buf = " << (void*) buf - << ", bufLen = " << bufLen_I - << ", #av_wr = " << d_n_avail_write_I - << ", #av_rd = " << d_n_avail_read_I << std::endl); - if (bufLen_I > d_bufLen_I) { - std::cerr << "ERROR: cannot add buffer longer (" - << bufLen_I << ") than instantiated length (" - << d_bufLen_I << ")." << std::endl; - throw std::runtime_error ("circular_buffer::enqueue()"); - } - - if (bufLen_I == 0) - return (0); - if (!buf) - throw std::runtime_error ("circular_buffer::enqueue(): " - "input buffer is NULL.\n"); - gruel::scoped_lock l (*d_internal); - if (d_doAbort) { - return (2); - } - // set the return value to 1: success; change if needed - int retval = 1; - if (bufLen_I > d_n_avail_write_I) { - if (d_doWriteBlock) { - while (bufLen_I > d_n_avail_write_I) { - DEBUG (std::cerr << "enqueue: #len > #a, waiting." << std::endl); - // wait; will automatically unlock() the internal mutex via - // the scoped lock - d_writeBlock->wait (l); - // and auto re-lock() it here. - if (d_doAbort) { - DEBUG (std::cerr << "enqueue: #len > #a, aborting." << std::endl); - return (2); - } - DEBUG (std::cerr << "enqueue: #len > #a, done waiting." << std::endl); - } - } else { - d_n_avail_read_I = d_bufLen_I - bufLen_I; - d_n_avail_write_I = bufLen_I; - DEBUG (std::cerr << "circular_buffer::enqueue: overflow" << std::endl); - retval = -1; - } - } - size_t n_now_I = d_bufLen_I - d_writeNdx_I, n_start_I = 0; - if (n_now_I > bufLen_I) - n_now_I = bufLen_I; - else if (n_now_I < bufLen_I) - n_start_I = bufLen_I - n_now_I; - bcopy (buf, &(d_buffer[d_writeNdx_I]), n_now_I * sizeof (T)); - if (n_start_I) { - bcopy (&(buf[n_now_I]), d_buffer, n_start_I * sizeof (T)); - d_writeNdx_I = n_start_I; - } else - d_writeNdx_I += n_now_I; - d_n_avail_read_I += bufLen_I; - d_n_avail_write_I -= bufLen_I; - d_readBlock->notify_one (); - return (retval); - }; - -/* - * dequeue: removes from the queue the number of items requested, or - * available, into the given buffer on a FIFO basis. - * - * inputs: - * buf: a pointer to the buffer into which to copy the data - * - * bufLen_I: pointer to the number of items to remove in items - * (of the instantiated type) - * - * returns: - * 0: if nothing to do (0 length buffer) - * 1: if success - * 2: in the process of aborting, do doing nothing - * - * will throw runtime errors if inputs are improper: - * buffer pointer is NULL - * buffer length pointer is NULL - * buffer length is larger than the instantiated buffer length - */ - - int dequeue (T* buf, size_t* bufLen_I) { - DEBUG (std::cerr << "dequeue: buf = " << ((void*) buf) - << ", *bufLen = " << (*bufLen_I) - << ", #av_wr = " << d_n_avail_write_I - << ", #av_rd = " << d_n_avail_read_I << std::endl); - if (!bufLen_I) - throw std::runtime_error ("circular_buffer::dequeue(): " - "input bufLen pointer is NULL.\n"); - if (!buf) - throw std::runtime_error ("circular_buffer::dequeue(): " - "input buffer pointer is NULL.\n"); - size_t l_bufLen_I = *bufLen_I; - if (l_bufLen_I == 0) - return (0); - if (l_bufLen_I > d_bufLen_I) { - std::cerr << "ERROR: cannot remove buffer longer (" - << l_bufLen_I << ") than instantiated length (" - << d_bufLen_I << ")." << std::endl; - throw std::runtime_error ("circular_buffer::dequeue()"); - } - - gruel::scoped_lock l (*d_internal); - if (d_doAbort) { - return (2); - } - if (d_doFullRead) { - while (d_n_avail_read_I < l_bufLen_I) { - DEBUG (std::cerr << "dequeue: #a < #len, waiting." << std::endl); - // wait; will automatically unlock() the internal mutex via - // the scoped lock - d_readBlock->wait (l); - // and re-lock() it here. - if (d_doAbort) { - DEBUG (std::cerr << "dequeue: #a < #len, aborting." << std::endl); - return (2); - } - DEBUG (std::cerr << "dequeue: #a < #len, done waiting." << std::endl); - } - } else { - while (d_n_avail_read_I == 0) { - DEBUG (std::cerr << "dequeue: #a == 0, waiting." << std::endl); - // wait; will automatically unlock() the internal mutex via - // the scoped lock - d_readBlock->wait (l); - // and re-lock() it here. - if (d_doAbort) { - DEBUG (std::cerr << "dequeue: #a == 0, aborting." << std::endl); - return (2); - } - DEBUG (std::cerr << "dequeue: #a == 0, done waiting." << std::endl); - } - } - if (l_bufLen_I > d_n_avail_read_I) - l_bufLen_I = d_n_avail_read_I; - size_t n_now_I = d_bufLen_I - d_readNdx_I, n_start_I = 0; - if (n_now_I > l_bufLen_I) - n_now_I = l_bufLen_I; - else if (n_now_I < l_bufLen_I) - n_start_I = l_bufLen_I - n_now_I; - bcopy (&(d_buffer[d_readNdx_I]), buf, n_now_I * sizeof (T)); - if (n_start_I) { - bcopy (d_buffer, &(buf[n_now_I]), n_start_I * sizeof (T)); - d_readNdx_I = n_start_I; - } else - d_readNdx_I += n_now_I; - *bufLen_I = l_bufLen_I; - d_n_avail_read_I -= l_bufLen_I; - d_n_avail_write_I += l_bufLen_I; - d_writeBlock->notify_one (); - return (1); - }; - - void abort () { - gruel::scoped_lock l (*d_internal); - d_doAbort = true; - d_writeBlock->notify_one (); - d_readBlock->notify_one (); - }; -}; - -#endif /* _CIRCULAR_BUFFER_H_ */ diff --git a/gr-audio-osx/src/qa_osx.py b/gr-audio-osx/src/qa_osx.py deleted file mode 100755 index 385aa0269..000000000 --- a/gr-audio-osx/src/qa_osx.py +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2006,2007 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. -# - -from gnuradio import gr, gr_unittest -import audio_osx - -class qa_osx (gr_unittest.TestCase): - - def setUp (self): - self.tb = gr.top_block () - - def tearDown (self): - self.tb = None - - def test_000_nop (self): - """Just see if we can import the module... - They may not have OSX drivers, etc. Don't try to run anything""" - pass - -if __name__ == '__main__': - gr_unittest.main () diff --git a/gr-audio-osx/src/run_tests.in b/gr-audio-osx/src/run_tests.in deleted file mode 100644 index d88c275e0..000000000 --- a/gr-audio-osx/src/run_tests.in +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -# 1st parameter is absolute path to component source directory -# 2nd parameter is absolute path to component build directory -# 3rd parameter is path to Python QA directory - -@top_builddir@/run_tests.sh \ - @abs_top_srcdir@/gr-audio-osx \ - @abs_top_builddir@/gr-audio-osx \ - @srcdir@ diff --git a/gr-audio-osx/src/test_audio_loop.py b/gr-audio-osx/src/test_audio_loop.py deleted file mode 100755 index 662631dfb..000000000 --- a/gr-audio-osx/src/test_audio_loop.py +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2006,2007 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. -# - -from gnuradio import gr -from gnuradio import audio -from gnuradio.eng_option import eng_option -from optparse import OptionParser - -class my_graph(gr.top_block): - - def __init__(self): - gr.top_block.__init__(self) - - parser = OptionParser(option_class=eng_option) - parser.add_option("-O", "--audio-output", - type="string", - default="", - help="audio output device name. E.g., hw:0,0 or /dev/dsp") - parser.add_option("-I", "--audio-input", - type="string", - default="", - help="audio input device name. E.g., hw:0,0 or /dev/dsp") - parser.add_option("-r", "--sample-rate", - type="eng_float", - default=48000, - help="set sample rate to RATE (48000)") - (options, args) = parser.parse_args () - if len(args) != 0: - parser.print_help() - raise SystemExit, 1 - - sample_rate = int(options.sample_rate) - src = audio.source (sample_rate, options.audio_output) - dst = audio.sink (sample_rate, options.audio_output) - - max_chan = max (src.output_signature().max_streams(), - dst.output_signature().max_streams()) - - for i in range (max_chan): - self.connect ((src, i), (dst, i)) - -if __name__ == '__main__': - try: - my_graph().run() - except KeyboardInterrupt: - pass |