Browse Source

–Added interpolation to WASAPI's sample rate converter

tags/5.0.0
Marcus Tomlinson 8 years ago
parent
commit
dc20fccbbe
1 changed files with 116 additions and 31 deletions
  1. +116
    -31
      RtAudio.cpp

+ 116
- 31
RtAudio.cpp View File

@@ -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;
}
}
}


Loading…
Cancel
Save