/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.stanford.edu/ http://chuck.cs.princeton.edu/ This program 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 2 of the License, or (at your option) any later version. This program 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 this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A.-----------------------------------------------------------------------------*/ //-----------------------------------------------------------------------------// name: chuck_audio.cpp// desc: chuck host digital audio I/O, using RtAudio//// author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)// Spencer Salazar (spencer@ccrma.stanford.edu)// RtAudio by: Gary Scavone//// date: Spring 2004 -- initial versions// Fall 2017 -- REFACTOR-2017: clean up to be more modular//-----------------------------------------------------------------------------#include "chuck_audio.h"#include "chuck_errmsg.h"#include "util_string.h"#include "util_thread.h"#include <limits.h>#include "rtmidi.h" #if (defined(__PLATFORM_WIN32__) && !defined(__WINDOWS_PTHREAD__)) #include <windows.h> #include <sys/timeb.h>#else #include <unistd.h> #include <sys/time.h>#endif // sample#if defined(__CHUCK_USE_64_BIT_SAMPLE__)#define CK_RTAUDIO_FORMAT RTAUDIO_FLOAT64#else#define CK_RTAUDIO_FORMAT RTAUDIO_FLOAT32#endif // real-time watch dogt_CKBOOL g_do_watchdog = FALSE;// countermeasure#ifdef __MACOSX_CORE__t_CKUINT g_watchdog_countermeasure_priority = 10;#elif defined(__PLATFORM_WIN32__) && !defined(__WINDOWS_PTHREAD__)t_CKUINT g_watchdog_countermeasure_priority = THREAD_PRIORITY_LOWEST;#elset_CKUINT g_watchdog_countermeasure_priority = 0;#endif// watchdog timeoutt_CKFLOAT g_watchdog_timeout = 0.5; // static initializationt_CKBOOL ChuckAudio::m_init = FALSE;t_CKBOOL ChuckAudio::m_start = FALSE;t_CKBOOL ChuckAudio::m_go = FALSE;t_CKBOOL ChuckAudio::m_silent = FALSE;t_CKBOOL ChuckAudio::m_expand_in_mono2stereo= FALSE;t_CKUINT ChuckAudio::m_num_channels_out = NUM_CHANNELS_DEFAULT;t_CKUINT ChuckAudio::m_num_channels_in = NUM_CHANNELS_DEFAULT;t_CKUINT ChuckAudio::m_num_channels_max = NUM_CHANNELS_DEFAULT;t_CKUINT ChuckAudio::m_sample_rate = SAMPLE_RATE_DEFAULT;t_CKUINT ChuckAudio::m_buffer_size = BUFFER_SIZE_DEFAULT;t_CKUINT ChuckAudio::m_num_buffers = NUM_BUFFERS_DEFAULT;SAMPLE * ChuckAudio::m_buffer_out = NULL;SAMPLE * ChuckAudio::m_buffer_in = NULL;SAMPLE * ChuckAudio::m_extern_in = NULL;SAMPLE * ChuckAudio::m_extern_out = NULL;t_CKINT ChuckAudio::m_dac_n = 0;t_CKINT ChuckAudio::m_adc_n = 0;std::string ChuckAudio::m_dac_name = "";std::string ChuckAudio::m_adc_name = "";std::string ChuckAudio::m_driver_name = "";RtAudio * ChuckAudio::m_rtaudio = NULL;f_audio_cb ChuckAudio::m_audio_cb = NULL;void * ChuckAudio::m_cb_user_data = NULL; //-----------------------------------------------------------------------------// global symbols expected from RtAudio | 1.5.0.1 (ge) added//-----------------------------------------------------------------------------extern "C" const unsigned int rtaudio_num_compiled_apis;extern "C" const unsigned int rtaudio_compiled_apis[];extern "C" const char* rtaudio_api_names[][2]; //-----------------------------------------------------------------------------// name: driverNameToApi()// desc: look up from driver name to API/driver//-----------------------------------------------------------------------------static RtAudio::Api driverNameToApi( const char * driver ){ RtAudio::Api api = RtAudio::UNSPECIFIED; if( driver ) { // get lowercase version std::string driverLower = ::tolower(::trim(driver)); // from what is available, match by driver name #if defined(__WINDOWS_ASIO__) if( driverLower == "asio" ) api = RtAudio::WINDOWS_ASIO; #endif #if defined(__WINDOWS_DS__) if( driverLower == "ds" || driverLower == "directsound" ) api = RtAudio::WINDOWS_DS; #endif #if defined(__WINDOWS_WASAPI__) if( driverLower == "wasapi" ) api = RtAudio::WINDOWS_WASAPI; #endif #if defined(__LINUX_ALSA__) if( driverLower == "alsa" ) api = RtAudio::LINUX_ALSA; #endif #if defined(__LINUX_PULSE__) if( driverLower == "pulse" ) api = RtAudio::LINUX_PULSE; #endif #if defined(__UNIX_JACK__) if( driverLower == "jack" ) api = RtAudio::UNIX_JACK; #endif #if defined(__MACOSX_CORE__) if( driverLower == "coreaudio" || driverLower == "core" ) api = RtAudio::MACOSX_CORE; #endif // check for Dummy if( driverLower == "(dummy)" ) api = RtAudio::RTAUDIO_DUMMY; // XXX: add swap between ALSA, PULSE, OSS? and JACK if( api == RtAudio::UNSPECIFIED ) { EM_error2( 0, "unsupported audio driver: %s", driver ); } } // 1.5.0.0 (nshaheed) If the audio driver is UNSPECIFIED then // return a default driver. This will depend on OS and, in the // case of linux, which drivers chuck is being compiled with. if( api == RtAudio::UNSPECIFIED ) { #if defined(__PLATFORM_WIN32__) // traditional chuck default behavior: // DirectSound is most general albeit high-latency api = RtAudio::WINDOWS_DS; #elif defined(__PLATFORM_LINUX__) && defined(__LINUX_PULSE__) api = RtAudio::LINUX_PULSE; #elif defined(__PLATFORM_LINUX__) && defined(__LINUX_ALSA__) api = RtAudio::LINUX_ALSA; #elif defined(__PLATFORM_LINUX__) && defined(__UNIX_JACK__) api = RtAudio::UNIX_JACK; #elif defined(__MACOSX_CORE__) api = RtAudio::MACOSX_CORE; #endif } return api;} //-----------------------------------------------------------------------------// name: apiToDriverName()// desc: get driver name from API//-----------------------------------------------------------------------------static const char * apiToDriverName( RtAudio::Api api ){ static const char * const drivers[] = { "(Unspecified)", "ALSA", "Pulse", "OSS", "Jack", "CoreAudio", "WASAPI", "ASIO", "DirectSound", // DirectSound "(DUMMY)" }; // cast and check t_CKINT index = (t_CKINT)api; if( index < 0 || index >= sizeof(drivers) / sizeof(const char *) ) return NULL; // return return drivers[index];} //-----------------------------------------------------------------------------// name: print()// desc: print info for an audio device//-----------------------------------------------------------------------------void print( const RtAudio::DeviceInfo & info ){ EM_error2b( 0, "device name = \"%s\"", info.name.c_str() ); if (!info.probed) EM_error2b( 0, "probe [failed] ..." ); else { EM_error2b( 0, "probe [success] ..." ); EM_error2b( 0, "# output channels = %d", info.outputChannels ); EM_error2b( 0, "# input channels = %d", info.inputChannels ); EM_error2b( 0, "# duplex Channels = %d", info.duplexChannels ); if( info.isDefaultOutput ) EM_error2b( 0, "default output = YES" ); else EM_error2b( 0, "default output = NO" ); if( info.isDefaultInput ) EM_error2b( 0, "default input = YES" ); else EM_error2b( 0, "default input = NO" ); if( info.nativeFormats == 0 ) EM_error2b( 0, "no natively supported data formats(?)!" ); else { EM_error2b( 0, "natively supported data formats:" ); if( info.nativeFormats & RTAUDIO_SINT8 ) EM_error2b( 0, " 8-bit int" ); if( info.nativeFormats & RTAUDIO_SINT16 ) EM_error2b( 0, " 16-bit int" ); if( info.nativeFormats & RTAUDIO_SINT24 ) EM_error2b( 0, " 24-bit int" ); if( info.nativeFormats & RTAUDIO_SINT32 ) EM_error2b( 0, " 32-bit int" ); if( info.nativeFormats & RTAUDIO_FLOAT32 ) EM_error2b( 0, " 32-bit float" ); if( info.nativeFormats & RTAUDIO_FLOAT64 ) EM_error2b( 0, " 64-bit float" ); } if ( info.sampleRates.size() < 1 ) EM_error2b( 0,"no supported sample rates found!" ); else { EM_error2b( 0, "supported sample rates:" ); for( unsigned int j = 0; j < info.sampleRates.size(); j++ ) EM_error2b( 0, " %d Hz", info.sampleRates[j] ); } }} //-----------------------------------------------------------------------------// name: rtAudioErrorHandler()// desc: the RtAudio error handler//-----------------------------------------------------------------------------static void rtAudioErrorHandler( RtAudioErrorType t, const std::string & errorText){ // problem finding audio devices, most likely EM_error2b( 0, "%s", errorText.c_str() );} //-----------------------------------------------------------------------------// name: probe()// desc: probe audio devices by driver//-----------------------------------------------------------------------------void ChuckAudio::probe( const char * driver ){ // get the audio driver enum by name; handles driver == NULL case RtAudio::Api api = driverNameToApi( driver ); // go back from driver enum to driver name const char * dnm = apiToDriverName( api ); // rtaudio pointer RtAudio * audio = NULL; // device info struct RtAudio::DeviceInfo info; // allocate RtAudio audio = new RtAudio( api, rtAudioErrorHandler ); if( !audio ) { // error reported by our errorHandler return; } // get count int devices = audio->getDeviceCount(); EM_error2b( 0, "[%s] driver found %d audio device(s)...", dnm, devices ); EM_error2( 0, "" ); // reset -- what does this do EM_reset_msg(); // loop over devices for( int i = 0; i < devices; i++ ) { info = audio->getDeviceInfo(i); if (!info.probed) { // errorHandle reports issues above EM_error2(0, ""); EM_reset_msg(); continue; } // print EM_error2b( 0, "------( audio device: %d )---------------", i+1 ); print( info ); // skip if( i < devices ) EM_error2( 0, "" ); // reset EM_reset_msg(); } // done SAFE_DELETE( audio ); return;} //-----------------------------------------------------------------------------// name: device_named()// desc: get device number by name; needs_dac/adc prompts further checks on// requested device having > 0 channels//-----------------------------------------------------------------------------t_CKINT ChuckAudio::device_named( const char * driver, const std::string & name, t_CKBOOL needs_dac, t_CKBOOL needs_adc ){ // rtaudio pointer RtAudio * audio = NULL; // device info struct RtAudio::DeviceInfo info; RtAudio::Api api = driverNameToApi(driver); // handles driver=NULL case // const char * dnm = apiToDriverName(api); // allocate RtAudio audio = new RtAudio(api, rtAudioErrorHandler); if(!audio) return -1; // reporting in errorHandler // get count int devices = audio->getDeviceCount(); int device_no = -1; // loop for( int i = 0; i < devices; i++ ) { // get info info = audio->getDeviceInfo(i); if(!info.probed) { // reportError handles problem break; } // compare name if( info.name.compare(name) == 0 ) { // found! device_no = i+1; break; } } // not found, yet if( device_no == -1 ) { // no exact match found; try partial match for( int i = 0; i < devices; i++ ) { info = audio->getDeviceInfo(i); if(!info.probed) { // errorHandler reports issues break; } if( info.name.find(name) != std::string::npos ) { // skip over ones with 0 channels, if needed if( (needs_dac && info.outputChannels == 0) || (needs_adc && info.inputChannels == 0) ) continue; // found device_no = i+1; break; } } } // clean up SAFE_DELETE( audio ); // done return device_no;} //-----------------------------------------------------------------------------// name: defaultDriverApi()// desc: get default audio driver number, i.e., RtAudio::Api enum//-----------------------------------------------------------------------------RtAudio::Api ChuckAudio::defaultDriverApi(){ return driverNameToApi( NULL );} //-----------------------------------------------------------------------------// name: defaultDriverName()// desc: get default audio driver name//-----------------------------------------------------------------------------const char * ChuckAudio::defaultDriverName(){ return driverApiToName( defaultDriverApi() );} //-----------------------------------------------------------------------------// name: driverNameToApi()// desc: get API/driver enum//-----------------------------------------------------------------------------RtAudio::Api ChuckAudio::driverNameToApi( const char * driver ){ // if empty string, make the pointer null, which will retrieve default if( driver != NULL && driver[0] == '\0' ) driver = NULL; // get the driver enum return ::driverNameToApi( driver );} //-----------------------------------------------------------------------------// name: driverApiToName()// desc: get API/driver name//-----------------------------------------------------------------------------const char * ChuckAudio::driverApiToName( t_CKUINT num ){ // pass it on return apiToDriverName( (RtAudio::Api)num );} //-----------------------------------------------------------------------------// name: numDrivers()// desc: get number of compiled audio driver APIs//-----------------------------------------------------------------------------t_CKUINT ChuckAudio::numDrivers(){ return (t_CKUINT)rtaudio_num_compiled_apis;} //-----------------------------------------------------------------------------// name: getDriver()// desc: get info on a particular driver//-----------------------------------------------------------------------------ChuckAudioDriverInfo ChuckAudio::getDriverInfo( t_CKUINT n ){ // check if( n >= numDrivers() ) return ChuckAudioDriverInfo(); ChuckAudioDriverInfo info; info.driver = rtaudio_compiled_apis[n]; info.name = rtaudio_api_names[info.driver][0]; info.userFriendlyName = rtaudio_api_names[info.driver][1]; return info;} Lines 1–500 of 1285. Load more
/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.stanford.edu/ http://chuck.cs.princeton.edu/ This program 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 2 of the License, or (at your option) any later version. This program 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 this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // name: chuck_audio.cpp // desc: chuck host digital audio I/O, using RtAudio // // author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu) // Spencer Salazar (spencer@ccrma.stanford.edu) // RtAudio by: Gary Scavone // // date: Spring 2004 -- initial versions // Fall 2017 -- REFACTOR-2017: clean up to be more modular //----------------------------------------------------------------------------- #include "chuck_audio.h" #include "chuck_errmsg.h" #include "util_string.h" #include "util_thread.h" #include <limits.h> #include "rtmidi.h" #if (defined(__PLATFORM_WIN32__) && !defined(__WINDOWS_PTHREAD__)) #include <windows.h> #include <sys/timeb.h> #else #include <unistd.h> #include <sys/time.h> #endif // sample #if defined(__CHUCK_USE_64_BIT_SAMPLE__) #define CK_RTAUDIO_FORMAT RTAUDIO_FLOAT64 #else #define CK_RTAUDIO_FORMAT RTAUDIO_FLOAT32 #endif // real-time watch dog t_CKBOOL g_do_watchdog = FALSE; // countermeasure #ifdef __MACOSX_CORE__ t_CKUINT g_watchdog_countermeasure_priority = 10; #elif defined(__PLATFORM_WIN32__) && !defined(__WINDOWS_PTHREAD__) t_CKUINT g_watchdog_countermeasure_priority = THREAD_PRIORITY_LOWEST; #else t_CKUINT g_watchdog_countermeasure_priority = 0; #endif // watchdog timeout t_CKFLOAT g_watchdog_timeout = 0.5; // static initialization t_CKBOOL ChuckAudio::m_init = FALSE; t_CKBOOL ChuckAudio::m_start = FALSE; t_CKBOOL ChuckAudio::m_go = FALSE; t_CKBOOL ChuckAudio::m_silent = FALSE; t_CKBOOL ChuckAudio::m_expand_in_mono2stereo= FALSE; t_CKUINT ChuckAudio::m_num_channels_out = NUM_CHANNELS_DEFAULT; t_CKUINT ChuckAudio::m_num_channels_in = NUM_CHANNELS_DEFAULT; t_CKUINT ChuckAudio::m_num_channels_max = NUM_CHANNELS_DEFAULT; t_CKUINT ChuckAudio::m_sample_rate = SAMPLE_RATE_DEFAULT; t_CKUINT ChuckAudio::m_buffer_size = BUFFER_SIZE_DEFAULT; t_CKUINT ChuckAudio::m_num_buffers = NUM_BUFFERS_DEFAULT; SAMPLE * ChuckAudio::m_buffer_out = NULL; SAMPLE * ChuckAudio::m_buffer_in = NULL; SAMPLE * ChuckAudio::m_extern_in = NULL; SAMPLE * ChuckAudio::m_extern_out = NULL; t_CKINT ChuckAudio::m_dac_n = 0; t_CKINT ChuckAudio::m_adc_n = 0; std::string ChuckAudio::m_dac_name = ""; std::string ChuckAudio::m_adc_name = ""; std::string ChuckAudio::m_driver_name = ""; RtAudio * ChuckAudio::m_rtaudio = NULL; f_audio_cb ChuckAudio::m_audio_cb = NULL; void * ChuckAudio::m_cb_user_data = NULL; //----------------------------------------------------------------------------- // global symbols expected from RtAudio | 1.5.0.1 (ge) added //----------------------------------------------------------------------------- extern "C" const unsigned int rtaudio_num_compiled_apis; extern "C" const unsigned int rtaudio_compiled_apis[]; extern "C" const char* rtaudio_api_names[][2]; //----------------------------------------------------------------------------- // name: driverNameToApi() // desc: look up from driver name to API/driver //----------------------------------------------------------------------------- static RtAudio::Api driverNameToApi( const char * driver ) { RtAudio::Api api = RtAudio::UNSPECIFIED; if( driver ) { // get lowercase version std::string driverLower = ::tolower(::trim(driver)); // from what is available, match by driver name #if defined(__WINDOWS_ASIO__) if( driverLower == "asio" ) api = RtAudio::WINDOWS_ASIO; #endif #if defined(__WINDOWS_DS__) if( driverLower == "ds" || driverLower == "directsound" ) api = RtAudio::WINDOWS_DS; #endif #if defined(__WINDOWS_WASAPI__) if( driverLower == "wasapi" ) api = RtAudio::WINDOWS_WASAPI; #endif #if defined(__LINUX_ALSA__) if( driverLower == "alsa" ) api = RtAudio::LINUX_ALSA; #endif #if defined(__LINUX_PULSE__) if( driverLower == "pulse" ) api = RtAudio::LINUX_PULSE; #endif #if defined(__UNIX_JACK__) if( driverLower == "jack" ) api = RtAudio::UNIX_JACK; #endif #if defined(__MACOSX_CORE__) if( driverLower == "coreaudio" || driverLower == "core" ) api = RtAudio::MACOSX_CORE; #endif // check for Dummy if( driverLower == "(dummy)" ) api = RtAudio::RTAUDIO_DUMMY; // XXX: add swap between ALSA, PULSE, OSS? and JACK if( api == RtAudio::UNSPECIFIED ) { EM_error2( 0, "unsupported audio driver: %s", driver ); } } // 1.5.0.0 (nshaheed) If the audio driver is UNSPECIFIED then // return a default driver. This will depend on OS and, in the // case of linux, which drivers chuck is being compiled with. if( api == RtAudio::UNSPECIFIED ) { #if defined(__PLATFORM_WIN32__) // traditional chuck default behavior: // DirectSound is most general albeit high-latency api = RtAudio::WINDOWS_DS; #elif defined(__PLATFORM_LINUX__) && defined(__LINUX_PULSE__) api = RtAudio::LINUX_PULSE; #elif defined(__PLATFORM_LINUX__) && defined(__LINUX_ALSA__) api = RtAudio::LINUX_ALSA; #elif defined(__PLATFORM_LINUX__) && defined(__UNIX_JACK__) api = RtAudio::UNIX_JACK; #elif defined(__MACOSX_CORE__) api = RtAudio::MACOSX_CORE; #endif } return api; } //----------------------------------------------------------------------------- // name: apiToDriverName() // desc: get driver name from API //----------------------------------------------------------------------------- static const char * apiToDriverName( RtAudio::Api api ) { static const char * const drivers[] = { "(Unspecified)", "ALSA", "Pulse", "OSS", "Jack", "CoreAudio", "WASAPI", "ASIO", "DirectSound", // DirectSound "(DUMMY)" }; // cast and check t_CKINT index = (t_CKINT)api; if( index < 0 || index >= sizeof(drivers) / sizeof(const char *) ) return NULL; // return return drivers[index]; } //----------------------------------------------------------------------------- // name: print() // desc: print info for an audio device //----------------------------------------------------------------------------- void print( const RtAudio::DeviceInfo & info ) { EM_error2b( 0, "device name = \"%s\"", info.name.c_str() ); if (!info.probed) EM_error2b( 0, "probe [failed] ..." ); else { EM_error2b( 0, "probe [success] ..." ); EM_error2b( 0, "# output channels = %d", info.outputChannels ); EM_error2b( 0, "# input channels = %d", info.inputChannels ); EM_error2b( 0, "# duplex Channels = %d", info.duplexChannels ); if( info.isDefaultOutput ) EM_error2b( 0, "default output = YES" ); else EM_error2b( 0, "default output = NO" ); if( info.isDefaultInput ) EM_error2b( 0, "default input = YES" ); else EM_error2b( 0, "default input = NO" ); if( info.nativeFormats == 0 ) EM_error2b( 0, "no natively supported data formats(?)!" ); else { EM_error2b( 0, "natively supported data formats:" ); if( info.nativeFormats & RTAUDIO_SINT8 ) EM_error2b( 0, " 8-bit int" ); if( info.nativeFormats & RTAUDIO_SINT16 ) EM_error2b( 0, " 16-bit int" ); if( info.nativeFormats & RTAUDIO_SINT24 ) EM_error2b( 0, " 24-bit int" ); if( info.nativeFormats & RTAUDIO_SINT32 ) EM_error2b( 0, " 32-bit int" ); if( info.nativeFormats & RTAUDIO_FLOAT32 ) EM_error2b( 0, " 32-bit float" ); if( info.nativeFormats & RTAUDIO_FLOAT64 ) EM_error2b( 0, " 64-bit float" ); } if ( info.sampleRates.size() < 1 ) EM_error2b( 0,"no supported sample rates found!" ); else { EM_error2b( 0, "supported sample rates:" ); for( unsigned int j = 0; j < info.sampleRates.size(); j++ ) EM_error2b( 0, " %d Hz", info.sampleRates[j] ); } } } //----------------------------------------------------------------------------- // name: rtAudioErrorHandler() // desc: the RtAudio error handler //----------------------------------------------------------------------------- static void rtAudioErrorHandler( RtAudioErrorType t, const std::string & errorText) { // problem finding audio devices, most likely EM_error2b( 0, "%s", errorText.c_str() ); } //----------------------------------------------------------------------------- // name: probe() // desc: probe audio devices by driver //----------------------------------------------------------------------------- void ChuckAudio::probe( const char * driver ) { // get the audio driver enum by name; handles driver == NULL case RtAudio::Api api = driverNameToApi( driver ); // go back from driver enum to driver name const char * dnm = apiToDriverName( api ); // rtaudio pointer RtAudio * audio = NULL; // device info struct RtAudio::DeviceInfo info; // allocate RtAudio audio = new RtAudio( api, rtAudioErrorHandler ); if( !audio ) { // error reported by our errorHandler return; } // get count int devices = audio->getDeviceCount(); EM_error2b( 0, "[%s] driver found %d audio device(s)...", dnm, devices ); EM_error2( 0, "" ); // reset -- what does this do EM_reset_msg(); // loop over devices for( int i = 0; i < devices; i++ ) { info = audio->getDeviceInfo(i); if (!info.probed) { // errorHandle reports issues above EM_error2(0, ""); EM_reset_msg(); continue; } // print EM_error2b( 0, "------( audio device: %d )---------------", i+1 ); print( info ); // skip if( i < devices ) EM_error2( 0, "" ); // reset EM_reset_msg(); } // done SAFE_DELETE( audio ); return; } //----------------------------------------------------------------------------- // name: device_named() // desc: get device number by name; needs_dac/adc prompts further checks on // requested device having > 0 channels //----------------------------------------------------------------------------- t_CKINT ChuckAudio::device_named( const char * driver, const std::string & name, t_CKBOOL needs_dac, t_CKBOOL needs_adc ) { // rtaudio pointer RtAudio * audio = NULL; // device info struct RtAudio::DeviceInfo info; RtAudio::Api api = driverNameToApi(driver); // handles driver=NULL case // const char * dnm = apiToDriverName(api); // allocate RtAudio audio = new RtAudio(api, rtAudioErrorHandler); if(!audio) return -1; // reporting in errorHandler // get count int devices = audio->getDeviceCount(); int device_no = -1; // loop for( int i = 0; i < devices; i++ ) { // get info info = audio->getDeviceInfo(i); if(!info.probed) { // reportError handles problem break; } // compare name if( info.name.compare(name) == 0 ) { // found! device_no = i+1; break; } } // not found, yet if( device_no == -1 ) { // no exact match found; try partial match for( int i = 0; i < devices; i++ ) { info = audio->getDeviceInfo(i); if(!info.probed) { // errorHandler reports issues break; } if( info.name.find(name) != std::string::npos ) { // skip over ones with 0 channels, if needed if( (needs_dac && info.outputChannels == 0) || (needs_adc && info.inputChannels == 0) ) continue; // found device_no = i+1; break; } } } // clean up SAFE_DELETE( audio ); // done return device_no; } //----------------------------------------------------------------------------- // name: defaultDriverApi() // desc: get default audio driver number, i.e., RtAudio::Api enum //----------------------------------------------------------------------------- RtAudio::Api ChuckAudio::defaultDriverApi() { return driverNameToApi( NULL ); } //----------------------------------------------------------------------------- // name: defaultDriverName() // desc: get default audio driver name //----------------------------------------------------------------------------- const char * ChuckAudio::defaultDriverName() { return driverApiToName( defaultDriverApi() ); } //----------------------------------------------------------------------------- // name: driverNameToApi() // desc: get API/driver enum //----------------------------------------------------------------------------- RtAudio::Api ChuckAudio::driverNameToApi( const char * driver ) { // if empty string, make the pointer null, which will retrieve default if( driver != NULL && driver[0] == '\0' ) driver = NULL; // get the driver enum return ::driverNameToApi( driver ); } //----------------------------------------------------------------------------- // name: driverApiToName() // desc: get API/driver name //----------------------------------------------------------------------------- const char * ChuckAudio::driverApiToName( t_CKUINT num ) { // pass it on return apiToDriverName( (RtAudio::Api)num ); } //----------------------------------------------------------------------------- // name: numDrivers() // desc: get number of compiled audio driver APIs //----------------------------------------------------------------------------- t_CKUINT ChuckAudio::numDrivers() { return (t_CKUINT)rtaudio_num_compiled_apis; } //----------------------------------------------------------------------------- // name: getDriver() // desc: get info on a particular driver //----------------------------------------------------------------------------- ChuckAudioDriverInfo ChuckAudio::getDriverInfo( t_CKUINT n ) { // check if( n >= numDrivers() ) return ChuckAudioDriverInfo(); ChuckAudioDriverInfo info; info.driver = rtaudio_compiled_apis[n]; info.name = rtaudio_api_names[info.driver][0]; info.userFriendlyName = rtaudio_api_names[info.driver][1]; return info; }