12 #define LOWPASSFREQREF (5000.0f)
13 #define HIGHPASSFREQREF (250.0f)
16 /* Filters implementation is based on the "Cookbook formulae for audio
17 * EQ biquad filter coefficients" by Robert Bristow-Johnson
18 * http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
20 /* Implementation note: For the shelf filters, the specified gain is for the
21 * reference frequency, which is the centerpoint of the transition band. This
22 * better matches EFX filter design. To set the gain for the shelf itself, use
23 * the square root of the desired linear gain (or halve the dB gain).
26 typedef enum ALfilterType
{
27 /** EFX-style low-pass filter, specifying a gain and reference frequency. */
28 ALfilterType_HighShelf
,
29 /** EFX-style high-pass filter, specifying a gain and reference frequency. */
30 ALfilterType_LowShelf
,
31 /** Peaking filter, specifying a gain and reference frequency. */
34 /** Low-pass cut-off filter, specifying a cut-off frequency. */
36 /** High-pass cut-off filter, specifying a cut-off frequency. */
37 ALfilterType_HighPass
,
38 /** Band-pass filter, specifying a center frequency. */
39 ALfilterType_BandPass
,
42 typedef struct ALfilterState
{
43 ALfloat x
[2]; /* History of two last input samples */
44 ALfloat y
[2]; /* History of two last output samples */
45 ALfloat a1
, a2
; /* Transfer function coefficients "a" (a0 is pre-applied) */
46 ALfloat b0
, b1
, b2
; /* Transfer function coefficients "b" */
48 void (*process
)(struct ALfilterState
*self
, ALfloat
*restrict dst
, const ALfloat
*src
, ALuint numsamples
);
50 #define ALfilterState_process(a, ...) ((a)->process((a), __VA_ARGS__))
52 /* Calculates the rcpQ (i.e. 1/Q) coefficient for shelving filters, using the
53 * reference gain and shelf slope parameter.
57 inline ALfloat
calc_rcpQ_from_slope(ALfloat gain
, ALfloat slope
)
59 return sqrtf((gain
+ 1.0f
/gain
)*(1.0f
/slope
- 1.0f
) + 2.0f
);
61 /* Calculates the rcpQ (i.e. 1/Q) coefficient for filters, using the frequency
62 * multiple (i.e. ref_freq / sampling_freq) and bandwidth.
63 * 0 < freq_mult < 0.5.
65 inline ALfloat
calc_rcpQ_from_bandwidth(ALfloat freq_mult
, ALfloat bandwidth
)
67 ALfloat w0
= F_TAU
* freq_mult
;
68 return 2.0f
*sinhf(logf(2.0f
)/2.0f
*bandwidth
*w0
/sinf(w0
));
71 inline void ALfilterState_clear(ALfilterState
*filter
)
79 void ALfilterState_setParams(ALfilterState
*filter
, ALfilterType type
, ALfloat gain
, ALfloat freq_mult
, ALfloat rcpQ
);
81 inline ALfloat
ALfilterState_processSingle(ALfilterState
*filter
, ALfloat sample
)
85 outsmp
= filter
->b0
* sample
+
86 filter
->b1
* filter
->x
[0] +
87 filter
->b2
* filter
->x
[1] -
88 filter
->a1
* filter
->y
[0] -
89 filter
->a2
* filter
->y
[1];
90 filter
->x
[1] = filter
->x
[0];
91 filter
->x
[0] = sample
;
92 filter
->y
[1] = filter
->y
[0];
93 filter
->y
[0] = outsmp
;
98 void ALfilterState_processC(ALfilterState
*filter
, ALfloat
*restrict dst
, const ALfloat
*src
, ALuint numsamples
);
100 inline void ALfilterState_processPassthru(ALfilterState
*filter
, const ALfloat
*src
, ALuint numsamples
)
104 filter
->x
[1] = src
[numsamples
-2];
105 filter
->x
[0] = src
[numsamples
-1];
106 filter
->y
[1] = src
[numsamples
-2];
107 filter
->y
[0] = src
[numsamples
-1];
109 else if(numsamples
== 1)
111 filter
->x
[1] = filter
->x
[0];
112 filter
->x
[0] = src
[0];
113 filter
->y
[1] = filter
->y
[0];
114 filter
->y
[0] = src
[0];
119 typedef struct ALfilter
{
120 // Filter type (AL_FILTER_NULL, ...)
129 void (*SetParami
)(struct ALfilter
*filter
, ALCcontext
*context
, ALenum param
, ALint val
);
130 void (*SetParamiv
)(struct ALfilter
*filter
, ALCcontext
*context
, ALenum param
, const ALint
*vals
);
131 void (*SetParamf
)(struct ALfilter
*filter
, ALCcontext
*context
, ALenum param
, ALfloat val
);
132 void (*SetParamfv
)(struct ALfilter
*filter
, ALCcontext
*context
, ALenum param
, const ALfloat
*vals
);
134 void (*GetParami
)(struct ALfilter
*filter
, ALCcontext
*context
, ALenum param
, ALint
*val
);
135 void (*GetParamiv
)(struct ALfilter
*filter
, ALCcontext
*context
, ALenum param
, ALint
*vals
);
136 void (*GetParamf
)(struct ALfilter
*filter
, ALCcontext
*context
, ALenum param
, ALfloat
*val
);
137 void (*GetParamfv
)(struct ALfilter
*filter
, ALCcontext
*context
, ALenum param
, ALfloat
*vals
);
143 #define ALfilter_SetParami(x, c, p, v) ((x)->SetParami((x),(c),(p),(v)))
144 #define ALfilter_SetParamiv(x, c, p, v) ((x)->SetParamiv((x),(c),(p),(v)))
145 #define ALfilter_SetParamf(x, c, p, v) ((x)->SetParamf((x),(c),(p),(v)))
146 #define ALfilter_SetParamfv(x, c, p, v) ((x)->SetParamfv((x),(c),(p),(v)))
148 #define ALfilter_GetParami(x, c, p, v) ((x)->GetParami((x),(c),(p),(v)))
149 #define ALfilter_GetParamiv(x, c, p, v) ((x)->GetParamiv((x),(c),(p),(v)))
150 #define ALfilter_GetParamf(x, c, p, v) ((x)->GetParamf((x),(c),(p),(v)))
151 #define ALfilter_GetParamfv(x, c, p, v) ((x)->GetParamfv((x),(c),(p),(v)))
153 inline void LockFiltersRead(ALCdevice
*device
)
154 { LockUIntMapRead(&device
->FilterMap
); }
155 inline void UnlockFiltersRead(ALCdevice
*device
)
156 { UnlockUIntMapRead(&device
->FilterMap
); }
157 inline void LockFiltersWrite(ALCdevice
*device
)
158 { LockUIntMapWrite(&device
->FilterMap
); }
159 inline void UnlockFiltersWrite(ALCdevice
*device
)
160 { UnlockUIntMapWrite(&device
->FilterMap
); }
162 inline struct ALfilter
*LookupFilter(ALCdevice
*device
, ALuint id
)
163 { return (struct ALfilter
*)LookupUIntMapKeyNoLock(&device
->FilterMap
, id
); }
164 inline struct ALfilter
*RemoveFilter(ALCdevice
*device
, ALuint id
)
165 { return (struct ALfilter
*)RemoveUIntMapKeyNoLock(&device
->FilterMap
, id
); }
167 ALvoid
ReleaseALFilters(ALCdevice
*device
);