+ Monosynth: add inertia for pitch wheel
[calf.git] / src / calf / multichorus.h
blobf4ab7ceff7f261de091f95a1121bd66c3005d049
1 /* Calf DSP Library
2 * Multitap chorus class.
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., 59 Temple Place, Suite 330,
19 * Boston, MA 02111-1307, USA.
21 #ifndef __CALF_MULTICHORUS_H
22 #define __CALF_MULTICHORUS_H
24 #include "audio_fx.h"
26 namespace dsp {
28 typedef fixed_point<unsigned int, 20> chorus_phase;
30 template<class T, uint32_t Voices>
31 class sine_multi_lfo
33 protected:
34 sine_table<int, 4096, 65535> sine;
36 public:
37 /// Current LFO phase
38 chorus_phase phase;
39 /// LFO phase increment
40 chorus_phase dphase;
41 /// LFO phase per-voice increment
42 chorus_phase vphase;
43 /// Current number of voices
44 uint32_t voices;
45 /// Current scale (output multiplier)
46 T scale;
47 public:
48 sine_multi_lfo()
50 phase = dphase = vphase = 0.0;
51 set_voices(Voices);
53 inline uint32_t get_voices() const
55 return voices;
57 inline void set_voices(uint32_t value)
59 voices = value;
60 // use sqrt, because some phases will cancel each other - so 1 / N is usually too low
61 scale = sqrt(1.0 / voices);
63 /// Get LFO value for given voice, returns a values in range of [-65536, 65535] (or close)
64 inline int get_value(uint32_t voice) {
65 // find this voice's phase (= phase + voice * 360 degrees / number of voices)
66 chorus_phase voice_phase = phase + vphase * (int)voice;
67 // find table offset
68 unsigned int ipart = voice_phase.ipart();
69 // interpolate (use 14 bits of precision - because the table itself uses 17 bits and the result of multiplication must fit in int32_t)
70 // note, the result is still -65535 .. 65535, it's just interpolated
71 // it is never reaching -65536 - but that's acceptable
72 return voice_phase.lerp_by_fract_int<int, 14, int>(sine.data[ipart], sine.data[ipart+1]);
74 inline void step() {
75 phase += dphase;
77 inline T get_scale() const {
78 return scale;
80 void reset() {
81 phase = 0.f;
85 /**
86 * Multi-tap chorus without feedback.
87 * Perhaps MaxDelay should be a bit longer!
89 template<class T, class MultiLfo, class Postprocessor, int MaxDelay=4096>
90 class multichorus: public chorus_base
92 protected:
93 simple_delay<MaxDelay,T> delay;
94 public:
95 MultiLfo lfo;
96 Postprocessor post;
97 public:
98 multichorus() {
99 rate = 0.63f;
100 dry = 0.5f;
101 wet = 0.5f;
102 min_delay = 0.005f;
103 mod_depth = 0.0025f;
104 setup(44100);
106 void reset() {
107 delay.reset();
108 lfo.reset();
110 void set_rate(float rate) {
111 chorus_base::set_rate(rate);
112 lfo.dphase = dphase;
114 virtual void setup(int sample_rate) {
115 modulation_effect::setup(sample_rate);
116 delay.reset();
117 lfo.reset();
118 set_min_delay(get_min_delay());
119 set_mod_depth(get_mod_depth());
121 template<class OutIter, class InIter>
122 void process(OutIter buf_out, InIter buf_in, int nsamples) {
123 int mds = min_delay_samples + mod_depth_samples * 1024 + 2*65536;
124 int mdepth = mod_depth_samples;
125 // 1 sample peak-to-peak = mod_depth_samples of 32 (this scaling stuff is tricky and may - but shouldn't - be wrong)
126 // with 192 kHz sample rate, 1 ms = 192 samples, and the maximum 20 ms = 3840 samples (so, 4096 will be used)
127 // 3840 samples of mod depth = mdepth of 122880 (which multiplied by 65536 doesn't fit in int32_t)
128 // so, it will be right-shifted by 2, which gives it a safe range of 30720
129 // NB: calculation of mod_depth_samples (and multiply-by-32) is in chorus_base::set_mod_depth
130 mdepth = mdepth >> 2;
131 T scale = lfo.get_scale();
132 for (int i=0; i<nsamples; i++) {
133 phase += dphase;
135 float in = *buf_in++;
137 delay.put(in);
138 unsigned int nvoices = lfo.get_voices();
139 T out = 0.f;
140 // add up values from all voices, each voice tell its LFO phase and the buffer value is picked at that location
141 for (unsigned int v = 0; v < nvoices; v++)
143 int lfo_output = lfo.get_value(v);
144 // 3 = log2(32 >> 2) + 1 because the LFO value is in range of [-65535, 65535] (17 bits)
145 int dv = mds + (mdepth * lfo_output >> (3 + 1));
146 int ifv = dv >> 16;
147 T fd; // signal from delay's output
148 delay.get_interp(fd, ifv, (dv & 0xFFFF)*(1.0/65536.0));
149 out += fd;
151 // apply the post filter
152 out = post.process(out);
153 T sdry = in * gs_dry.get();
154 T swet = out * gs_wet.get() * scale;
155 *buf_out++ = sdry + swet;
156 lfo.step();
158 post.sanitize();
160 float freq_gain(float freq, float sr)
162 typedef std::complex<double> cfloat;
163 freq *= 2.0 * M_PI / sr;
164 cfloat z = 1.0 / exp(cfloat(0.0, freq)); // z^-1
165 cfloat h = 0.0;
166 int mds = min_delay_samples + mod_depth_samples * 1024 + 2*65536;
167 int mdepth = mod_depth_samples;
168 mdepth = mdepth >> 2;
169 T scale = lfo.get_scale();
170 unsigned int nvoices = lfo.get_voices();
171 for (unsigned int v = 0; v < nvoices; v++)
173 int lfo_output = lfo.get_value(v);
174 // 3 = log2(32 >> 2) + 1 because the LFO value is in range of [-65535, 65535] (17 bits)
175 int dv = mds + (mdepth * lfo_output >> (3 + 1));
176 int fldp = dv >> 16;
177 cfloat zn = std::pow(z, fldp); // z^-N
178 h += zn + (zn * z - zn) * cfloat(dv / 65536.0 - fldp);
180 // apply the post filter
181 h *= post.h_z(z);
182 // mix with dry signal
183 float v = std::abs(cfloat(gs_dry.get_last()) + cfloat(scale * gs_wet.get_last()) * h);
184 return v;
190 #endif