2 * OpenAL cross platform audio library
3 * Copyright (C) 2009 by Chris Robinson.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
28 #include "alAuxEffectSlot.h"
33 typedef struct ALmodulatorState
{
34 // Must be first in all effects!
46 ALfloat Gain
[MAXCHANNELS
];
52 #define WAVEFORM_FRACBITS 16
53 #define WAVEFORM_FRACMASK ((1<<WAVEFORM_FRACBITS)-1)
55 static __inline ALdouble
Sin(ALuint index
)
57 return sin(index
* (M_PI
*2.0 / (1<<WAVEFORM_FRACBITS
)));
60 static __inline ALdouble
Saw(ALuint index
)
62 return index
*(2.0/(1<<WAVEFORM_FRACBITS
)) - 1.0;
65 static __inline ALdouble
Square(ALuint index
)
67 return (index
&(1<<(WAVEFORM_FRACBITS
-1))) ? -1.0 : 1.0;
71 static __inline ALfloat
hpFilter1P(FILTER
*iir
, ALuint offset
, ALfloat input
)
73 ALfloat
*history
= &iir
->history
[offset
];
74 ALfloat a
= iir
->coeff
;
75 ALfloat output
= input
;
77 output
= output
+ (history
[0]-output
)*a
;
80 return input
- output
;
84 #define DECL_TEMPLATE(func) \
85 static void Process##func(ALmodulatorState *state, const ALeffectslot *Slot, \
86 ALuint SamplesToDo, const ALfloat *SamplesIn, \
87 ALfloat (*SamplesOut)[MAXCHANNELS]) \
89 const ALfloat gain = Slot->Gain; \
90 const ALuint step = state->step; \
91 ALuint index = state->index; \
95 for(i = 0;i < SamplesToDo;i++) \
97 samp = SamplesIn[i]; \
100 index &= WAVEFORM_FRACMASK; \
101 samp *= func(index); \
103 samp = hpFilter1P(&state->iirFilter, 0, samp); \
105 /* Apply slot gain */ \
108 SamplesOut[i][FRONT_LEFT] += state->Gain[FRONT_LEFT] * samp; \
109 SamplesOut[i][FRONT_RIGHT] += state->Gain[FRONT_RIGHT] * samp; \
110 SamplesOut[i][FRONT_CENTER] += state->Gain[FRONT_CENTER] * samp; \
111 SamplesOut[i][SIDE_LEFT] += state->Gain[SIDE_LEFT] * samp; \
112 SamplesOut[i][SIDE_RIGHT] += state->Gain[SIDE_RIGHT] * samp; \
113 SamplesOut[i][BACK_LEFT] += state->Gain[BACK_LEFT] * samp; \
114 SamplesOut[i][BACK_RIGHT] += state->Gain[BACK_RIGHT] * samp; \
115 SamplesOut[i][BACK_CENTER] += state->Gain[BACK_CENTER] * samp; \
117 state->index = index; \
122 DECL_TEMPLATE(Square
)
127 static ALvoid
ModulatorDestroy(ALeffectState
*effect
)
129 ALmodulatorState
*state
= (ALmodulatorState
*)effect
;
133 static ALboolean
ModulatorDeviceUpdate(ALeffectState
*effect
, ALCdevice
*Device
)
135 ALmodulatorState
*state
= (ALmodulatorState
*)effect
;
138 for(index
= 0;index
< MAXCHANNELS
;index
++)
139 state
->Gain
[index
] = 0.0f
;
140 for(index
= 0;index
< Device
->NumChan
;index
++)
142 enum Channel chan
= Device
->Speaker2Chan
[index
];
143 state
->Gain
[chan
] = 1.0f
;
149 static ALvoid
ModulatorUpdate(ALeffectState
*effect
, ALCcontext
*Context
, const ALeffect
*Effect
)
151 ALmodulatorState
*state
= (ALmodulatorState
*)effect
;
152 ALfloat cw
, a
= 0.0f
;
154 if(Effect
->Params
.Modulator
.Waveform
== AL_RING_MODULATOR_SINUSOID
)
155 state
->Waveform
= SINUSOID
;
156 else if(Effect
->Params
.Modulator
.Waveform
== AL_RING_MODULATOR_SAWTOOTH
)
157 state
->Waveform
= SAWTOOTH
;
158 else if(Effect
->Params
.Modulator
.Waveform
== AL_RING_MODULATOR_SQUARE
)
159 state
->Waveform
= SQUARE
;
161 state
->step
= Effect
->Params
.Modulator
.Frequency
*(1<<WAVEFORM_FRACBITS
) /
162 Context
->Device
->Frequency
;
166 cw
= cos(2.0*M_PI
* Effect
->Params
.Modulator
.HighPassCutoff
/
167 Context
->Device
->Frequency
);
168 a
= (2.0f
-cw
) - aluSqrt(aluPow(2.0f
-cw
, 2.0f
) - 1.0f
);
169 state
->iirFilter
.coeff
= a
;
172 static ALvoid
ModulatorProcess(ALeffectState
*effect
, const ALeffectslot
*Slot
, ALuint SamplesToDo
, const ALfloat
*SamplesIn
, ALfloat (*SamplesOut
)[MAXCHANNELS
])
174 ALmodulatorState
*state
= (ALmodulatorState
*)effect
;
176 switch(state
->Waveform
)
179 ProcessSin(state
, Slot
, SamplesToDo
, SamplesIn
, SamplesOut
);
183 ProcessSaw(state
, Slot
, SamplesToDo
, SamplesIn
, SamplesOut
);
187 ProcessSquare(state
, Slot
, SamplesToDo
, SamplesIn
, SamplesOut
);
192 ALeffectState
*ModulatorCreate(void)
194 ALmodulatorState
*state
;
196 state
= malloc(sizeof(*state
));
200 state
->state
.Destroy
= ModulatorDestroy
;
201 state
->state
.DeviceUpdate
= ModulatorDeviceUpdate
;
202 state
->state
.Update
= ModulatorUpdate
;
203 state
->state
.Process
= ModulatorProcess
;
208 state
->iirFilter
.coeff
= 0.0f
;
209 state
->iirFilter
.history
[0] = 0.0f
;
211 return &state
->state
;