Merge pull request #1 from atsampson/master
[calfbox.git] / phaser.c
blob4d1196fc34aee73bd095b8a8b22d4974c539c3a9
1 /*
2 Calf Box, an open source musical instrument.
3 Copyright (C) 2010-2011 Krzysztof Foltman
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "config.h"
20 #include "config-api.h"
21 #include "dspmath.h"
22 #include "module.h"
23 #include "onepole-float.h"
24 #include <glib.h>
25 #include <malloc.h>
26 #include <math.h>
27 #include <memory.h>
28 #include <sndfile.h>
29 #include <stdio.h>
30 #include <stdlib.h>
32 #define NO_STAGES 12
34 #define MODULE_PARAMS phaser_params
36 struct phaser_params
38 float center;
39 float mdepth;
40 float fb_amt;
41 float lfo_freq;
42 float sphase;
43 float wet_dry;
44 int stages;
47 #if USE_NEON
48 #include <arm_neon.h>
50 struct cbox_onepolef_stereo_state_neon {
51 float32x2_t x1;
52 float32x2_t y1;
54 #endif
56 struct phaser_module
58 struct cbox_module module;
60 #if USE_NEON
61 struct cbox_onepolef_stereo_state_neon state[NO_STAGES];
62 #else
63 struct cbox_onepolef_state state[NO_STAGES][2];
64 #endif
65 struct cbox_onepolef_coeffs coeffs[2];
66 float fb[2];
67 float tpdsr;
68 struct phaser_params *params;
70 float phase;
73 gboolean phaser_process_cmd(struct cbox_command_target *ct, struct cbox_command_target *fb, struct cbox_osc_command *cmd, GError **error)
75 struct phaser_module *m = (struct phaser_module *)ct->user_data;
77 EFFECT_PARAM("/center_freq", "f", center, double, , 10, 20000) else
78 EFFECT_PARAM("/mod_depth", "f", mdepth, double, , 0, 10000) else
79 EFFECT_PARAM("/fb_amt", "f", fb_amt, double, , -1, 1) else
80 EFFECT_PARAM("/lfo_freq", "f", lfo_freq, double, , 0, 20) else
81 EFFECT_PARAM("/stereo_phase", "f", sphase, double, deg2rad, 0, 360) else
82 EFFECT_PARAM("/wet_dry", "f", wet_dry, double, , 0, 1) else
83 EFFECT_PARAM("/stages", "i", stages, int, , 1, 12) else
84 if (!strcmp(cmd->command, "/status") && !strcmp(cmd->arg_types, ""))
86 if (!cbox_check_fb_channel(fb, cmd->command, error))
87 return FALSE;
88 return cbox_execute_on(fb, NULL, "/center_freq", "f", error, m->params->center) &&
89 cbox_execute_on(fb, NULL, "/mod_depth", "f", error, m->params->mdepth) &&
90 cbox_execute_on(fb, NULL, "/fb_amt", "f", error, m->params->fb_amt) &&
91 cbox_execute_on(fb, NULL, "/lfo_freq", "f", error, m->params->lfo_freq) &&
92 cbox_execute_on(fb, NULL, "/stereo_phase", "f", error, rad2deg(m->params->sphase)) &&
93 cbox_execute_on(fb, NULL, "/wet_dry", "f", error, m->params->wet_dry) &&
94 cbox_execute_on(fb, NULL, "/stages", "i", error, m->params->stages) &&
95 CBOX_OBJECT_DEFAULT_STATUS(&m->module, fb, error);
97 else
98 return cbox_object_default_process_cmd(ct, fb, cmd, error);
99 return TRUE;
102 void phaser_process_event(struct cbox_module *module, const uint8_t *data, uint32_t len)
104 // struct phaser_module *m = (struct phaser_module *)module;
107 static inline float clip_w(float w)
109 if (w > 0.9 * M_PI)
110 return 0.9 * M_PI;
111 return w;
114 void phaser_process_block(struct cbox_module *module, cbox_sample_t **inputs, cbox_sample_t **outputs)
116 struct phaser_module *m = (struct phaser_module *)module;
117 struct phaser_params *p = m->params;
118 int s, i;
119 int stages = p->stages;
120 float fb_amt = p->fb_amt;
121 if (stages < 0 || stages > NO_STAGES)
122 stages = 0;
124 if (p->mdepth)
126 cbox_onepolef_set_allpass(&m->coeffs[0], clip_w(m->tpdsr * p->center * cent2factor(p->mdepth * sin(m->phase))));
127 cbox_onepolef_set_allpass(&m->coeffs[1], clip_w(m->tpdsr * p->center * cent2factor(p->mdepth * sin(m->phase + p->sphase))));
129 else
131 cbox_onepolef_set_allpass(&m->coeffs[0], m->tpdsr * p->center);
132 cbox_onepolef_set_allpass(&m->coeffs[1], m->tpdsr * p->center);
134 m->phase += p->lfo_freq * CBOX_BLOCK_SIZE * m->tpdsr;
136 #if USE_NEON
137 float *__restrict input1 = inputs[0];
138 float *__restrict input2 = inputs[1];
139 float *__restrict output1 = outputs[0];
140 float *__restrict output2 = outputs[1];
141 float32x2_t wetdry = {p->wet_dry, p->wet_dry};
142 float32x2_t fb_amt2 = {fb_amt, fb_amt};
143 float32x2_t fb = {m->fb[0], m->fb[1]};
144 float32x2_t a0 = {m->coeffs[0].a0, m->coeffs[1].a0};
145 float32x2_t a1 = {m->coeffs[0].a1, m->coeffs[1].a1};
146 float32x2_t b1 = {m->coeffs[0].b1, m->coeffs[1].b1};
147 float32x2_t zero = {0.f, 0.f};
148 const float32x2_t thresh = {(1.0 / (65536.0 * 65536.0)), (1.0 / (65536.0 * 65536.0))};
149 for (i = 0; i < CBOX_BLOCK_SIZE; i++)
151 float32x2_t dry = {input1[i], input2[i]};
152 float32x2_t wet = vsub_f32(dry, vmul_f32(fb, fb_amt2));
153 for (s = 0; s < (stages & ~1); s += 2)
155 // wet = sanef(coeffs->a0 * wet + coeffs->a1 * state->x1 - coeffs->b1 * state->y1);
156 float32x2_t pre = wet;
157 wet = vmla_f32(vmls_f32(vmul_f32(a1, m->state[s].x1), b1, m->state[s].y1), a0, wet);
158 m->state[s].x1 = pre;
159 m->state[s].y1 = wet;
160 pre = wet;
161 wet = vmla_f32(vmls_f32(vmul_f32(a1, m->state[s + 1].x1), b1, m->state[s + 1].y1), a0, wet);
162 m->state[s + 1].x1 = pre;
163 m->state[s + 1].y1 = wet;
165 for (; s < stages; s++)
167 // wet = sanef(coeffs->a0 * wet + coeffs->a1 * state->x1 - coeffs->b1 * state->y1);
168 float32x2_t pre = wet;
169 wet = vmla_f32(vmls_f32(vmul_f32(a1, m->state[s].x1), b1, m->state[s].y1), a0, wet);
170 m->state[s].x1 = pre;
171 m->state[s].y1 = wet;
173 fb = wet;
174 wet = vadd_f32(dry, vmul_f32(vsub_f32(wet, dry), wetdry));
175 output1[i] = wet[0];
176 output2[i] = wet[1];
178 // set values < threshold to zero
179 for (s = 0; s < stages; s++)
180 m->state[s].y1 = vbsl_f32(vcage_f32(m->state[s].y1, thresh), m->state[s].y1, zero);
181 m->fb[0] = fb[0];
182 m->fb[1] = fb[1];
183 #else
184 for (int c = 0; c < 2; c++)
186 for (i = 0; i < CBOX_BLOCK_SIZE; i++)
188 float dry = inputs[c][i];
189 float wet = dry - m->fb[c] * fb_amt;
190 for (s = 0; s < stages; s++)
191 wet = cbox_onepolef_process_sample(&m->state[s][c], &m->coeffs[c], wet);
192 m->fb[c] = wet;
193 outputs[c][i] = dry + (wet - dry) * p->wet_dry;
196 #endif
199 MODULE_SIMPLE_DESTROY_FUNCTION(phaser)
201 MODULE_CREATE_FUNCTION(phaser)
203 int b;
205 static int inited = 0;
206 if (!inited)
208 inited = 1;
211 struct phaser_module *m = malloc(sizeof(struct phaser_module));
212 CALL_MODULE_INIT(m, 2, 2, phaser);
213 m->module.process_event = phaser_process_event;
214 m->module.process_block = phaser_process_block;
215 m->tpdsr = 2.0 * M_PI / m->module.srate;
216 m->phase = 0;
217 struct phaser_params *p = malloc(sizeof(struct phaser_params));
218 m->params = p;
219 p->sphase = deg2rad(cbox_config_get_float(cfg_section, "stereo_phase", 90.f));
220 p->lfo_freq = cbox_config_get_float(cfg_section, "lfo_freq", 1.f);
221 p->center = cbox_config_get_float(cfg_section, "center_freq", 1500.f);
222 p->mdepth = cbox_config_get_float(cfg_section, "mod_depth", 1200.f);
223 p->fb_amt = cbox_config_get_float(cfg_section, "feedback", 0.f);
224 p->wet_dry = cbox_config_get_float(cfg_section, "wet_dry", 0.5f);
225 p->stages = cbox_config_get_int(cfg_section, "stages", NO_STAGES);
227 #if USE_NEON
228 for (b = 0; b < NO_STAGES; b++)
230 float32x2_t zero = {0.f, 0.f};
231 m->state[b].x1 = zero;
232 m->state[b].y1 = zero;
234 #else
235 for (b = 0; b < NO_STAGES; b++)
236 for (int c = 0; c < 2; c++)
237 cbox_onepolef_reset(&m->state[b][c]);
238 #endif
240 return &m->module;
244 struct cbox_module_keyrange_metadata phaser_keyranges[] = {
247 struct cbox_module_livecontroller_metadata phaser_controllers[] = {
250 DEFINE_MODULE(phaser, 2, 2)