2 * Reusable audio effect classes.
4 * Copyright (C) 2001-2007 Krzysztof Foltman
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General
17 * Public License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
21 #ifndef __CALF_DELAY_H
22 #define __CALF_DELAY_H
24 #include "primitives.h"
31 * Delay primitive. Can be used for most delay stuff, including
32 * variable (modulated) delays like chorus/flanger. Note that
33 * for modulated delay effects use of GetInterp is preferred,
34 * because it handles fractional positions and uses linear
35 * interpolation, which sounds better most of the time.
37 * @param N maximum length
38 * @param C number of channels read/written for each sample (1 mono, 2 stereo etc)
40 template<int N
, class T
>
42 auto_buffer
<N
, T
> data
;
50 for (int i
=0; i
<N
; i
++)
53 /** Write one C-channel sample from idata[0], idata[1] etc into buffer */
54 inline void put(T idata
) {
56 pos
= wrap_around
<N
>(pos
+1);
60 * Read one C-channel sample into odata[0], odata[1] etc into buffer.
61 * Don't use for modulated delays (chorus/flanger etc) unless you
62 * want them to crackle and generally sound ugly
63 * @param odata pointer to write into
64 * @param delay delay relative to current writing pos
67 inline void get(U
&odata
, int delay
) {
68 assert(delay
>= 0 && delay
< N
);
69 int ppos
= wrap_around
<N
>(pos
+ N
- delay
);
74 * Read and write during the same function call
76 inline T
process(T idata
, int delay
)
78 assert(delay
>= 0 && delay
< N
);
79 int ppos
= wrap_around
<N
>(pos
+ N
- delay
);
82 pos
= wrap_around
<N
>(pos
+1);
86 /** Read one C-channel sample at fractional position.
87 * This version can be used for modulated delays, because
88 * it uses linear interpolation.
89 * @param odata value to write into
90 * @param delay delay relative to current writing pos
91 * @param udelay fractional delay (0..1)
94 inline void get_interp(U
&odata
, int delay
, float udelay
) {
95 // assert(delay >= 0 && delay <= N-1);
96 int ppos
= wrap_around
<N
>(pos
+ N
- delay
);
97 int pppos
= wrap_around
<N
>(ppos
+ N
- 1);
98 odata
= lerp(data
[ppos
], data
[pppos
], udelay
);
101 /** Read one C-channel sample at fractional position.
102 * This version can be used for modulated delays, because
103 * it uses linear interpolation.
104 * @param odata value to write into
105 * @param delay delay relative to current writing pos
106 * @param udelay fractional delay (0..1)
108 inline T
get_interp_1616(unsigned int delay
) {
109 float udelay
= (float)((delay
& 0xFFFF) * (1.0 / 65536.0));
111 // assert(delay >= 0 && delay < N-1);
112 int ppos
= wrap_around
<N
>(pos
+ N
- delay
);
113 int pppos
= wrap_around
<N
>(ppos
+ N
- 1);
114 return lerp(data
[ppos
], data
[pppos
], udelay
);
118 * Comb filter. Feedback delay line with given delay and feedback values
119 * @param in input signal
120 * @param delay delay length (must be <N and integer)
121 * @param fb feedback (must be <1 or it will be unstable)
123 inline T
process_comb(T in
, unsigned int delay
, float fb
)
134 * Comb filter with linear interpolation. Feedback delay line with given delay and feedback values
135 * Note that linear interpolation introduces some weird effects in frequency response.
136 * @param in input signal
137 * @param delay fractional delay length (must be < 65536 * N)
138 * @param fb feedback (must be <1 or it will be unstable)
140 inline T
process_comb_lerp16(T in
, unsigned int delay
, float udelay
, float fb
)
143 get_interp(old
, delay
>>16, dsp::fract16(delay
));
151 * Comb allpass filter. The comb filter with additional direct path, which is supposed to cancel the coloration.
152 * @param in input signal
153 * @param delay delay length (must be <N and integer)
154 * @param fb feedback (must be <1 or it will be unstable)
156 inline T
process_allpass_comb(T in
, unsigned int delay
, float fb
)
163 return old
- fb
* cur
;
167 * Comb allpass filter. The comb filter with additional direct path, which is supposed to cancel the coloration.
168 * @param in input signal
169 * @param delay fractional delay length (must be < 65536 * N)
170 * @param fb feedback (must be <1 or it will be unstable)
172 inline T
process_allpass_comb_lerp16(T in
, unsigned int delay
, float fb
)
175 get_interp(old
, delay
>>16, dsp::fract16(delay
));
179 return old
- fb
* cur
;