if (AUDIO_LINUX_PULSE)
find_library(PULSE_LIB pulse)
find_library(PULSESIMPLE_LIB pulse-simple)
- list(APPEND LINKLIBS ${PULSE_LIB} ${PULSESIMPLE_LIB})
+ find_package(Threads REQUIRED CMAKE_THREAD_PREFER_PTHREAD)
+ list(APPEND LINKLIBS ${PULSE_LIB} ${PULSESIMPLE_LIB} ${CMAKE_THREAD_LIBS_INIT})
add_definitions(-D__LINUX_PULSE__)
message(STATUS "Using Linux PulseAudio")
endif (AUDIO_LINUX_PULSE)
-/************************************************************************/\r
+/************************************************************************/\r
/*! \class RtAudio\r
\brief Realtime audio i/o C++ classes.\r
\r
// In order to satisfy WASAPI's buffer requirements, we need a means of converting sample rate\r
// between HW and the user. The convertBufferWasapi function is used to perform this conversion\r
// between HwIn->UserIn and UserOut->HwOut during the stream callback loop.\r
-// This sample rate converter favors speed over quality, and works best with conversions between\r
-// one rate and its multiple.\r
+// This sample rate converter works best with conversions between one rate and its multiple.\r
void convertBufferWasapi( char* outBuffer,\r
const char* inBuffer,\r
const unsigned int& channelCount,\r
{\r
// calculate the new outSampleCount and relative sampleStep\r
float sampleRatio = ( float ) outSampleRate / inSampleRate;\r
+ float sampleRatioInv = ( float ) 1 / sampleRatio;\r
float sampleStep = 1.0f / sampleRatio;\r
float inSampleFraction = 0.0f;\r
\r
outSampleCount = ( unsigned int ) roundf( inSampleCount * sampleRatio );\r
\r
- // frame-by-frame, copy each relative input sample into it's corresponding output sample\r
- for ( unsigned int outSample = 0; outSample < outSampleCount; outSample++ )\r
+ // if inSampleRate is a multiple of outSampleRate (or vice versa) there's no need to interpolate\r
+ if ( floor( sampleRatio ) == sampleRatio || floor( sampleRatioInv ) == sampleRatioInv )\r
{\r
- unsigned int inSample = ( unsigned int ) inSampleFraction;\r
-\r
- switch ( format )\r
+ // frame-by-frame, copy each relative input sample into it's corresponding output sample\r
+ for ( unsigned int outSample = 0; outSample < outSampleCount; outSample++ )\r
{\r
- case RTAUDIO_SINT8:\r
- memcpy( &( ( char* ) outBuffer )[ outSample * channelCount ], &( ( char* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( char ) );\r
- break;\r
- case RTAUDIO_SINT16:\r
- memcpy( &( ( short* ) outBuffer )[ outSample * channelCount ], &( ( short* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( short ) );\r
- break;\r
- case RTAUDIO_SINT24:\r
- memcpy( &( ( S24* ) outBuffer )[ outSample * channelCount ], &( ( S24* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( S24 ) );\r
- break;\r
- case RTAUDIO_SINT32:\r
- memcpy( &( ( int* ) outBuffer )[ outSample * channelCount ], &( ( int* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( int ) );\r
- break;\r
- case RTAUDIO_FLOAT32:\r
- memcpy( &( ( float* ) outBuffer )[ outSample * channelCount ], &( ( float* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( float ) );\r
- break;\r
- case RTAUDIO_FLOAT64:\r
- memcpy( &( ( double* ) outBuffer )[ outSample * channelCount ], &( ( double* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( double ) );\r
- break;\r
+ unsigned int inSample = ( unsigned int ) inSampleFraction;\r
+\r
+ switch ( format )\r
+ {\r
+ case RTAUDIO_SINT8:\r
+ memcpy( &( ( char* ) outBuffer )[ outSample * channelCount ], &( ( char* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( char ) );\r
+ break;\r
+ case RTAUDIO_SINT16:\r
+ memcpy( &( ( short* ) outBuffer )[ outSample * channelCount ], &( ( short* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( short ) );\r
+ break;\r
+ case RTAUDIO_SINT24:\r
+ memcpy( &( ( S24* ) outBuffer )[ outSample * channelCount ], &( ( S24* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( S24 ) );\r
+ break;\r
+ case RTAUDIO_SINT32:\r
+ memcpy( &( ( int* ) outBuffer )[ outSample * channelCount ], &( ( int* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( int ) );\r
+ break;\r
+ case RTAUDIO_FLOAT32:\r
+ memcpy( &( ( float* ) outBuffer )[ outSample * channelCount ], &( ( float* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( float ) );\r
+ break;\r
+ case RTAUDIO_FLOAT64:\r
+ memcpy( &( ( double* ) outBuffer )[ outSample * channelCount ], &( ( double* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( double ) );\r
+ break;\r
+ }\r
+\r
+ // jump to next in sample\r
+ inSampleFraction += sampleStep;\r
}\r
+ }\r
+ else // else interpolate\r
+ {\r
+ // frame-by-frame, copy each relative input sample into it's corresponding output sample\r
+ for ( unsigned int outSample = 0; outSample < outSampleCount; outSample++ )\r
+ {\r
+ unsigned int inSample = ( unsigned int ) inSampleFraction;\r
+ float inSampleDec = inSampleFraction - inSample;\r
+ unsigned int frameInSample = inSample * channelCount;\r
+ unsigned int frameOutSample = outSample * channelCount;\r
+\r
+ switch ( format )\r
+ {\r
+ case RTAUDIO_SINT8:\r
+ {\r
+ for ( unsigned int channel = 0; channel < channelCount; channel++ )\r
+ {\r
+ char fromSample = ( ( char* ) inBuffer )[ frameInSample + channel ];\r
+ char toSample = ( ( char* ) inBuffer )[ frameInSample + channelCount + channel ];\r
+ char sampleDiff = ( char ) ( ( toSample - fromSample ) * inSampleDec );\r
+ ( ( char* ) outBuffer )[ frameOutSample + channel ] = fromSample + sampleDiff;\r
+ }\r
+ break;\r
+ }\r
+ case RTAUDIO_SINT16:\r
+ {\r
+ for ( unsigned int channel = 0; channel < channelCount; channel++ )\r
+ {\r
+ short fromSample = ( ( short* ) inBuffer )[ frameInSample + channel ];\r
+ short toSample = ( ( short* ) inBuffer )[ frameInSample + channelCount + channel ];\r
+ short sampleDiff = ( short ) ( ( toSample - fromSample ) * inSampleDec );\r
+ ( ( short* ) outBuffer )[ frameOutSample + channel ] = fromSample + sampleDiff;\r
+ }\r
+ break;\r
+ }\r
+ case RTAUDIO_SINT24:\r
+ {\r
+ for ( unsigned int channel = 0; channel < channelCount; channel++ )\r
+ {\r
+ int fromSample = ( ( S24* ) inBuffer )[ frameInSample + channel ].asInt();\r
+ int toSample = ( ( S24* ) inBuffer )[ frameInSample + channelCount + channel ].asInt();\r
+ int sampleDiff = ( int ) ( ( toSample - fromSample ) * inSampleDec );\r
+ ( ( S24* ) outBuffer )[ frameOutSample + channel ] = fromSample + sampleDiff;\r
+ }\r
+ break;\r
+ }\r
+ case RTAUDIO_SINT32:\r
+ {\r
+ for ( unsigned int channel = 0; channel < channelCount; channel++ )\r
+ {\r
+ int fromSample = ( ( int* ) inBuffer )[ frameInSample + channel ];\r
+ int toSample = ( ( int* ) inBuffer )[ frameInSample + channelCount + channel ];\r
+ int sampleDiff = ( int ) ( ( toSample - fromSample ) * inSampleDec );\r
+ ( ( int* ) outBuffer )[ frameOutSample + channel ] = fromSample + sampleDiff;\r
+ }\r
+ break;\r
+ }\r
+ case RTAUDIO_FLOAT32:\r
+ {\r
+ for ( unsigned int channel = 0; channel < channelCount; channel++ )\r
+ {\r
+ float fromSample = ( ( float* ) inBuffer )[ frameInSample + channel ];\r
+ float toSample = ( ( float* ) inBuffer )[ frameInSample + channelCount + channel ];\r
+ float sampleDiff = ( toSample - fromSample ) * inSampleDec;\r
+ ( ( float* ) outBuffer )[ frameOutSample + channel ] = fromSample + sampleDiff;\r
+ }\r
+ break;\r
+ }\r
+ case RTAUDIO_FLOAT64:\r
+ {\r
+ for ( unsigned int channel = 0; channel < channelCount; channel++ )\r
+ {\r
+ double fromSample = ( ( double* ) inBuffer )[ frameInSample + channel ];\r
+ double toSample = ( ( double* ) inBuffer )[ frameInSample + channelCount + channel ];\r
+ double sampleDiff = ( toSample - fromSample ) * inSampleDec;\r
+ ( ( double* ) outBuffer )[ frameOutSample + channel ] = fromSample + sampleDiff;\r
+ }\r
+ break;\r
+ }\r
+ }\r
\r
- // jump to next in sample\r
- inSampleFraction += sampleStep;\r
+ // jump to next in sample\r
+ inSampleFraction += sampleStep;\r
+ }\r
}\r
}\r
\r
info.nativeFormats |= RTAUDIO_SINT8;\r
if ( mask & AFMT_S32_LE || mask & AFMT_S32_BE )\r
info.nativeFormats |= RTAUDIO_SINT32;\r
+#ifdef AFMT_FLOAT\r
if ( mask & AFMT_FLOAT )\r
info.nativeFormats |= RTAUDIO_FLOAT32;\r
+#endif\r
if ( mask & AFMT_S24_LE || mask & AFMT_S24_BE )\r
info.nativeFormats |= RTAUDIO_SINT24;\r
\r
}\r
\r
// Verify the sample rate setup worked.\r
- if ( abs( srate - sampleRate ) > 100 ) {\r
+ if ( abs( srate - (int)sampleRate ) > 100 ) {\r
close( fd );\r
errorStream_ << "RtApiOss::probeDeviceOpen: device (" << ainfo.name << ") does not support sample rate (" << sampleRate << ").";\r
errorText_ = errorStream_.str();\r
// Default constructor.
CallbackInfo()
- :object(0), callback(0), userData(0), errorCallback(0), apiInfo(0), isRunning(false), doRealtime(false) {}
+ :object(0), callback(0), userData(0), errorCallback(0), apiInfo(0), isRunning(false), doRealtime(false), priority(0) {}
};
// **************************************************************** //
PyObject *callback_func;
} PyRtAudio;
- static PyObject *RtAudioError;
+ static PyObject *RtAudioErrorException;
static int callback(void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
double streamTime, RtAudioStreamStatus status, void *data )
else if(!strcmp(api, "directsound"))
self->dac = new RtAudio(RtAudio::WINDOWS_DS);
}
- catch (RtError &error) {
- PyErr_SetString(RtAudioError, error.getMessage().c_str());
- Py_INCREF(RtAudioError);
+ catch (RtAudioError &error) {
+ PyErr_SetString(RtAudioErrorException, error.getMessage().c_str());
+ Py_INCREF(RtAudioErrorException);
return NULL;
}
self->dac->closeStream();
self->dac->openStream(&oParams, &iParams, self->_format, fs, &bf, &callback, self, &options);
}
- catch ( RtError& error ) {
- PyErr_SetString(RtAudioError, error.getMessage().c_str());
- Py_INCREF(RtAudioError);
+ catch ( RtAudioError& error ) {
+ PyErr_SetString(RtAudioErrorException, error.getMessage().c_str());
+ Py_INCREF(RtAudioErrorException);
return NULL;
}
self->dac->closeStream();
Py_CLEAR(self->callback_func);
}
- catch(RtError &error) {
- PyErr_SetString(RtAudioError, error.getMessage().c_str());
- Py_INCREF(RtAudioError);
+ catch(RtAudioError &error) {
+ PyErr_SetString(RtAudioErrorException, error.getMessage().c_str());
+ Py_INCREF(RtAudioErrorException);
return NULL;
}
try {
self->dac->startStream();
}
- catch(RtError &error) {
- PyErr_SetString(RtAudioError, error.getMessage().c_str());
- Py_INCREF(RtAudioError);
+ catch(RtAudioError &error) {
+ PyErr_SetString(RtAudioErrorException, error.getMessage().c_str());
+ Py_INCREF(RtAudioErrorException);
return NULL;
}
try {
self->dac->stopStream();
}
- catch(RtError &error) {
- PyErr_SetString(RtAudioError, error.getMessage().c_str());
- Py_INCREF(RtAudioError);
+ catch(RtAudioError &error) {
+ PyErr_SetString(RtAudioErrorException, error.getMessage().c_str());
+ Py_INCREF(RtAudioErrorException);
return NULL;
}
try {
self->dac->abortStream();
}
- catch(RtError &error) {
- PyErr_SetString(RtAudioError, error.getMessage().c_str());
- Py_INCREF(RtAudioError);
+ catch(RtAudioError &error) {
+ PyErr_SetString(RtAudioErrorException, error.getMessage().c_str());
+ Py_INCREF(RtAudioErrorException);
return NULL;
}
Py_RETURN_NONE;
return info_dict;
}
- catch(RtError &error) {
- PyErr_SetString(RtAudioError, error.getMessage().c_str());
- Py_INCREF(RtAudioError);
+ catch(RtAudioError &error) {
+ PyErr_SetString(RtAudioErrorException, error.getMessage().c_str());
+ Py_INCREF(RtAudioErrorException);
return NULL;
}
}
Py_INCREF(&RtAudio_type);
PyModule_AddObject(module, "RtAudio", (PyObject *)&RtAudio_type);
- RtAudioError = PyErr_NewException("rtaudio.RtError", NULL, NULL);
- Py_INCREF(RtAudioError);
- PyModule_AddObject(module, "RtError", RtAudioError);
+ RtAudioErrorException = PyErr_NewException("rtaudio.RtError", NULL, NULL);
+ Py_INCREF(RtAudioErrorException);
+ PyModule_AddObject(module, "RtError", RtAudioErrorException);
}
}
if OSNAME == 'Linux':
define_macros=[("__LINUX_ALSA__", ''),
- ('__LINUX_JACK__', ''),
- ('__LINUX_OSS__', '')]
+ ('__LINUX_JACK__', '')]
libraries = ['asound', 'jack', 'pthread']
elif OSNAME == 'Darwin':
<TD>RtApiCore</TD>
<TD>__MACOSX_CORE__</TD>
<TD><TT>pthread, CoreAudio</TT></TD>
- <TD><TT>g++ -Wall -D__MACOSX_CORE__ -o audioprobe audioprobe.cpp RtAudio.cpp -framework CoreAudio -lpthread</TT></TD>
+ <TD><TT>g++ -Wall -D__MACOSX_CORE__ -o audioprobe audioprobe.cpp RtAudio.cpp -framework CoreAudio -framework CoreFoundation -lpthread</TT></TD>
</TR>
<TR>
<TD>Windows</TD>
bool isDefaultOutput; // true if this is the default output device.
bool isDefaultInput; // true if this is the default input device.
std::vector<unsigned int> sampleRates; // Supported sample rates.
+ unsigned int preferredSampleRate; // Preferred sample rate, eg. for WASAPI the system sample rate.
RtAudioFormat nativeFormats; // Bit mask of supported data formats.
};
\endcode
RtAudio::StreamOptions options;
//options.flags |= RTAUDIO_NONINTERLEAVED;
+ bufferBytes = bufferFrames * channels * sizeof( MY_TYPE );
try {
adac.openStream( &oParams, &iParams, FORMAT, fs, &bufferFrames, &inout, (void *)&bufferBytes, &options );
}
exit( 1 );
}
- bufferBytes = bufferFrames * channels * sizeof( MY_TYPE );
-
// Test RtAudio functionality for reporting latency.
std::cout << "\nStream latency = " << adac.getStreamLatency() << " frames" << std::endl;
if ( status )
std::cout << "Stream underflow detected!" << std::endl;
- float increment;
+ double increment;
for ( j=0; j<channels; j++ ) {
increment = BASE_RATE * (j+1+(j*0.1));
for ( i=0; i<nBufferFrames; i++ ) {
if ( status ) std::cout << "Stream over/underflow detected!" << std::endl;\r
\r
for ( i=0; i<nBufferFrames; i++ ) {\r
- if ( data->frameCounter % data->pulseCount == 0 ) sample = 0.9;\r
+ if ( data->frameCounter % data->pulseCount == 0 ) sample = 0.9f;\r
else sample = 0.0;\r
for ( j=0; j<data->channels; j++ )\r
*buffer++ = sample;\r
// Let RtAudio print messages to stderr.\r
adc->showWarnings( true );\r
\r
- runtime = RUNTIME * 1000;\r
- pausetime = PAUSETIME * 1000;\r
+ runtime = static_cast<unsigned int>(RUNTIME * 1000);\r
+ pausetime = static_cast<unsigned int>(PAUSETIME * 1000);\r
\r
// Set our stream parameters for a duplex stream.\r
bufferFrames = 512;\r
oParams.deviceId = adc->getDefaultOutputDevice();\r
\r
// First, test external stopStream() calls.\r
- mydata.pulseCount = PULSE_RATE * fs;\r
+ mydata.pulseCount = static_cast<unsigned int>(PULSE_RATE * fs);\r
mydata.nFrames = 50 * fs;\r
mydata.returnValue = 0;\r
try {\r