diff options
-rw-r--r-- | src/audio.c | 16 | ||||
-rw-r--r-- | src/audio.h | 3 | ||||
-rw-r--r-- | src/audioOutput.c | 2 | ||||
-rw-r--r-- | src/inputPlugins/mp3_plugin.c | 47 | ||||
-rw-r--r-- | src/inputPlugins/mpc_plugin.c | 26 | ||||
-rw-r--r-- | src/mpd_types.h | 2 | ||||
-rw-r--r-- | src/pcm_utils.c | 596 | ||||
-rw-r--r-- | src/replayGain.c | 108 |
8 files changed, 291 insertions, 509 deletions
diff --git a/src/audio.c b/src/audio.c index 0fb2b3e2d..1bcd24de6 100644 --- a/src/audio.c +++ b/src/audio.c @@ -111,15 +111,9 @@ void getInternalAudioFormat(AudioFormat * inAudioFormat, /* take the input format... */ copyAudioFormat(outAudioFormat,inAudioFormat); -#ifdef MPD_FIXED_POINT - /* .. change to 16 bit integer */ - outAudioFormat->bits = 16; - outAudioFormat->floatSamples = 0; -#else - /* .. change to 32 bit float */ + /* .. change to 32 bit integers with 28 bit resolution */ outAudioFormat->bits = 32; - outAudioFormat->floatSamples = 1; -#endif + outAudioFormat->fracBits = 28; /* if forced output sample rate - use that as internal sample rate */ if(audio_configFormat && (audio_configFormat->sampleRate != 0)) outAudioFormat->sampleRate = audio_configFormat->sampleRate; @@ -132,7 +126,7 @@ void getOutputAudioFormat(AudioFormat * inAudioFormat, * for plugins who still use this we copy the format from in to out * these plugin don't know about the floatSample flag so we set it * for them - in both in and out */ - inAudioFormat->floatSamples = 0; + inAudioFormat->fracBits = 0; copyAudioFormat(outAudioFormat,inAudioFormat); } @@ -214,8 +208,8 @@ int parseAudioConfig(AudioFormat * audioFormat, char * conf) { return -1; } - /* audioFormat is never float */ - audioFormat->floatSamples = 0; + /* audioFormat is never shifted */ + audioFormat->fracBits = 0; return 0; } diff --git a/src/audio.h b/src/audio.h index 0cc879b28..518db0588 100644 --- a/src/audio.h +++ b/src/audio.h @@ -34,7 +34,8 @@ typedef struct _AudioFormat { volatile mpd_sint8 channels; volatile mpd_uint32 sampleRate; volatile mpd_sint8 bits; - volatile mpd_sint8 floatSamples; + volatile mpd_sint8 fracBits; + /*volatile mpd_sint8 floatSamples;*/ } AudioFormat; void copyAudioFormat(AudioFormat * dest, AudioFormat * src); diff --git a/src/audioOutput.c b/src/audioOutput.c index dcb264e45..fe4dd0ce9 100644 --- a/src/audioOutput.c +++ b/src/audioOutput.c @@ -164,7 +164,7 @@ int openAudioOutput(AudioOutput * audioOutput, AudioFormat * audioFormat) { &audioOutput->inAudioFormat); /* default to 16 bit integer samples */ audioOutput->outAudioFormat.bits = 16; - audioOutput->outAudioFormat.floatSamples = 0; + audioOutput->outAudioFormat.fracBits = 0; } ret = audioOutput->openDeviceFunc(audioOutput); diff --git a/src/inputPlugins/mp3_plugin.c b/src/inputPlugins/mp3_plugin.c index 471a173a1..15e69c385 100644 --- a/src/inputPlugins/mp3_plugin.c +++ b/src/inputPlugins/mp3_plugin.c @@ -57,7 +57,8 @@ #define MUTEFRAME_SEEK 2 /* this is stolen from mpg321! */ -struct audio_dither { + +/*struct audio_dither { mad_fixed_t error[3]; mad_fixed_t random; }; @@ -108,7 +109,7 @@ signed long audio_linear_dither(unsigned int bits, mad_fixed_t sample, struct au dither->error[0] = sample - output; return output >> scalebits; -} +}*/ /* end of stolen stuff from mpg321 */ /* decoder stuff is based on madlld */ @@ -135,7 +136,7 @@ typedef struct _mp3DecodeData { int flush; unsigned long bitRate; InputStream * inStream; - struct audio_dither dither; + /*struct audio_dither dither;*/ } mp3DecodeData; void initMp3DecodeData(mp3DecodeData * data, InputStream * inStream) { @@ -149,7 +150,7 @@ void initMp3DecodeData(mp3DecodeData * data, InputStream * inStream) { data->currentFrame = 0; data->flush = 1; data->inStream = inStream; - memset(&(data->dither), 0, sizeof(struct audio_dither)); +/* memset(&(data->dither), 0, sizeof(struct audio_dither));*/ mad_stream_init(&data->stream); data->stream.options |= MAD_OPTION_IGNORECRC; @@ -566,35 +567,18 @@ int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc) { } for(i=0;i<(data->synth).pcm.length;i++) { -#ifdef MPD_FIXED_POINT - mpd_sint16 * sample; - sample = (mpd_sint16 *)data->outputPtr; - *sample = (mpd_sint16) audio_linear_dither(16, - (data->synth).pcm.samples[0][i], - &(data->dither)); - data->outputPtr+=2; - - if(MAD_NCHANNELS(&(data->frame).header)==2) { - sample = (mpd_sint16 *)data->outputPtr; - *sample = (mpd_sint16) audio_linear_dither(16, - (data->synth).pcm.samples[1][i], - &(data->dither)); - data->outputPtr+=2; - } -#else - mpd_float32 * sample; - sample = (mpd_float32 *)data->outputPtr; - *sample = (mpd_float32) mad_f_todouble( - (data->synth).pcm.samples[0][i]); + mpd_fixed_t * sample; + sample = (mpd_fixed_t *)data->outputPtr; + *sample = (mpd_fixed_t) + ((data->synth).pcm.samples[0][i]); data->outputPtr+=4; if(MAD_NCHANNELS(&(data->frame).header)==2) { - sample = (mpd_sint16 *)data->outputPtr; - *sample = (mpd_float32) mad_f_todouble( - (data->synth).pcm.samples[0][i]); + sample = (mpd_fixed_t *)data->outputPtr; + *sample = (mpd_fixed_t) + ((data->synth).pcm.samples[0][i]); data->outputPtr+=4; } -#endif if(data->outputPtr>=data->outputBufferEnd) { long ret; @@ -667,13 +651,8 @@ int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc) { } void initAudioFormatFromMp3DecodeData(mp3DecodeData * data, AudioFormat * af) { -#ifdef MPD_FIXED_POINT - af->bits = 16; - af->floatSamples = 0; -#else af->bits = 32; - af->floatSamples = 1; -#endif + af->fracBits = MAD_F_FRACBITS; af->sampleRate = (data->frame).header.samplerate; af->channels = MAD_NCHANNELS(&(data->frame).header); } diff --git a/src/inputPlugins/mpc_plugin.c b/src/inputPlugins/mpc_plugin.c index 107792125..799664f2c 100644 --- a/src/inputPlugins/mpc_plugin.c +++ b/src/inputPlugins/mpc_plugin.c @@ -82,17 +82,14 @@ static mpc_int32_t mpc_getsize_cb(void * vdata) { return data->inStream->size; } -inline mpd_sint16 convertSample(MPC_SAMPLE_FORMAT sample) { +inline mpd_fixed_t convertSample(MPC_SAMPLE_FORMAT sample) { /* only doing 16-bit audio for now */ mpd_sint32 val; - const int clip_min = -1 << (16 - 1); - const int clip_max = (1 << (16 - 1)) - 1; - #ifdef MPC_FIXED_POINT - const int shift = 16 - MPC_FIXED_POINT_SCALE_SHIFT; + const int shift = 28 - MPC_FIXED_POINT_SCALE_SHIFT; - if( ssample > 0 ) { + if( shift > 0 ) { sample <<= shift; } else if ( shift < 0 ) { @@ -100,15 +97,12 @@ inline mpd_sint16 convertSample(MPC_SAMPLE_FORMAT sample) { } val = sample; #else - const int float_scale = 1 << (16 - 1); + const mpd_sint32 float_scale = 1L << 28; val = sample * float_scale; #endif - - if( val < clip_min) val = clip_min; - else if ( val > clip_max ) val = clip_max; - return val; + } static int mpc_decode(OutputBuffer * cb, DecoderControl * dc, @@ -129,7 +123,7 @@ static int mpc_decode(OutputBuffer * cb, DecoderControl * dc, int chunkpos = 0; long bitRate = 0; mpd_sint16 * s16 = (mpd_sint16 *) chunk; - float * f32 = (float *) chunk; + mpd_fixed_t * s32 = (mpd_fixed_t *) chunk; unsigned long samplePos = 0; mpc_uint32_t vbrUpdateAcc; mpc_uint32_t vbrUpdateBits; @@ -178,7 +172,7 @@ static int mpc_decode(OutputBuffer * cb, DecoderControl * dc, dc->totalTime = mpc_streaminfo_get_length(&info); dc->audioFormat.bits = 32; - dc->audioFormat.floatSamples = 1; + dc->audioFormat.fracBits = 28; dc->audioFormat.channels = info.channels; dc->audioFormat.sampleRate = info.sample_freq; @@ -221,9 +215,9 @@ static int mpc_decode(OutputBuffer * cb, DecoderControl * dc, chunkpos += 2; s16++; */ - *f32 = (float)(sample_buffer[i]); + *s32 = convertSample(sample_buffer[i]); chunkpos += 4; - f32++; + s32++; if(chunkpos >= MPC_CHUNK_SIZE) { time = ((float)samplePos) / @@ -242,7 +236,7 @@ static int mpc_decode(OutputBuffer * cb, DecoderControl * dc, chunkpos = 0; s16 = (mpd_sint16 *)chunk; - f32 = (float*)chunk; + s32 = (mpd_fixed_t *)chunk; if(dc->stop) { eof = 1; break; diff --git a/src/mpd_types.h b/src/mpd_types.h index 1ef87afd8..01182527e 100644 --- a/src/mpd_types.h +++ b/src/mpd_types.h @@ -40,6 +40,6 @@ typedef unsigned long mpd_uint32; typedef signed long mpd_sint32; #endif -typedef float mpd_float32; +typedef mpd_sint32 mpd_fixed_t; #endif diff --git a/src/pcm_utils.c b/src/pcm_utils.c index bfb11e3ff..8341272e7 100644 --- a/src/pcm_utils.c +++ b/src/pcm_utils.c @@ -28,278 +28,34 @@ #include <assert.h> #include <time.h> -void pcm_changeBufferEndianness(char * buffer, int bufferSize, int bits) { - -ERROR("pcm_changeBufferEndianess\n"); - switch(bits) { - case 16: - while(bufferSize) { - 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) -{ -#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; - - if(volume<=0) { - memset(buffer,0,bufferSize); - 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) { - float sample = *buffer16 * fvolume; - *buffer16++ = rintf(sample); - bufferSize-=2; - } - break; - case 8: - while(bufferSize) { - float sample = *buffer8 * fvolume; - *buffer8++ = rintf(sample); - bufferSize--; - } - break; - default: - ERROR("%i bits not supported by pcm_volumeChange!\n", - 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) -{ -#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 && 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) memcpy(buffer16_1,buffer16_2,bufferSize2); - break; - case 8: - 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) 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, - size_t bufferSize2, AudioFormat * format, float portion1) -{ - int vol1; - float s = sin(M_PI_2*portion1); - s*=s; - - vol1 = s*1000+0.5; - vol1 = vol1>1000 ? 1000 : ( vol1<0 ? 0 : vol1 ); - - pcm_add(buffer1,buffer2,bufferSize1,bufferSize2,vol1,1000-vol1,format); -} - -void pcm_convertToFloat(AudioFormat * inFormat, char * inBuffer, size_t - samples, char * outBuffer) +void pcm_convertToMpdFixed(AudioFormat * inFormat, char * inBuffer, int + samples, char * outBuffer, int fracBits) { mpd_sint8 * in8 = (mpd_sint8 *)inBuffer; mpd_sint16 * in16 = (mpd_sint16 *)inBuffer; mpd_sint32 * in32 = (mpd_sint32 *)inBuffer; - float * out = (float *)outBuffer; - float multiplier; - + mpd_fixed_t * out = (mpd_fixed_t *)outBuffer; + int shift; + switch(inFormat->bits) { case 8: - multiplier = 1.0 / 128.0; + shift = fracBits - 8; while(samples--) { - *out++ = (*in8++) * multiplier; + *out++ = (mpd_fixed_t)(*in8++) << shift; } break; case 16: - multiplier = 1.0 / 32768.0; + shift = fracBits - 16; while(samples--) { - *out++ = (*in16++) * multiplier; + *out++ = (mpd_fixed_t)(*in16++) << shift; } break; -/* case 32: - multiplier = 1.0 / (1L << 31); + case 32: + shift = 32 - fracBits; while(samples--) { - *out++ = (*in32++) * multiplier; + *out++ = (mpd_fixed_t)(*in32++) >> shift; } - break; */ + break; default: ERROR("%i bit samples are not supported for conversion!\n", inFormat->bits); @@ -307,12 +63,43 @@ void pcm_convertToFloat(AudioFormat * inFormat, char * inBuffer, size_t } } +/* this is stolen from mpg321! */ +inline mpd_uint32 prng(mpd_uint32 state) { + return (state * 0x0019660dL + 0x3c6ef35fL) & 0xffffffffL; +} +/* end of stolen stuff from mpg321 */ + +void pcm_convertToIntWithDither(int bits, + mpd_fixed_t *buffer, int samples, int fracBits) +{ + static mpd_uint32 ditherRandom = 0; + mpd_fixed_t mask = ~(~0L << (fracBits - bits)); + mpd_fixed_t max = (1L << (fracBits)) - 1; + mpd_fixed_t min = ~0L << (fracBits); + mpd_fixed_t sample; +ERROR("conv: max=%x, min=%x \n", max, min); +//buffer += samples - 25; +//samples = 20; + while(samples--) { +//ERROR("*buffer=%x, mask=%x\n", *buffer, mask); + sample = *buffer + (ditherRandom & mask); + if(sample > max || sample < min) + ERROR("clipping! %x\n", sample); + sample = sample>max ? max : (sample<min ? min : sample); + *buffer = sample >> (fracBits - bits + 1); +//ERROR("sample=%x, *buffer=%x, dither=%x\n", sample, *buffer, ditherRandom & mask); + buffer++; + ditherRandom = prng(ditherRandom); + } +//exit(EXIT_FAILURE); +} + -char *pcm_convertSampleRate(AudioFormat *inFormat, char *inBuffer, size_t inFrames, - AudioFormat *outFormat, size_t outFrames) +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 */ + /* Interpolate using a second order polynomial */ /* k0 = s0 * * k2 = (s0 - 2*s1 + s2) * 0.5 * * k1 = s1 - s0 - k2 * @@ -447,66 +234,149 @@ char *pcm_convertSampleRate(AudioFormat *inFormat, char *inBuffer, size_t inFram return (char *)sampleConvBuffer; } +/****** exported procedures ***************************************************/ -/* 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); +void pcm_changeBufferEndianness(char * buffer, int bufferSize, int bits) { + +ERROR("pcm_changeBufferEndianess\n"); + switch(bits) { + case 16: + while(bufferSize) { + mpd_uint8 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) { + mpd_uint8 temp = *buffer; + mpd_uint8 temp1 = *(buffer+1); + *buffer = *(buffer+3); + *(buffer+1) = *(buffer+2); + *(buffer+2) = temp1; + *(buffer+3) = temp; + bufferSize-=4; + } + break; } - if(inFormat->sampleRate || outFormat->sampleRate) { - ERROR("Sample rate conversions not supported in fixed point mode!\n"); +} + +void pcm_volumeChange(char * buffer, int bufferSize, AudioFormat * format, + int volume) +{ + mpd_fixed_t * buffer32 = (mpd_fixed_t *)buffer; + int iScale; + int samples; + int shift; + + if(format->bits!=32 || format->channels!=2) { + ERROR("Only 32 bit stereo is supported for pcm_volumeChange!\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 */ - } + + /* take care of full and no volume cases */ + if(volume>=1000) return; + + if(volume<=0) { + memset(buffer,0,bufferSize); + return; } - 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 */ - } + + /****** change volume ******/ + samples = bufferSize >> 2; + iScale = (mpd_uint32)(volume * 256) / 1000; + shift = 8; + +ERROR("vol1: iScale=%i, shift=%i, volume=%i\n", iScale, shift, volume); + /* lower shifting value as much as possible */ + while(!(iScale & 1) && shift) { + iScale >>= 1; + shift--; + } +ERROR("vol2: iScale=%i, shift=%i\n", iScale, shift); + /* change */ + if(iScale == 1) { + while(samples--) + *buffer32++ = *buffer32 >> shift; } else { - ERROR("More then 2 channels are not supported!\n"); + while(samples--) + *buffer32++ = (*buffer32 >> shift) * iScale; + } + +} + +void pcm_add(char * buffer1, char * buffer2, size_t bufferSize1, + size_t bufferSize2, int vol1, int vol2, AudioFormat * format) +{ + mpd_fixed_t * buffer32_1 = (mpd_fixed_t *)buffer1; + mpd_fixed_t * buffer32_2 = (mpd_fixed_t *)buffer2; + mpd_fixed_t temp; + int samples1; + int samples2; + int iScale1; + int iScale2; + int shift; + + if(format->bits!=32 || format->channels!=2 ) { + ERROR("Only 32 bit stereo is supported for pcm_add!\n"); exit(EXIT_FAILURE); } + + samples1 = bufferSize1 >> 2; + samples2 = bufferSize1 >> 2; + iScale1 = (mpd_uint32)(vol1 * 256) / 1000; + iScale2 = (mpd_uint32)(vol2 * 256) / 1000; + shift = 8; + + /* scale and add samples */ + /* no check for overflow needed - we trust our headroom is enough */ + while(samples1 && samples2) { + *buffer32_1++ = (*buffer32_1 >> shift) * iScale1 + + (*buffer32_2 >> shift) * iScale2; + } + /* take care of case where buffer2 > buffer1 */ + if(samples2) memcpy(buffer32_1,buffer32_2,samples2<<2); return; + +} + +void pcm_mix(char * buffer1, char * buffer2, size_t bufferSize1, + size_t bufferSize2, AudioFormat * format, float portion1) +{ + int vol1; + float s = sin(M_PI_2*portion1); + s*=s; -#else -/* DEBUG */ - if(inSize % (inFormat->channels * 4)) { - ERROR("pcm_convertAudioFormat: inSize=%i not multipel of %i\n", - inSize, inFormat->channels * 4); - } -/* /DEBUG */ + vol1 = s*1000+0.5; + vol1 = vol1>1000 ? 1000 : ( vol1<0 ? 0 : vol1 ); + + pcm_add(buffer1,buffer2,bufferSize1,bufferSize2,vol1,1000-vol1,format); +} + +void pcm_convertAudioFormat(AudioFormat * inFormat, char * inBuffer, size_t + inSize, AudioFormat * outFormat, char * outBuffer) +{ 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)) / + int fracBits; + const int inSamples = (inSize << 3) / inFormat->bits; + const int inFrames = inSamples / inFormat->channels; + const int 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 */ + const int outSamples = outFrames * outFormat->channels; + +ERROR("0 inSamples=%i in:bits=%i, fracBits=%i\n", + inSamples, inFormat->bits, inFormat->fracBits); +ERROR(" out:bits=%i, fracBits=%i\n", + outFormat->bits, outFormat->fracBits); + /* make sure convBuffer is big enough for 2 channels of 32 bit samples */ dataLen = inFrames << 3; if(dataLen > convBufferLength) { convBuffer = (char *) realloc(convBuffer, dataLen); @@ -518,28 +388,28 @@ void pcm_convertAudioFormat(AudioFormat * inFormat, char * inBuffer, size_t convBufferLength = dataLen; } - /* make sure dataConv points to 32 bit float samples */ - if(inFormat->floatSamples && inFormat->bits==32) { + /* make sure dataConv points to mpd_fixed_t samples */ + if(inFormat->fracBits && inFormat->bits==32) { + fracBits = inFormat->fracBits; 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); + fracBits = 28; /* use 28 bits as default */ + dataConv = convBuffer; + pcm_convertToMpdFixed(inFormat, inBuffer, inSamples, + dataConv, fracBits); } - /* convert between mono and stereo samples*/ + /****** 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: { - float *out = ((float *)convBuffer)+(inFrames<<1); + /* 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; while(f--) { *out-- = *in; @@ -550,11 +420,12 @@ void pcm_convertAudioFormat(AudioFormat * inFormat, char * inBuffer, size_t /* convert from 2 -> 1 channels */ case 2: { - float * out = (float *)convBuffer; + mpd_fixed_t *in = ((mpd_fixed_t *)dataConv); + mpd_fixed_t *out = ((mpd_fixed_t *)convBuffer); int f = inFrames; while(f--) { - *out = (*in++)*0.5; - *out++ += (*in++)*0.5; + *out = (*in++)>>1; + *out++ += (*in++)>>1; } } break; @@ -565,89 +436,75 @@ void pcm_convertAudioFormat(AudioFormat * inFormat, char * inBuffer, size_t dataConv = convBuffer; } - /* convert sample rate */ + /****** convert sample rate ******/ + if(inFormat->sampleRate != outFormat->sampleRate) { dataConv = pcm_convertSampleRate( inFormat, dataConv, inFrames, outFormat, outFrames); } - /* convert to output format */ - if(outFormat->floatSamples && outFormat->bits==32) { - if(outBuffer != dataConv) - memcpy(outBuffer, dataConv, outSamples << 2); - return; - } - else if(outFormat->floatSamples) { - ERROR("%i bit float are not supported for conversion!\n", + /****** convert to output format ******/ + + /* if outformat is mpd_fixed_t then we are done TODO */ + if(outFormat->fracBits) { + if(outFormat->bits==32) { + if(outBuffer != dataConv) + memcpy(outBuffer, dataConv, outSamples << 2); + return; + } + else { + ERROR("%i bit float are not supported for conversion!\n", outFormat->bits); - exit(EXIT_FAILURE); + exit(EXIT_FAILURE); + } } + /* convert to regular integer while adding dither and checking range */ + pcm_convertToIntWithDither(outFormat->bits, + (mpd_fixed_t *)dataConv, outSamples, fracBits); + + /* copy to output buffer*/ switch(outFormat->bits) { case 8: { - /* 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)); - } + mpd_fixed_t *in = (mpd_fixed_t *)dataConv; + mpd_sint8 * out = (mpd_sint8 *)outBuffer; + int s = outSamples; + while(s--) + *out++ = *in++; } 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)); - } + mpd_fixed_t *in = (mpd_fixed_t *)dataConv; + mpd_sint16 *out = (mpd_sint16 *)outBuffer; + int s = outSamples; + while(s--) + *out++ = *in++; } 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); - } + mpd_fixed_t *in = (mpd_fixed_t *)dataConv; + mpd_sint32 *out = (mpd_sint32 *)outBuffer; + int s = outSamples; + while(s--) + *out++ = *in++; } break; - case 24: /* how do we store 24 bit? Maybe sint32 is all we need? */ + case 24: /* TODO! how do we store 24 bit? */ default: ERROR("%i bits are not supported for conversion!\n", outFormat->bits); exit(EXIT_FAILURE); } 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; @@ -659,3 +516,6 @@ size_t pcm_sizeOfOutputBufferForAudioFormatConversion(AudioFormat * inFormat, return outSize; } + + + diff --git a/src/replayGain.c b/src/replayGain.c index f052c68bc..aac057668 100644 --- a/src/replayGain.c +++ b/src/replayGain.c @@ -107,20 +107,19 @@ void freeReplayGainInfo(ReplayGainInfo * info) { void doReplayGain(ReplayGainInfo * info, char * buffer, int bufferSize, AudioFormat * format) { - float * bufferFloat = (float *)buffer; mpd_sint32 * buffer32 = (mpd_sint32 *)buffer; - mpd_sint16 * buffer16 = (mpd_sint16 *)buffer; - mpd_sint8 * buffer8 = (mpd_sint8 *)buffer; - float scale; - mpd_sint32 iScale; + int samples; + int shift; + int iScale; + if(format->bits!=32 || format->channels!=2 ) { + ERROR("Only 32 bit stereo is supported for doReplayGain!\n"); + exit(EXIT_FAILURE); + return; + } + if(replayGainState == REPLAYGAIN_OFF || !info) return; -/* DEBUG */ - if(bufferSize % (format->channels * 4)) - ERROR("doReplayGain: bufferSize=%i not multipel of %i\n", - bufferSize, format->channels); -/* /DEBUG */ if(info->scale < 0) { switch(replayGainState) { case REPLAYGAIN_TRACK: @@ -133,79 +132,34 @@ void doReplayGain(ReplayGainInfo * info, char * buffer, int bufferSize, break; } } - -#ifdef MPD_FIXED_POINT - if(format->bits!=16 || format.channels!=2 || format->floatSamples) { - ERROR("Only 16 bit stereo is supported in fixed point mode!\n"); - exit(EXIT_FAILURE); - } - /* If the volume change is very small then we hardly here the - * difference anyway, and if the change is positiv then clipping - * may occur. We don't want that. */ - if(info->scale > 0.99) return; + samples = bufferSize >> 2; + iScale = info->scale * 256; + shift = 8; - iScale = scale * 32768.0; /* << 15 */ - while(bufferSize) { - sample32 = (mpd_sint32)(*buffer16) * iScale; - /* no need to check boundaries - we only lower the volume*/ - /* It would be good to add some kind of dither here... TODO?! */ - *buffer16 = (sample32 >> 15); - bufferSize -= 2; + /* handle negative or zero scale */ + if(iScale<=0) { + memset(buffer,0,bufferSize); + return; } - return; -#else - - scale = info->scale; - if(format->floatSamples) { - if(format->bits==32) { - while(bufferSize) { - *bufferFloat *= scale; - bufferFloat++; - bufferSize-=4; - } - return; - } - else { - ERROR("%i bit float not supported by doReplaygain!\n", - format->bits); - exit(EXIT_FAILURE); - } + /* lower shift value as much as possible */ + while(!(iScale & 1) && shift) { + iScale >>= 1; + shift--; } - switch(format->bits) { - case 32: - while(bufferSize) { - double sample = (double)(*buffer32) * scale; - if(sample>2147483647.0) *buffer32 = 2147483647; - else if(sample<-2147483647.0) *buffer32 = -2147483647; - else *buffer32 = rintf(sample); - *buffer32++; - bufferSize-=4; - } - break; - case 16: - while(bufferSize){ - float sample = *buffer16 * scale; - *buffer16 = sample>32767.0 ? 32767 : - (sample<-32768.0 ? -32768 : rintf(sample)); - buffer16++; - bufferSize-=2; - } - break; - case 8: - while(bufferSize){ - float sample = *buffer8 * scale; - *buffer8 = sample>127.0 ? 127 : - (sample<-128.0 ? -128 : rintf(sample)); - buffer8++; - bufferSize--; - } - break; - default: - ERROR("%i bits not supported by doReplaygain!\n", format->bits); + /* change samples */ + /* no check for overflow needed - replaygain peak info prevent + * clipping and we have 3 headroom bits in our 32 bit samples */ + if(iScale == 1) { + while(samples--) + *buffer32++ = *buffer32 >> shift; } -#endif + else { + while(samples--) + *buffer32++ = (*buffer32 >> shift) * iScale; + } + } |