From 65f14260d6e70264651fcfe82173ad0a96e155fc Mon Sep 17 00:00:00 2001
From: moon2 <moon2protonmail@protonmail.com>
Date: Tue, 21 Nov 2023 04:16:19 +0100
Subject: [PATCH] bl00mbox updates

---
 .../bl00mbox/micropython/bl00mbox/_patches.py |  25 ++--
 .../bl00mbox/micropython/bl00mbox/_plugins.py | 122 ++++++++++++++----
 .../radspa/standard_plugin_lib/delay.c        |   2 +-
 .../radspa/standard_plugin_lib/distortion.c   |  37 ++++--
 .../radspa/standard_plugin_lib/filter.c       |  90 +++++++------
 .../radspa/standard_plugin_lib/flanger.c      |  26 ++--
 .../radspa/standard_plugin_lib/mixer.c        |   4 +-
 7 files changed, 203 insertions(+), 103 deletions(-)

diff --git a/components/bl00mbox/micropython/bl00mbox/_patches.py b/components/bl00mbox/micropython/bl00mbox/_patches.py
index 34f76868c7..794e340e3e 100644
--- a/components/bl00mbox/micropython/bl00mbox/_patches.py
+++ b/components/bl00mbox/micropython/bl00mbox/_patches.py
@@ -242,10 +242,7 @@ class sampler(_Patch):
 class sequencer(_Patch):
     def __init__(self, chan, num_tracks, num_steps):
         super().__init__(chan)
-        self.num_steps = num_steps
-        self.num_tracks = num_tracks
-        init_var = (self.num_steps * 256) + (self.num_tracks)  # magic
-        self.plugins.seq = chan.new(bl00mbox.plugins.sequencer, init_var)
+        self.plugins.seq = chan.new(bl00mbox.plugins.sequencer, num_tracks, num_steps)
 
         self.signals.bpm = self.plugins.seq.signals.bpm
         self.signals.beat_div = self.plugins.seq.signals.beat_div
@@ -254,6 +251,8 @@ class sequencer(_Patch):
         self.signals.step_start = self.plugins.seq.signals.step_start
         self.signals.sync_in = self.plugins.seq.signals.sync_in
 
+        self.num_tracks = num_tracks
+        self.num_steps = num_steps
         tracktable = [-32767] + ([0] * self.num_steps)
         self.plugins.seq.table = tracktable * self.num_tracks
 
@@ -380,28 +379,28 @@ class karplus_strong(_Patch):
 
         self.plugins.flanger = chan._new_plugin(bl00mbox.plugins.flanger)
 
-        self.plugins.flanger.signals.resonance = 32500
+        self.plugins.flanger.signals.resonance = 0
+        self.plugins.flanger.signals.decay = 1000
         self.plugins.flanger.signals.manual.tone = "A2"
 
         self.plugins.flanger.signals.input = self.plugins.noise.signals.output
 
         self.signals.trigger = self.plugins.noise.signals.trigger
+        self.signals.trigger_length = self.plugins.noise.signals.length
         self.signals.pitch = self.plugins.flanger.signals.manual
         self.signals.output = self.plugins.flanger.signals.output
 
         self.signals.level = self.plugins.flanger.signals.level
         self.signals.decay = self.plugins.flanger.signals.decay
-        self.decay = 1000
+        self.signals.resonance = self.plugins.flanger.signals.resonance
 
     @property
     def decay(self):
-        return self._decay
+        # deprecated
+        return self.plugins.flanger.signals.decay.value
 
     @decay.setter
     def decay(self, val):
