2 * OpenAL cross platform audio library
3 * Copyright (C) 2013 by Anis A. Hireche
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
26 #include "alAuxEffectSlot.h"
30 typedef struct ALcompressorState
{
31 DERIVE_FROM_TYPE(ALeffectState
);
33 /* Effect gains for each channel */
34 ALfloat Gain
[MaxChannels
];
36 /* Effect parameters */
43 static ALvoid
ALcompressorState_Destruct(ALcompressorState
*UNUSED(state
))
47 static ALboolean
ALcompressorState_deviceUpdate(ALcompressorState
*state
, ALCdevice
*device
)
49 const ALfloat attackTime
= device
->Frequency
* 0.2f
; /* 200ms Attack */
50 const ALfloat releaseTime
= device
->Frequency
* 0.4f
; /* 400ms Release */
52 state
->AttackRate
= 1.0f
/ attackTime
;
53 state
->ReleaseRate
= 1.0f
/ releaseTime
;
58 static ALvoid
ALcompressorState_update(ALcompressorState
*state
, ALCdevice
*Device
, const ALeffectslot
*Slot
)
62 state
->Enabled
= Slot
->EffectProps
.Compressor
.OnOff
;
64 gain
= sqrtf(1.0f
/ Device
->NumChan
) * Slot
->Gain
;
65 SetGains(Device
, gain
, state
->Gain
);
68 static ALvoid
ALcompressorState_process(ALcompressorState
*state
, ALuint SamplesToDo
, const ALfloat
*SamplesIn
, ALfloat (*SamplesOut
)[BUFFERSIZE
])
73 for(base
= 0;base
< SamplesToDo
;)
76 ALuint td
= minu(SamplesToDo
-base
, 64);
80 ALfloat output
, smp
, amplitude
;
81 ALfloat gain
= state
->GainCtrl
;
83 for(it
= 0;it
< td
;it
++)
85 smp
= SamplesIn
[it
+base
];
87 amplitude
= fabsf(smp
);
89 gain
= minf(gain
+state
->AttackRate
, amplitude
);
90 else if(amplitude
< gain
)
91 gain
= maxf(gain
-state
->ReleaseRate
, amplitude
);
92 output
= 1.0f
/ clampf(gain
, 0.5f
, 2.0f
);
94 temps
[it
] = smp
* output
;
97 state
->GainCtrl
= gain
;
101 ALfloat output
, smp
, amplitude
;
102 ALfloat gain
= state
->GainCtrl
;
104 for(it
= 0;it
< td
;it
++)
106 smp
= SamplesIn
[it
+base
];
110 gain
= minf(gain
+state
->AttackRate
, amplitude
);
111 else if(amplitude
< gain
)
112 gain
= maxf(gain
-state
->ReleaseRate
, amplitude
);
113 output
= 1.0f
/ clampf(gain
, 0.5f
, 2.0f
);
115 temps
[it
] = smp
* output
;
118 state
->GainCtrl
= gain
;
122 for(kt
= 0;kt
< MaxChannels
;kt
++)
124 ALfloat gain
= state
->Gain
[kt
];
125 if(!(gain
> GAIN_SILENCE_THRESHOLD
))
128 for(it
= 0;it
< td
;it
++)
129 SamplesOut
[kt
][base
+it
] += gain
* temps
[it
];
136 DECLARE_DEFAULT_ALLOCATORS(ALcompressorState
)
138 DEFINE_ALEFFECTSTATE_VTABLE(ALcompressorState
);
141 typedef struct ALcompressorStateFactory
{
142 DERIVE_FROM_TYPE(ALeffectStateFactory
);
143 } ALcompressorStateFactory
;
145 static ALeffectState
*ALcompressorStateFactory_create(ALcompressorStateFactory
*UNUSED(factory
))
147 ALcompressorState
*state
;
149 state
= ALcompressorState_New(sizeof(*state
));
150 if(!state
) return NULL
;
151 SET_VTABLE2(ALcompressorState
, ALeffectState
, state
);
153 state
->Enabled
= AL_TRUE
;
154 state
->AttackRate
= 0.0f
;
155 state
->ReleaseRate
= 0.0f
;
156 state
->GainCtrl
= 1.0f
;
158 return STATIC_CAST(ALeffectState
, state
);
161 DEFINE_ALEFFECTSTATEFACTORY_VTABLE(ALcompressorStateFactory
);
163 ALeffectStateFactory
*ALcompressorStateFactory_getFactory(void)
165 static ALcompressorStateFactory CompressorFactory
= { { GET_VTABLE2(ALcompressorStateFactory
, ALeffectStateFactory
) } };
167 return STATIC_CAST(ALeffectStateFactory
, &CompressorFactory
);
171 void ALcompressor_setParami(ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALint val
)
173 ALeffectProps
*props
= &effect
->Props
;
176 case AL_COMPRESSOR_ONOFF
:
177 if(!(val
>= AL_COMPRESSOR_MIN_ONOFF
&& val
<= AL_COMPRESSOR_MAX_ONOFF
))
178 SET_ERROR_AND_RETURN(context
, AL_INVALID_VALUE
);
179 props
->Compressor
.OnOff
= val
;
183 SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
);
186 void ALcompressor_setParamiv(ALeffect
*effect
, ALCcontext
*context
, ALenum param
, const ALint
*vals
)
188 ALcompressor_setParami(effect
, context
, param
, vals
[0]);
190 void ALcompressor_setParamf(ALeffect
*UNUSED(effect
), ALCcontext
*context
, ALenum
UNUSED(param
), ALfloat
UNUSED(val
))
191 { SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
); }
192 void ALcompressor_setParamfv(ALeffect
*effect
, ALCcontext
*context
, ALenum param
, const ALfloat
*vals
)
194 ALcompressor_setParamf(effect
, context
, param
, vals
[0]);
197 void ALcompressor_getParami(const ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALint
*val
)
199 const ALeffectProps
*props
= &effect
->Props
;
202 case AL_COMPRESSOR_ONOFF
:
203 *val
= props
->Compressor
.OnOff
;
206 SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
);
209 void ALcompressor_getParamiv(const ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALint
*vals
)
211 ALcompressor_getParami(effect
, context
, param
, vals
);
213 void ALcompressor_getParamf(const ALeffect
*UNUSED(effect
), ALCcontext
*context
, ALenum
UNUSED(param
), ALfloat
*UNUSED(val
))
214 { SET_ERROR_AND_RETURN(context
, AL_INVALID_ENUM
); }
215 void ALcompressor_getParamfv(const ALeffect
*effect
, ALCcontext
*context
, ALenum param
, ALfloat
*vals
)
217 ALcompressor_getParamf(effect
, context
, param
, vals
);
220 DEFINE_ALEFFECT_VTABLE(ALcompressor
);