Remove another duplicate function
[openal-soft.git] / Alc / effects / fshifter.c
blob7d72472ae00c67086ac7043183aa52a7693091c7
1 /**
2 * OpenAL cross platform audio library
3 * Copyright (C) 2018 by Raul Herraiz.
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.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
21 #include "config.h"
23 #include <math.h>
24 #include <stdlib.h>
26 #include "alMain.h"
27 #include "alAuxEffectSlot.h"
28 #include "alError.h"
29 #include "alu.h"
30 #include "filters/defs.h"
32 #include "alcomplex.h"
34 #define HIL_SIZE 1024
35 #define OVERSAMP (1<<2)
37 #define HIL_STEP (HIL_SIZE / OVERSAMP)
38 #define FIFO_LATENCY (HIL_STEP * (OVERSAMP-1))
41 typedef struct ALfshifterState {
42 DERIVE_FROM_TYPE(ALeffectState);
44 /* Effect parameters */
45 ALsizei count;
46 ALsizei PhaseStep;
47 ALsizei Phase;
48 ALdouble ld_sign;
50 /*Effects buffers*/
51 ALfloat InFIFO[HIL_SIZE];
52 ALcomplex OutFIFO[HIL_SIZE];
53 ALcomplex OutputAccum[HIL_SIZE];
54 ALcomplex Analytic[HIL_SIZE];
55 ALcomplex Outdata[BUFFERSIZE];
57 alignas(16) ALfloat BufferOut[BUFFERSIZE];
59 /* Effect gains for each output channel */
60 ALfloat CurrentGains[MAX_OUTPUT_CHANNELS];
61 ALfloat TargetGains[MAX_OUTPUT_CHANNELS];
62 } ALfshifterState;
64 static ALvoid ALfshifterState_Destruct(ALfshifterState *state);
65 static ALboolean ALfshifterState_deviceUpdate(ALfshifterState *state, ALCdevice *device);
66 static ALvoid ALfshifterState_update(ALfshifterState *state, const ALCcontext *context, const ALeffectslot *slot, const ALeffectProps *props);
67 static ALvoid ALfshifterState_process(ALfshifterState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
68 DECLARE_DEFAULT_ALLOCATORS(ALfshifterState)
70 DEFINE_ALEFFECTSTATE_VTABLE(ALfshifterState);
72 /* Define a Hann window, used to filter the HIL input and output. */
73 alignas(16) static ALdouble HannWindow[HIL_SIZE];
75 static void InitHannWindow(void)
77 ALsizei i;
79 /* Create lookup table of the Hann window for the desired size, i.e. HIL_SIZE */
80 for(i = 0;i < HIL_SIZE>>1;i++)
82 ALdouble val = sin(M_PI * (ALdouble)i / (ALdouble)(HIL_SIZE-1));
83 HannWindow[i] = HannWindow[HIL_SIZE-1-i] = val * val;
87 static alonce_flag HannInitOnce = AL_ONCE_FLAG_INIT;
89 static void ALfshifterState_Construct(ALfshifterState *state)
91 ALeffectState_Construct(STATIC_CAST(ALeffectState, state));
92 SET_VTABLE2(ALfshifterState, ALeffectState, state);
94 alcall_once(&HannInitOnce, InitHannWindow);
97 static ALvoid ALfshifterState_Destruct(ALfshifterState *state)
99 ALeffectState_Destruct(STATIC_CAST(ALeffectState,state));
102 static ALboolean ALfshifterState_deviceUpdate(ALfshifterState *state, ALCdevice *UNUSED(device))
104 /* (Re-)initializing parameters and clear the buffers. */
105 state->count = FIFO_LATENCY;
106 state->PhaseStep = 0;
107 state->Phase = 0;
108 state->ld_sign = 1.0;
110 memset(state->InFIFO, 0, sizeof(state->InFIFO));
111 memset(state->OutFIFO, 0, sizeof(state->OutFIFO));
112 memset(state->OutputAccum, 0, sizeof(state->OutputAccum));
113 memset(state->Analytic, 0, sizeof(state->Analytic));
115 memset(state->CurrentGains, 0, sizeof(state->CurrentGains));
116 memset(state->TargetGains, 0, sizeof(state->TargetGains));
118 return AL_TRUE;
121 static ALvoid ALfshifterState_update(ALfshifterState *state, const ALCcontext *context, const ALeffectslot *slot, const ALeffectProps *props)
123 const ALCdevice *device = context->Device;
124 ALfloat coeffs[MAX_AMBI_COEFFS];
125 ALfloat step;
127 step = props->Fshifter.Frequency / (ALfloat)device->Frequency;
128 state->PhaseStep = fastf2i(minf(step, 0.5f) * FRACTIONONE);
130 switch(props->Fshifter.LeftDirection)
132 case AL_FREQUENCY_SHIFTER_DIRECTION_DOWN:
133 state->ld_sign = -1.0;
134 break;
136 case AL_FREQUENCY_SHIFTER_DIRECTION_UP:
137 state->ld_sign = 1.0;
138 break;
140 case AL_FREQUENCY_SHIFTER_DIRECTION_OFF:
141 state->Phase = 0;
142 state->PhaseStep = 0;
143 break;
146 CalcAngleCoeffs(0.0f, 0.0f, 0.0f, coeffs);
147 ComputePanGains(&device->Dry, coeffs, slot->Params.Gain, state->TargetGains);
150 static ALvoid ALfshifterState_process(ALfshifterState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
152 static const ALcomplex complex_zero = { 0.0, 0.0 };
153 ALfloat *restrict BufferOut = state->BufferOut;
154 ALsizei j, k, base;
156 for(base = 0;base < SamplesToDo;)
158 ALsizei todo = mini(HIL_SIZE-state->count, SamplesToDo-base);
160 ASSUME(todo > 0);
162 /* Fill FIFO buffer with samples data */
163 k = state->count;
164 for(j = 0;j < todo;j++,k++)
166 state->InFIFO[k] = SamplesIn[0][base+j];
167 state->Outdata[base+j] = state->OutFIFO[k-FIFO_LATENCY];
169 state->count += todo;
170 base += todo;
172 /* Check whether FIFO buffer is filled */
173 if(state->count < HIL_SIZE) continue;
175 state->count = FIFO_LATENCY;
177 /* Real signal windowing and store in Analytic buffer */
178 for(k = 0;k < HIL_SIZE;k++)
180 state->Analytic[k].Real = state->InFIFO[k] * HannWindow[k];
181 state->Analytic[k].Imag = 0.0;
184 /* Processing signal by Discrete Hilbert Transform (analytical signal). */
185 complex_hilbert(state->Analytic, HIL_SIZE);
187 /* Windowing and add to output accumulator */
188 for(k = 0;k < HIL_SIZE;k++)
190 state->OutputAccum[k].Real += 2.0/OVERSAMP*HannWindow[k]*state->Analytic[k].Real;
191 state->OutputAccum[k].Imag += 2.0/OVERSAMP*HannWindow[k]*state->Analytic[k].Imag;
194 /* Shift accumulator, input & output FIFO */
195 for(k = 0;k < HIL_STEP;k++) state->OutFIFO[k] = state->OutputAccum[k];
196 for(j = 0;k < HIL_SIZE;k++,j++) state->OutputAccum[j] = state->OutputAccum[k];
197 for(;j < HIL_SIZE;j++) state->OutputAccum[j] = complex_zero;
198 for(k = 0;k < FIFO_LATENCY;k++)
199 state->InFIFO[k] = state->InFIFO[k+HIL_STEP];
202 /* Process frequency shifter using the analytic signal obtained. */
203 for(k = 0;k < SamplesToDo;k++)
205 ALdouble phase = state->Phase * ((1.0/FRACTIONONE) * 2.0*M_PI);
206 BufferOut[k] = (ALfloat)(state->Outdata[k].Real*cos(phase) +
207 state->Outdata[k].Imag*sin(phase)*state->ld_sign);
209 state->Phase += state->PhaseStep;
210 state->Phase &= FRACTIONMASK;
213 /* Now, mix the processed sound data to the output. */
214 MixSamples(BufferOut, NumChannels, SamplesOut, state->CurrentGains, state->TargetGains,
215 maxi(SamplesToDo, 512), 0, SamplesToDo);
218 typedef struct FshifterStateFactory {
219 DERIVE_FROM_TYPE(EffectStateFactory);
220 } FshifterStateFactory;
222 static ALeffectState *FshifterStateFactory_create(FshifterStateFactory *UNUSED(factory))
224 ALfshifterState *state;
226 NEW_OBJ0(state, ALfshifterState)();
227 if(!state) return NULL;
229 return STATIC_CAST(ALeffectState, state);
232 DEFINE_EFFECTSTATEFACTORY_VTABLE(FshifterStateFactory);
234 EffectStateFactory *FshifterStateFactory_getFactory(void)
236 static FshifterStateFactory FshifterFactory = { { GET_VTABLE2(FshifterStateFactory, EffectStateFactory) } };
238 return STATIC_CAST(EffectStateFactory, &FshifterFactory);
241 void ALfshifter_setParamf(ALeffect *effect, ALCcontext *context, ALenum param, ALfloat val)
243 ALeffectProps *props = &effect->Props;
244 switch(param)
246 case AL_FREQUENCY_SHIFTER_FREQUENCY:
247 if(!(val >= AL_FREQUENCY_SHIFTER_MIN_FREQUENCY && val <= AL_FREQUENCY_SHIFTER_MAX_FREQUENCY))
248 SETERR_RETURN(context, AL_INVALID_VALUE,,"Frequency shifter frequency out of range");
249 props->Fshifter.Frequency = val;
250 break;
252 default:
253 alSetError(context, AL_INVALID_ENUM, "Invalid frequency shifter float property 0x%04x", param);
257 void ALfshifter_setParamfv(ALeffect *effect, ALCcontext *context, ALenum param, const ALfloat *vals)
259 ALfshifter_setParamf(effect, context, param, vals[0]);
262 void ALfshifter_setParami(ALeffect *effect, ALCcontext *context, ALenum param, ALint val)
264 ALeffectProps *props = &effect->Props;
265 switch(param)
267 case AL_FREQUENCY_SHIFTER_LEFT_DIRECTION:
268 if(!(val >= AL_FREQUENCY_SHIFTER_MIN_LEFT_DIRECTION && val <= AL_FREQUENCY_SHIFTER_MAX_LEFT_DIRECTION))
269 SETERR_RETURN(context, AL_INVALID_VALUE,,"Frequency shifter left direction out of range");
270 props->Fshifter.LeftDirection = val;
271 break;
273 case AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION:
274 if(!(val >= AL_FREQUENCY_SHIFTER_MIN_RIGHT_DIRECTION && val <= AL_FREQUENCY_SHIFTER_MAX_RIGHT_DIRECTION))
275 SETERR_RETURN(context, AL_INVALID_VALUE,,"Frequency shifter right direction out of range");
276 props->Fshifter.RightDirection = val;
277 break;
279 default:
280 alSetError(context, AL_INVALID_ENUM, "Invalid frequency shifter integer property 0x%04x", param);
283 void ALfshifter_setParamiv(ALeffect *effect, ALCcontext *context, ALenum param, const ALint *vals)
285 ALfshifter_setParami(effect, context, param, vals[0]);
288 void ALfshifter_getParami(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *val)
290 const ALeffectProps *props = &effect->Props;
291 switch(param)
293 case AL_FREQUENCY_SHIFTER_LEFT_DIRECTION:
294 *val = props->Fshifter.LeftDirection;
295 break;
296 case AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION:
297 *val = props->Fshifter.RightDirection;
298 break;
299 default:
300 alSetError(context, AL_INVALID_ENUM, "Invalid frequency shifter integer property 0x%04x", param);
303 void ALfshifter_getParamiv(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *vals)
305 ALfshifter_getParami(effect, context, param, vals);
308 void ALfshifter_getParamf(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *val)
311 const ALeffectProps *props = &effect->Props;
312 switch(param)
314 case AL_FREQUENCY_SHIFTER_FREQUENCY:
315 *val = props->Fshifter.Frequency;
316 break;
318 default:
319 alSetError(context, AL_INVALID_ENUM, "Invalid frequency shifter float property 0x%04x", param);
324 void ALfshifter_getParamfv(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *vals)
326 ALfshifter_getParamf(effect, context, param, vals);
329 DEFINE_ALEFFECT_VTABLE(ALfshifter);