diff options
author | Chris Robinson <[email protected]> | 2008-08-14 05:43:52 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2008-08-14 05:43:52 -0700 |
commit | 22557070ec4852d64ad153f5cac907f84119702c (patch) | |
tree | 5ef3211350145257afdd1642699a206da89d8bfe /Alc | |
parent | f8ef66954c4cd95a8c91a458b33a8e8318a72d5b (diff) |
Ramp channel gains to remove pops and clicks from abrupt changes
Thanks to Christopher Fitzgerald for helping me work on it
Diffstat (limited to 'Alc')
-rw-r--r-- | Alc/ALu.c | 72 |
1 files changed, 52 insertions, 20 deletions
@@ -31,6 +31,7 @@ #include "alThunk.h" #include "alListener.h" #include "alAuxEffectSlot.h" +#include "alu.h" #include "bs2b.h" #if defined(HAVE_STDINT_H) @@ -69,18 +70,9 @@ typedef long long ALint64; #define FRACTIONMASK ((1L<<FRACTIONBITS)-1) #define MAX_PITCH 4 -enum { - FRONT_LEFT = 0, - FRONT_RIGHT, - SIDE_LEFT, - SIDE_RIGHT, - BACK_LEFT, - BACK_RIGHT, - CENTER, - LFE, - - OUTPUTCHANNELS -}; +/* Minimum ramp length in milliseconds. The value below was chosen to + * adequately reduce clicks and pops from harsh gain changes. */ +#define MIN_RAMP_LENGTH 16 ALboolean DuplicateStereo = AL_FALSE; @@ -628,10 +620,17 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma { static float DryBuffer[BUFFERSIZE][OUTPUTCHANNELS]; static float WetBuffer[BUFFERSIZE][OUTPUTCHANNELS]; - ALfloat DrySend[OUTPUTCHANNELS] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; - ALfloat WetSend[OUTPUTCHANNELS] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + ALfloat newDrySend[OUTPUTCHANNELS] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + ALfloat newWetSend[OUTPUTCHANNELS] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; ALfloat DryGainHF = 0.0f; ALfloat WetGainHF = 0.0f; + ALfloat *DrySend; + ALfloat *WetSend; + ALuint rampLength; + ALfloat dryGainStep[OUTPUTCHANNELS]; + ALfloat wetGainStep[OUTPUTCHANNELS]; + ALfloat dryGainHFStep; + ALfloat wetGainHFStep; ALuint BlockAlign,BufferSize; ALuint DataSize=0,DataPosInt=0,DataPosFrac=0; ALuint Channels,Frequency,ulExtraSamples; @@ -672,9 +671,20 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma while(size > 0) { //Setup variables - ALEffectSlot = (ALContext ? ALContext->AuxiliaryEffectSlot : NULL); - ALSource = (ALContext ? ALContext->Source : NULL); SamplesToDo = min(size, BUFFERSIZE); + if(ALContext) + { + ALEffectSlot = ALContext->AuxiliaryEffectSlot; + ALSource = ALContext->Source; + rampLength = ALContext->Frequency * MIN_RAMP_LENGTH / 1000; + } + else + { + ALEffectSlot = NULL; + ALSource = NULL; + rampLength = 0; + } + rampLength = max(rampLength, SamplesToDo); //Clear mixing buffer memset(DryBuffer, 0, SamplesToDo*OUTPUTCHANNELS*sizeof(ALfloat)); @@ -703,10 +713,9 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma Frequency = ALBuffer->frequency; CalcSourceParams(ALContext, ALSource, - (Channels==1) ? AL_TRUE : AL_FALSE, - format, DrySend, WetSend, &Pitch, - &DryGainHF, &WetGainHF); - + (Channels==1) ? AL_TRUE : AL_FALSE, + format, newDrySend, newWetSend, &Pitch, + &DryGainHF, &WetGainHF); Pitch = (Pitch*Frequency) / ALContext->Frequency; DataSize /= Channels * aluBytesFromFormat(ALBuffer->format); @@ -715,6 +724,19 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma DataPosInt = ALSource->position; DataPosFrac = ALSource->position_fraction; Filter = &ALSource->iirFilter; + DrySend = ALSource->DryGains; + WetSend = ALSource->WetGains; + + //Compute the gain steps for each output channel + for(i = 0;i < OUTPUTCHANNELS;i++) + { + dryGainStep[i] = (newDrySend[i]-DrySend[i]) / rampLength; + wetGainStep[i] = (newWetSend[i]-WetSend[i]) / rampLength; + } + dryGainHFStep = (DryGainHF-ALSource->DryGainHF) / rampLength; + wetGainHFStep = (WetGainHF-ALSource->WetGainHF) / rampLength; + DryGainHF = ALSource->DryGainHF; + WetGainHF = ALSource->WetGainHF; //Compute 18.14 fixed point step increment = (ALint)(Pitch*(ALfloat)(1L<<FRACTIONBITS)); @@ -767,6 +789,14 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma k = DataPosFrac>>FRACTIONBITS; fraction = DataPosFrac&FRACTIONMASK; + for(i = 0;i < OUTPUTCHANNELS;i++) + { + DrySend[i] += dryGainStep[i]; + WetSend[i] += wetGainStep[i]; + } + DryGainHF += dryGainHFStep; + WetGainHF += wetGainHFStep; + if(Channels==1) { ALfloat sample, lowsamp, outsamp; @@ -872,6 +902,8 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma //Update source info ALSource->position = DataPosInt; ALSource->position_fraction = DataPosFrac; + ALSource->DryGainHF = DryGainHF; + ALSource->WetGainHF = WetGainHF; } //Handle looping sources |