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, ALuint SamplesToDo, \
86 const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS]) \
88 const ALuint step = state->step; \
89 ALuint index = state->index; \
93 for(i = 0;i < SamplesToDo;i++) \
95 samp = SamplesIn[i]; \
98 index &= WAVEFORM_FRACMASK; \
99 samp *= func(index); \
101 samp = hpFilter1P(&state->iirFilter, 0, samp); \
103 SamplesOut[i][FRONT_LEFT] += state->Gain[FRONT_LEFT] * samp; \
104 SamplesOut[i][FRONT_RIGHT] += state->Gain[FRONT_RIGHT] * samp; \
105 SamplesOut[i][FRONT_CENTER] += state->Gain[FRONT_CENTER] * samp; \
106 SamplesOut[i][SIDE_LEFT] += state->Gain[SIDE_LEFT] * samp; \
107 SamplesOut[i][SIDE_RIGHT] += state->Gain[SIDE_RIGHT] * samp; \
108 SamplesOut[i][BACK_LEFT] += state->Gain[BACK_LEFT] * samp; \
109 SamplesOut[i][BACK_RIGHT] += state->Gain[BACK_RIGHT] * samp; \
110 SamplesOut[i][BACK_CENTER] += state->Gain[BACK_CENTER] * samp; \
112 state->index = index; \
117 DECL_TEMPLATE(Square
)
122 static ALvoid
ModulatorDestroy(ALeffectState
*effect
)
124 ALmodulatorState
*state
= (ALmodulatorState
*)effect
;
128 static ALboolean
ModulatorDeviceUpdate(ALeffectState
*effect
, ALCdevice
*Device
)
135 static ALvoid
ModulatorUpdate(ALeffectState
*effect
, ALCcontext
*Context
, const ALeffectslot
*Slot
)
137 ALmodulatorState
*state
= (ALmodulatorState
*)effect
;
138 ALCdevice
*Device
= Context
->Device
;
139 ALfloat gain
, cw
, a
= 0.0f
;
142 if(Slot
->effect
.Modulator
.Waveform
== AL_RING_MODULATOR_SINUSOID
)
143 state
->Waveform
= SINUSOID
;
144 else if(Slot
->effect
.Modulator
.Waveform
== AL_RING_MODULATOR_SAWTOOTH
)
145 state
->Waveform
= SAWTOOTH
;
146 else if(Slot
->effect
.Modulator
.Waveform
== AL_RING_MODULATOR_SQUARE
)
147 state
->Waveform
= SQUARE
;
149 state
->step
= Slot
->effect
.Modulator
.Frequency
*(1<<WAVEFORM_FRACBITS
) /
154 cw
= cos(2.0*M_PI
* Slot
->effect
.Modulator
.HighPassCutoff
/
156 a
= (2.0f
-cw
) - aluSqrt(aluPow(2.0f
-cw
, 2.0f
) - 1.0f
);
157 state
->iirFilter
.coeff
= a
;
160 for(index
= 0;index
< MAXCHANNELS
;index
++)
161 state
->Gain
[index
] = 0.0f
;
162 for(index
= 0;index
< Device
->NumChan
;index
++)
164 enum Channel chan
= Device
->Speaker2Chan
[index
];
165 state
->Gain
[chan
] = gain
;
169 static ALvoid
ModulatorProcess(ALeffectState
*effect
, ALuint SamplesToDo
, const ALfloat
*SamplesIn
, ALfloat (*SamplesOut
)[MAXCHANNELS
])
171 ALmodulatorState
*state
= (ALmodulatorState
*)effect
;
173 switch(state
->Waveform
)
176 ProcessSin(state
, SamplesToDo
, SamplesIn
, SamplesOut
);
180 ProcessSaw(state
, SamplesToDo
, SamplesIn
, SamplesOut
);
184 ProcessSquare(state
, SamplesToDo
, SamplesIn
, SamplesOut
);
189 ALeffectState
*ModulatorCreate(void)
191 ALmodulatorState
*state
;
193 state
= malloc(sizeof(*state
));
197 state
->state
.Destroy
= ModulatorDestroy
;
198 state
->state
.DeviceUpdate
= ModulatorDeviceUpdate
;
199 state
->state
.Update
= ModulatorUpdate
;
200 state
->state
.Process
= ModulatorProcess
;
205 state
->iirFilter
.coeff
= 0.0f
;
206 state
->iirFilter
.history
[0] = 0.0f
;
208 return &state
->state
;