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 | |
parent | f8ef66954c4cd95a8c91a458b33a8e8318a72d5b (diff) |
Ramp channel gains to remove pops and clicks from abrupt changes
Thanks to Christopher Fitzgerald for helping me work on it
-rw-r--r-- | Alc/ALu.c | 72 | ||||
-rw-r--r-- | OpenAL32/Include/alSource.h | 7 | ||||
-rw-r--r-- | OpenAL32/Include/alu.h | 13 |
3 files changed, 72 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 diff --git a/OpenAL32/Include/alSource.h b/OpenAL32/Include/alSource.h index 73b02609..42a1b915 100644 --- a/OpenAL32/Include/alSource.h +++ b/OpenAL32/Include/alSource.h @@ -7,6 +7,7 @@ #define MAX_SENDS 1 #include "alFilter.h" +#include "alu.h" #include "AL/al.h" #define AL_DIRECT_FILTER 0x20005 @@ -94,6 +95,12 @@ typedef struct ALsource // Source Type (Static, Streaming, or Undetermined) ALint lSourceType; + // Current gains, which are ramped while mixed + ALfloat DryGains[OUTPUTCHANNELS]; + ALfloat WetGains[OUTPUTCHANNELS]; + ALfloat DryGainHF; + ALfloat WetGainHF; + struct ALsource *next; } ALsource; diff --git a/OpenAL32/Include/alu.h b/OpenAL32/Include/alu.h index 6fab1fae..b14180b2 100644 --- a/OpenAL32/Include/alu.h +++ b/OpenAL32/Include/alu.h @@ -8,6 +8,19 @@ extern "C" { #endif +enum { + FRONT_LEFT = 0, + FRONT_RIGHT, + SIDE_LEFT, + SIDE_RIGHT, + BACK_LEFT, + BACK_RIGHT, + CENTER, + LFE, + + OUTPUTCHANNELS +}; + extern ALboolean DuplicateStereo; __inline ALuint aluBytesFromFormat(ALenum format); |