diff 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
line wrap: on
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/Alc/alcModulator.c	Tue Oct 25 13:02:31 2011 -0700
     1.3 @@ -0,0 +1,210 @@
     1.4 +/**
     1.5 + * OpenAL cross platform audio library
     1.6 + * Copyright (C) 2009 by Chris Robinson.
     1.7 + * This library is free software; you can redistribute it and/or
     1.8 + *  modify it under the terms of the GNU Library General Public
     1.9 + *  License as published by the Free Software Foundation; either
    1.10 + *  version 2 of the License, or (at your option) any later version.
    1.11 + *
    1.12 + * This library is distributed in the hope that it will be useful,
    1.13 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.14 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    1.15 + *  Library General Public License for more details.
    1.16 + *
    1.17 + * You should have received a copy of the GNU Library General Public
    1.18 + *  License along with this library; if not, write to the
    1.19 + *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    1.20 + *  Boston, MA  02111-1307, USA.
    1.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html
    1.22 + */
    1.23 +
    1.24 +#include "config.h"
    1.25 +
    1.26 +#include <math.h>
    1.27 +#include <stdlib.h>
    1.28 +
    1.29 +#include "alMain.h"
    1.30 +#include "alFilter.h"
    1.31 +#include "alAuxEffectSlot.h"
    1.32 +#include "alError.h"
    1.33 +#include "alu.h"
    1.34 +
    1.35 +
    1.36 +typedef struct ALmodulatorState {
    1.37 +    // Must be first in all effects!
    1.38 +    ALeffectState state;
    1.39 +
    1.40 +    enum {
    1.41 +        SINUSOID,
    1.42 +        SAWTOOTH,
    1.43 +        SQUARE
    1.44 +    } Waveform;
    1.45 +
    1.46 +    ALuint index;
    1.47 +    ALuint step;
    1.48 +
    1.49 +    ALfloat Gain[MAXCHANNELS];
    1.50 +
    1.51 +    FILTER iirFilter;
    1.52 +    ALfloat history[1];
    1.53 +} ALmodulatorState;
    1.54 +
    1.55 +#define WAVEFORM_FRACBITS  16
    1.56 +#define WAVEFORM_FRACMASK  ((1<<WAVEFORM_FRACBITS)-1)
    1.57 +
    1.58 +static __inline ALdouble Sin(ALuint index)
    1.59 +{
    1.60 +    return sin(index * (M_PI*2.0 / (1<<WAVEFORM_FRACBITS)));
    1.61 +}
    1.62 +
    1.63 +static __inline ALdouble Saw(ALuint index)
    1.64 +{
    1.65 +    return index*(2.0/(1<<WAVEFORM_FRACBITS)) - 1.0;
    1.66 +}
    1.67 +
    1.68 +static __inline ALdouble Square(ALuint index)
    1.69 +{
    1.70 +    return (index&(1<<(WAVEFORM_FRACBITS-1))) ? -1.0 : 1.0;
    1.71 +}
    1.72 +
    1.73 +
    1.74 +static __inline ALfloat hpFilter1P(FILTER *iir, ALuint offset, ALfloat input)
    1.75 +{
    1.76 +    ALfloat *history = &iir->history[offset];
    1.77 +    ALfloat a = iir->coeff;
    1.78 +    ALfloat output = input;
    1.79 +
    1.80 +    output = output + (history[0]-output)*a;
    1.81 +    history[0] = output;
    1.82 +
    1.83 +    return input - output;
    1.84 +}
    1.85 +
    1.86 +
    1.87 +#define DECL_TEMPLATE(func)                                                   \
    1.88 +static void Process##func(ALmodulatorState *state, ALuint SamplesToDo,        \
    1.89 +  const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS])               \
    1.90 +{                                                                             \
    1.91 +    const ALuint step = state->step;                                          \
    1.92 +    ALuint index = state->index;                                              \
    1.93 +    ALfloat samp;                                                             \
    1.94 +    ALuint i;                                                                 \
    1.95 +                                                                              \
    1.96 +    for(i = 0;i < SamplesToDo;i++)                                            \
    1.97 +    {                                                                         \
    1.98 +        samp = SamplesIn[i];                                                  \
    1.99 +                                                                              \
   1.100 +        index += step;                                                        \
   1.101 +        index &= WAVEFORM_FRACMASK;                                           \
   1.102 +        samp *= func(index);                                                  \
   1.103 +                                                                              \
   1.104 +        samp = hpFilter1P(&state->iirFilter, 0, samp);                        \
   1.105 +                                                                              \
   1.106 +        SamplesOut[i][FRONT_LEFT]   += state->Gain[FRONT_LEFT]   * samp;      \
   1.107 +        SamplesOut[i][FRONT_RIGHT]  += state->Gain[FRONT_RIGHT]  * samp;      \
   1.108 +        SamplesOut[i][FRONT_CENTER] += state->Gain[FRONT_CENTER] * samp;      \
   1.109 +        SamplesOut[i][SIDE_LEFT]    += state->Gain[SIDE_LEFT]    * samp;      \
   1.110 +        SamplesOut[i][SIDE_RIGHT]   += state->Gain[SIDE_RIGHT]   * samp;      \
   1.111 +        SamplesOut[i][BACK_LEFT]    += state->Gain[BACK_LEFT]    * samp;      \
   1.112 +        SamplesOut[i][BACK_RIGHT]   += state->Gain[BACK_RIGHT]   * samp;      \
   1.113 +        SamplesOut[i][BACK_CENTER]  += state->Gain[BACK_CENTER]  * samp;      \
   1.114 +    }                                                                         \
   1.115 +    state->index = index;                                                     \
   1.116 +}
   1.117 +
   1.118 +DECL_TEMPLATE(Sin)
   1.119 +DECL_TEMPLATE(Saw)
   1.120 +DECL_TEMPLATE(Square)
   1.121 +
   1.122 +#undef DECL_TEMPLATE
   1.123 +
   1.124 +
   1.125 +static ALvoid ModulatorDestroy(ALeffectState *effect)
   1.126 +{
   1.127 +    ALmodulatorState *state = (ALmodulatorState*)effect;
   1.128 +    free(state);
   1.129 +}
   1.130 +
   1.131 +static ALboolean ModulatorDeviceUpdate(ALeffectState *effect, ALCdevice *Device)
   1.132 +{
   1.133 +    return AL_TRUE;
   1.134 +    (void)effect;
   1.135 +    (void)Device;
   1.136 +}
   1.137 +
   1.138 +static ALvoid ModulatorUpdate(ALeffectState *effect, ALCcontext *Context, const ALeffectslot *Slot)
   1.139 +{
   1.140 +    ALmodulatorState *state = (ALmodulatorState*)effect;
   1.141 +    ALCdevice *Device = Context->Device;
   1.142 +    ALfloat gain, cw, a = 0.0f;
   1.143 +    ALuint index;
   1.144 +
   1.145 +    if(Slot->effect.Params.Modulator.Waveform == AL_RING_MODULATOR_SINUSOID)
   1.146 +        state->Waveform = SINUSOID;
   1.147 +    else if(Slot->effect.Params.Modulator.Waveform == AL_RING_MODULATOR_SAWTOOTH)
   1.148 +        state->Waveform = SAWTOOTH;
   1.149 +    else if(Slot->effect.Params.Modulator.Waveform == AL_RING_MODULATOR_SQUARE)
   1.150 +        state->Waveform = SQUARE;
   1.151 +
   1.152 +    state->step = Slot->effect.Params.Modulator.Frequency*(1<<WAVEFORM_FRACBITS) /
   1.153 +                  Device->Frequency;
   1.154 +    if(!state->step)
   1.155 +        state->step = 1;
   1.156 +
   1.157 +    cw = cos(2.0*M_PI * Slot->effect.Params.Modulator.HighPassCutoff /
   1.158 +                        Device->Frequency);
   1.159 +    a = (2.0f-cw) - aluSqrt(aluPow(2.0f-cw, 2.0f) - 1.0f);
   1.160 +    state->iirFilter.coeff = a;
   1.161 +
   1.162 +    gain = Slot->Gain;
   1.163 +    for(index = 0;index < MAXCHANNELS;index++)
   1.164 +        state->Gain[index] = 0.0f;
   1.165 +    for(index = 0;index < Device->NumChan;index++)
   1.166 +    {
   1.167 +        enum Channel chan = Device->Speaker2Chan[index];
   1.168 +        state->Gain[chan] = gain;
   1.169 +    }
   1.170 +}
   1.171 +
   1.172 +static ALvoid ModulatorProcess(ALeffectState *effect, const ALeffectslot *Slot, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS])
   1.173 +{
   1.174 +    ALmodulatorState *state = (ALmodulatorState*)effect;
   1.175 +    (void)Slot;
   1.176 +
   1.177 +    switch(state->Waveform)
   1.178 +    {
   1.179 +        case SINUSOID:
   1.180 +            ProcessSin(state, SamplesToDo, SamplesIn, SamplesOut);
   1.181 +            break;
   1.182 +
   1.183 +        case SAWTOOTH:
   1.184 +            ProcessSaw(state, SamplesToDo, SamplesIn, SamplesOut);
   1.185 +            break;
   1.186 +
   1.187 +        case SQUARE:
   1.188 +            ProcessSquare(state, SamplesToDo, SamplesIn, SamplesOut);
   1.189 +            break;
   1.190 +    }
   1.191 +}
   1.192 +
   1.193 +ALeffectState *ModulatorCreate(void)
   1.194 +{
   1.195 +    ALmodulatorState *state;
   1.196 +
   1.197 +    state = malloc(sizeof(*state));
   1.198 +    if(!state)
   1.199 +        return NULL;
   1.200 +
   1.201 +    state->state.Destroy = ModulatorDestroy;
   1.202 +    state->state.DeviceUpdate = ModulatorDeviceUpdate;
   1.203 +    state->state.Update = ModulatorUpdate;
   1.204 +    state->state.Process = ModulatorProcess;
   1.205 +
   1.206 +    state->index = 0.0f;
   1.207 +    state->step = 1.0f;
   1.208 +
   1.209 +    state->iirFilter.coeff = 0.0f;
   1.210 +    state->iirFilter.history[0] = 0.0f;
   1.211 +
   1.212 +    return &state->state;
   1.213 +}