-        tone = self.plugins.flanger.signals.manual.tone
-        loss = (50 * (2 ** (-tone / 12))) // (val / 1000)
-        if loss < 2:
-            loss = 2
-        self.plugins.flanger.signals.resonance = 32767 - loss
-        self._decay = val
+        # deprecated
+        self.plugins.flanger.signals.resonance = -2
+        self.plugins.flanger.signals.decay = int(val)
diff --git a/components/bl00mbox/micropython/bl00mbox/_plugins.py b/components/bl00mbox/micropython/bl00mbox/_plugins.py
index c3eb2b41b8..edfb7edd00 100644
--- a/components/bl00mbox/micropython/bl00mbox/_plugins.py
+++ b/components/bl00mbox/micropython/bl00mbox/_plugins.py
@@ -39,10 +39,12 @@ def _fill():
     for name, value in plugins_list.items():
         setattr(plugins, name, _PluginDescriptor(value))
         # legacy
-        if name == "sequencer":
+        if name == "sequencer" or name == "distortion":
             setattr(plugins, "_" + name, _PluginDescriptor(value))
-        if name == "sampler":
+        elif name == "sampler":
             setattr(plugins, "_sampler_ram", _PluginDescriptor(value))
+        elif name == "delay_static":
+            setattr(plugins, "delay", _PluginDescriptor(value))
 
 
 _fill()
@@ -431,12 +433,12 @@ class _Sampler(_Plugin):
             table[self._SAMPLE_RATE] = int(val)
 
 
-"""
 @_plugin_set_subclass(9000)
 class _Distortion(_Plugin):
-    def symmetric_power(self, power=2, volume=32767, gate=0):
-        table = list(range(129))
-        for num in table:
+    def curve_set_power(self, power=2, volume=32767, gate=0):
+        volume = min(max(volume, -32767), 32767)
+        table = [0] * 129
+        for num in range(len(table)):
             if num < 64:
                 ret = num / 64  # scale to [0..1[ range
                 ret = ret**power
@@ -447,25 +449,60 @@ class _Distortion(_Plugin):
                 ret = (128 - num) / 64  # scale to [0..1] range
                 ret = ret**power
                 table[num] = int(volume * (1 - ret))
-        gate = int(gate) >> 9
+        gate = min(abs(int(gate)), 32767) >> 9
         for i in range(64 - gate, 64 + gate):
             table[i] = 0
         self.table = table
 
+    @property
+    def _secret_sauce(self):
+        table = self.table_int16_array
+        return table[129]
+
+    @_secret_sauce.setter
+    def _secret_sauce(self, val):
+        val = min(max(int(val), 0), 7)
+        table = self.table_int16_array
+        table[129] = val
+
+    @property
+    def curve(self):
+        return self.table[:129]
+
+    @curve.setter
+    def curve(self, points):
+        # interpolation only implemented for len(points) <= 129,
+        # for longer lists data may be dropped.
+        points_size = len(points)
+        if not points_size:
+            return
+        table = [0] * 129
+        for x, num in enumerate(table):
+            position = x * points_size / 129
+            lower = int(position)
+            lerp = position - lower
+            if position < points_size - 1:
+                table[x] = int(
+                    (1 - lerp) * points[position] + lerp * points[position + 1]
+                )
+            else:
+                table[x] = int(points[points_size - 1])
+        self.table = table
+
     def __repr__(self):
         ret = super().__repr__()
         wave = self.table[:129]
         ret += "\n  curve:\n"
-        ret += "   " + "_"*67 + "\n"
-        ret += "  |" + " "*67 + "|\n"
+        ret += "   " + "_" * 67 + "\n"
+        ret += "  |" + " " * 67 + "|\n"
         symbols = "UW"
         symbol_counter = 0
         for i in range(15, -1, -1):
             line = "  |  "
             for k in range(63):
-                vals = wave[2*k:2*k+4]
-                upper = ((max(vals)>>8) + 128) >> 4
-                lower = ((min(vals)>>8) + 128) >> 4
+                vals = wave[2 * k : 2 * k + 4]
+                upper = ((max(vals) >> 8) + 128) >> 4
+                lower = ((min(vals) >> 8) + 128) >> 4
                 if (i >= lower) and (i <= upper):
                     line += symbols[symbol_counter]
                     symbol_counter = (symbol_counter + 1) % len(symbols)
@@ -473,9 +510,20 @@ class _Distortion(_Plugin):
                     line += " "
             line += "  |\n"
             ret += line
-        ret += "  |" + "_"*67 + "|"
+        ret += "  |" + "_" * 67 + "|"
         return ret
-"""
+
+
+@_plugin_set_subclass(172)
+class _PolySqueeze(_Plugin):
+    def __init__(self, channel, plugin_id, bud_num, num_outputs=3, num_inputs=10):
+        if bud_num is None:
+            outs = min(max(num_outputs, 16), 1)
+            ins = min(max(num_inputs, 32), num_outputs)
+            init_var = outs + (ins * 256)
+            super().__init__(channel, plugin_id, init_var=init_var)
+        else:
+            super().__init__(channel, plugin_id, bud_num=bud_num)
 
 
 @_plugin_set_subclass(420)
