diff options
author | Warren Dukes <warren.dukes@gmail.com> | 2004-05-10 17:08:46 +0000 |
---|---|---|
committer | Warren Dukes <warren.dukes@gmail.com> | 2004-05-10 17:08:46 +0000 |
commit | 4f76ba5a427b27c9d354f2fca762eebacea5ee0c (patch) | |
tree | 96c41a85dc4b4db04b5c5a269979e4f5e7a87def | |
parent | 872af2077706da859b5a64c2e06bfd06de80387b (diff) | |
download | mpd-4f76ba5a427b27c9d354f2fca762eebacea5ee0c.tar.gz mpd-4f76ba5a427b27c9d354f2fca762eebacea5ee0c.tar.xz mpd-4f76ba5a427b27c9d354f2fca762eebacea5ee0c.zip |
format conversion for 8->16 bis and mono->stereo
git-svn-id: https://svn.musicpd.org/mpd/trunk@973 09075e82-0dd4-0310-85a5-a0d7c8717e4f
Diffstat (limited to '')
-rw-r--r-- | src/pcm_utils.c | 87 |
1 files changed, 75 insertions, 12 deletions
diff --git a/src/pcm_utils.c b/src/pcm_utils.c index 8ef431841..5465af65e 100644 --- a/src/pcm_utils.c +++ b/src/pcm_utils.c @@ -138,27 +138,92 @@ 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) { - /*int inSampleSize = inFormat->bits*inFormat->channels/8; - int outSampleSize = outFormat->bits*outFormat->channels/8;*/ + 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(inFormat->bits==16); assert(outFormat->bits==16); - assert(inFormat->channels==2); assert(outFormat->channels==2); - if(inFormat->sampleRate == outFormat->sampleRate) return; + /* converts */ + 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; + } + } + break; + case 16: + dataBitConv = inBuffer; + dataBitLen = inSize; + break; + case 24: + /* put dithering code from mp3_decode here */ + default: + ERROR("only 8 or 16 bits are supported for conversion!\n"); + exit(EXIT_FAILURE); + } - /* only works if outFormat is 16-bit stereo! */ - /* resampling code blatantly ripped from XMMS */ - { + /* converts only between 16 bit audio between mono and stereo */ + switch(inFormat->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 = dataChannelLen >> 1; + for(i=0;i<inSamples;i++) { + *out++ = *in; + *out++ = *in++; + } + } + break; + case 2: + dataChannelConv = dataBitConv; + dataChannelLen = dataBitLen; + break; + default: + ERROR("only 1 or 2 channels are supported for conversion!\n"); + exit(EXIT_FAILURE); + } + + if(inFormat->sampleRate == outFormat->sampleRate) { + memcpy(outBuffer,dataChannelConv,dataChannelLen); + } + else { + /* only works if outFormat is 16-bit stereo! */ + /* resampling code blatantly ripped from XMMS */ const int shift = sizeof(mpd_sint16); mpd_sint32 i, in_samples, out_samples, x, delta; - mpd_sint16 * inptr = (mpd_sint16 *)inBuffer; + mpd_sint16 * inptr = (mpd_sint16 *)dataChannelConv; mpd_sint16 * outptr = (mpd_sint16 *)outBuffer; - mpd_uint32 nlen = (((inSize >> shift) * + mpd_uint32 nlen = (((dataChannelLen >> shift) * (mpd_uint32)(outFormat->sampleRate)) / inFormat->sampleRate); nlen <<= shift; @@ -197,9 +262,7 @@ size_t pcm_sizeOfOutputBufferForAudioFormatConversion(AudioFormat * inFormat, nlen <<= shift; - assert(inFormat->bits==16); assert(outFormat->bits==16); - assert(inFormat->channels==2); assert(outFormat->channels==2); return nlen; |