diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/pcm_utils.c | 129 |
1 files changed, 59 insertions, 70 deletions
diff --git a/src/pcm_utils.c b/src/pcm_utils.c index 8454c8871..1dbc7b3a0 100644 --- a/src/pcm_utils.c +++ b/src/pcm_utils.c @@ -117,13 +117,13 @@ void pcm_convertSampleRate( AudioFormat * inFormat, mpd_fixed_t * inBuffer, int inFrames, AudioFormat *outFormat, mpd_fixed_t *outBuffer, int outFrames) { - static int inRate; /* reduced bitRate */ + static int inRate; static int outRate; static int shift; - static int unshift; + static int rateShift; static mpd_fixed_t oldSampleL = 0; static mpd_fixed_t oldSampleR = 0; - mpd_uint32 curTime; + int delay; /* recalculate static data if samplerate has changed */ if(inFormat->sampleRate != convSampleRateData.inRate || @@ -135,11 +135,11 @@ void pcm_convertSampleRate( /* calculate the rates to use in calculations... */ inRate = inFormat->sampleRate; outRate = outFormat->sampleRate; - unshift=0; + rateShift=0; shift = 16; /* worst case shift */ /* ...reduce them to minimize shifting */ while(!(inRate & 1) && !(outRate & 1)) { - unshift++; + rateShift++; shift--; inRate >>= 1; outRate >>= 1; @@ -149,59 +149,50 @@ void pcm_convertSampleRate( } /* compute */ - curTime = convSampleRateData.delay >> unshift; -/* -ERROR("pcm_convertSampleRate2: inFrames=%i, outFrames=%i, inRate=%i, outRate=%i, curTime=%i\n", - inFrames, outFrames, inRate, outRate, curTime);*/ + + delay = convSampleRateData.delay >> rateShift; switch(inFormat->channels) { case 1: while(inFrames--) { - curTime += outRate; + delay += outRate; /* calculate new samples */ - while(curTime >= inRate) { - curTime -= inRate; + while(delay >= inRate) { + mpd_sint32 raise; + delay -= inRate; + raise = *inBuffer - oldSampleL; *outBuffer++ = oldSampleL + - (((*inBuffer - oldSampleL) * - ((outRate - curTime) >> shift)) / - outRate); - outFrames--; + ((((raise>>shift) * (outRate - delay)) / + outRate) << shift); } oldSampleL = *inBuffer++; } + break; case 2: while(inFrames--) { - curTime += outRate; + delay += outRate; /* calculate new samples */ - while(curTime >= inRate) { - curTime -= inRate; + while(delay >= inRate) { + mpd_sint32 raise; + delay -= inRate; + /* left channel */ + raise = *inBuffer - oldSampleL; *outBuffer++ = oldSampleL + - (((*inBuffer - oldSampleL) * - ((outRate - curTime) >> shift)) / - outRate); + ((((raise>>shift) * (outRate - delay)) / + outRate) << shift); + /* right channel */ + raise = inBuffer[1] - oldSampleR; *outBuffer++ = oldSampleR + - (((inBuffer[1] - oldSampleR) * - ((outRate - curTime) >> shift)) / - outRate); - outFrames--; + ((((raise>>shift) * (outRate - delay)) / + outRate) << shift); } oldSampleL = *inBuffer++; oldSampleR = *inBuffer++; } - } - convSampleRateData.delay = curTime << unshift; -/* -ERROR("pcm_convertSampleRate2: inFrames=%i, outFrames=%i, curTime=%i\n\n", - inFrames, outFrames, curTime);*/ - - /* some temporary debugging tests */ - if(inFrames>0) { - ERROR("pcm_convertSampleRate produced to few outFrames!\n"); - exit(EXIT_FAILURE); - } - if(outFrames>0) { - ERROR("pcm_convertSampleRate produced to many outFrames!\n"); - exit(EXIT_FAILURE); + /* exit(EXIT_FAILURE);*/ + break; } + + convSampleRateData.delay = delay << rateShift; } @@ -358,9 +349,7 @@ void pcm_convertAudioFormat(AudioFormat * inFormat, char * inBuffer, size_t inFormat, inSize, outFormat); const int outSamples = (outSize << 3) / outFormat->bits; const int outFrames = outSamples / outFormat->channels; -/*ERROR("pcm_convertAudioFormat: outSize=%i, outSamples=%i, outFrames=%i," - "outFormat.bits=%i, outFormat.channels=%i\n", - outSize, outSamples, outFrames, outFormat->bits, outFormat->channels);*/ + /* make sure convBuffer is big enough for 2 channels of 32 bit samples */ dataLen = inFrames << 3; if(dataLen > convBufferLength) { @@ -384,6 +373,27 @@ void pcm_convertAudioFormat(AudioFormat * inFormat, char * inBuffer, size_t dataConv, fracBits); } + /****** convert sample rate ******/ + + if(inFormat->sampleRate != outFormat->sampleRate) { + /* check size of buffer */ + dataLen = outFrames << 3; + if(dataLen > convSampleBufferLength) { + convSampleBuffer = (char *) + realloc(convSampleBuffer, dataLen); + if(!convSampleBuffer) { + ERROR("Could not allocate memory for " + "convSampleBuffer!\n"); + exit(EXIT_FAILURE); + } + convSampleBufferLength = dataLen; + } + /* convert samples */ + pcm_convertSampleRate(inFormat, (mpd_fixed_t*)dataConv, inFrames, + outFormat, (mpd_fixed_t*)convSampleBuffer, outFrames); + dataConv = convSampleBuffer; + } + /****** convert between mono and stereo samples ******/ if(inFormat->channels != outFormat->channels) { @@ -394,7 +404,7 @@ void pcm_convertAudioFormat(AudioFormat * inFormat, char * inBuffer, size_t /* in reverse order to allow for same in and out buffer */ mpd_fixed_t *in = ((mpd_fixed_t *)dataConv)+inFrames; mpd_fixed_t *out = ((mpd_fixed_t *)convBuffer)+(inFrames<<1); - int f = inFrames; + int f = outFrames; while(f--) { *out-- = *in; *out-- = *in--; @@ -406,7 +416,7 @@ void pcm_convertAudioFormat(AudioFormat * inFormat, char * inBuffer, size_t { mpd_fixed_t *in = ((mpd_fixed_t *)dataConv); mpd_fixed_t *out = ((mpd_fixed_t *)convBuffer); - int f = inFrames; + int f = outFrames; while(f--) { *out = (*in++)>>1; *out++ += (*in++)>>1; @@ -420,30 +430,10 @@ void pcm_convertAudioFormat(AudioFormat * inFormat, char * inBuffer, size_t dataConv = convBuffer; } - /****** convert sample rate ******/ - - if(inFormat->sampleRate != outFormat->sampleRate) { - /* check size of buffer */ - dataLen = outFrames << 3; - if(dataLen > convSampleBufferLength) { - convSampleBuffer = (char *) - realloc(convSampleBuffer, dataLen); - if(!convSampleBuffer) { - ERROR("Could not allocate memory for " - "convSampleBuffer!\n"); - exit(EXIT_FAILURE); - } - convSampleBufferLength = dataLen; - } - /* convert samples */ - pcm_convertSampleRate(inFormat, (mpd_fixed_t*)dataConv, inFrames, - outFormat, (mpd_fixed_t*)convSampleBuffer, outFrames); - dataConv = convSampleBuffer; - } - /****** convert to output format ******/ - /* if outformat is mpd_fixed_t then we are done ?! TODO */ + /* if outformat is mpd_fixed_t then we are done ?! + * TODO take care of case when in and out have different fracBits */ if(outFormat->fracBits==fracBits) { if(outFormat->bits==32) { if(outBuffer != dataConv) @@ -510,6 +500,8 @@ size_t pcm_sizeOfOutputBufferForAudioFormatConversion(AudioFormat * inFormat, if(inFormat->sampleRate == outFormat->sampleRate) outFrames = inFrames; else { + /* The previous delay from the sample rate conversion affect + * the size of the output */ mpd_uint32 delay = convSampleRateData.delay; if(inFormat->sampleRate != convSampleRateData.inRate || outFormat->sampleRate != convSampleRateData.outRate) @@ -518,9 +510,6 @@ size_t pcm_sizeOfOutputBufferForAudioFormatConversion(AudioFormat * inFormat, } outFrames = (inFrames * (mpd_uint32)(outFormat->sampleRate) + delay) / inFormat->sampleRate; -/* -ERROR("pcm_size... inSize=%i, inShift=%i, outShift=%i, inFrames=%i, outFrames=%i, delay=%i\n", - inSize, inShift, outShift, inFrames, outFrames, delay); */ } return outFrames * outShift; } |