diff options
Diffstat (limited to 'src/pcm_utils.c')
-rw-r--r-- | src/pcm_utils.c | 669 |
1 files changed, 505 insertions, 164 deletions
diff --git a/src/pcm_utils.c b/src/pcm_utils.c index adcc90122..bfb11e3ff 100644 --- a/src/pcm_utils.c +++ b/src/pcm_utils.c @@ -22,31 +22,72 @@ #include "mpd_types.h" #include "log.h" +#include <stdlib.h> #include <string.h> #include <math.h> #include <assert.h> +#include <time.h> void pcm_changeBufferEndianness(char * buffer, int bufferSize, int bits) { - char temp; - + +ERROR("pcm_changeBufferEndianess\n"); switch(bits) { case 16: while(bufferSize) { - temp = *buffer; + char temp = *buffer; *buffer = *(buffer+1); *(buffer+1) = temp; bufferSize-=2; } break; + case 32: + /* I'm not sure if this code is correct */ + /* I guess it is OK for 32 bit int, but how about float? */ + while(bufferSize) { + char temp = *buffer; + char temp1 = *(buffer+1); + *buffer = *(buffer+3); + *(buffer+1) = *(buffer+2); + *(buffer+2) = temp1; + *(buffer+3) = temp; + bufferSize-=4; + } + break; } } void pcm_volumeChange(char * buffer, int bufferSize, AudioFormat * format, int volume) { - mpd_sint32 temp32; +#ifdef MPD_FIXED_POINT + mpd_sint16 * buffer16 = (mpd_sint16 *)buffer; + mpd_sint32 sample32; + + if(volume>=1000) return; + + if(volume<=0) { + memset(buffer,0,bufferSize); + return; + } + + if(format->bits!=16 || format.channels!=2 || format->floatSamples) { + ERROR("Only 16 bit stereo is supported in fixed point mode!\n"); + exit(EXIT_FAILURE); + } + + while(bufferSize) { + sample32 = (mpd_sint32)(*buffer16) * volume; + /* no need to check boundaries - can't overflow */ + *buffer16 = sample32 >> 10; + bufferSize -= 2; + } + return; +#else mpd_sint8 * buffer8 = (mpd_sint8 *)buffer; mpd_sint16 * buffer16 = (mpd_sint16 *)buffer; + mpd_sint32 * buffer32 = (mpd_sint32 *)buffer; + float * bufferFloat = (float *)buffer; + float fvolume = volume * 0.001; if(volume>=1000) return; @@ -55,26 +96,50 @@ void pcm_volumeChange(char * buffer, int bufferSize, AudioFormat * format, return; } +/* DEBUG */ + if(bufferSize % (format->channels * 4)) { + ERROR("pcm_volumeChange: bufferSize=%i not multipel of %i\n", + bufferSize, format->channels * 4); + } + if(!format->floatSamples) + ERROR("pcm_volumeChange: not floatSamples\n"); +/* /DEBUG */ + + if(format->floatSamples) { + if(format->bits==32) { + while(bufferSize) { + *bufferFloat *= fvolume; + bufferFloat++; + bufferSize-=4; + } + return; + } + else { + ERROR("%i bit float not supported by pcm_volumeChange!\n", + format->bits); + exit(EXIT_FAILURE); + } + } + switch(format->bits) { + case 32: + while(bufferSize) { + double sample = (double)(*buffer32) * fvolume; + *buffer32++ = rint(sample); + bufferSize-=4; + } + break; case 16: - while(bufferSize>0) { - temp32 = *buffer16; - temp32*= volume; - temp32/=1000; - *buffer16 = temp32>32767 ? 32767 : - (temp32<-32768 ? -32768 : temp32); - buffer16++; + while(bufferSize) { + float sample = *buffer16 * fvolume; + *buffer16++ = rintf(sample); bufferSize-=2; } break; case 8: - while(bufferSize>0) { - temp32 = *buffer8; - temp32*= volume; - temp32/=1000; - *buffer8 = temp32>127 ? 127 : - (temp32<-128 ? -128 : temp32); - buffer8++; + while(bufferSize) { + float sample = *buffer8 * fvolume; + *buffer8++ = rintf(sample); bufferSize--; } break; @@ -83,46 +148,115 @@ void pcm_volumeChange(char * buffer, int bufferSize, AudioFormat * format, format->bits); exit(EXIT_FAILURE); } +#endif } void pcm_add(char * buffer1, char * buffer2, size_t bufferSize1, size_t bufferSize2, int vol1, int vol2, AudioFormat * format) { - mpd_sint32 temp32; +#ifdef MPD_FIXED_POINT + mpd_sint16 * buffer16_1 = (mpd_sint16 *)buffer1; + mpd_sint16 * buffer16_2 = (mpd_sint16 *)buffer2; + mpd_sint32 sample; + + if(format->bits!=16 || format.channels!=2 || format->floatSamples) { + ERROR("Only 16 bit stereo is supported in fixed point mode!\n"); + exit(EXIT_FAILURE); + } + + while(bufferSize1 && bufferSize2) { + sample = ((mpd_sint32)(*buffer16_1) * vol1 + + (mpd_sint32)(*buffer16_2) * vol2) >> 10; + *buffer16_1 = sample>32767 ? 32767 : + (sample<-32768 ? -32768 : sample); + bufferSize1 -= 2; + bufferSize2 -= 2; + } + if(bufferSize2) memcpy(buffer16_1,buffer16_2,bufferSize2); + return; +#else +/* DEBUG */ + if(bufferSize1 % (format->channels * 4)) { + ERROR("pcm_add: bufferSize1=%i not multipel of %i\n", + bufferSize1, format->channels * 4); + } + if(bufferSize2 % (format->channels * 4)) { + ERROR("pcm_add: bufferSize2=%i not multipel of %i\n", + bufferSize2, format->channels * 4); + } + if(!format->floatSamples) + ERROR("pcm_add: not floatSamples\n"); +/* /DEBUG */ mpd_sint8 * buffer8_1 = (mpd_sint8 *)buffer1; mpd_sint8 * buffer8_2 = (mpd_sint8 *)buffer2; mpd_sint16 * buffer16_1 = (mpd_sint16 *)buffer1; mpd_sint16 * buffer16_2 = (mpd_sint16 *)buffer2; - + mpd_sint32 * buffer32_1 = (mpd_sint32 *)buffer1; + mpd_sint32 * buffer32_2 = (mpd_sint32 *)buffer2; + float * bufferFloat_1 = (float *)buffer1; + float * bufferFloat_2 = (float *)buffer2; + float fvol1 = vol1 * 0.001; + float fvol2 = vol2 * 0.001; + float sample; + + if(format->floatSamples) { + /* 32 bit float */ + while(bufferSize1 && bufferSize2) { + *bufferFloat_1 = fvol1*(*bufferFloat_1) + + fvol2*(*bufferFloat_2); + bufferFloat_1++; + bufferFloat_2++; + bufferSize1-=4; + bufferSize2-=4; + } + if(bufferSize2) memcpy(bufferFloat_1,bufferFloat_2,bufferSize2); + } + switch(format->bits) { + case 32: + while(bufferSize1 && bufferSize2) { + sample = fvol1*(*buffer32_1) + fvol2*(*buffer32_2); + if(sample>2147483647.0) *buffer32_1 = 2147483647; + else if(sample<-2147483647.0) *buffer32_1 = -2147483647; + else *buffer32_1 = rintf(sample); + bufferFloat_1++; + bufferFloat_2++; + bufferSize1-=4; + bufferSize2-=4; + } + if(bufferSize2) memcpy(bufferFloat_1,bufferFloat_2,bufferSize2); + break; case 16: - while(bufferSize1>0 && bufferSize2>0) { - temp32 = (vol1*(*buffer16_1)+vol2*(*buffer16_2))/1000; - *buffer16_1 = temp32>32767 ? 32767 : - (temp32<-32768 ? -32768 : temp32); + while(bufferSize1 && bufferSize2) { + sample = fvol1*(*buffer16_1) + fvol2*(*buffer16_2); + *buffer16_1 = sample>32767.0 ? 32767 : + (sample<-32768.0 ? -32768 : + rintf(sample)); buffer16_1++; buffer16_2++; bufferSize1-=2; bufferSize2-=2; } - if(bufferSize2>0) memcpy(buffer16_1,buffer16_2,bufferSize2); + if(bufferSize2) memcpy(buffer16_1,buffer16_2,bufferSize2); break; case 8: - while(bufferSize1>0 && bufferSize2>0) { - temp32 = (vol1*(*buffer8_1)+vol2*(*buffer8_2))/1000; - *buffer8_1 = temp32>127 ? 127 : - (temp32<-128 ? -128 : temp32); + while(bufferSize1 && bufferSize2) { + sample = fvol1*(*buffer8_1) + fvol2*(*buffer8_2); + *buffer8_1 = sample>127.0 ? 127 : + (sample<-128.0 ? -128 : + rintf(sample)); buffer8_1++; buffer8_2++; bufferSize1--; bufferSize2--; } - if(bufferSize2>0) memcpy(buffer8_1,buffer8_2,bufferSize2); + if(bufferSize2) memcpy(buffer8_1,buffer8_2,bufferSize2); break; default: ERROR("%i bits not supported by pcm_add!\n",format->bits); exit(EXIT_FAILURE); } +#endif } void pcm_mix(char * buffer1, char * buffer2, size_t bufferSize1, @@ -138,183 +272,390 @@ void pcm_mix(char * buffer1, char * buffer2, size_t bufferSize1, pcm_add(buffer1,buffer2,bufferSize1,bufferSize2,vol1,1000-vol1,format); } - -/* outFormat bits must be 16 and channels must be 2! */ -void pcm_convertAudioFormat(AudioFormat * inFormat, char * inBuffer, size_t - inSize, AudioFormat * outFormat, char * outBuffer) +void pcm_convertToFloat(AudioFormat * inFormat, char * inBuffer, size_t + samples, char * outBuffer) { - static char * bitConvBuffer = NULL; - static int bitConvBufferLength = 0; - static char * channelConvBuffer = NULL; - static int channelConvBufferLength = 0; - char * dataChannelConv; - int dataChannelLen; - char * dataBitConv; - int dataBitLen; - - assert(outFormat->bits==16); - assert(outFormat->channels==2 || outFormat->channels==1); - - /* converts */ + mpd_sint8 * in8 = (mpd_sint8 *)inBuffer; + mpd_sint16 * in16 = (mpd_sint16 *)inBuffer; + mpd_sint32 * in32 = (mpd_sint32 *)inBuffer; + float * out = (float *)outBuffer; + float multiplier; + switch(inFormat->bits) { case 8: - dataBitLen = inSize << 1; - if(dataBitLen > bitConvBufferLength) { - bitConvBuffer = realloc(bitConvBuffer, dataBitLen); - bitConvBufferLength = dataBitLen; - } - dataBitConv = bitConvBuffer; - { - mpd_sint8 * in = (mpd_sint8 *)inBuffer; - mpd_sint16 * out = (mpd_sint16 *)dataBitConv; - int i; - for(i=0; i<inSize; i++) { - *out++ = (*in++) << 8; - } + multiplier = 1.0 / 128.0; + while(samples--) { + *out++ = (*in8++) * multiplier; } break; case 16: - dataBitConv = inBuffer; - dataBitLen = inSize; + multiplier = 1.0 / 32768.0; + while(samples--) { + *out++ = (*in16++) * multiplier; + } break; - case 24: - /* put dithering code from mp3_decode here */ +/* case 32: + multiplier = 1.0 / (1L << 31); + while(samples--) { + *out++ = (*in32++) * multiplier; + } + break; */ default: - ERROR("only 8 or 16 bits are supported for conversion!\n"); + ERROR("%i bit samples are not supported for conversion!\n", + inFormat->bits); exit(EXIT_FAILURE); } +} + + +char *pcm_convertSampleRate(AudioFormat *inFormat, char *inBuffer, size_t inFrames, + AudioFormat *outFormat, size_t outFrames) +{ + /* Input must be float32, 1 or 2 channels */ + /* Interpolate using a second order polynom */ + /* k0 = s0 * + * k2 = (s0 - 2*s1 + s2) * 0.5 * + * k1 = s1 - s0 - k2 * + * s[t] = k0 + k1*t +k2*t*t */ + + static float * sampleConvBuffer = NULL; + static int sampleConvBufferLength = 0; + size_t dataSampleLen = 0; + + float *out; + float *in = (float *)inBuffer; + + static float shift; + static float offset; + static float sample0l; + static float sample0r; + static float sample1l; + static float sample1r; + + static int rateCheck = 0; + static time_t timeCheck = 0; + size_t c_rate = inFormat->sampleRate + inFormat->channels; + time_t c_time = time(NULL); + + /* reset static data if changed samplerate ...*/ + if(c_rate != rateCheck || c_time != timeCheck) { + ERROR("reset resampling\n",c_rate, rateCheck); + rateCheck = c_rate; + shift = (float)inFrames / (float)outFrames; + offset = 1.5; + sample0l = 0.0; + sample0r = 0.0; + sample1l = 0.0; + sample1r = 0.0; + } + else { + /* ... otherwise check that shift is within bounds */ + float s = offset + (outFrames * shift) - inFrames; + if(s > 1.5) { + shift = (1.5-offset+(float)inFrames) / (float)outFrames; + } + else if(s < 0.5) { + shift = (0.5-offset+(float)inFrames) / (float)outFrames; + } + } + timeCheck = c_time; - /* converts only between 16 bit audio between mono and stereo */ - if(inFormat->channels == outFormat->channels) + /* allocate data */ + dataSampleLen = 8 * outFrames; + if(dataSampleLen > sampleConvBufferLength) { + sampleConvBuffer = (float *)realloc(sampleConvBuffer,dataSampleLen); + sampleConvBufferLength = dataSampleLen; + } + out = sampleConvBuffer; + + + /* convert */ + switch(outFormat->channels) { + case 1: + { + float sample2l; + float k0l, k1l, k2l; + while(inFrames--) { + sample2l = *in++; + /* set coefficients */ + k0l = sample0l; + k2l = (sample0l - 2.0 * sample1l + sample2l) * 0.5; + k1l = sample1l - sample0l - k2l; + /* calculate sample(s) */ + while(offset <= 1.5 && outFrames--) { + *out++ = k0l + k1l*offset + k2l*offset*offset; + offset += shift; + } + /* prepare for next frame */ + sample0l = sample1l; + sample1l = sample2l; + offset -= 1.0; + } + + /* fill the last frames */ + while(outFrames--) { + *out++ = k0l + k1l*offset + k2l*offset*offset; + offset += shift; + } + } + break; + case 2: { - dataChannelConv = dataBitConv; - dataChannelLen = dataBitLen; + float *out = sampleConvBuffer; + float *in = (float *)inBuffer; + float sample2l; + float sample2r; + float k0l, k1l, k2l; + float k0r, k1r, k2r; + while(inFrames--) { + sample2l = *in++; + sample2r = *in++; + /* set coefficients */ + k0l = sample0l; + k0r = sample0r; + k2l = (sample0l - 2.0 * sample1l + sample2l) * 0.5; + k2r = (sample0r - 2.0 * sample1r + sample2r) * 0.5; + k1l = sample1l - sample0l - k2l; + k1r = sample1r - sample0r - k2r; + /* calculate sample(s) */ + while(offset <= 1.5 && outFrames--) { + if(offset<0.5) + ERROR("offset to small in resampling - %f\n",offset); + *out++ = k0l + k1l*offset + k2l*offset*offset; + *out++ = k0r + k1r*offset + k2r*offset*offset; + offset += shift; + } + /* prepare for next frame */ + sample0l = sample1l; + sample0r = sample1r; + sample1l = sample2l; + sample1r = sample2r; + offset -= 1.0; + } + + /* fill the last frame(s) */ + while(outFrames--) { + if(offset>2.0) + ERROR("offset to big in resampling - %f\n",offset); + *out++ = k0l + k1l*offset + k2l*offset*offset; + *out++ = k0r+ k1r*offset + k2r*offset*offset; + offset += shift; + } + } + break; + } + return (char *)sampleConvBuffer; +} + + +/* now support conversions between sint8, sint16, sint32 and float32, + * 1 or 2 channels and (although badly) all sample rates */ +void pcm_convertAudioFormat(AudioFormat * inFormat, char * inBuffer, size_t + inSize, AudioFormat * outFormat, char * outBuffer) +{ +#ifdef MPD_FIXED_POINT + /* In fixed mode the conversion support is limited... */ + if(inFormat->bits != outFormat->bits || inFormat->bits != 16) { + ERROR("Only 16 bit samples supported in fixed point mode!\n"); + exit(EXIT_FAILURE); + } + if(inFormat->sampleRate || outFormat->sampleRate) { + ERROR("Sample rate conversions not supported in fixed point mode!\n"); + exit(EXIT_FAILURE); + } + if(inFormat->channels == 2 && outFormat->channels == 1) { + size_t frames = inSize >> 2; /* 16 bit stereo == 4 bytes */ + mpd_sint16 *in = (mpd_sint16 *)inBuffer; + mpd_sint16 *out = (mpd_sint16 *)outBuffer; + while(frames--) { + *out++ = *in++; + *in++; /* skip the other channel */ + } + } + if(inFormat->channels == 1 && outFormat->channels == 2) { + size_t frames = inSize >> 1; /* 16 bit mono == 2 bytes */ + mpd_sint16 *in = (mpd_sint16 *)inBuffer; + mpd_sint16 *out = (mpd_sint16 *)outBuffer; + while(frames--) { + *out++ = *in; + *out++ = *in++; /* duplicate the channel */ + } + } + else { + ERROR("More then 2 channels are not supported!\n"); + exit(EXIT_FAILURE); + } + return; + +#else +/* DEBUG */ + if(inSize % (inFormat->channels * 4)) { + ERROR("pcm_convertAudioFormat: inSize=%i not multipel of %i\n", + inSize, inFormat->channels * 4); + } +/* /DEBUG */ + + static char *convBuffer = NULL; + static int convBufferLength = 0; + char * dataConv; + int dataLen; + static float ditherAmount = 2.0 / RAND_MAX; + const size_t inSamples = (inSize << 3) / inFormat->bits; + const size_t inFrames = inSamples / inFormat->channels; + const size_t outFrames = (inFrames * (mpd_uint32)(outFormat->sampleRate)) / + inFormat->sampleRate; + const size_t outSamples = outFrames * outFormat->channels; + + /* make sure convBuffer is big enough for 2 channels of float samples */ + dataLen = inFrames << 3; + if(dataLen > convBufferLength) { + convBuffer = (char *) realloc(convBuffer, dataLen); + if(!convBuffer) + { + ERROR("Could not allocate more memory for convBuffer!\n"); + exit(EXIT_FAILURE); + } + convBufferLength = dataLen; + } + + /* make sure dataConv points to 32 bit float samples */ + if(inFormat->floatSamples && inFormat->bits==32) { + dataConv = inBuffer; + } + else if(!inFormat->floatSamples) { + dataConv = convBuffer; + pcm_convertToFloat(inFormat, inBuffer, inSamples, dataConv); } else { + ERROR("%i bit float are not supported for conversion!\n", + inFormat->bits); + exit(EXIT_FAILURE); + } + + /* convert between mono and stereo samples*/ + if(inFormat->channels != outFormat->channels) { + float *in = ((float *)dataConv)+inFrames; switch(inFormat->channels) { /* convert from 1 -> 2 channels */ case 1: - dataChannelLen = (dataBitLen >> 1) << 2; - if(dataChannelLen > channelConvBufferLength) { - channelConvBuffer = realloc(channelConvBuffer, - dataChannelLen); - channelConvBufferLength = dataChannelLen; - } - dataChannelConv = channelConvBuffer; { - mpd_sint16 * in = (mpd_sint16 *)dataBitConv; - mpd_sint16 * out = (mpd_sint16 *)dataChannelConv; - int i, inSamples = dataBitLen >> 1; - for(i=0;i<inSamples;i++) { - *out++ = *in; - *out++ = *in++; - } + float *out = ((float *)convBuffer)+(inFrames<<1); + int f = inFrames; + while(f--) { + *out-- = *in; + *out-- = *in--; + } } break; /* convert from 2 -> 1 channels */ case 2: - dataChannelLen = dataBitLen >> 1; - if(dataChannelLen > channelConvBufferLength) { - channelConvBuffer = realloc(channelConvBuffer, - dataChannelLen); - channelConvBufferLength = dataChannelLen; - } - dataChannelConv = channelConvBuffer; { - mpd_sint16 * in = (mpd_sint16 *)dataBitConv; - mpd_sint16 * out = (mpd_sint16 *)dataChannelConv; - int i, inSamples = dataBitLen >> 2; - for(i=0;i<inSamples;i++) { - *out = (*in++)/2; - *out++ += (*in++)/2; - } + float * out = (float *)convBuffer; + int f = inFrames; + while(f--) { + *out = (*in++)*0.5; + *out++ += (*in++)*0.5; + } } break; default: ERROR("only 1 or 2 channels are supported for conversion!\n"); exit(EXIT_FAILURE); } + dataConv = convBuffer; } - if(inFormat->sampleRate == outFormat->sampleRate) { - memcpy(outBuffer,dataChannelConv,dataChannelLen); + /* convert sample rate */ + if(inFormat->sampleRate != outFormat->sampleRate) { + dataConv = pcm_convertSampleRate( + inFormat, dataConv, inFrames, + outFormat, outFrames); } - else { - /* only works if outFormat is 16-bit stereo! */ - /* resampling code blatantly ripped from ESD */ - mpd_uint32 rd_dat = 0; - mpd_uint32 wr_dat = 0; - mpd_sint16 lsample, rsample; - mpd_sint16 * out = (mpd_sint16 *)outBuffer; - mpd_sint16 * in = (mpd_sint16 *)dataChannelConv; - const int shift = sizeof(mpd_sint16)*outFormat->channels; - mpd_uint32 nlen = ((( dataChannelLen / shift) * - (mpd_uint32)(outFormat->sampleRate)) / - inFormat->sampleRate); - nlen *= outFormat->channels; - - switch(outFormat->channels) { - case 1: - while( wr_dat < nlen) { - rd_dat = wr_dat * inFormat->sampleRate / - outFormat->sampleRate; - - lsample = in[ rd_dat++ ]; - - out[ wr_dat++ ] = lsample; - } - break; - case 2: - while( wr_dat < nlen) { - rd_dat = wr_dat * inFormat->sampleRate / - outFormat->sampleRate; - rd_dat &= ~1; - lsample = in[ rd_dat++ ]; - rsample = in[ rd_dat++ ]; - - out[ wr_dat++ ] = lsample; - out[ wr_dat++ ] = rsample; - } - break; - } + /* convert to output format */ + if(outFormat->floatSamples && outFormat->bits==32) { + if(outBuffer != dataConv) + memcpy(outBuffer, dataConv, outSamples << 2); + return; } - - return; -} - -size_t pcm_sizeOfOutputBufferForAudioFormatConversion(AudioFormat * inFormat, - size_t inSize, AudioFormat * outFormat) -{ - const int shift = sizeof(mpd_sint16)*outFormat->channels; - size_t outSize = inSize; - - switch(inFormat->bits) { + else if(outFormat->floatSamples) { + ERROR("%i bit float are not supported for conversion!\n", + outFormat->bits); + exit(EXIT_FAILURE); + } + + switch(outFormat->bits) { case 8: - outSize = outSize << 1; + { + /* add triangular dither and convert to sint8 */ + float * in = (float *)dataConv; + mpd_sint8 * out = (mpd_sint8 *)outBuffer; + int s = outSamples; + while(s--) { + float sample = (*in++) * 128.0 + + ditherAmount*(rand()-rand()); + *out++ = sample>127.0 ? 127 : + (sample<-128.0 ? -128 : + rintf(sample)); + } + } break; case 16: + { + /* add triangular dither and convert to sint16 */ + float * in = (float *)dataConv; + mpd_sint16 * out = (mpd_sint16 *)outBuffer; + int s = outSamples; + while(s--) { + float sample = (*in++) * 32766.0 + + ditherAmount*(rand()-rand()); + *out++ = sample>32767.0 ? 32767 : + (sample<-32768.0 ? -32768 : + rintf(sample)); + } + } break; + case 32: + { + /* convert to sint32 */ + float * in = (float *)dataConv; + mpd_sint32 * out = (mpd_sint32 *)outBuffer; + int s = outSamples; + while(s--) { + float sample = (*in++) * 2147483647.0; + if(sample>2147483647.0) *out++ = 2147483647; + else if(sample<-2147483647.0) *out++ = -2147483647; + else *out++ = rintf(sample); + } + } + break; + case 24: /* how do we store 24 bit? Maybe sint32 is all we need? */ default: - ERROR("only 8 or 16 bits are supported for conversion!\n"); + ERROR("%i bits are not supported for conversion!\n", outFormat->bits); exit(EXIT_FAILURE); } - if(inFormat->channels != outFormat->channels) { - switch(inFormat->channels) { - case 1: - outSize = (outSize >> 1) << 2; - break; - case 2: - outSize >>= 1; - break; - } + return; +#endif +} + +size_t pcm_sizeOfOutputBufferForAudioFormatConversion(AudioFormat * inFormat, + size_t inSize, AudioFormat * outFormat) +{ +/* DEBUG */ + if(inSize % (inFormat->channels * 4)) { + ERROR("pcm_sizeOOBFAFC: inSize=%i not multipel of %i\n", + inSize, inFormat->channels * 4); } +/* /DEBUG */ + const int inShift = (inFormat->bits * inFormat->channels) >> 3; + const int outShift = (outFormat->bits * outFormat->channels) >> 3; + + size_t inFrames = inSize / inShift; + size_t outFrames = (inFrames * (mpd_uint32)(outFormat->sampleRate)) / + inFormat->sampleRate; + + size_t outSize = outFrames * outShift; - outSize = (((outSize / shift) * (mpd_uint32)(outFormat->sampleRate)) / - inFormat->sampleRate); - - outSize *= shift; - return outSize; } |