static ALvoid EchoUpdate(ALeffectState *effect, ALCdevice *Device, const ALeffectslot *Slot) { ALechoState *state = (ALechoState*)effect; ALuint frequency = Device->Frequency; ALfloat lrpan, cw, g, gain; ALfloat dirGain; ALuint i; state->Tap[0].delay = fastf2u(Slot->effect.Echo.Delay * frequency) + 1; state->Tap[1].delay = fastf2u(Slot->effect.Echo.LRDelay * frequency); state->Tap[1].delay += state->Tap[0].delay; lrpan = Slot->effect.Echo.Spread; state->FeedGain = Slot->effect.Echo.Feedback; cw = aluCos(F_PI*2.0f * LOWPASSFREQREF / frequency); g = 1.0f - Slot->effect.Echo.Damping; state->iirFilter.coeff = lpCoeffCalc(g, cw); gain = Slot->Gain; for(i = 0;i < MAXCHANNELS;i++) { state->Gain[0][i] = 0.0f; state->Gain[1][i] = 0.0f; } dirGain = aluFabs(lrpan); /* First tap panning */ ComputeAngleGains(Device, aluAtan2(-lrpan, 0.0f), (1.0f-dirGain)*F_PI, gain, state->Gain[0]); /* Second tap panning */ ComputeAngleGains(Device, aluAtan2(+lrpan, 0.0f), (1.0f-dirGain)*F_PI, gain, state->Gain[1]); }
static ALvoid ALchorusState_update(ALchorusState *state, ALCdevice *Device, const ALeffectslot *Slot) { ALfloat frequency = (ALfloat)Device->Frequency; ALfloat rate; ALint phase; switch(Slot->EffectProps.Chorus.Waveform) { case AL_CHORUS_WAVEFORM_TRIANGLE: state->waveform = CWF_Triangle; break; case AL_CHORUS_WAVEFORM_SINUSOID: state->waveform = CWF_Sinusoid; break; } state->depth = Slot->EffectProps.Chorus.Depth; state->feedback = Slot->EffectProps.Chorus.Feedback; state->delay = fastf2i(Slot->EffectProps.Chorus.Delay * frequency); /* Gains for left and right sides */ ComputeAngleGains(Device, atan2f(-1.0f, 0.0f), 0.0f, Slot->Gain, state->Gain[0]); ComputeAngleGains(Device, atan2f(+1.0f, 0.0f), 0.0f, Slot->Gain, state->Gain[1]); phase = Slot->EffectProps.Chorus.Phase; rate = Slot->EffectProps.Chorus.Rate; if(!(rate > 0.0f)) { state->lfo_scale = 0.0f; state->lfo_range = 1; state->lfo_disp = 0; } else { /* Calculate LFO coefficient */ state->lfo_range = fastf2u(frequency/rate + 0.5f); switch(state->waveform) { case CWF_Triangle: state->lfo_scale = 4.0f / state->lfo_range; break; case CWF_Sinusoid: state->lfo_scale = F_2PI / state->lfo_range; break; } /* Calculate lfo phase displacement */ state->lfo_disp = fastf2i(state->lfo_range * (phase/360.0f)); } }
static ALvoid ALdedicatedState_update(ALdedicatedState *state, ALCdevice *device, const ALeffectslot *Slot) { ALfloat Gain; ALsizei s; Gain = Slot->Gain * Slot->EffectProps.Dedicated.Gain; if(Slot->EffectType == AL_EFFECT_DEDICATED_DIALOGUE) ComputeAngleGains(device, atan2f(0.0f, 1.0f), 0.0f, Gain, state->gains); else if(Slot->EffectType == AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT) { for(s = 0;s < MaxChannels;s++) state->gains[s] = 0.0f; state->gains[LFE] = Gain; } }
ALvoid CalcNonAttnSourceParams(ALvoice *voice, const ALsource *ALSource, const ALCcontext *ALContext) { static const struct ChanMap MonoMap[1] = { { FrontCenter, 0.0f, 0.0f } }, StereoMap[2] = { { FrontLeft, DEG2RAD(-30.0f), DEG2RAD(0.0f) }, { FrontRight, DEG2RAD( 30.0f), DEG2RAD(0.0f) } }, StereoWideMap[2] = { { FrontLeft, DEG2RAD(-90.0f), DEG2RAD(0.0f) }, { FrontRight, DEG2RAD( 90.0f), DEG2RAD(0.0f) } }, RearMap[2] = { { BackLeft, DEG2RAD(-150.0f), DEG2RAD(0.0f) }, { BackRight, DEG2RAD( 150.0f), DEG2RAD(0.0f) } }, QuadMap[4] = { { FrontLeft, DEG2RAD( -45.0f), DEG2RAD(0.0f) }, { FrontRight, DEG2RAD( 45.0f), DEG2RAD(0.0f) }, { BackLeft, DEG2RAD(-135.0f), DEG2RAD(0.0f) }, { BackRight, DEG2RAD( 135.0f), DEG2RAD(0.0f) } }, X51Map[6] = { { FrontLeft, DEG2RAD( -30.0f), DEG2RAD(0.0f) }, { FrontRight, DEG2RAD( 30.0f), DEG2RAD(0.0f) }, { FrontCenter, DEG2RAD( 0.0f), DEG2RAD(0.0f) }, { LFE, 0.0f, 0.0f }, { SideLeft, DEG2RAD(-110.0f), DEG2RAD(0.0f) }, { SideRight, DEG2RAD( 110.0f), DEG2RAD(0.0f) } }, X61Map[7] = { { FrontLeft, DEG2RAD(-30.0f), DEG2RAD(0.0f) }, { FrontRight, DEG2RAD( 30.0f), DEG2RAD(0.0f) }, { FrontCenter, DEG2RAD( 0.0f), DEG2RAD(0.0f) }, { LFE, 0.0f, 0.0f }, { BackCenter, DEG2RAD(180.0f), DEG2RAD(0.0f) }, { SideLeft, DEG2RAD(-90.0f), DEG2RAD(0.0f) }, { SideRight, DEG2RAD( 90.0f), DEG2RAD(0.0f) } }, X71Map[8] = { { FrontLeft, DEG2RAD( -30.0f), DEG2RAD(0.0f) }, { FrontRight, DEG2RAD( 30.0f), DEG2RAD(0.0f) }, { FrontCenter, DEG2RAD( 0.0f), DEG2RAD(0.0f) }, { LFE, 0.0f, 0.0f }, { BackLeft, DEG2RAD(-150.0f), DEG2RAD(0.0f) }, { BackRight, DEG2RAD( 150.0f), DEG2RAD(0.0f) }, { SideLeft, DEG2RAD( -90.0f), DEG2RAD(0.0f) }, { SideRight, DEG2RAD( 90.0f), DEG2RAD(0.0f) } }; ALCdevice *Device = ALContext->Device; ALfloat SourceVolume,ListenerGain,MinVolume,MaxVolume; ALbufferlistitem *BufferListItem; enum FmtChannels Channels; ALfloat DryGain, DryGainHF, DryGainLF; ALfloat WetGain[MAX_SENDS]; ALfloat WetGainHF[MAX_SENDS]; ALfloat WetGainLF[MAX_SENDS]; ALuint NumSends, Frequency; ALboolean Relative; const struct ChanMap *chans = NULL; ALuint num_channels = 0; ALboolean DirectChannels; ALboolean isbformat = AL_FALSE; ALfloat Pitch; ALuint i, j, c; /* Get device properties */ NumSends = Device->NumAuxSends; Frequency = Device->Frequency; /* Get listener properties */ ListenerGain = ALContext->Listener->Gain; /* Get source properties */ SourceVolume = ALSource->Gain; MinVolume = ALSource->MinGain; MaxVolume = ALSource->MaxGain; Pitch = ALSource->Pitch; Relative = ALSource->HeadRelative; DirectChannels = ALSource->DirectChannels; voice->Direct.OutBuffer = Device->DryBuffer; voice->Direct.OutChannels = Device->NumChannels; for(i = 0;i < NumSends;i++) { ALeffectslot *Slot = ALSource->Send[i].Slot; if(!Slot && i == 0) Slot = Device->DefaultSlot; if(!Slot || Slot->EffectType == AL_EFFECT_NULL) voice->Send[i].OutBuffer = NULL; else voice->Send[i].OutBuffer = Slot->WetBuffer; } /* Calculate the stepping value */ Channels = FmtMono; BufferListItem = ATOMIC_LOAD(&ALSource->queue); while(BufferListItem != NULL) { ALbuffer *ALBuffer; if((ALBuffer=BufferListItem->buffer) != NULL) { Pitch = Pitch * ALBuffer->Frequency / Frequency; if(Pitch > (ALfloat)MAX_PITCH) voice->Step = MAX_PITCH<<FRACTIONBITS; else { voice->Step = fastf2i(Pitch*FRACTIONONE); if(voice->Step == 0) voice->Step = 1; } Channels = ALBuffer->FmtChannels; break; } BufferListItem = BufferListItem->next; } /* Calculate gains */ DryGain = clampf(SourceVolume, MinVolume, MaxVolume); DryGain *= ALSource->Direct.Gain * ListenerGain; DryGainHF = ALSource->Direct.GainHF; DryGainLF = ALSource->Direct.GainLF; for(i = 0;i < NumSends;i++) { WetGain[i] = clampf(SourceVolume, MinVolume, MaxVolume); WetGain[i] *= ALSource->Send[i].Gain * ListenerGain; WetGainHF[i] = ALSource->Send[i].GainHF; WetGainLF[i] = ALSource->Send[i].GainLF; } switch(Channels) { case FmtMono: chans = MonoMap; num_channels = 1; break; case FmtStereo: /* HACK: Place the stereo channels at +/-90 degrees when using non- * HRTF stereo output. This helps reduce the "monoization" caused * by them panning towards the center. */ if(Device->FmtChans == DevFmtStereo && !Device->Hrtf) chans = StereoWideMap; else chans = StereoMap; num_channels = 2; break; case FmtRear: chans = RearMap; num_channels = 2; break; case FmtQuad: chans = QuadMap; num_channels = 4; break; case FmtX51: chans = X51Map; num_channels = 6; break; case FmtX61: chans = X61Map; num_channels = 7; break; case FmtX71: chans = X71Map; num_channels = 8; break; case FmtBFormat2D: num_channels = 3; isbformat = AL_TRUE; DirectChannels = AL_FALSE; break; case FmtBFormat3D: num_channels = 4; isbformat = AL_TRUE; DirectChannels = AL_FALSE; break; } if(isbformat) { ALfloat N[3], V[3], U[3]; aluMatrix matrix; /* AT then UP */ N[0] = ALSource->Orientation[0][0]; N[1] = ALSource->Orientation[0][1]; N[2] = ALSource->Orientation[0][2]; aluNormalize(N); V[0] = ALSource->Orientation[1][0]; V[1] = ALSource->Orientation[1][1]; V[2] = ALSource->Orientation[1][2]; aluNormalize(V); if(!Relative) { const aluMatrix *lmatrix = &ALContext->Listener->Params.Matrix; aluVector at, up; aluVectorSet(&at, N[0], N[1], N[2], 0.0f); aluVectorSet(&up, V[0], V[1], V[2], 0.0f); aluMatrixVector(&at, lmatrix); aluMatrixVector(&up, lmatrix); N[0] = at.v[0]; N[1] = at.v[1]; N[2] = at.v[2]; V[0] = up.v[0]; V[1] = up.v[1]; V[2] = up.v[2]; } /* Build and normalize right-vector */ aluCrossproduct(N, V, U); aluNormalize(U); aluMatrixSet(&matrix, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -N[2], -N[0], N[1], 0.0f, U[2], U[0], -U[1], 0.0f, -V[2], -V[0], V[1] ); for(c = 0;c < num_channels;c++) { MixGains *gains = voice->Direct.Gains[c]; ALfloat Target[MAX_OUTPUT_CHANNELS]; ComputeBFormatGains(Device, matrix.m[c], DryGain, Target); for(i = 0;i < MAX_OUTPUT_CHANNELS;i++) gains[i].Target = Target[i]; } UpdateDryStepping(&voice->Direct, num_channels, (voice->Direct.Moving ? 64 : 0)); voice->Direct.Moving = AL_TRUE; voice->IsHrtf = AL_FALSE; for(i = 0;i < NumSends;i++) WetGain[i] *= 1.4142f; } else if(DirectChannels != AL_FALSE) { if(Device->Hrtf) { voice->Direct.OutBuffer += voice->Direct.OutChannels; voice->Direct.OutChannels = 2; for(c = 0;c < num_channels;c++) { MixGains *gains = voice->Direct.Gains[c]; for(j = 0;j < MAX_OUTPUT_CHANNELS;j++) gains[j].Target = 0.0f; if(chans[c].channel == FrontLeft) gains[0].Target = DryGain; else if(chans[c].channel == FrontRight) gains[1].Target = DryGain; } } else for(c = 0;c < num_channels;c++) { MixGains *gains = voice->Direct.Gains[c]; int idx; for(j = 0;j < MAX_OUTPUT_CHANNELS;j++) gains[j].Target = 0.0f; if((idx=GetChannelIdxByName(Device, chans[c].channel)) != -1) gains[idx].Target = DryGain; } UpdateDryStepping(&voice->Direct, num_channels, (voice->Direct.Moving ? 64 : 0)); voice->Direct.Moving = AL_TRUE; voice->IsHrtf = AL_FALSE; } else if(Device->Hrtf_Mode == FullHrtf) { voice->Direct.OutBuffer += voice->Direct.OutChannels; voice->Direct.OutChannels = 2; for(c = 0;c < num_channels;c++) { if(chans[c].channel == LFE) { /* Skip LFE */ voice->Direct.Hrtf[c].Params.Delay[0] = 0; voice->Direct.Hrtf[c].Params.Delay[1] = 0; for(i = 0;i < HRIR_LENGTH;i++) { voice->Direct.Hrtf[c].Params.Coeffs[i][0] = 0.0f; voice->Direct.Hrtf[c].Params.Coeffs[i][1] = 0.0f; } } else { /* Get the static HRIR coefficients and delays for this * channel. */ GetLerpedHrtfCoeffs(Device->Hrtf, chans[c].elevation, chans[c].angle, 1.0f, DryGain, voice->Direct.Hrtf[c].Params.Coeffs, voice->Direct.Hrtf[c].Params.Delay); } } voice->Direct.Counter = 0; voice->Direct.Moving = AL_TRUE; voice->IsHrtf = AL_TRUE; } else { for(c = 0;c < num_channels;c++) { MixGains *gains = voice->Direct.Gains[c]; ALfloat Target[MAX_OUTPUT_CHANNELS]; /* Special-case LFE */ if(chans[c].channel == LFE) { int idx; for(i = 0;i < MAX_OUTPUT_CHANNELS;i++) gains[i].Target = 0.0f; if((idx=GetChannelIdxByName(Device, chans[c].channel)) != -1) gains[idx].Target = DryGain; continue; } ComputeAngleGains(Device, chans[c].angle, chans[c].elevation, DryGain, Target); for(i = 0;i < MAX_OUTPUT_CHANNELS;i++) gains[i].Target = Target[i]; } UpdateDryStepping(&voice->Direct, num_channels, (voice->Direct.Moving ? 64 : 0)); voice->Direct.Moving = AL_TRUE; voice->IsHrtf = AL_FALSE; } for(i = 0;i < NumSends;i++) { voice->Send[i].Gain.Target = WetGain[i]; UpdateWetStepping(&voice->Send[i], (voice->Send[i].Moving ? 64 : 0)); voice->Send[i].Moving = AL_TRUE; } { ALfloat gainhf = maxf(0.01f, DryGainHF); ALfloat gainlf = maxf(0.01f, DryGainLF); ALfloat hfscale = ALSource->Direct.HFReference / Frequency; ALfloat lfscale = ALSource->Direct.LFReference / Frequency; for(c = 0;c < num_channels;c++) { voice->Direct.Filters[c].ActiveType = AF_None; if(gainhf != 1.0f) voice->Direct.Filters[c].ActiveType |= AF_LowPass; if(gainlf != 1.0f) voice->Direct.Filters[c].ActiveType |= AF_HighPass; ALfilterState_setParams( &voice->Direct.Filters[c].LowPass, ALfilterType_HighShelf, gainhf, hfscale, 0.0f ); ALfilterState_setParams( &voice->Direct.Filters[c].HighPass, ALfilterType_LowShelf, gainlf, lfscale, 0.0f ); } } for(i = 0;i < NumSends;i++) { ALfloat gainhf = maxf(0.01f, WetGainHF[i]); ALfloat gainlf = maxf(0.01f, WetGainLF[i]); ALfloat hfscale = ALSource->Send[i].HFReference / Frequency; ALfloat lfscale = ALSource->Send[i].LFReference / Frequency; for(c = 0;c < num_channels;c++) { voice->Send[i].Filters[c].ActiveType = AF_None; if(gainhf != 1.0f) voice->Send[i].Filters[c].ActiveType |= AF_LowPass; if(gainlf != 1.0f) voice->Send[i].Filters[c].ActiveType |= AF_HighPass; ALfilterState_setParams( &voice->Send[i].Filters[c].LowPass, ALfilterType_HighShelf, gainhf, hfscale, 0.0f ); ALfilterState_setParams( &voice->Send[i].Filters[c].HighPass, ALfilterType_LowShelf, gainlf, lfscale, 0.0f ); } } }