summaryrefslogtreecommitdiff
path: root/RtAudio.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'RtAudio.cpp')
-rw-r--r--RtAudio.cpp162
1 files changed, 128 insertions, 34 deletions
diff --git a/RtAudio.cpp b/RtAudio.cpp
index a6b4a47..61b4708 100644
--- a/RtAudio.cpp
+++ b/RtAudio.cpp
@@ -1,4 +1,4 @@
-/************************************************************************/
+/************************************************************************/
/*! \class RtAudio
\brief Realtime audio i/o C++ classes.
@@ -45,6 +45,7 @@
#include <cstdlib>
#include <cstring>
#include <climits>
+#include <cmath>
#include <algorithm>
// Static variable definitions.
@@ -92,12 +93,12 @@ const unsigned int RtApi::SAMPLE_RATES[] = {
//
// *************************************************** //
-std::string RtAudio :: getVersion( void ) throw()
+std::string RtAudio :: getVersion( void )
{
return RTAUDIO_VERSION;
}
-void RtAudio :: getCompiledApi( std::vector<RtAudio::Api> &apis ) throw()
+void RtAudio :: getCompiledApi( std::vector<RtAudio::Api> &apis )
{
apis.clear();
@@ -209,7 +210,7 @@ RtAudio :: RtAudio( RtAudio::Api api )
throw( RtAudioError( errorText, RtAudioError::UNSPECIFIED ) );
}
-RtAudio :: ~RtAudio() throw()
+RtAudio :: ~RtAudio()
{
if ( rtapi_ )
delete rtapi_;
@@ -427,6 +428,9 @@ void RtApi :: setStreamTime( double time )
if ( time >= 0.0 )
stream_.streamTime = time;
+#if defined( HAVE_GETTIMEOFDAY )
+ gettimeofday( &stream_.lastTickTimestamp, NULL );
+#endif
}
unsigned int RtApi :: getStreamSampleRate( void )
@@ -3859,8 +3863,7 @@ private:
// In order to satisfy WASAPI's buffer requirements, we need a means of converting sample rate
// between HW and the user. The convertBufferWasapi function is used to perform this conversion
// between HwIn->UserIn and UserOut->HwOut during the stream callback loop.
-// This sample rate converter favors speed over quality, and works best with conversions between
-// one rate and its multiple.
+// This sample rate converter works best with conversions between one rate and its multiple.
void convertBufferWasapi( char* outBuffer,
const char* inBuffer,
const unsigned int& channelCount,
@@ -3872,40 +3875,129 @@ void convertBufferWasapi( char* outBuffer,
{
// calculate the new outSampleCount and relative sampleStep
float sampleRatio = ( float ) outSampleRate / inSampleRate;
+ float sampleRatioInv = ( float ) 1 / sampleRatio;
float sampleStep = 1.0f / sampleRatio;
float inSampleFraction = 0.0f;
- outSampleCount = ( unsigned int ) roundf( inSampleCount * sampleRatio );
+ outSampleCount = ( unsigned int ) std::roundf( inSampleCount * sampleRatio );
- // frame-by-frame, copy each relative input sample into it's corresponding output sample
- for ( unsigned int outSample = 0; outSample < outSampleCount; outSample++ )
+ // if inSampleRate is a multiple of outSampleRate (or vice versa) there's no need to interpolate
+ if ( floor( sampleRatio ) == sampleRatio || floor( sampleRatioInv ) == sampleRatioInv )
{
- unsigned int inSample = ( unsigned int ) inSampleFraction;
-
- switch ( format )
+ // frame-by-frame, copy each relative input sample into it's corresponding output sample
+ for ( unsigned int outSample = 0; outSample < outSampleCount; outSample++ )
{
- case RTAUDIO_SINT8:
- memcpy( &( ( char* ) outBuffer )[ outSample * channelCount ], &( ( char* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( char ) );
- break;
- case RTAUDIO_SINT16:
- memcpy( &( ( short* ) outBuffer )[ outSample * channelCount ], &( ( short* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( short ) );
- break;
- case RTAUDIO_SINT24:
- memcpy( &( ( S24* ) outBuffer )[ outSample * channelCount ], &( ( S24* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( S24 ) );
- break;
- case RTAUDIO_SINT32:
- memcpy( &( ( int* ) outBuffer )[ outSample * channelCount ], &( ( int* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( int ) );
- break;
- case RTAUDIO_FLOAT32:
- memcpy( &( ( float* ) outBuffer )[ outSample * channelCount ], &( ( float* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( float ) );
- break;
- case RTAUDIO_FLOAT64:
- memcpy( &( ( double* ) outBuffer )[ outSample * channelCount ], &( ( double* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( double ) );
- break;
+ unsigned int inSample = ( unsigned int ) inSampleFraction;
+
+ switch ( format )
+ {
+ case RTAUDIO_SINT8:
+ memcpy( &( ( char* ) outBuffer )[ outSample * channelCount ], &( ( char* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( char ) );
+ break;
+ case RTAUDIO_SINT16:
+ memcpy( &( ( short* ) outBuffer )[ outSample * channelCount ], &( ( short* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( short ) );
+ break;
+ case RTAUDIO_SINT24:
+ memcpy( &( ( S24* ) outBuffer )[ outSample * channelCount ], &( ( S24* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( S24 ) );
+ break;
+ case RTAUDIO_SINT32:
+ memcpy( &( ( int* ) outBuffer )[ outSample * channelCount ], &( ( int* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( int ) );
+ break;
+ case RTAUDIO_FLOAT32:
+ memcpy( &( ( float* ) outBuffer )[ outSample * channelCount ], &( ( float* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( float ) );
+ break;
+ case RTAUDIO_FLOAT64:
+ memcpy( &( ( double* ) outBuffer )[ outSample * channelCount ], &( ( double* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( double ) );
+ break;
+ }
+
+ // jump to next in sample
+ inSampleFraction += sampleStep;
}
+ }
+ else // else interpolate
+ {
+ // frame-by-frame, copy each relative input sample into it's corresponding output sample
+ for ( unsigned int outSample = 0; outSample < outSampleCount; outSample++ )
+ {
+ unsigned int inSample = ( unsigned int ) inSampleFraction;
+ float inSampleDec = inSampleFraction - inSample;
+ unsigned int frameInSample = inSample * channelCount;
+ unsigned int frameOutSample = outSample * channelCount;
- // jump to next in sample
- inSampleFraction += sampleStep;
+ switch ( format )
+ {
+ case RTAUDIO_SINT8:
+ {
+ for ( unsigned int channel = 0; channel < channelCount; channel++ )
+ {
+ char fromSample = ( ( char* ) inBuffer )[ frameInSample + channel ];
+ char toSample = ( ( char* ) inBuffer )[ frameInSample + channelCount + channel ];
+ char sampleDiff = ( char ) ( ( toSample - fromSample ) * inSampleDec );
+ ( ( char* ) outBuffer )[ frameOutSample + channel ] = fromSample + sampleDiff;
+ }
+ break;
+ }
+ case RTAUDIO_SINT16:
+ {
+ for ( unsigned int channel = 0; channel < channelCount; channel++ )
+ {
+ short fromSample = ( ( short* ) inBuffer )[ frameInSample + channel ];
+ short toSample = ( ( short* ) inBuffer )[ frameInSample + channelCount + channel ];
+ short sampleDiff = ( short ) ( ( toSample - fromSample ) * inSampleDec );
+ ( ( short* ) outBuffer )[ frameOutSample + channel ] = fromSample + sampleDiff;
+ }
+ break;
+ }
+ case RTAUDIO_SINT24:
+ {
+ for ( unsigned int channel = 0; channel < channelCount; channel++ )
+ {
+ int fromSample = ( ( S24* ) inBuffer )[ frameInSample + channel ].asInt();
+ int toSample = ( ( S24* ) inBuffer )[ frameInSample + channelCount + channel ].asInt();
+ int sampleDiff = ( int ) ( ( toSample - fromSample ) * inSampleDec );
+ ( ( S24* ) outBuffer )[ frameOutSample + channel ] = fromSample + sampleDiff;
+ }
+ break;
+ }
+ case RTAUDIO_SINT32:
+ {
+ for ( unsigned int channel = 0; channel < channelCount; channel++ )
+ {
+ int fromSample = ( ( int* ) inBuffer )[ frameInSample + channel ];
+ int toSample = ( ( int* ) inBuffer )[ frameInSample + channelCount + channel ];
+ int sampleDiff = ( int ) ( ( toSample - fromSample ) * inSampleDec );
+ ( ( int* ) outBuffer )[ frameOutSample + channel ] = fromSample + sampleDiff;
+ }
+ break;
+ }
+ case RTAUDIO_FLOAT32:
+ {
+ for ( unsigned int channel = 0; channel < channelCount; channel++ )
+ {
+ float fromSample = ( ( float* ) inBuffer )[ frameInSample + channel ];
+ float toSample = ( ( float* ) inBuffer )[ frameInSample + channelCount + channel ];
+ float sampleDiff = ( toSample - fromSample ) * inSampleDec;
+ ( ( float* ) outBuffer )[ frameOutSample + channel ] = fromSample + sampleDiff;
+ }
+ break;
+ }
+ case RTAUDIO_FLOAT64:
+ {
+ for ( unsigned int channel = 0; channel < channelCount; channel++ )
+ {
+ double fromSample = ( ( double* ) inBuffer )[ frameInSample + channel ];
+ double toSample = ( ( double* ) inBuffer )[ frameInSample + channelCount + channel ];
+ double sampleDiff = ( toSample - fromSample ) * inSampleDec;
+ ( ( double* ) outBuffer )[ frameOutSample + channel ] = fromSample + sampleDiff;
+ }
+ break;
+ }
+ }
+
+ // jump to next in sample
+ inSampleFraction += sampleStep;
+ }
}
}
@@ -5277,8 +5369,8 @@ RtApiDs :: RtApiDs()
RtApiDs :: ~RtApiDs()
{
- if ( coInitialized_ ) CoUninitialize(); // balanced call.
if ( stream_.state != STREAM_CLOSED ) closeStream();
+ if ( coInitialized_ ) CoUninitialize(); // balanced call.
}
// The DirectSound default output is always the first device.
@@ -8697,8 +8789,10 @@ RtAudio::DeviceInfo RtApiOss :: getDeviceInfo( unsigned int device )
info.nativeFormats |= RTAUDIO_SINT8;
if ( mask & AFMT_S32_LE || mask & AFMT_S32_BE )
info.nativeFormats |= RTAUDIO_SINT32;
+#ifdef AFMT_FLOAT
if ( mask & AFMT_FLOAT )
info.nativeFormats |= RTAUDIO_FLOAT32;
+#endif
if ( mask & AFMT_S24_LE || mask & AFMT_S24_BE )
info.nativeFormats |= RTAUDIO_SINT24;
@@ -9025,7 +9119,7 @@ bool RtApiOss :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned
}
// Verify the sample rate setup worked.
- if ( abs( srate - sampleRate ) > 100 ) {
+ if ( abs( srate - (int)sampleRate ) > 100 ) {
close( fd );
errorStream_ << "RtApiOss::probeDeviceOpen: device (" << ainfo.name << ") does not support sample rate (" << sampleRate << ").";
errorText_ = errorStream_.str();