2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
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
28 #include "alcontext.h"
34 #define FILTER_MIN_GAIN 0.0f
35 #define FILTER_MAX_GAIN 4.0f /* +12dB */
37 static ALfilter
*AllocFilter(ALCcontext
*context
);
38 static void FreeFilter(ALCdevice
*device
, ALfilter
*filter
);
39 static void InitFilterParams(ALfilter
*filter
, ALenum type
);
41 static inline ALfilter
*LookupFilter(ALCdevice
*device
, ALuint id
)
43 ALuint lidx
= (id
-1) >> 6;
44 ALsizei slidx
= (id
-1) & 0x3f;
46 if(UNLIKELY(lidx
>= device
->FilterList
.size()))
48 FilterSubList
&sublist
= device
->FilterList
[lidx
];
49 if(UNLIKELY(sublist
.FreeMask
& (U64(1)<<slidx
)))
51 return sublist
.Filters
+ slidx
;
55 AL_API ALvoid AL_APIENTRY
alGenFilters(ALsizei n
, ALuint
*filters
)
60 context
= GetContextRef();
64 alSetError(context
, AL_INVALID_VALUE
, "Generating %d filters", n
);
65 else for(cur
= 0;cur
< n
;cur
++)
67 ALfilter
*filter
= AllocFilter(context
);
70 alDeleteFilters(cur
, filters
);
74 filters
[cur
] = filter
->id
;
77 ALCcontext_DecRef(context
);
80 AL_API ALvoid AL_APIENTRY
alDeleteFilters(ALsizei n
, const ALuint
*filters
)
87 context
= GetContextRef();
90 device
= context
->Device
;
91 LockFilterList(device
);
93 SETERR_GOTO(context
, AL_INVALID_VALUE
, done
, "Deleting %d filters", n
);
96 if(filters
[i
] && LookupFilter(device
, filters
[i
]) == NULL
)
97 SETERR_GOTO(context
, AL_INVALID_NAME
, done
, "Invalid filter ID %u", filters
[i
]);
101 if((filter
=LookupFilter(device
, filters
[i
])) != NULL
)
102 FreeFilter(device
, filter
);
106 UnlockFilterList(device
);
107 ALCcontext_DecRef(context
);
110 AL_API ALboolean AL_APIENTRY
alIsFilter(ALuint filter
)
115 Context
= GetContextRef();
116 if(!Context
) return AL_FALSE
;
118 LockFilterList(Context
->Device
);
119 result
= ((!filter
|| LookupFilter(Context
->Device
, filter
)) ?
121 UnlockFilterList(Context
->Device
);
123 ALCcontext_DecRef(Context
);
128 AL_API ALvoid AL_APIENTRY
alFilteri(ALuint filter
, ALenum param
, ALint value
)
134 Context
= GetContextRef();
137 Device
= Context
->Device
;
138 LockFilterList(Device
);
139 if((ALFilter
=LookupFilter(Device
, filter
)) == NULL
)
140 alSetError(Context
, AL_INVALID_NAME
, "Invalid filter ID %u", filter
);
143 if(param
== AL_FILTER_TYPE
)
145 if(value
== AL_FILTER_NULL
|| value
== AL_FILTER_LOWPASS
||
146 value
== AL_FILTER_HIGHPASS
|| value
== AL_FILTER_BANDPASS
)
147 InitFilterParams(ALFilter
, value
);
149 alSetError(Context
, AL_INVALID_VALUE
, "Invalid filter type 0x%04x", value
);
153 /* Call the appropriate handler */
154 ALfilter_setParami(ALFilter
, Context
, param
, value
);
157 UnlockFilterList(Device
);
159 ALCcontext_DecRef(Context
);
162 AL_API ALvoid AL_APIENTRY
alFilteriv(ALuint filter
, ALenum param
, const ALint
*values
)
171 alFilteri(filter
, param
, values
[0]);
175 Context
= GetContextRef();
178 Device
= Context
->Device
;
179 LockFilterList(Device
);
180 if((ALFilter
=LookupFilter(Device
, filter
)) == NULL
)
181 alSetError(Context
, AL_INVALID_NAME
, "Invalid filter ID %u", filter
);
184 /* Call the appropriate handler */
185 ALfilter_setParamiv(ALFilter
, Context
, param
, values
);
187 UnlockFilterList(Device
);
189 ALCcontext_DecRef(Context
);
192 AL_API ALvoid AL_APIENTRY
alFilterf(ALuint filter
, ALenum param
, ALfloat value
)
198 Context
= GetContextRef();
201 Device
= Context
->Device
;
202 LockFilterList(Device
);
203 if((ALFilter
=LookupFilter(Device
, filter
)) == NULL
)
204 alSetError(Context
, AL_INVALID_NAME
, "Invalid filter ID %u", filter
);
207 /* Call the appropriate handler */
208 ALfilter_setParamf(ALFilter
, Context
, param
, value
);
210 UnlockFilterList(Device
);
212 ALCcontext_DecRef(Context
);
215 AL_API ALvoid AL_APIENTRY
alFilterfv(ALuint filter
, ALenum param
, const ALfloat
*values
)
221 Context
= GetContextRef();
224 Device
= Context
->Device
;
225 LockFilterList(Device
);
226 if((ALFilter
=LookupFilter(Device
, filter
)) == NULL
)
227 alSetError(Context
, AL_INVALID_NAME
, "Invalid filter ID %u", filter
);
230 /* Call the appropriate handler */
231 ALfilter_setParamfv(ALFilter
, Context
, param
, values
);
233 UnlockFilterList(Device
);
235 ALCcontext_DecRef(Context
);
238 AL_API ALvoid AL_APIENTRY
alGetFilteri(ALuint filter
, ALenum param
, ALint
*value
)
244 Context
= GetContextRef();
247 Device
= Context
->Device
;
248 LockFilterList(Device
);
249 if((ALFilter
=LookupFilter(Device
, filter
)) == NULL
)
250 alSetError(Context
, AL_INVALID_NAME
, "Invalid filter ID %u", filter
);
253 if(param
== AL_FILTER_TYPE
)
254 *value
= ALFilter
->type
;
257 /* Call the appropriate handler */
258 ALfilter_getParami(ALFilter
, Context
, param
, value
);
261 UnlockFilterList(Device
);
263 ALCcontext_DecRef(Context
);
266 AL_API ALvoid AL_APIENTRY
alGetFilteriv(ALuint filter
, ALenum param
, ALint
*values
)
275 alGetFilteri(filter
, param
, values
);
279 Context
= GetContextRef();
282 Device
= Context
->Device
;
283 LockFilterList(Device
);
284 if((ALFilter
=LookupFilter(Device
, filter
)) == NULL
)
285 alSetError(Context
, AL_INVALID_NAME
, "Invalid filter ID %u", filter
);
288 /* Call the appropriate handler */
289 ALfilter_getParamiv(ALFilter
, Context
, param
, values
);
291 UnlockFilterList(Device
);
293 ALCcontext_DecRef(Context
);
296 AL_API ALvoid AL_APIENTRY
alGetFilterf(ALuint filter
, ALenum param
, ALfloat
*value
)
302 Context
= GetContextRef();
305 Device
= Context
->Device
;
306 LockFilterList(Device
);
307 if((ALFilter
=LookupFilter(Device
, filter
)) == NULL
)
308 alSetError(Context
, AL_INVALID_NAME
, "Invalid filter ID %u", filter
);
311 /* Call the appropriate handler */
312 ALfilter_getParamf(ALFilter
, Context
, param
, value
);
314 UnlockFilterList(Device
);
316 ALCcontext_DecRef(Context
);
319 AL_API ALvoid AL_APIENTRY
alGetFilterfv(ALuint filter
, ALenum param
, ALfloat
*values
)
325 Context
= GetContextRef();
328 Device
= Context
->Device
;
329 LockFilterList(Device
);
330 if((ALFilter
=LookupFilter(Device
, filter
)) == NULL
)
331 alSetError(Context
, AL_INVALID_NAME
, "Invalid filter ID %u", filter
);
334 /* Call the appropriate handler */
335 ALfilter_getParamfv(ALFilter
, Context
, param
, values
);
337 UnlockFilterList(Device
);
339 ALCcontext_DecRef(Context
);
343 static void ALlowpass_setParami(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, ALint
UNUSED(val
))
344 { alSetError(context
, AL_INVALID_ENUM
, "Invalid low-pass integer property 0x%04x", param
); }
345 static void ALlowpass_setParamiv(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, const ALint
*UNUSED(vals
))
346 { alSetError(context
, AL_INVALID_ENUM
, "Invalid low-pass integer-vector property 0x%04x", param
); }
347 static void ALlowpass_setParamf(ALfilter
*filter
, ALCcontext
*context
, ALenum param
, ALfloat val
)
351 case AL_LOWPASS_GAIN
:
352 if(!(val
>= FILTER_MIN_GAIN
&& val
<= FILTER_MAX_GAIN
))
353 SETERR_RETURN(context
, AL_INVALID_VALUE
,, "Low-pass gain %f out of range", val
);
357 case AL_LOWPASS_GAINHF
:
358 if(!(val
>= AL_LOWPASS_MIN_GAINHF
&& val
<= AL_LOWPASS_MAX_GAINHF
))
359 SETERR_RETURN(context
, AL_INVALID_VALUE
,, "Low-pass gainhf %f out of range", val
);
360 filter
->GainHF
= val
;
364 alSetError(context
, AL_INVALID_ENUM
, "Invalid low-pass float property 0x%04x", param
);
367 static void ALlowpass_setParamfv(ALfilter
*filter
, ALCcontext
*context
, ALenum param
, const ALfloat
*vals
)
368 { ALlowpass_setParamf(filter
, context
, param
, vals
[0]); }
370 static void ALlowpass_getParami(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, ALint
*UNUSED(val
))
371 { alSetError(context
, AL_INVALID_ENUM
, "Invalid low-pass integer property 0x%04x", param
); }
372 static void ALlowpass_getParamiv(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, ALint
*UNUSED(vals
))
373 { alSetError(context
, AL_INVALID_ENUM
, "Invalid low-pass integer-vector property 0x%04x", param
); }
374 static void ALlowpass_getParamf(ALfilter
*filter
, ALCcontext
*context
, ALenum param
, ALfloat
*val
)
378 case AL_LOWPASS_GAIN
:
382 case AL_LOWPASS_GAINHF
:
383 *val
= filter
->GainHF
;
387 alSetError(context
, AL_INVALID_ENUM
, "Invalid low-pass float property 0x%04x", param
);
390 static void ALlowpass_getParamfv(ALfilter
*filter
, ALCcontext
*context
, ALenum param
, ALfloat
*vals
)
391 { ALlowpass_getParamf(filter
, context
, param
, vals
); }
393 DEFINE_ALFILTER_VTABLE(ALlowpass
);
396 static void ALhighpass_setParami(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, ALint
UNUSED(val
))
397 { alSetError(context
, AL_INVALID_ENUM
, "Invalid high-pass integer property 0x%04x", param
); }
398 static void ALhighpass_setParamiv(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, const ALint
*UNUSED(vals
))
399 { alSetError(context
, AL_INVALID_ENUM
, "Invalid high-pass integer-vector property 0x%04x", param
); }
400 static void ALhighpass_setParamf(ALfilter
*filter
, ALCcontext
*context
, ALenum param
, ALfloat val
)
404 case AL_HIGHPASS_GAIN
:
405 if(!(val
>= FILTER_MIN_GAIN
&& val
<= FILTER_MAX_GAIN
))
406 SETERR_RETURN(context
, AL_INVALID_VALUE
,, "High-pass gain out of range");
410 case AL_HIGHPASS_GAINLF
:
411 if(!(val
>= AL_HIGHPASS_MIN_GAINLF
&& val
<= AL_HIGHPASS_MAX_GAINLF
))
412 SETERR_RETURN(context
, AL_INVALID_VALUE
,, "High-pass gainlf out of range");
413 filter
->GainLF
= val
;
417 alSetError(context
, AL_INVALID_ENUM
, "Invalid high-pass float property 0x%04x", param
);
420 static void ALhighpass_setParamfv(ALfilter
*filter
, ALCcontext
*context
, ALenum param
, const ALfloat
*vals
)
421 { ALhighpass_setParamf(filter
, context
, param
, vals
[0]); }
423 static void ALhighpass_getParami(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, ALint
*UNUSED(val
))
424 { alSetError(context
, AL_INVALID_ENUM
, "Invalid high-pass integer property 0x%04x", param
); }
425 static void ALhighpass_getParamiv(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, ALint
*UNUSED(vals
))
426 { alSetError(context
, AL_INVALID_ENUM
, "Invalid high-pass integer-vector property 0x%04x", param
); }
427 static void ALhighpass_getParamf(ALfilter
*filter
, ALCcontext
*context
, ALenum param
, ALfloat
*val
)
431 case AL_HIGHPASS_GAIN
:
435 case AL_HIGHPASS_GAINLF
:
436 *val
= filter
->GainLF
;
440 alSetError(context
, AL_INVALID_ENUM
, "Invalid high-pass float property 0x%04x", param
);
443 static void ALhighpass_getParamfv(ALfilter
*filter
, ALCcontext
*context
, ALenum param
, ALfloat
*vals
)
444 { ALhighpass_getParamf(filter
, context
, param
, vals
); }
446 DEFINE_ALFILTER_VTABLE(ALhighpass
);
449 static void ALbandpass_setParami(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, ALint
UNUSED(val
))
450 { alSetError(context
, AL_INVALID_ENUM
, "Invalid band-pass integer property 0x%04x", param
); }
451 static void ALbandpass_setParamiv(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, const ALint
*UNUSED(vals
))
452 { alSetError(context
, AL_INVALID_ENUM
, "Invalid band-pass integer-vector property 0x%04x", param
); }
453 static void ALbandpass_setParamf(ALfilter
*filter
, ALCcontext
*context
, ALenum param
, ALfloat val
)
457 case AL_BANDPASS_GAIN
:
458 if(!(val
>= FILTER_MIN_GAIN
&& val
<= FILTER_MAX_GAIN
))
459 SETERR_RETURN(context
, AL_INVALID_VALUE
,, "Band-pass gain out of range");
463 case AL_BANDPASS_GAINHF
:
464 if(!(val
>= AL_BANDPASS_MIN_GAINHF
&& val
<= AL_BANDPASS_MAX_GAINHF
))
465 SETERR_RETURN(context
, AL_INVALID_VALUE
,, "Band-pass gainhf out of range");
466 filter
->GainHF
= val
;
469 case AL_BANDPASS_GAINLF
:
470 if(!(val
>= AL_BANDPASS_MIN_GAINLF
&& val
<= AL_BANDPASS_MAX_GAINLF
))
471 SETERR_RETURN(context
, AL_INVALID_VALUE
,, "Band-pass gainlf out of range");
472 filter
->GainLF
= val
;
476 alSetError(context
, AL_INVALID_ENUM
, "Invalid band-pass float property 0x%04x", param
);
479 static void ALbandpass_setParamfv(ALfilter
*filter
, ALCcontext
*context
, ALenum param
, const ALfloat
*vals
)
480 { ALbandpass_setParamf(filter
, context
, param
, vals
[0]); }
482 static void ALbandpass_getParami(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, ALint
*UNUSED(val
))
483 { alSetError(context
, AL_INVALID_ENUM
, "Invalid band-pass integer property 0x%04x", param
); }
484 static void ALbandpass_getParamiv(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, ALint
*UNUSED(vals
))
485 { alSetError(context
, AL_INVALID_ENUM
, "Invalid band-pass integer-vector property 0x%04x", param
); }
486 static void ALbandpass_getParamf(ALfilter
*filter
, ALCcontext
*context
, ALenum param
, ALfloat
*val
)
490 case AL_BANDPASS_GAIN
:
494 case AL_BANDPASS_GAINHF
:
495 *val
= filter
->GainHF
;
498 case AL_BANDPASS_GAINLF
:
499 *val
= filter
->GainLF
;
503 alSetError(context
, AL_INVALID_ENUM
, "Invalid band-pass float property 0x%04x", param
);
506 static void ALbandpass_getParamfv(ALfilter
*filter
, ALCcontext
*context
, ALenum param
, ALfloat
*vals
)
507 { ALbandpass_getParamf(filter
, context
, param
, vals
); }
509 DEFINE_ALFILTER_VTABLE(ALbandpass
);
512 static void ALnullfilter_setParami(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, ALint
UNUSED(val
))
513 { alSetError(context
, AL_INVALID_ENUM
, "Invalid null filter property 0x%04x", param
); }
514 static void ALnullfilter_setParamiv(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, const ALint
*UNUSED(vals
))
515 { alSetError(context
, AL_INVALID_ENUM
, "Invalid null filter property 0x%04x", param
); }
516 static void ALnullfilter_setParamf(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, ALfloat
UNUSED(val
))
517 { alSetError(context
, AL_INVALID_ENUM
, "Invalid null filter property 0x%04x", param
); }
518 static void ALnullfilter_setParamfv(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, const ALfloat
*UNUSED(vals
))
519 { alSetError(context
, AL_INVALID_ENUM
, "Invalid null filter property 0x%04x", param
); }
521 static void ALnullfilter_getParami(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, ALint
*UNUSED(val
))
522 { alSetError(context
, AL_INVALID_ENUM
, "Invalid null filter property 0x%04x", param
); }
523 static void ALnullfilter_getParamiv(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, ALint
*UNUSED(vals
))
524 { alSetError(context
, AL_INVALID_ENUM
, "Invalid null filter property 0x%04x", param
); }
525 static void ALnullfilter_getParamf(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, ALfloat
*UNUSED(val
))
526 { alSetError(context
, AL_INVALID_ENUM
, "Invalid null filter property 0x%04x", param
); }
527 static void ALnullfilter_getParamfv(ALfilter
*UNUSED(filter
), ALCcontext
*context
, ALenum param
, ALfloat
*UNUSED(vals
))
528 { alSetError(context
, AL_INVALID_ENUM
, "Invalid null filter property 0x%04x", param
); }
530 DEFINE_ALFILTER_VTABLE(ALnullfilter
);
533 static ALfilter
*AllocFilter(ALCcontext
*context
)
535 ALCdevice
*device
= context
->Device
;
536 almtx_lock(&device
->FilterLock
);
538 auto sublist
= std::find_if(device
->FilterList
.begin(), device
->FilterList
.end(),
539 [](const FilterSubList
&entry
) noexcept
-> bool
540 { return entry
.FreeMask
!= 0; }
543 auto lidx
= std::distance(device
->FilterList
.begin(), sublist
);
544 ALfilter
*filter
{nullptr};
546 if(LIKELY(sublist
!= device
->FilterList
.end()))
548 slidx
= CTZ64(sublist
->FreeMask
);
549 filter
= sublist
->Filters
+ slidx
;
553 /* Don't allocate so many list entries that the 32-bit ID could
556 if(UNLIKELY(device
->FilterList
.size() >= 1<<25))
558 almtx_unlock(&device
->FilterLock
);
559 alSetError(context
, AL_OUT_OF_MEMORY
, "Too many filters allocated");
562 device
->FilterList
.emplace_back();
563 sublist
= device
->FilterList
.end() - 1;
564 sublist
->FreeMask
= ~U64(0);
565 sublist
->Filters
= static_cast<ALfilter
*>(al_calloc(16, sizeof(ALfilter
)*64));
566 if(UNLIKELY(!sublist
->Filters
))
568 device
->FilterList
.pop_back();
569 almtx_unlock(&device
->FilterLock
);
570 alSetError(context
, AL_OUT_OF_MEMORY
, "Failed to allocate filter batch");
575 filter
= sublist
->Filters
+ slidx
;
578 filter
= new (filter
) ALfilter
{};
579 InitFilterParams(filter
, AL_FILTER_NULL
);
581 /* Add 1 to avoid filter ID 0. */
582 filter
->id
= ((lidx
<<6) | slidx
) + 1;
584 sublist
->FreeMask
&= ~(U64(1)<<slidx
);
585 almtx_unlock(&device
->FilterLock
);
590 static void FreeFilter(ALCdevice
*device
, ALfilter
*filter
)
592 ALuint id
= filter
->id
- 1;
593 ALsizei lidx
= id
>> 6;
594 ALsizei slidx
= id
& 0x3f;
598 device
->FilterList
[lidx
].FreeMask
|= U64(1) << slidx
;
601 void ReleaseALFilters(ALCdevice
*device
)
604 for(auto &sublist
: device
->FilterList
)
606 ALuint64 usemask
= ~sublist
.FreeMask
;
609 ALsizei idx
= CTZ64(usemask
);
610 ALfilter
*filter
= sublist
.Filters
+ idx
;
615 usemask
&= ~(U64(1) << idx
);
617 sublist
.FreeMask
= ~usemask
;
620 WARN("(%p) Deleted " SZFMT
" Filter%s\n", device
, leftover
, (leftover
==1)?"":"s");
624 static void InitFilterParams(ALfilter
*filter
, ALenum type
)
626 if(type
== AL_FILTER_LOWPASS
)
628 filter
->Gain
= AL_LOWPASS_DEFAULT_GAIN
;
629 filter
->GainHF
= AL_LOWPASS_DEFAULT_GAINHF
;
630 filter
->HFReference
= LOWPASSFREQREF
;
631 filter
->GainLF
= 1.0f
;
632 filter
->LFReference
= HIGHPASSFREQREF
;
633 filter
->vtab
= &ALlowpass_vtable
;
635 else if(type
== AL_FILTER_HIGHPASS
)
637 filter
->Gain
= AL_HIGHPASS_DEFAULT_GAIN
;
638 filter
->GainHF
= 1.0f
;
639 filter
->HFReference
= LOWPASSFREQREF
;
640 filter
->GainLF
= AL_HIGHPASS_DEFAULT_GAINLF
;
641 filter
->LFReference
= HIGHPASSFREQREF
;
642 filter
->vtab
= &ALhighpass_vtable
;
644 else if(type
== AL_FILTER_BANDPASS
)
646 filter
->Gain
= AL_BANDPASS_DEFAULT_GAIN
;
647 filter
->GainHF
= AL_BANDPASS_DEFAULT_GAINHF
;
648 filter
->HFReference
= LOWPASSFREQREF
;
649 filter
->GainLF
= AL_BANDPASS_DEFAULT_GAINLF
;
650 filter
->LFReference
= HIGHPASSFREQREF
;
651 filter
->vtab
= &ALbandpass_vtable
;
656 filter
->GainHF
= 1.0f
;
657 filter
->HFReference
= LOWPASSFREQREF
;
658 filter
->GainLF
= 1.0f
;
659 filter
->LFReference
= HIGHPASSFREQREF
;
660 filter
->vtab
= &ALnullfilter_vtable
;