@@ -516,15 +564,11 @@ class _Osc(_Plugin):
 
 @_plugin_set_subclass(56709)
 class _Sequencer(_Plugin):
-    def __init__(self, channel, plugin_id, bud_num, init_var=None, tracks=4, steps=16):
+    def __init__(self, channel, plugin_id, bud_num, num_tracks=4, num_steps=16):
         if bud_num is None:
-            if init_var is None:
-                self.num_steps = steps % 256
-                self.num_tracks = tracks % 256
-                init_var = (self.num_steps * 256) + (self.num_tracks)
-            else:
-                self.num_tracks = init_var % 256
-                self.num_steps = (init_var // 256) % 256
+            self.num_steps = num_steps % 256
+            self.num_tracks = num_tracks % 256
+            init_var = (self.num_steps * 256) + (self.num_tracks)
 
             super().__init__(channel, plugin_id, init_var=init_var)
 
@@ -593,3 +637,37 @@ class _Sequencer(_Plugin):
             self.trigger_start(track, step)
         else:
             self.trigger_clear(track, step)
+
+    def save_track_pattern(self, track_index):
+        start = track_index * (self.num_steps + 1)
+        stop = start + self.num_steps + 1
+        track = {}
+        table = self.table
+        if self.table[start] == -32767:
+            track["type"] = "trigger"
+        else:
+            track["type"] = "value"
+        track["steps"] = list(table[start + 1 : stop])
+        return track
+
+    def load_track_pattern(self, track, track_index):
+        start = track_index * (self.num_steps + 1)
+        table = self.table_int16_array
+        stop = start + 1 + min(self.num_steps, len(track["steps"]))
+        for i in range(start + 1, stop):
+            x = track["steps"][i - start - 1]
+            assert (x < 32768) and (x > -32768)
+            table[i] = x
+        if track["type"] == "trigger":
+            table[start] = -32767
+        else:
+            table[start] = 32767
+
+    def save_pattern(self):
+        beat = {}
+        beat["tracks"] = [self.save_track_pattern(i) for i in range(self.num_tracks)]
+        return beat
+
+    def load_pattern(self, beat):
+        num_tracks = min(len(beat["tracks"]), self.num_tracks)
+        [self.load_track_pattern(beat["tracks"][i], i) for i in range(num_tracks)]
diff --git a/components/bl00mbox/radspa/standard_plugin_lib/delay.c b/components/bl00mbox/radspa/standard_plugin_lib/delay.c
index 099dd82fae..f6521569bb 100644
--- a/components/bl00mbox/radspa/standard_plugin_lib/delay.c
+++ b/components/bl00mbox/radspa/standard_plugin_lib/delay.c
@@ -2,7 +2,7 @@
 
 radspa_t * delay_create(uint32_t init_var);
 radspa_descriptor_t delay_desc = {
-    .name = "delay",
+    .name = "delay_static",
     .id = 42069,
     .description = "simple delay with ms input and feedback\n"
                     "init_var: delay buffer length in ms, default 500",
diff --git a/components/bl00mbox/radspa/standard_plugin_lib/distortion.c b/components/bl00mbox/radspa/standard_plugin_lib/distortion.c
index 60625c959d..e5a9cc68b7 100644
--- a/components/bl00mbox/radspa/standard_plugin_lib/distortion.c
+++ b/components/bl00mbox/radspa/standard_plugin_lib/distortion.c
@@ -2,7 +2,7 @@
 
 radspa_t * distortion_create(uint32_t init_var);
 radspa_descriptor_t distortion_desc = {
-    .name = "_distortion",
+    .name = "distortion",
     .id = 9000,
     .description = "distortion with linear interpolation between int16 values in plugin_table[129]",
     .create_plugin_instance = distortion_create,
@@ -13,28 +13,36 @@ radspa_descriptor_t distortion_desc = {
 #define DISTORTION_OUTPUT 0
 #define DISTORTION_INPUT 1
 
+static inline int32_t distort(int32_t input, int16_t * dist, uint8_t lerp_glitch){
+    // lerp glitch is a legacy feature from a math error of the 0th gen
+    // pass 9 normally, pass 7 for legacy glitch
+    input += 32768;
+    uint8_t index = input >> 9;
+    int32_t blend = input & ((1<<lerp_glitch)-1);
+    int32_t ret = dist[index]*((1<<lerp_glitch)-blend) + dist[index+1]*blend;
+    return ret >> lerp_glitch;
+}
+
 void distortion_run(radspa_t * distortion, uint16_t num_samples, uint32_t render_pass_id){
     radspa_signal_t * output_sig = radspa_signal_get_by_index(distortion, DISTORTION_OUTPUT);
     if(output_sig->buffer == NULL) return;
     int16_t * dist = distortion->plugin_table;
     radspa_signal_t * input_sig = radspa_signal_get_by_index(distortion, DISTORTION_INPUT);
-
-    static int32_t ret = 0;
-    
-    for(uint16_t i = 0; i < num_samples; i++){
-
-        int32_t input = radspa_signal_get_value(input_sig, i, render_pass_id);
-        input += 32768;
-        uint8_t index = input>>9;
-        int32_t blend = input & ((1<<7)-1);
-        ret = dist[index]*((1<<7)-blend) + dist[index+1]*blend;
-        ret = ret >> 7;
-        radspa_signal_set_value(output_sig, i, ret);
+    int32_t input = radspa_signal_get_const_value(input_sig, render_pass_id);
+    uint8_t lerp_glitch = 9 - ((dist[129]) & 7); // legacy glitch
+    if(input != RADSPA_SIGNAL_NONCONST){
+        radspa_signal_set_const_value(output_sig, distort(input, dist, lerp_glitch));
+    } else {
+        for(uint16_t i = 0; i < num_samples; i++){
+            int32_t input = radspa_signal_get_value(input_sig, i, render_pass_id);
+            radspa_signal_set_value(output_sig, i, distort(input, dist, lerp_glitch));
+        }
     }
+
 }
 
 radspa_t * distortion_create(uint32_t init_var){
-    radspa_t * distortion = radspa_standard_plugin_create(&distortion_desc, DISTORTION_NUM_SIGNALS, 0, (1<<7) + 1);
+    radspa_t * distortion = radspa_standard_plugin_create(&distortion_desc, DISTORTION_NUM_SIGNALS, 0, (1<<7) + 2);
     if(distortion == NULL) return NULL;
     distortion->render = distortion_run;
     radspa_signal_set(distortion, DISTORTION_OUTPUT, "output", RADSPA_SIGNAL_HINT_OUTPUT, 0);
@@ -49,6 +57,7 @@ radspa_t * distortion_create(uint32_t init_var){
             dist[i] = -((128-i)*(128-i)*32767>>12) + 32767;
         }
     }
+    dist[129] = 0;
 
     return distortion;
 }
diff --git a/components/bl00mbox/radspa/standard_plugin_lib/filter.c b/components/bl00mbox/radspa/standard_plugin_lib/filter.c
index 7096e52786..b821b827b1 100644
--- a/components/bl00mbox/radspa/standard_plugin_lib/filter.c
+++ b/components/bl00mbox/radspa/standard_plugin_lib/filter.c
@@ -22,6 +22,8 @@ radspa_descriptor_t filter_desc = {
 #define FILTER_MODE_BANDPASS 1
 #define FILTER_MODE_HIGHPASS 2
 
+#define INV_NORM_BOOST 5
+
 static inline int32_t approx_cos(uint32_t x){
     // x: full circle: 1<<32
     // return val: 1<<30 <=> 1
@@ -37,17 +39,17 @@ static inline int32_t approx_cos(uint32_t x){
 static inline void get_mode_coeffs(uint8_t mode, filter_data_t * data, int32_t * coeffs){
     switch(mode){
         case FILTER_MODE_LOWPASS:
-            coeffs[1] = ((1L<<21) - data->cos_omega) * data->inv_norm;
-            coeffs[0] = coeffs[1]/2;
+            coeffs[1] = ((((1L<<21) - data->cos_omega)>>INV_NORM_BOOST) * data->inv_norm)>>1;
+            coeffs[0] = coeffs[1]>>1;
             coeffs[2] = coeffs[0];
             break;
         case FILTER_MODE_BANDPASS:
-            coeffs[0] = data->alpha * data->inv_norm;
+            coeffs[0] = (data->alpha>>INV_NORM_BOOST) * data->inv_norm;
             coeffs[1] = 0;
             coeffs[2] = -coeffs[0];
             break;
         case FILTER_MODE_HIGHPASS:
-            coeffs[1] = -((1L<<21) + data->cos_omega) * data->inv_norm;
+            coeffs[1] = ((-((1L<<21) + data->cos_omega)>>INV_NORM_BOOST) * data->inv_norm)>>1;
             coeffs[0] = -coeffs[1]/2;
             coeffs[2] = coeffs[0];
             break;
@@ -64,48 +66,56 @@ static inline void get_coeffs(filter_data_t * data, int16_t pitch, int16_t reso,
         if(freq > (3UL<<29)) freq = 3UL<<29;
 
         // unit: 1<<21 <=> 1, range: [0..1<<21]
-        data->cos_omega = approx_cos(freq)>>9;
+        int32_t cos_omega = approx_cos(freq)>>9;
         // unit: 1<<21 <=> 1, range: [0..3<<21]
-        data->alpha = approx_cos(freq + (3UL<<30))/mqi;
-        // unit transform from 1<<21 to 1<<29 <=> 1
-        data->inv_norm = (1L<<29)/((1L<<21) + data->alpha);
+        int32_t alpha = approx_cos(freq + (3UL<<30))/mqi;
+        // unit transform from 1<<21 to 1<<30 <=> 1
+        int32_t inv_norm = (1L<<30)/(((1L<<(21)) + alpha)>>INV_NORM_BOOST);
+
+        data->cos_omega = cos_omega;
+        data->alpha = alpha;
+        data->inv_norm = inv_norm;
 
-        data->pitch_prev = pitch;
-        data->reso_prev = reso;
     }
     if((pitch != data->pitch_prev) || (reso != data->reso_prev) || (mode != data->mode_prev)){
         // unit for {in/out}_coeffs: 1<<29 <=> 1, range: full
-        data->out_coeffs[1] = -2*data->cos_omega * data->inv_norm;
-        data->out_coeffs[2] = ((1<<21) - data->alpha) * data->inv_norm;
+        data->out_coeffs[1] = (-data->cos_omega>>INV_NORM_BOOST) * data->inv_norm;
+        data->out_coeffs[2] = ((((1<<21) - data->alpha)>>INV_NORM_BOOST) * data->inv_norm) >> 1;
         if(mode == -32767){
             get_mode_coeffs(FILTER_MODE_LOWPASS, data, data->in_coeffs);
-            return;
         } else if(mode == 0){
             get_mode_coeffs(FILTER_MODE_BANDPASS, data, data->in_coeffs);
-            return;
         } else if(mode == 32767){
             get_mode_coeffs(FILTER_MODE_HIGHPASS, data, data->in_coeffs);
-            return;
-        }
-        int32_t a[3];
-        int32_t b[3];
-        int32_t blend = mode;
-        if(mode < 0){
-            get_mode_coeffs(FILTER_MODE_LOWPASS, data, a);
-            get_mode_coeffs(FILTER_MODE_BANDPASS, data, b);
-            blend += 32767;
         } else {
-            get_mode_coeffs(FILTER_MODE_BANDPASS, data, a);
-            get_mode_coeffs(FILTER_MODE_HIGHPASS, data, b);
-        }
-        blend = blend << 16;
-        for(uint8_t i = 0; i<3; i++){
-            data->in_coeffs[i] = ((int64_t) b[i] * blend) >> 32;
-            data->in_coeffs[i] += ((int64_t) a[i] * ((1L<<31) - blend)) >> 32;
-            data->in_coeffs[i] = data->in_coeffs[i] << 1;
+            int32_t a[3];
+            int32_t b[3];
+            int32_t blend = mode;
+            if(mode < 0){
+                get_mode_coeffs(FILTER_MODE_LOWPASS, data, a);
+                get_mode_coeffs(FILTER_MODE_BANDPASS, data, b);
+                blend += 32767;
+            } else {
+                get_mode_coeffs(FILTER_MODE_BANDPASS, data, a);
+                get_mode_coeffs(FILTER_MODE_HIGHPASS, data, b);
+            }
+            blend = blend << 16;
+            for(uint8_t i = 0; i<3; i++){
+                data->in_coeffs[i] = ((int64_t) b[i] * blend) >> 32;
+                data->in_coeffs[i] += ((int64_t) a[i] * ((1L<<31) - blend)) >> 32;
+                data->in_coeffs[i] = data->in_coeffs[i] << 1;
+            }
+            data->const_output = RADSPA_SIGNAL_NONCONST;
         }
-        data->const_output = RADSPA_SIGNAL_NONCONST;
+        /*
+        printf("cos_omega: %ld alpha: %ld inv_norm: %ld\n",data->cos_omega, data->alpha, data->inv_norm);
+        printf("in_coeffs: %ld %ld %ld\n",data->in_coeffs[0], data->in_coeffs[1], data->in_coeffs[2]);
+        printf("out_coeffs: %ld %ld\n", data->out_coeffs[1], data->out_coeffs[2]);
+        */
     }
+    data->pitch_prev = pitch;
+    data->reso_prev = reso;
+    data->mode_prev = mode;
 }
 
 void filter_run(radspa_t * filter, uint16_t num_samples, uint32_t render_pass_id){
@@ -131,7 +141,7 @@ void filter_run(radspa_t * filter, uint16_t num_samples, uint32_t render_pass_id
     int16_t reso = reso_const;
     int16_t mode = mode_const;
     int16_t mix = mix_const;
-    int16_t input = input_const;
+    int32_t input = input_const;
     bool always_update_coeffs = true;
 
     if((pitch_const != RADSPA_SIGNAL_NONCONST) && (reso_const != RADSPA_SIGNAL_NONCONST) && (mode_const != RADSPA_SIGNAL_NONCONST)){
@@ -159,16 +169,15 @@ void filter_run(radspa_t * filter, uint16_t num_samples, uint32_t render_pass_id
         }
 
         if(input_const == RADSPA_SIGNAL_NONCONST) input = radspa_signal_get_value(input_sig, i, render_pass_id);
-        int32_t in = radspa_clip(radspa_gain(input, gain));
 
         data->pos++;
         if(data->pos >= 3) data->pos = 0;
 
-        data->in_history[data->pos] = in << 12;
+        data->in_history[data->pos] = input << 12;
 
         int32_t ret = ((int64_t) data->in_coeffs[0] * data->in_history[data->pos]) >> 32;
 
-        for(int8_t i = 1; i<3; i++){
+        for(int8_t i = 1; i < 3; i++){
             int8_t pos = data->pos - i;
             if(pos < 0) pos += 3;
             ret += ((int64_t) data->in_history[pos] * data->in_coeffs[i]) >> 32;
@@ -179,10 +188,9 @@ void filter_run(radspa_t * filter, uint16_t num_samples, uint32_t render_pass_id
         } else if(ret <= -(1L<<28)){
             ret = 1-(1L<<28);
         }
-        ret = ret << 3;
-        data->out_history[data->pos] = ret;
+        data->out_history[data->pos] = ret << 3;
 
-        ret = ret >> 12;
+        ret = ret >> 9;
 
         if(reso < 0) ret = input - (ret<<1); //allpass mode
         if(mix == -32767){
@@ -192,10 +200,10 @@ void filter_run(radspa_t * filter, uint16_t num_samples, uint32_t render_pass_id
         } else  if(mix != 32767){
             ret *= mix;
             int32_t dry_vol = mix > 0 ? 32767 - mix : 32767 + mix;
-            ret += radspa_gain(dry_vol, gain) * input;
+            ret += dry_vol * input;
             ret = ret >> 15;
         }
-        out[i] = radspa_clip(ret);
+        out[i] = radspa_clip(radspa_gain(ret, gain));
     }
 
     if(input_const == RADSPA_SIGNAL_NONCONST){
diff --git a/components/bl00mbox/radspa/standard_plugin_lib/flanger.c b/components/bl00mbox/radspa/standard_plugin_lib/flanger.c
index 44b21543f3..40dee9c70e 100644
--- a/components/bl00mbox/radspa/standard_plugin_lib/flanger.c
+++ b/components/bl00mbox/radspa/standard_plugin_lib/flanger.c
@@ -22,13 +22,13 @@ radspa_descriptor_t flanger_desc = {
 #define FLANGER_LEVEL 5
 #define FLANGER_MIX 6
 
-static inline int16_t fixed_point_list_access(int32_t * buf, uint32_t fp_index, uint32_t buf_len){
-    uint32_t index = (fp_index) >> (FIXED_POINT_DIGITS);
+static inline int32_t fixed_point_list_access(int32_t * buf, int32_t fp_index, uint32_t buf_len){
+    int32_t index = (fp_index) >> (FIXED_POINT_DIGITS);
     while(index >= buf_len) index -= buf_len;
-    uint32_t next_index = index + 1;
+    int32_t next_index = index + 1;
     while(next_index >= buf_len) next_index -= buf_len;
 
-    uint32_t subindex = (fp_index) & ((1<<(FIXED_POINT_DIGITS)) - 1);
+    int32_t subindex = (fp_index) & ((1<<(FIXED_POINT_DIGITS)) - 1);
     int32_t ret =  buf[index] * ((1<<(FIXED_POINT_DIGITS)) - subindex);
     ret += (buf[next_index]) * subindex;
     ret = ret >> (FIXED_POINT_DIGITS);
@@ -61,7 +61,7 @@ void flanger_run(radspa_t * flanger, uint16_t num_samples, uint32_t render_pass_
     radspa_signal_t * mix_sig = radspa_signal_get_by_index(flanger, FLANGER_MIX);
 
     int32_t reso = radspa_signal_get_value(reso_sig, 0, render_pass_id);
-    reso = reso << 16;
+    reso = reso << 14;
     int32_t level = radspa_signal_get_value(level_sig, 0, render_pass_id);
     int32_t mix = radspa_signal_get_value(mix_sig, 0, render_pass_id);
     int32_t decay = radspa_signal_get_value(decay_sig, 0, render_pass_id);
@@ -78,9 +78,9 @@ void flanger_run(radspa_t * flanger, uint16_t num_samples, uint32_t render_pass_
         int32_t sgn_decay = decay > 0 ? 1 : -1;
         int32_t abs_decay = decay * sgn_decay;
         if((abs_decay != data->abs_decay_prev) || (manual != data->manual_prev)){
-            int32_t decay_invert = - ((data->read_head_offset * 50) >> FIXED_POINT_DIGITS)/decay;
-            decay_invert += 34614; // magic number
-            data->decay_reso = radspa_sct_to_rel_freq(radspa_clip(decay_invert), 0) >> 1;
+            int32_t decay_invert = - ((data->read_head_offset * 50) >> FIXED_POINT_DIGITS)/abs_decay;
+            decay_invert += 34614 - 4800 - 2400; // magic number
+            data->decay_reso = radspa_sct_to_rel_freq(radspa_clip(decay_invert), 0);
         }
         int32_t tmp = reso + sgn_decay * data->decay_reso;
         if((sgn_decay == 1) && (tmp < reso)){
@@ -103,8 +103,14 @@ void flanger_run(radspa_t * flanger, uint16_t num_samples, uint32_t render_pass_
         while(data->read_head_position < 0) data->read_head_position += VARIABLE_NAME; //underflow
 
         buf[data->write_head_position] = dry;
-        int32_t wet = fixed_point_list_access(buf, data->read_head_position, FLANGER_BUFFER_SIZE) << 1;
-        buf[data->write_head_position] += ((int64_t) wet * reso) >> 32;
+        int32_t wet = fixed_point_list_access(buf, data->read_head_position, FLANGER_BUFFER_SIZE) << 3;
+        bool sgn_wet = wet > 0;
+        bool sgn_reso = reso > 0;
+        if(sgn_wet != sgn_reso){
+            buf[data->write_head_position] -= ((int64_t) (-wet) * reso) >> 32;
+        } else {
+            buf[data->write_head_position] += ((int64_t) wet * reso) >> 32;
+        }
 
         int32_t ret = radspa_add_sat(radspa_mult_shift(dry, dry_vol), radspa_mult_shift(radspa_clip(wet), mix));
         ret = radspa_clip(radspa_gain(ret, level));
diff --git a/components/bl00mbox/radspa/standard_plugin_lib/mixer.c b/components/bl00mbox/radspa/standard_plugin_lib/mixer.c
index 1b07a26147..4dcd5011d9 100644
--- a/components/bl00mbox/radspa/standard_plugin_lib/mixer.c
+++ b/components/bl00mbox/radspa/standard_plugin_lib/mixer.c
@@ -86,7 +86,7 @@ void mixer_run(radspa_t * mixer, uint16_t num_samples, uint32_t render_pass_id){
             for(uint16_t i = 0; i < num_samples; i++){
                 bool invert = data->dc < 0;
                 if(invert) data->dc = -data->dc;
-                data->dc = ((uint64_t) data->dc * (((1<<12) - 1)<<20)) >> 32;
+                data->dc = ((uint64_t) data->dc * (((1UL<<12) - 1)<<20)) >> 32;
                 if(invert) data->dc = -data->dc;
                 data->dc += ret[i];
                 ret[i] -= (data->dc >> 12);
@@ -96,7 +96,7 @@ void mixer_run(radspa_t * mixer, uint16_t num_samples, uint32_t render_pass_id){
                 for(uint16_t i = 0; i < num_samples; i++){
                     bool invert = data->dc < 0;
                     if(invert) data->dc = -data->dc;
-                    data->dc = ((uint64_t) data->dc * (((1<<12) - 1)<<20)) >> 32;
+                    data->dc = ((uint64_t) data->dc * (((1UL<<12) - 1)<<20)) >> 32;
                     if(invert) data->dc = -data->dc;
                     ret[i] = -(data->dc >> 12);
                     ret_init = true;
-- 
GitLab