| @@ -1,4 +1,4 @@ | |||
| /************************************************************************/ | |||
| /************************************************************************/ | |||
| /*! \class RtAudio | |||
| \brief Realtime audio i/o C++ classes. | |||
| @@ -3859,8 +3859,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 +3871,126 @@ 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 ); | |||
| // 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 ) | |||
| { | |||
| 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; | |||
| // 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; | |||
| 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; | |||
| switch (format) | |||
| { | |||
| case RTAUDIO_SINT8: | |||
| { | |||
| for (unsigned int channel = 0; channel < channelCount; channel++) | |||
| { | |||
| char fromSample = ((char*)inBuffer)[(inSample * channelCount) + channel]; | |||
| char toSample = ((char*)inBuffer)[((inSample + 1) * channelCount) + channel]; | |||
| float sampleDiff = (toSample - fromSample) * (inSampleFraction - floor(inSampleFraction)); | |||
| ((char*)outBuffer)[(outSample * channelCount) + channel] = fromSample + (char)sampleDiff; | |||
| } | |||
| break; | |||
| } | |||
| case RTAUDIO_SINT16: | |||
| { | |||
| for (unsigned int channel = 0; channel < channelCount; channel++) | |||
| { | |||
| short fromSample = ((short*)inBuffer)[(inSample * channelCount) + channel]; | |||
| short toSample = ((short*)inBuffer)[((inSample + 1) * channelCount) + channel]; | |||
| float sampleDiff = (toSample - fromSample) * (inSampleFraction - floor(inSampleFraction)); | |||
| ((short*)outBuffer)[(outSample * channelCount) + channel] = fromSample + (short)sampleDiff; | |||
| } | |||
| break; | |||
| } | |||
| case RTAUDIO_SINT24: | |||
| { | |||
| for (unsigned int channel = 0; channel < channelCount; channel++) | |||
| { | |||
| int fromSample = ((S24*)inBuffer)[(inSample * channelCount) + channel].asInt(); | |||
| int toSample = ((S24*)inBuffer)[((inSample + 1) * channelCount) + channel].asInt(); | |||
| float sampleDiff = (toSample - fromSample) * (inSampleFraction - floor(inSampleFraction)); | |||
| ((S24*)outBuffer)[(outSample * channelCount) + channel] = fromSample + (int)sampleDiff; | |||
| } | |||
| break; | |||
| } | |||
| case RTAUDIO_SINT32: | |||
| { | |||
| for (unsigned int channel = 0; channel < channelCount; channel++) | |||
| { | |||
| int fromSample = ((int*)inBuffer)[(inSample * channelCount) + channel]; | |||
| int toSample = ((int*)inBuffer)[((inSample + 1) * channelCount) + channel]; | |||
| float sampleDiff = (toSample - fromSample) * (inSampleFraction - floor(inSampleFraction)); | |||
| ((int*)outBuffer)[(outSample * channelCount) + channel] = fromSample + (int)sampleDiff; | |||
| } | |||
| break; | |||
| } | |||
| case RTAUDIO_FLOAT32: | |||
| { | |||
| for (unsigned int channel = 0; channel < channelCount; channel++) | |||
| { | |||
| float fromSample = ((float*)inBuffer)[(inSample * channelCount) + channel]; | |||
| float toSample = ((float*)inBuffer)[((inSample + 1) * channelCount) + channel]; | |||
| float sampleDiff = (toSample - fromSample) * (inSampleFraction - floor(inSampleFraction)); | |||
| ((float*)outBuffer)[(outSample * channelCount) + channel] = fromSample + sampleDiff; | |||
| } | |||
| break; | |||
| } | |||
| case RTAUDIO_FLOAT64: | |||
| { | |||
| for (unsigned int channel = 0; channel < channelCount; channel++) | |||
| { | |||
| double fromSample = ((double*)inBuffer)[(inSample * channelCount) + channel]; | |||
| double toSample = ((double*)inBuffer)[((inSample + 1) * channelCount) + channel]; | |||
| double sampleDiff = (toSample - fromSample) * (inSampleFraction - floor(inSampleFraction)); | |||
| ((double*)outBuffer)[(outSample * channelCount) + channel] = fromSample + sampleDiff; | |||
| } | |||
| break; | |||
| } | |||
| } | |||
| // jump to next in sample | |||
| inSampleFraction += sampleStep; | |||
| } | |||
| } | |||
| } | |||