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
[OUTPUTCHANNELS
];
52 #define WAVEFORM_FRACBITS 16
53 #define WAVEFORM_FRACMASK ((1<<WAVEFORM_FRACBITS)-1)
55 static __inline ALfloat
sin_func(ALuint index
)
57 return sin(index
/ (double)(1<<WAVEFORM_FRACBITS
) * M_PI
* 2.0f
);
60 static __inline ALfloat
saw_func(ALuint index
)
62 return index
*2.0f
/(1<<WAVEFORM_FRACBITS
) - 1.0f
;
65 static __inline ALfloat
square_func(ALuint index
)
67 return ((index
>>(WAVEFORM_FRACBITS
-1))&1) ? -1.0f
: 1.0f
;
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 static ALvoid
ModulatorDestroy(ALeffectState
*effect
)
86 ALmodulatorState
*state
= (ALmodulatorState
*)effect
;
90 static ALboolean
ModulatorDeviceUpdate(ALeffectState
*effect
, ALCdevice
*Device
)
92 ALmodulatorState
*state
= (ALmodulatorState
*)effect
;
95 for(index
= 0;index
< OUTPUTCHANNELS
;index
++)
96 state
->Gain
[index
] = 0.0f
;
97 for(index
= 0;index
< Device
->NumChan
;index
++)
99 Channel chan
= Device
->Speaker2Chan
[index
];
100 state
->Gain
[chan
] = 1.0f
;
106 static ALvoid
ModulatorUpdate(ALeffectState
*effect
, ALCcontext
*Context
, const ALeffect
*Effect
)
108 ALmodulatorState
*state
= (ALmodulatorState
*)effect
;
109 ALfloat cw
, a
= 0.0f
;
111 if(Effect
->Modulator
.Waveform
== AL_RING_MODULATOR_SINUSOID
)
112 state
->Waveform
= SINUSOID
;
113 else if(Effect
->Modulator
.Waveform
== AL_RING_MODULATOR_SAWTOOTH
)
114 state
->Waveform
= SAWTOOTH
;
115 else if(Effect
->Modulator
.Waveform
== AL_RING_MODULATOR_SQUARE
)
116 state
->Waveform
= SQUARE
;
118 state
->step
= Effect
->Modulator
.Frequency
*(1<<WAVEFORM_FRACBITS
) /
119 Context
->Device
->Frequency
;
123 cw
= cos(2.0*M_PI
* Effect
->Modulator
.HighPassCutoff
/ Context
->Device
->Frequency
);
124 a
= (2.0f
-cw
) - aluSqrt(aluPow(2.0f
-cw
, 2.0f
) - 1.0f
);
125 state
->iirFilter
.coeff
= a
;
128 static ALvoid
ModulatorProcess(ALeffectState
*effect
, const ALeffectslot
*Slot
, ALuint SamplesToDo
, const ALfloat
*SamplesIn
, ALfloat (*SamplesOut
)[OUTPUTCHANNELS
])
130 ALmodulatorState
*state
= (ALmodulatorState
*)effect
;
131 const ALfloat gain
= Slot
->Gain
;
132 const ALuint step
= state
->step
;
133 ALuint index
= state
->index
;
137 switch(state
->Waveform
)
140 for(i
= 0;i
< SamplesToDo
;i
++)
142 #define FILTER_OUT(func) do { \
143 samp = SamplesIn[i]; \
146 index &= WAVEFORM_FRACMASK; \
147 samp *= func(index); \
149 samp = hpFilter1P(&state->iirFilter, 0, samp); \
151 /* Apply slot gain */ \
154 SamplesOut[i][FRONT_LEFT] += state->Gain[FRONT_LEFT] * samp; \
155 SamplesOut[i][FRONT_RIGHT] += state->Gain[FRONT_RIGHT] * samp; \
156 SamplesOut[i][FRONT_CENTER] += state->Gain[FRONT_CENTER] * samp; \
157 SamplesOut[i][SIDE_LEFT] += state->Gain[SIDE_LEFT] * samp; \
158 SamplesOut[i][SIDE_RIGHT] += state->Gain[SIDE_RIGHT] * samp; \
159 SamplesOut[i][BACK_LEFT] += state->Gain[BACK_LEFT] * samp; \
160 SamplesOut[i][BACK_RIGHT] += state->Gain[BACK_RIGHT] * samp; \
161 SamplesOut[i][BACK_CENTER] += state->Gain[BACK_CENTER] * samp; \
163 FILTER_OUT(sin_func
);
168 for(i
= 0;i
< SamplesToDo
;i
++)
170 FILTER_OUT(saw_func
);
175 for(i
= 0;i
< SamplesToDo
;i
++)
177 FILTER_OUT(square_func
);
182 state
->index
= index
;
185 ALeffectState
*ModulatorCreate(void)
187 ALmodulatorState
*state
;
189 state
= malloc(sizeof(*state
));
193 state
->state
.Destroy
= ModulatorDestroy
;
194 state
->state
.DeviceUpdate
= ModulatorDeviceUpdate
;
195 state
->state
.Update
= ModulatorUpdate
;
196 state
->state
.Process
= ModulatorProcess
;
201 state
->iirFilter
.coeff
= 0.0f
;
202 state
->iirFilter
.history
[0] = 0.0f
;
204 return &state
->state
;