Mercurial > audio-send
comparison Alc/alcModulator.c @ 0:f9476ff7637e
initial forking of open-al to create multiple listeners
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Tue, 25 Oct 2011 13:02:31 -0700 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:f9476ff7637e |
---|---|
1 /** | |
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. | |
8 * | |
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. | |
13 * | |
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 | |
19 */ | |
20 | |
21 #include "config.h" | |
22 | |
23 #include <math.h> | |
24 #include <stdlib.h> | |
25 | |
26 #include "alMain.h" | |
27 #include "alFilter.h" | |
28 #include "alAuxEffectSlot.h" | |
29 #include "alError.h" | |
30 #include "alu.h" | |
31 | |
32 | |
33 typedef struct ALmodulatorState { | |
34 // Must be first in all effects! | |
35 ALeffectState state; | |
36 | |
37 enum { | |
38 SINUSOID, | |
39 SAWTOOTH, | |
40 SQUARE | |
41 } Waveform; | |
42 | |
43 ALuint index; | |
44 ALuint step; | |
45 | |
46 ALfloat Gain[MAXCHANNELS]; | |
47 | |
48 FILTER iirFilter; | |
49 ALfloat history[1]; | |
50 } ALmodulatorState; | |
51 | |
52 #define WAVEFORM_FRACBITS 16 | |
53 #define WAVEFORM_FRACMASK ((1<<WAVEFORM_FRACBITS)-1) | |
54 | |
55 static __inline ALdouble Sin(ALuint index) | |
56 { | |
57 return sin(index * (M_PI*2.0 / (1<<WAVEFORM_FRACBITS))); | |
58 } | |
59 | |
60 static __inline ALdouble Saw(ALuint index) | |
61 { | |
62 return index*(2.0/(1<<WAVEFORM_FRACBITS)) - 1.0; | |
63 } | |
64 | |
65 static __inline ALdouble Square(ALuint index) | |
66 { | |
67 return (index&(1<<(WAVEFORM_FRACBITS-1))) ? -1.0 : 1.0; | |
68 } | |
69 | |
70 | |
71 static __inline ALfloat hpFilter1P(FILTER *iir, ALuint offset, ALfloat input) | |
72 { | |
73 ALfloat *history = &iir->history[offset]; | |
74 ALfloat a = iir->coeff; | |
75 ALfloat output = input; | |
76 | |
77 output = output + (history[0]-output)*a; | |
78 history[0] = output; | |
79 | |
80 return input - output; | |
81 } | |
82 | |
83 | |
84 #define DECL_TEMPLATE(func) \ | |
85 static void Process##func(ALmodulatorState *state, ALuint SamplesToDo, \ | |
86 const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS]) \ | |
87 { \ | |
88 const ALuint step = state->step; \ | |
89 ALuint index = state->index; \ | |
90 ALfloat samp; \ | |
91 ALuint i; \ | |
92 \ | |
93 for(i = 0;i < SamplesToDo;i++) \ | |
94 { \ | |
95 samp = SamplesIn[i]; \ | |
96 \ | |
97 index += step; \ | |
98 index &= WAVEFORM_FRACMASK; \ | |
99 samp *= func(index); \ | |
100 \ | |
101 samp = hpFilter1P(&state->iirFilter, 0, samp); \ | |
102 \ | |
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; \ | |
111 } \ | |
112 state->index = index; \ | |
113 } | |
114 | |
115 DECL_TEMPLATE(Sin) | |
116 DECL_TEMPLATE(Saw) | |
117 DECL_TEMPLATE(Square) | |
118 | |
119 #undef DECL_TEMPLATE | |
120 | |
121 | |
122 static ALvoid ModulatorDestroy(ALeffectState *effect) | |
123 { | |
124 ALmodulatorState *state = (ALmodulatorState*)effect; | |
125 free(state); | |
126 } | |
127 | |
128 static ALboolean ModulatorDeviceUpdate(ALeffectState *effect, ALCdevice *Device) | |
129 { | |
130 return AL_TRUE; | |
131 (void)effect; | |
132 (void)Device; | |
133 } | |
134 | |
135 static ALvoid ModulatorUpdate(ALeffectState *effect, ALCcontext *Context, const ALeffectslot *Slot) | |
136 { | |
137 ALmodulatorState *state = (ALmodulatorState*)effect; | |
138 ALCdevice *Device = Context->Device; | |
139 ALfloat gain, cw, a = 0.0f; | |
140 ALuint index; | |
141 | |
142 if(Slot->effect.Params.Modulator.Waveform == AL_RING_MODULATOR_SINUSOID) | |
143 state->Waveform = SINUSOID; | |
144 else if(Slot->effect.Params.Modulator.Waveform == AL_RING_MODULATOR_SAWTOOTH) | |
145 state->Waveform = SAWTOOTH; | |
146 else if(Slot->effect.Params.Modulator.Waveform == AL_RING_MODULATOR_SQUARE) | |
147 state->Waveform = SQUARE; | |
148 | |
149 state->step = Slot->effect.Params.Modulator.Frequency*(1<<WAVEFORM_FRACBITS) / | |
150 Device->Frequency; | |
151 if(!state->step) | |
152 state->step = 1; | |
153 | |
154 cw = cos(2.0*M_PI * Slot->effect.Params.Modulator.HighPassCutoff / | |
155 Device->Frequency); | |
156 a = (2.0f-cw) - aluSqrt(aluPow(2.0f-cw, 2.0f) - 1.0f); | |
157 state->iirFilter.coeff = a; | |
158 | |
159 gain = Slot->Gain; | |
160 for(index = 0;index < MAXCHANNELS;index++) | |
161 state->Gain[index] = 0.0f; | |
162 for(index = 0;index < Device->NumChan;index++) | |
163 { | |
164 enum Channel chan = Device->Speaker2Chan[index]; | |
165 state->Gain[chan] = gain; | |
166 } | |
167 } | |
168 | |
169 static ALvoid ModulatorProcess(ALeffectState *effect, const ALeffectslot *Slot, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS]) | |
170 { | |
171 ALmodulatorState *state = (ALmodulatorState*)effect; | |
172 (void)Slot; | |
173 | |
174 switch(state->Waveform) | |
175 { | |
176 case SINUSOID: | |
177 ProcessSin(state, SamplesToDo, SamplesIn, SamplesOut); | |
178 break; | |
179 | |
180 case SAWTOOTH: | |
181 ProcessSaw(state, SamplesToDo, SamplesIn, SamplesOut); | |
182 break; | |
183 | |
184 case SQUARE: | |
185 ProcessSquare(state, SamplesToDo, SamplesIn, SamplesOut); | |
186 break; | |
187 } | |
188 } | |
189 | |
190 ALeffectState *ModulatorCreate(void) | |
191 { | |
192 ALmodulatorState *state; | |
193 | |
194 state = malloc(sizeof(*state)); | |
195 if(!state) | |
196 return NULL; | |
197 | |
198 state->state.Destroy = ModulatorDestroy; | |
199 state->state.DeviceUpdate = ModulatorDeviceUpdate; | |
200 state->state.Update = ModulatorUpdate; | |
201 state->state.Process = ModulatorProcess; | |
202 | |
203 state->index = 0.0f; | |
204 state->step = 1.0f; | |
205 | |
206 state->iirFilter.coeff = 0.0f; | |
207 state->iirFilter.history[0] = 0.0f; | |
208 | |
209 return &state->state; | |
210 } |