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_FRACONE (1<<WAVEFORM_FRACBITS)
54 #define WAVEFORM_FRACMASK (WAVEFORM_FRACONE-1)
56 static __inline ALfloat
Sin(ALuint index
)
58 return aluSin(index
* (F_PI
*2.0f
/ WAVEFORM_FRACONE
));
61 static __inline ALfloat
Saw(ALuint index
)
63 return index
*(2.0f
/WAVEFORM_FRACONE
) - 1.0f
;
66 static __inline ALfloat
Square(ALuint index
)
68 return ((index
>>(WAVEFORM_FRACBITS
-1))&1)*2.0f
- 1.0f
;
72 static __inline ALfloat
hpFilter1P(FILTER
*iir
, ALuint offset
, ALfloat input
)
74 ALfloat
*history
= &iir
->history
[offset
];
75 ALfloat a
= iir
->coeff
;
76 ALfloat output
= input
;
78 output
= output
+ (history
[0]-output
)*a
;
81 return input
- output
;
85 #define DECL_TEMPLATE(func) \
86 static void Process##func(ALmodulatorState *state, ALuint SamplesToDo, \
87 const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS]) \
89 const ALuint step = state->step; \
90 ALuint index = state->index; \
94 for(i = 0;i < SamplesToDo;i++) \
96 samp = SamplesIn[i]; \
99 index &= WAVEFORM_FRACMASK; \
100 samp *= func(index); \
102 samp = hpFilter1P(&state->iirFilter, 0, samp); \
104 for(k = 0;k < MAXCHANNELS;k++) \
105 SamplesOut[i][k] += state->Gain[k] * samp; \
107 state->index = index; \
112 DECL_TEMPLATE(Square
)
117 static ALvoid
ModulatorDestroy(ALeffectState
*effect
)
119 ALmodulatorState
*state
= (ALmodulatorState
*)effect
;
123 static ALboolean
ModulatorDeviceUpdate(ALeffectState
*effect
, ALCdevice
*Device
)
130 static ALvoid
ModulatorUpdate(ALeffectState
*effect
, ALCdevice
*Device
, const ALeffectslot
*Slot
)
132 ALmodulatorState
*state
= (ALmodulatorState
*)effect
;
133 ALfloat gain
, cw
, a
= 0.0f
;
136 if(Slot
->effect
.Modulator
.Waveform
== AL_RING_MODULATOR_SINUSOID
)
137 state
->Waveform
= SINUSOID
;
138 else if(Slot
->effect
.Modulator
.Waveform
== AL_RING_MODULATOR_SAWTOOTH
)
139 state
->Waveform
= SAWTOOTH
;
140 else if(Slot
->effect
.Modulator
.Waveform
== AL_RING_MODULATOR_SQUARE
)
141 state
->Waveform
= SQUARE
;
143 state
->step
= fastf2u(Slot
->effect
.Modulator
.Frequency
*WAVEFORM_FRACONE
/
145 if(state
->step
== 0) state
->step
= 1;
147 cw
= aluCos(F_PI
*2.0f
* Slot
->effect
.Modulator
.HighPassCutoff
/
149 a
= (2.0f
-cw
) - aluSqrt(aluPow(2.0f
-cw
, 2.0f
) - 1.0f
);
150 state
->iirFilter
.coeff
= a
;
152 gain
= aluSqrt(1.0f
/Device
->NumChan
);
154 for(index
= 0;index
< MAXCHANNELS
;index
++)
155 state
->Gain
[index
] = 0.0f
;
156 for(index
= 0;index
< Device
->NumChan
;index
++)
158 enum Channel chan
= Device
->Speaker2Chan
[index
];
159 state
->Gain
[chan
] = gain
;
163 static ALvoid
ModulatorProcess(ALeffectState
*effect
, ALuint SamplesToDo
, const ALfloat
*SamplesIn
, ALfloat (*SamplesOut
)[MAXCHANNELS
])
165 ALmodulatorState
*state
= (ALmodulatorState
*)effect
;
167 switch(state
->Waveform
)
170 ProcessSin(state
, SamplesToDo
, SamplesIn
, SamplesOut
);
174 ProcessSaw(state
, SamplesToDo
, SamplesIn
, SamplesOut
);
178 ProcessSquare(state
, SamplesToDo
, SamplesIn
, SamplesOut
);
183 ALeffectState
*ModulatorCreate(void)
185 ALmodulatorState
*state
;
187 state
= malloc(sizeof(*state
));
191 state
->state
.Destroy
= ModulatorDestroy
;
192 state
->state
.DeviceUpdate
= ModulatorDeviceUpdate
;
193 state
->state
.Update
= ModulatorUpdate
;
194 state
->state
.Process
= ModulatorProcess
;
199 state
->iirFilter
.coeff
= 0.0f
;
200 state
->iirFilter
.history
[0] = 0.0f
;
202 return &state
->state
;