Deluge Firmware
1.3.0
Build date: 2026.08.29
Toggle main menu visibility
Loading...
Searching...
No Matches
filter.h
1
/*
2
* Copyright © 2015-2023 Synthstrom Audible Limited
3
*
4
* This file is part of The Synthstrom Audible Deluge Firmware.
5
*
6
* The Synthstrom Audible Deluge Firmware is free software: you can redistribute it and/or modify it under the
7
* terms of the GNU General Public License as published by the Free Software Foundation,
8
* either version 3 of the License, or (at your option) any later version.
9
*
10
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
* See the GNU General Public License for more details.
13
*
14
* You should have received a copy of the GNU General Public License along with this program.
15
* If not, see <https://www.gnu.org/licenses/>.
16
*/
17
18
#pragma once
19
20
#include "model/mod_controllable/filters/filter_config.h"
21
#include "util/fixedpoint.h"
22
#include "util/functions.h"
23
#include <cstdint>
24
25
namespace
deluge::dsp::filter {
26
constexpr
int32_t ONE_Q16 = 134217728;
27
28
extern
q31_t blendBuffer[SSI_TX_BUFFER_NUM_SAMPLES * 2];
42
template
<
typename
T>
43
class
[[gnu::hot]] Filter {
44
public
:
45
Filter() =
default
;
46
// returns a gain compensation value
47
q31_t configure(q31_t frequency, q31_t resonance, FilterMode lpfMode, q31_t lpfMorph, q31_t filterGain) {
48
49
// lpfmorph comes in q28 but we want q31
50
return
static_cast<
T*
>
(
this
)->setConfig(frequency, resonance, lpfMode, lshiftAndSaturate<2>(lpfMorph),
51
filterGain);
52
}
60
[[gnu::hot]]
void
filterMono
(q31_t* startSample, q31_t* endSample, int32_t sampleIncrememt = 1) {
61
if
(dryFade < 0.001) {
62
static_cast<
T*
>
(
this
)->doFilter(startSample, endSample, sampleIncrememt);
63
}
64
else
{
65
memcpy(blendBuffer, startSample, (endSample - startSample) *
sizeof
(q31_t));
66
static_cast<
T*
>
(
this
)->doFilter(startSample, endSample, sampleIncrememt);
67
68
q31_t* currentSample = startSample;
69
q31_t* currentDrySample = blendBuffer;
70
do
{
71
q31_t wet = multiply_32x32_rshift32(*currentSample, wetLevel);
72
*currentSample = multiply_accumulate_32x32_rshift32_rounded(wet, *currentDrySample, ONE_Q31 - wetLevel)
73
<< 1;
74
currentSample += 1;
75
currentDrySample += 1;
76
updateBlend();
// will go to one over 512 samples
77
}
while
(currentSample < endSample);
78
}
79
}
80
86
[[gnu::hot]]
void
filterStereo
(q31_t* startSample, q31_t* endSample) {
87
if
(dryFade < 0.001) {
88
static_cast<
T*
>
(
this
)->doFilterStereo(startSample, endSample);
89
}
90
else
{
91
memcpy(blendBuffer, startSample, (endSample - startSample) *
sizeof
(q31_t));
92
static_cast<
T*
>
(
this
)->doFilterStereo(startSample, endSample);
93
94
q31_t* currentSample = startSample;
95
q31_t* currentDrySample = blendBuffer;
96
do
{
97
q31_t wet = multiply_32x32_rshift32(*currentSample, wetLevel);
98
*currentSample = multiply_accumulate_32x32_rshift32_rounded(wet, *currentDrySample, ONE_Q31 - wetLevel)
99
<< 1;
100
currentSample += 1;
101
currentDrySample += 1;
102
updateBlend();
103
}
while
(currentSample < endSample);
104
}
105
}
106
110
void
reset
(
bool
fade =
false
) {
111
static_cast<
T*
>
(
this
)->resetFilter();
112
if
(fade) {
113
dryFade = 1;
114
wetLevel = 0;
115
}
116
}
117
118
inline
void
updateBlend() {
119
// fades over around 500 samples
120
dryFade = dryFade * 0.99;
121
wetLevel = (q31_t)(ONE_Q31 * (1 - dryFade));
122
}
123
128
void
curveFrequency
(q31_t frequency) {
129
// Between 0 and 8, by my making. 1 represented by 268435456
130
tannedFrequency = instantTan(lshiftAndSaturate<5>(frequency));
131
132
// this is 1q31*1q16/(1q16+tan(f)/2)
133
// tan(f) is q17
134
divideBy1PlusTannedFrequency = (q31_t)(288230376151711744.0 / (
double
)(ONE_Q16 + (tannedFrequency >> 1)));
135
fc = multiply_32x32_rshift32_rounded(tannedFrequency, divideBy1PlusTannedFrequency) << 4;
136
}
137
q31_t fc;
138
float
dryFade = 1;
139
q31_t wetLevel = ONE_Q31;
140
q31_t tannedFrequency;
141
q31_t divideBy1PlusTannedFrequency;
142
};
143
144
}
// namespace deluge::dsp::filter
deluge::dsp::filter::Filter::reset
void reset(bool fade=false)
Definition
filter.h:110
deluge::dsp::filter::Filter::filterMono
void filterMono(q31_t *startSample, q31_t *endSample, int32_t sampleIncrememt=1)
Definition
filter.h:60
deluge::dsp::filter::Filter::filterStereo
void filterStereo(q31_t *startSample, q31_t *endSample)
Definition
filter.h:86
deluge::dsp::filter::Filter::curveFrequency
void curveFrequency(q31_t frequency)
Definition
filter.h:128