Ramp channel gains to remove pops and clicks from abrupt changes
Thanks to Christopher Fitzgerald for helping me work on it
This commit is contained in:
parent
f8ef66954c
commit
22557070ec
68
Alc/ALu.c
68
Alc/ALu.c
@ -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));
|
||||
@ -704,10 +714,9 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma
|
||||
|
||||
CalcSourceParams(ALContext, ALSource,
|
||||
(Channels==1) ? AL_TRUE : AL_FALSE,
|
||||
format, DrySend, WetSend, &Pitch,
|
||||
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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user