aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/pcm_utils.c129
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;
}