annotate Alc/alcModulator.c @ 19:22ac5a0367cd

finally, a first pass at ear.org
author Robert McIntyre <rlm@mit.edu>
date Thu, 03 Nov 2011 14:54:45 -0700
parents f9476ff7637e
children
rev   line source
rlm@0 1 /**
rlm@0 2 * OpenAL cross platform audio library
rlm@0 3 * Copyright (C) 2009 by Chris Robinson.
rlm@0 4 * This library is free software; you can redistribute it and/or
rlm@0 5 * modify it under the terms of the GNU Library General Public
rlm@0 6 * License as published by the Free Software Foundation; either
rlm@0 7 * version 2 of the License, or (at your option) any later version.
rlm@0 8 *
rlm@0 9 * This library is distributed in the hope that it will be useful,
rlm@0 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
rlm@0 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
rlm@0 12 * Library General Public License for more details.
rlm@0 13 *
rlm@0 14 * You should have received a copy of the GNU Library General Public
rlm@0 15 * License along with this library; if not, write to the
rlm@0 16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
rlm@0 17 * Boston, MA 02111-1307, USA.
rlm@0 18 * Or go to http://www.gnu.org/copyleft/lgpl.html
rlm@0 19 */
rlm@0 20
rlm@0 21 #include "config.h"
rlm@0 22
rlm@0 23 #include <math.h>
rlm@0 24 #include <stdlib.h>
rlm@0 25
rlm@0 26 #include "alMain.h"
rlm@0 27 #include "alFilter.h"
rlm@0 28 #include "alAuxEffectSlot.h"
rlm@0 29 #include "alError.h"
rlm@0 30 #include "alu.h"
rlm@0 31
rlm@0 32
rlm@0 33 typedef struct ALmodulatorState {
rlm@0 34 // Must be first in all effects!
rlm@0 35 ALeffectState state;
rlm@0 36
rlm@0 37 enum {
rlm@0 38 SINUSOID,
rlm@0 39 SAWTOOTH,
rlm@0 40 SQUARE
rlm@0 41 } Waveform;
rlm@0 42
rlm@0 43 ALuint index;
rlm@0 44 ALuint step;
rlm@0 45
rlm@0 46 ALfloat Gain[MAXCHANNELS];
rlm@0 47
rlm@0 48 FILTER iirFilter;
rlm@0 49 ALfloat history[1];
rlm@0 50 } ALmodulatorState;
rlm@0 51
rlm@0 52 #define WAVEFORM_FRACBITS 16
rlm@0 53 #define WAVEFORM_FRACMASK ((1<<WAVEFORM_FRACBITS)-1)
rlm@0 54
rlm@0 55 static __inline ALdouble Sin(ALuint index)
rlm@0 56 {
rlm@0 57 return sin(index * (M_PI*2.0 / (1<<WAVEFORM_FRACBITS)));
rlm@0 58 }
rlm@0 59
rlm@0 60 static __inline ALdouble Saw(ALuint index)
rlm@0 61 {
rlm@0 62 return index*(2.0/(1<<WAVEFORM_FRACBITS)) - 1.0;
rlm@0 63 }
rlm@0 64
rlm@0 65 static __inline ALdouble Square(ALuint index)
rlm@0 66 {
rlm@0 67 return (index&(1<<(WAVEFORM_FRACBITS-1))) ? -1.0 : 1.0;
rlm@0 68 }
rlm@0 69
rlm@0 70
rlm@0 71 static __inline ALfloat hpFilter1P(FILTER *iir, ALuint offset, ALfloat input)
rlm@0 72 {
rlm@0 73 ALfloat *history = &iir->history[offset];
rlm@0 74 ALfloat a = iir->coeff;
rlm@0 75 ALfloat output = input;
rlm@0 76
rlm@0 77 output = output + (history[0]-output)*a;
rlm@0 78 history[0] = output;
rlm@0 79
rlm@0 80 return input - output;
rlm@0 81 }
rlm@0 82
rlm@0 83
rlm@0 84 #define DECL_TEMPLATE(func) \
rlm@0 85 static void Process##func(ALmodulatorState *state, ALuint SamplesToDo, \
rlm@0 86 const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS]) \
rlm@0 87 { \
rlm@0 88 const ALuint step = state->step; \
rlm@0 89 ALuint index = state->index; \
rlm@0 90 ALfloat samp; \
rlm@0 91 ALuint i; \
rlm@0 92 \
rlm@0 93 for(i = 0;i < SamplesToDo;i++) \
rlm@0 94 { \
rlm@0 95 samp = SamplesIn[i]; \
rlm@0 96 \
rlm@0 97 index += step; \
rlm@0 98 index &= WAVEFORM_FRACMASK; \
rlm@0 99 samp *= func(index); \
rlm@0 100 \
rlm@0 101 samp = hpFilter1P(&state->iirFilter, 0, samp); \
rlm@0 102 \
rlm@0 103 SamplesOut[i][FRONT_LEFT] += state->Gain[FRONT_LEFT] * samp; \
rlm@0 104 SamplesOut[i][FRONT_RIGHT] += state->Gain[FRONT_RIGHT] * samp; \
rlm@0 105 SamplesOut[i][FRONT_CENTER] += state->Gain[FRONT_CENTER] * samp; \
rlm@0 106 SamplesOut[i][SIDE_LEFT] += state->Gain[SIDE_LEFT] * samp; \
rlm@0 107 SamplesOut[i][SIDE_RIGHT] += state->Gain[SIDE_RIGHT] * samp; \
rlm@0 108 SamplesOut[i][BACK_LEFT] += state->Gain[BACK_LEFT] * samp; \
rlm@0 109 SamplesOut[i][BACK_RIGHT] += state->Gain[BACK_RIGHT] * samp; \
rlm@0 110 SamplesOut[i][BACK_CENTER] += state->Gain[BACK_CENTER] * samp; \
rlm@0 111 } \
rlm@0 112 state->index = index; \
rlm@0 113 }
rlm@0 114
rlm@0 115 DECL_TEMPLATE(Sin)
rlm@0 116 DECL_TEMPLATE(Saw)
rlm@0 117 DECL_TEMPLATE(Square)
rlm@0 118
rlm@0 119 #undef DECL_TEMPLATE
rlm@0 120
rlm@0 121
rlm@0 122 static ALvoid ModulatorDestroy(ALeffectState *effect)
rlm@0 123 {
rlm@0 124 ALmodulatorState *state = (ALmodulatorState*)effect;
rlm@0 125 free(state);
rlm@0 126 }
rlm@0 127
rlm@0 128 static ALboolean ModulatorDeviceUpdate(ALeffectState *effect, ALCdevice *Device)
rlm@0 129 {
rlm@0 130 return AL_TRUE;
rlm@0 131 (void)effect;
rlm@0 132 (void)Device;
rlm@0 133 }
rlm@0 134
rlm@0 135 static ALvoid ModulatorUpdate(ALeffectState *effect, ALCcontext *Context, const ALeffectslot *Slot)
rlm@0 136 {
rlm@0 137 ALmodulatorState *state = (ALmodulatorState*)effect;
rlm@0 138 ALCdevice *Device = Context->Device;
rlm@0 139 ALfloat gain, cw, a = 0.0f;
rlm@0 140 ALuint index;
rlm@0 141
rlm@0 142 if(Slot->effect.Params.Modulator.Waveform == AL_RING_MODULATOR_SINUSOID)
rlm@0 143 state->Waveform = SINUSOID;
rlm@0 144 else if(Slot->effect.Params.Modulator.Waveform == AL_RING_MODULATOR_SAWTOOTH)
rlm@0 145 state->Waveform = SAWTOOTH;
rlm@0 146 else if(Slot->effect.Params.Modulator.Waveform == AL_RING_MODULATOR_SQUARE)
rlm@0 147 state->Waveform = SQUARE;
rlm@0 148
rlm@0 149 state->step = Slot->effect.Params.Modulator.Frequency*(1<<WAVEFORM_FRACBITS) /
rlm@0 150 Device->Frequency;
rlm@0 151 if(!state->step)
rlm@0 152 state->step = 1;
rlm@0 153
rlm@0 154 cw = cos(2.0*M_PI * Slot->effect.Params.Modulator.HighPassCutoff /
rlm@0 155 Device->Frequency);
rlm@0 156 a = (2.0f-cw) - aluSqrt(aluPow(2.0f-cw, 2.0f) - 1.0f);
rlm@0 157 state->iirFilter.coeff = a;
rlm@0 158
rlm@0 159 gain = Slot->Gain;
rlm@0 160 for(index = 0;index < MAXCHANNELS;index++)
rlm@0 161 state->Gain[index] = 0.0f;
rlm@0 162 for(index = 0;index < Device->NumChan;index++)
rlm@0 163 {
rlm@0 164 enum Channel chan = Device->Speaker2Chan[index];
rlm@0 165 state->Gain[chan] = gain;
rlm@0 166 }
rlm@0 167 }
rlm@0 168
rlm@0 169 static ALvoid ModulatorProcess(ALeffectState *effect, const ALeffectslot *Slot, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS])
rlm@0 170 {
rlm@0 171 ALmodulatorState *state = (ALmodulatorState*)effect;
rlm@0 172 (void)Slot;
rlm@0 173
rlm@0 174 switch(state->Waveform)
rlm@0 175 {
rlm@0 176 case SINUSOID:
rlm@0 177 ProcessSin(state, SamplesToDo, SamplesIn, SamplesOut);
rlm@0 178 break;
rlm@0 179
rlm@0 180 case SAWTOOTH:
rlm@0 181 ProcessSaw(state, SamplesToDo, SamplesIn, SamplesOut);
rlm@0 182 break;
rlm@0 183
rlm@0 184 case SQUARE:
rlm@0 185 ProcessSquare(state, SamplesToDo, SamplesIn, SamplesOut);
rlm@0 186 break;
rlm@0 187 }
rlm@0 188 }
rlm@0 189
rlm@0 190 ALeffectState *ModulatorCreate(void)
rlm@0 191 {
rlm@0 192 ALmodulatorState *state;
rlm@0 193
rlm@0 194 state = malloc(sizeof(*state));
rlm@0 195 if(!state)
rlm@0 196 return NULL;
rlm@0 197
rlm@0 198 state->state.Destroy = ModulatorDestroy;
rlm@0 199 state->state.DeviceUpdate = ModulatorDeviceUpdate;
rlm@0 200 state->state.Update = ModulatorUpdate;
rlm@0 201 state->state.Process = ModulatorProcess;
rlm@0 202
rlm@0 203 state->index = 0.0f;
rlm@0 204 state->step = 1.0f;
rlm@0 205
rlm@0 206 state->iirFilter.coeff = 0.0f;
rlm@0 207 state->iirFilter.history[0] = 0.0f;
rlm@0 208
rlm@0 209 return &state->state;
rlm@0 210 }