From ce2212708a54cbe6c79bab3165301c4c35206c40 Mon Sep 17 00:00:00 2001
From: Michael Sippel <micha@fragmental.art>
Date: Thu, 13 Feb 2025 18:00:59 +0100
Subject: [PATCH 1/5] up expr threshold

---
 guitfx.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/guitfx.c b/guitfx.c
index 11ffe2c..561156e 100644
--- a/guitfx.c
+++ b/guitfx.c
@@ -92,11 +92,12 @@ static void on_process(void *userdata, struct spa_io_position *position)
 									    // expr pedal
 							      		    float val_f = ((float)midi_data[2]) / 128.0;
 
-									    float thres = 0.4;
+									    float thres = 0.5;
 									    
 								            if ( val_f > thres ) {
-									        printf("Expr Pedal %f\n", val_f);
-										data->delay.mix = (val_f - thres) / (1.0-thres);
+   									        float expr_mix = (val_f - thres) / (1.0-thres);
+									        printf("Expr Pedal %f\n", expr_mix);
+										data->delay.mix = expr_mix;
 									    } else {
 									        data->delay.mix = 0.0;
 								            }

From 62acece20421a86bb769128a3bd8df2871e1ff65 Mon Sep 17 00:00:00 2001
From: Michael Sippel <micha@fragmental.art>
Date: Mon, 17 Feb 2025 17:56:58 +0100
Subject: [PATCH 2/5] gate: decrease attack, increase release

---
 gate.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/gate.c b/gate.c
index bb11f25..8829c9f 100644
--- a/gate.c
+++ b/gate.c
@@ -17,8 +17,8 @@ void gate_init(
 
     gate->is_active = false;
     gate->cur_gain = 1.0;
-    gate->attack = 1.0 / 512.0;
-    gate->release = 1.0 / 4096.0;
+    gate->attack = 1.0 / 128.0;
+    gate->release = 1.0 / 8192.0;
 }
 
 void gate_process(

From a6970aeed3b1f28b7f0dfc4ec2d2acec0a707675 Mon Sep 17 00:00:00 2001
From: Michael Sippel <micha@fragmental.art>
Date: Mon, 17 Feb 2025 18:06:56 +0100
Subject: [PATCH 3/5] clang format

---
 delay.c  |  47 ++++---
 delay.h  |  19 ++-
 gate.c   |  62 ++++-----
 gate.h   |  33 +++--
 guitfx.c | 400 ++++++++++++++++++++++++++-----------------------------
 sust.c   |  78 ++++++-----
 sust.h   |  18 ++-
 7 files changed, 315 insertions(+), 342 deletions(-)

diff --git a/delay.c b/delay.c
index 31f3089..1723ca9 100644
--- a/delay.c
+++ b/delay.c
@@ -1,12 +1,12 @@
-#include <stdint.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <stdio.h>
 #include "delay.h"
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
 
 void delay_init(
-    struct delay * delay
-) {
+    struct delay* delay)
+{
     delay->mix = 0.8;
     delay->feedback = 0.8;
     delay->duration = 0;
@@ -16,39 +16,38 @@ void delay_init(
 }
 
 void delay_set_time(
-    struct delay * delay,
-    uint64_t new_duration
-) {
+    struct delay* delay,
+    uint64_t new_duration)
+{
     printf("set delay duration to %lu samples\n", new_duration);
-    if( new_duration > delay->buf_capacity ) {
+    if (new_duration > delay->buf_capacity) {
         delay->buf_capacity = new_duration;
-        delay->buf = realloc( delay->buf, sizeof(float) * new_duration );
+        delay->buf = realloc(delay->buf, sizeof(float) * new_duration);
     }
 
-    for( int i = delay->duration; i < new_duration; ++i ) {
+    for (int i = delay->duration; i < new_duration; ++i) {
         delay->buf[i] = delay->buf[i - delay->duration];
     }
 
     delay->duration = new_duration;
-    if( new_duration > 0 ) {
+    if (new_duration > 0) {
         delay->buf_idx %= new_duration;
     }
 }
 
 void delay_process(
-    struct delay * delay,
+    struct delay* delay,
     size_t frame_size,
-    float const * in,
-    float * out
-) {
-    for( size_t i = 0; i < frame_size; ++i ) {
-        if( delay->duration > 0 ) {
-            out[i] =
-                in[i]
-                + delay->mix * delay->buf[ delay->buf_idx ];
+    float const* in,
+    float* out)
+{
+    for (size_t i = 0; i < frame_size; ++i) {
+        if (delay->duration > 0) {
+            out[i] = in[i]
+                + delay->mix * delay->buf[delay->buf_idx];
 
-            delay->buf[ delay->buf_idx ] *= delay->feedback;
-            delay->buf[ delay->buf_idx ] += (1.0 - delay->feedback) * in[i];
+            delay->buf[delay->buf_idx] *= delay->feedback;
+            delay->buf[delay->buf_idx] += (1.0 - delay->feedback) * in[i];
             delay->buf_idx = (delay->buf_idx + 1) % delay->duration;
         } else {
             out[i] = 0.5 * in[i];
diff --git a/delay.h b/delay.h
index 4ed2cf5..499b1cc 100644
--- a/delay.h
+++ b/delay.h
@@ -1,7 +1,7 @@
 #pragma once
 
-#include <stdint.h>
 #include <stddef.h>
+#include <stdint.h>
 
 struct delay {
     uint64_t duration;
@@ -10,21 +10,18 @@ struct delay {
 
     uint64_t buf_idx;
     size_t buf_capacity;
-    float * buf;
+    float* buf;
 };
 
 void delay_init(
-    struct delay * delay
-);
+    struct delay* delay);
 
 void delay_set_time(
-    struct delay * delay,
-    uint64_t new_duration
-);
+    struct delay* delay,
+    uint64_t new_duration);
 
 void delay_process(
-    struct delay * delay,
+    struct delay* delay,
     size_t frame_size,
-    float const * in,
-    float * out
-);
+    float const* in,
+    float* out);
diff --git a/gate.c b/gate.c
index 8829c9f..3f13c6a 100644
--- a/gate.c
+++ b/gate.c
@@ -1,13 +1,13 @@
-#include <stdint.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <stdio.h>
 #include "gate.h"
 #include <math.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
 
 void gate_init(
-    struct gate * gate
-) {
+    struct gate* gate)
+{
     gate->threshold = 0.0;
     gate->enable_calibration = false;
 
@@ -22,42 +22,42 @@ void gate_init(
 }
 
 void gate_process(
-    struct gate * gate,
+    struct gate* gate,
     size_t frame_size,
-    float const * in,
-    float * out
-) {
+    float const* in,
+    float* out)
+{
 
-  bool act = false;
+    bool act = false;
 
-    for( size_t i = 0; i < frame_size; ++i ) {
-        gate->cur_block_sum += fabs( in[i] );
-	gate->cur_block_count += 1;
+    for (size_t i = 0; i < frame_size; ++i) {
+        gate->cur_block_sum += fabs(in[i]);
+        gate->cur_block_count += 1;
 
-        if( gate->cur_block_count >= gate->block_size ) {
-	  //printf("new block sum %f, gain = %f\n", gate->cur_block_sum, gate->cur_gain);
+        if (gate->cur_block_count >= gate->block_size) {
+            // printf("new block sum %f, gain = %f\n", gate->cur_block_sum, gate->cur_gain);
 
-	  gate->last_block_sum = gate->cur_block_sum;
-	  gate->cur_block_sum = 0.0;
+            gate->last_block_sum = gate->cur_block_sum;
+            gate->cur_block_sum = 0.0;
 
-	  if( gate->last_block_sum > 0.03 ) {
-              act = true;
-	  } else {
-              act = false;
-	  }
-	}
+            if (gate->last_block_sum > 0.03) {
+                act = true;
+            } else {
+                act = false;
+            }
+        }
 
-	if( act ) {
-	    gate->cur_gain += gate->attack;
-	    if( gate->cur_gain > 1.0 ) {
+        if (act) {
+            gate->cur_gain += gate->attack;
+            if (gate->cur_gain > 1.0) {
                 gate->cur_gain = 1.0;
             }
-	} else {
-	    gate->cur_gain -= gate->release;
-	    if( gate->cur_gain < 0.0 ) {
+        } else {
+            gate->cur_gain -= gate->release;
+            if (gate->cur_gain < 0.0) {
                 gate->cur_gain = 0.0;
             }
-	}
+        }
 
         out[i] = in[i] * gate->cur_gain;
     }
diff --git a/gate.h b/gate.h
index 7f96d6a..3773e5c 100644
--- a/gate.h
+++ b/gate.h
@@ -1,29 +1,28 @@
 #pragma once
 
-#include <stdint.h>
-#include <stddef.h>
 #include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
 
 struct gate {
-  float threshold;
-  bool enable_calibration;
+    float threshold;
+    bool enable_calibration;
 
-  unsigned block_size;
-  unsigned cur_block_count;
-  float cur_block_sum;
-  float last_block_sum;
+    unsigned block_size;
+    unsigned cur_block_count;
+    float cur_block_sum;
+    float last_block_sum;
 
-  bool is_active;
-  float cur_gain;
+    bool is_active;
+    float cur_gain;
 
-  float attack;
-  float release;
+    float attack;
+    float release;
 };
 
 void gate_init();
 void gate_process(
-     struct gate * gate,
-     size_t frame_size,
-     float const * in,
-     float * out
-);
+    struct gate* gate,
+    size_t frame_size,
+    float const* in,
+    float* out);
diff --git a/guitfx.c b/guitfx.c
index 561156e..90d2f4f 100644
--- a/guitfx.c
+++ b/guitfx.c
@@ -2,283 +2,259 @@
 #include "pipewire/port.h"
 #include "spa/pod/iter.h"
 #include "spa/utils/defs.h"
-#include <stdio.h>
 #include <signal.h>
+#include <stdio.h>
 
-#include <spa/pod/pod.h>
-#include <spa/pod/builder.h>
 #include <spa/control/control.h>
 #include <spa/param/latency-utils.h>
+#include <spa/pod/builder.h>
+#include <spa/pod/pod.h>
 
-#include <pipewire/pipewire.h>
 #include <pipewire/filter.h>
+#include <pipewire/pipewire.h>
 
 #include "delay.h"
-#include "sust.h"
 #include "gate.h"
+#include "sust.h"
 
-float envelope( float x );
+float envelope(float x);
 
 struct data;
 
 struct port {
-	struct data *data;
+    struct data* data;
 };
 
 struct data {
-	struct pw_main_loop * loop;
-	struct pw_filter * filter;
-	struct port * guit_in_port;
-	struct port * midi_in_port;
-	struct port * out_port;
+    struct pw_main_loop* loop;
+    struct pw_filter* filter;
+    struct port* guit_in_port;
+    struct port* midi_in_port;
+    struct port* out_port;
 
-	//! effect data
-	uint64_t last_tap;
-	struct delay delay;
-	struct sust sust;
-        struct gate gate;
+    //! effect data
+    uint64_t last_tap;
+    struct delay delay;
+    struct sust sust;
+    struct gate gate;
 
-        unsigned prog;
+    unsigned prog;
 
-	//! elapsed time in number of samples
-	uint64_t time;
+    //! elapsed time in number of samples
+    uint64_t time;
 };
 
-static void on_process(void *userdata, struct spa_io_position *position)
+static void on_process(void* userdata, struct spa_io_position* position)
 {
-	struct data *data = userdata;
+    struct data* data = userdata;
 
-	uint32_t n_samples = position->clock.duration;
-	uint64_t frame = data->time;
-	data->time += n_samples;
+    uint32_t n_samples = position->clock.duration;
+    uint64_t frame = data->time;
+    data->time += n_samples;
 
-	struct pw_buffer * b = pw_filter_dequeue_buffer(data->midi_in_port);
-	if( b == NULL ) {
-	   fprintf(stderr, "on_process(): no buffer for midi_in_port\n");
-	   return;
-	}
+    struct pw_buffer* b = pw_filter_dequeue_buffer(data->midi_in_port);
+    if (b == NULL) {
+        fprintf(stderr, "on_process(): no buffer for midi_in_port\n");
+        return;
+    }
 
-	struct spa_buffer * buf = b->buffer;
-	spa_assert(buf->n_datas == 1);
-	struct spa_data   * d   = &buf->datas[0];
+    struct spa_buffer* buf = b->buffer;
+    spa_assert(buf->n_datas == 1);
+    struct spa_data* d = &buf->datas[0];
 
-	if( d->data ) {
-	    struct spa_pod * pod =
-			spa_pod_from_data(
-			    d->data,
-				d->maxsize,
-				d->chunk->offset,
-				d->chunk->size
-			);
+    if (d->data) {
+        struct spa_pod* pod = spa_pod_from_data(d->data, d->maxsize,
+            d->chunk->offset, d->chunk->size);
 
-		if( pod ) {
-		    if( spa_pod_is_sequence(pod) ) {
-				struct spa_pod_sequence * pod_seq = (struct spa_pod_sequence*) pod;
-				struct spa_pod_control * c;
-				SPA_POD_SEQUENCE_FOREACH(pod_seq, c) {
-				    if( c->type == SPA_CONTROL_Midi ) {
-						unsigned sec =
-						      (frame + c->offset)
-							/ (float) position->clock.rate.denom;
-						char * midi_data = SPA_POD_BODY(&c->value);
-						unsigned size = SPA_POD_BODY_SIZE(&c->value);
+        if (pod) {
+            if (spa_pod_is_sequence(pod)) {
+                struct spa_pod_sequence* pod_seq = (struct spa_pod_sequence*)pod;
+                struct spa_pod_control* c;
+                SPA_POD_SEQUENCE_FOREACH(pod_seq, c)
+                {
+                    if (c->type == SPA_CONTROL_Midi) {
+                        unsigned sec = (frame + c->offset) / (float)position->clock.rate.denom;
+                        char* midi_data = SPA_POD_BODY(&c->value);
+                        unsigned size = SPA_POD_BODY_SIZE(&c->value);
 
-						printf("[%d] MIDI message (%d bytes) : %x, %x, %x\n", sec, size, midi_data[0], midi_data[1], midi_data[2]);
+                        printf("[%d] MIDI message (%d bytes) : %x, %x, %x\n", sec, size,
+                            midi_data[0], midi_data[1], midi_data[2]);
 
-						switch( midi_data[0] & 0xff ) {
-						    case 0xb0:
-								switch( midi_data[1] ) {
-									case 0x0b:
-									    // expr pedal
-							      		    float val_f = ((float)midi_data[2]) / 128.0;
+                        switch (midi_data[0] & 0xff) {
+                        case 0xb0:
+                            switch (midi_data[1]) {
+                            case 0x0b:
+                                // expr pedal
+                                float val_f = ((float)midi_data[2]) / 128.0;
 
-									    float thres = 0.5;
-									    
-								            if ( val_f > thres ) {
-   									        float expr_mix = (val_f - thres) / (1.0-thres);
-									        printf("Expr Pedal %f\n", expr_mix);
-										data->delay.mix = expr_mix;
-									    } else {
-									        data->delay.mix = 0.0;
-								            }
-									    break;
+                                float thres = 0.5;
 
-								    case 0x42:
+                                if (val_f > thres) {
+                                    float expr_mix = (val_f - thres) / (1.0 - thres);
+                                    printf("Expr Pedal %f\n", expr_mix);
+                                    data->delay.mix = expr_mix;
+                                } else {
+                                    data->delay.mix = 0.0;
+                                }
+                                break;
 
-								      // noise gate calibration
-								      if( data->prog == 2 ) {
-									if( midi_data[2] >= 64) {
-									  data->gate.threshold = data->gate.cur_block_sum * 0.8;
-									  printf("calibrate noise gate: threshold = %f\n", data->gate.threshold); 
-									}
-								      }
+                            case 0x42:
 
-							  	      // sust pedal
-								      if( data->prog == 1 ) {
-										if( midi_data[2] >= 64) {
-											sust_swap( &data->sust );
-										    data->sust.playing = true;
+                                // noise gate calibration
+                                if (data->prog == 2) {
+                                    if (midi_data[2] >= 64) {
+                                        data->gate.threshold = data->gate.cur_block_sum * 0.8;
+                                        printf("calibrate noise gate: threshold = %f\n",
+                                            data->gate.threshold);
+                                    }
+                                }
 
-											data->sust.start_idx = data->sust.idx;
-											data->sust.idx = 0;
-										} else {
-											data->sust.playing = false;
-										}
-								      }
+                                // sust pedal
+                                if (data->prog == 1) {
+                                    if (midi_data[2] >= 64) {
+                                        sust_swap(&data->sust);
+                                        data->sust.playing = true;
 
-										// tap tempo
-										if( data->prog == 0 ) {
-										  uint64_t cur_tap = frame + c->offset;
-										  uint64_t duration = cur_tap - data->last_tap;
-										  data->last_tap = cur_tap;
-										  if( duration < (4*position->clock.rate.denom) ) {
-										    delay_set_time( &data->delay, duration );
-										  }
+                                        data->sust.start_idx = data->sust.idx;
+                                        data->sust.idx = 0;
+                                    } else {
+                                        data->sust.playing = false;
+                                    }
+                                }
 
+                                // tap tempo
+                                if (data->prog == 0) {
+                                    uint64_t cur_tap = frame + c->offset;
+                                    uint64_t duration = cur_tap - data->last_tap;
+                                    data->last_tap = cur_tap;
+                                    if (duration < (4 * position->clock.rate.denom)) {
+                                        delay_set_time(&data->delay, duration);
+                                    }
 
-										  sust_resize( &data->sust, duration );
-										}
+                                    sust_resize(&data->sust, duration);
+                                }
 
-										break;
-								}
+                                break;
+                            }
 
-								break;
+                            break;
 
-							case 0xc0:
-							    // program change
-										if( midi_data[2] >= 64) {
-											sust_swap( &data->sust );
-										    data->sust.playing = true;
+                        case 0xc0:
+                            // program change
+                            if (midi_data[2] >= 64) {
+                                sust_swap(&data->sust);
+                                data->sust.playing = true;
 
-											data->sust.start_idx = data->sust.idx;
-											data->sust.idx = 0;
-										} else {
-											data->sust.playing = false;
-										}
-								printf("program change: %u\n", midi_data[1]);
-								data->prog = midi_data[1];
-							    break;
-						}
-					} else {
-					    printf("on_process(): non midi-control\n");
-					}
-				}
-			} else {
-			    fprintf(stderr, "on_process(): unexpected POD that is not a sequence (midi_in_port)\n");
-			}
-		} else {
-		    fprintf(stderr, "on_process(): pod is NULL\n");
-		}
-	} else {
-	    fprintf(stderr, "on_process(): no data in buffer of midi_in_port\n");
-	}
+                                data->sust.start_idx = data->sust.idx;
+                                data->sust.idx = 0;
+                            } else {
+                                data->sust.playing = false;
+                            }
+                            printf("program change: %u\n", midi_data[1]);
+                            data->prog = midi_data[1];
+                            break;
+                        }
+                    } else {
+                        printf("on_process(): non midi-control\n");
+                    }
+                }
+            } else {
+                fprintf(stderr, "on_process(): unexpected POD that is not a sequence "
+                                "(midi_in_port)\n");
+            }
+        } else {
+            fprintf(stderr, "on_process(): pod is NULL\n");
+        }
+    } else {
+        fprintf(stderr, "on_process(): no data in buffer of midi_in_port\n");
+    }
 
-	pw_filter_queue_buffer(data->midi_in_port, b);
+    pw_filter_queue_buffer(data->midi_in_port, b);
 
-
-	float * const in = pw_filter_get_dsp_buffer(data->guit_in_port, n_samples);
-	float tmp1[n_samples];
-	float tmp2[n_samples];
-	float * out = pw_filter_get_dsp_buffer(data->out_port, n_samples);
-	if( in && out ) {
-	  gate_process( &data->gate, n_samples, in, tmp1 );
-	  sust_process( &data->sust, n_samples, tmp1, tmp2 );
-	  delay_process( &data->delay, n_samples, tmp2, out );
-	}
+    float* const in = pw_filter_get_dsp_buffer(data->guit_in_port, n_samples);
+    float tmp1[n_samples];
+    float tmp2[n_samples];
+    float* out = pw_filter_get_dsp_buffer(data->out_port, n_samples);
+    if (in && out) {
+        gate_process(&data->gate, n_samples, in, tmp1);
+        sust_process(&data->sust, n_samples, tmp1, tmp2);
+        delay_process(&data->delay, n_samples, tmp2, out);
+    }
 }
 
 static const struct pw_filter_events filter_events = {
-	PW_VERSION_FILTER_EVENTS,
-	.process = on_process,
+    PW_VERSION_FILTER_EVENTS,
+    .process = on_process,
 };
 
-static void do_quit(void *userdata, int signal_number)
+static void do_quit(void* userdata, int signal_number)
 {
-	struct data *data = userdata;
-	pw_main_loop_quit(data->loop);
+    struct data* data = userdata;
+    pw_main_loop_quit(data->loop);
 }
 
-int main(int argc, char *argv[])
+int main(int argc, char* argv[])
 {
-	struct data data = { 0, };
+    struct data data = {
+        0,
+    };
 
-	gate_init( &data.gate );
-	delay_init( &data.delay );
-	sust_init( &data.sust );
-	data.prog = 0;
+    gate_init(&data.gate);
+    delay_init(&data.delay);
+    sust_init(&data.sust);
+    data.prog = 0;
 
-	const struct spa_pod *params[1];
-	uint8_t buffer[1024];
-	struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
+    const struct spa_pod* params[1];
+    uint8_t buffer[1024];
+    struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
 
-	pw_init(&argc, &argv);
+    pw_init(&argc, &argv);
 
-	data.loop = pw_main_loop_new(NULL);
+    data.loop = pw_main_loop_new(NULL);
 
-	pw_loop_add_signal(pw_main_loop_get_loop(data.loop), SIGINT, do_quit, &data);
-	pw_loop_add_signal(pw_main_loop_get_loop(data.loop), SIGTERM, do_quit, &data);
+    pw_loop_add_signal(pw_main_loop_get_loop(data.loop), SIGINT, do_quit, &data);
+    pw_loop_add_signal(pw_main_loop_get_loop(data.loop), SIGTERM, do_quit, &data);
 
-	data.filter = pw_filter_new_simple(
-			pw_main_loop_get_loop(data.loop),
-			"Guitar FX",
-			pw_properties_new(
-				PW_KEY_MEDIA_TYPE, "Audio",
-				PW_KEY_MEDIA_CATEGORY, "Filter",
-				PW_KEY_MEDIA_ROLE, "DSP",
-				NULL),
-			&filter_events,
-			&data);
+    data.filter = pw_filter_new_simple(
+        pw_main_loop_get_loop(data.loop), "Guitar FX",
+        pw_properties_new(PW_KEY_MEDIA_TYPE, "Audio", PW_KEY_MEDIA_CATEGORY,
+            "Filter", PW_KEY_MEDIA_ROLE, "DSP", NULL),
+        &filter_events, &data);
 
-	data.midi_in_port = pw_filter_add_port(data.filter,
-		    PW_DIRECTION_INPUT,
-			PW_FILTER_PORT_FLAG_MAP_BUFFERS,
-			sizeof(struct port),
-			pw_properties_new(
-			    PW_KEY_FORMAT_DSP, "8 bit raw midi",
-				PW_KEY_PORT_NAME, "midi in",
-				NULL
-			),
-			NULL, 0
-		);
+    data.midi_in_port = pw_filter_add_port(data.filter, PW_DIRECTION_INPUT,
+        PW_FILTER_PORT_FLAG_MAP_BUFFERS, sizeof(struct port),
+        pw_properties_new(PW_KEY_FORMAT_DSP, "8 bit raw midi",
+            PW_KEY_PORT_NAME, "midi in", NULL),
+        NULL, 0);
 
-	data.guit_in_port = pw_filter_add_port(data.filter,
-			PW_DIRECTION_INPUT,
-			PW_FILTER_PORT_FLAG_MAP_BUFFERS,
-			sizeof(struct port),
-			pw_properties_new(
-				PW_KEY_FORMAT_DSP, "32 bit float mono audio",
-				PW_KEY_PORT_NAME, "guitar in",
-				NULL),
-			NULL, 0);
+    data.guit_in_port = pw_filter_add_port(
+        data.filter, PW_DIRECTION_INPUT, PW_FILTER_PORT_FLAG_MAP_BUFFERS,
+        sizeof(struct port),
+        pw_properties_new(PW_KEY_FORMAT_DSP, "32 bit float mono audio",
+            PW_KEY_PORT_NAME, "guitar in", NULL),
+        NULL, 0);
 
-	data.out_port = pw_filter_add_port(data.filter,
-			PW_DIRECTION_OUTPUT,
-			PW_FILTER_PORT_FLAG_MAP_BUFFERS,
-			sizeof(struct port),
-			pw_properties_new(
-				PW_KEY_FORMAT_DSP, "32 bit float mono audio",
-				PW_KEY_PORT_NAME, "fx out",
-				NULL),
-			NULL, 0);
+    data.out_port = pw_filter_add_port(
+        data.filter, PW_DIRECTION_OUTPUT, PW_FILTER_PORT_FLAG_MAP_BUFFERS,
+        sizeof(struct port),
+        pw_properties_new(PW_KEY_FORMAT_DSP, "32 bit float mono audio",
+            PW_KEY_PORT_NAME, "fx out", NULL),
+        NULL, 0);
 
-	params[0] = spa_process_latency_build(&b,
-			SPA_PARAM_ProcessLatency,
-			&SPA_PROCESS_LATENCY_INFO_INIT(
-				.ns = 10 * SPA_NSEC_PER_MSEC
-			));
+    params[0] = spa_process_latency_build(
+        &b, SPA_PARAM_ProcessLatency,
+        &SPA_PROCESS_LATENCY_INFO_INIT(.ns = 10 * SPA_NSEC_PER_MSEC));
 
-	if (pw_filter_connect(data.filter,
-				PW_FILTER_FLAG_RT_PROCESS,
-				params, 1) < 0) {
-		fprintf(stderr, "can't connect\n");
-		return -1;
-	}
+    if (pw_filter_connect(data.filter, PW_FILTER_FLAG_RT_PROCESS, params, 1) < 0) {
+        fprintf(stderr, "can't connect\n");
+        return -1;
+    }
 
-	pw_main_loop_run(data.loop);
+    pw_main_loop_run(data.loop);
 
-	pw_filter_destroy(data.filter);
-	pw_main_loop_destroy(data.loop);
-	pw_deinit();
+    pw_filter_destroy(data.filter);
+    pw_main_loop_destroy(data.loop);
+    pw_deinit();
 
-	return 0;
+    return 0;
 }
diff --git a/sust.c b/sust.c
index d684930..f9d31a2 100644
--- a/sust.c
+++ b/sust.c
@@ -1,9 +1,10 @@
 #include "sust.h"
 #include <math.h>
-#include <stdlib.h>
 #include <stdio.h>
+#include <stdlib.h>
 
-void sust_init( struct sust * sust ) {
+void sust_init(struct sust* sust)
+{
     sust->mode = MODE_Sostenuto;
 
     sust->playing = false;
@@ -12,73 +13,76 @@ void sust_init( struct sust * sust ) {
     sust->idx = 0;
 
     sust->buf_len = 51200;
-    sust->record_buf = malloc( sizeof(float) * sust->buf_len );
-    sust->play_buf = malloc( sizeof(float) * sust->buf_len );
+    sust->record_buf = malloc(sizeof(float) * sust->buf_len);
+    sust->play_buf = malloc(sizeof(float) * sust->buf_len);
 }
 
-float envelope( float x ) {
-    if( x < 0.4 )
+float envelope(float x)
+{
+    if (x < 0.4)
         return (x / 0.4) * (x / 0.4);
-    if( x < 0.6 )
+    if (x < 0.6)
         return 1.0;
 
-   float v  = 1.0 - ((x - 0.6) / 0.4);
-   return v*v;
+    float v = 1.0 - ((x - 0.6) / 0.4);
+    return v * v;
 }
 
-float softcos( float x ) {
-    return sin( x * (3.141 / 2.0) );
+float softcos(float x)
+{
+    return sin(x * (3.141 / 2.0));
 }
 
-void sust_resize( struct sust * sust, size_t new_len ) {
-  sust->buf_len = new_len;
-  sust->play_buf = realloc( sust->play_buf, sizeof(float) * new_len );
-  sust->record_buf = realloc( sust->record_buf, sizeof(float) * new_len );
-  sust->idx %= new_len;
+void sust_resize(struct sust* sust, size_t new_len)
+{
+    sust->buf_len = new_len;
+    sust->play_buf = realloc(sust->play_buf, sizeof(float) * new_len);
+    sust->record_buf = realloc(sust->record_buf, sizeof(float) * new_len);
+    sust->idx %= new_len;
 }
 
 void sust_swap(
-    struct sust * sust
-) {
-    float * tmp = sust->play_buf;
+    struct sust* sust)
+{
+    float* tmp = sust->play_buf;
     sust->play_buf = sust->record_buf;
     sust->record_buf = tmp;
 
-    for( int i = 0; i  < sust->buf_len; ++i ) {
+    for (int i = 0; i < sust->buf_len; ++i) {
         sust->record_buf[i] = sust->play_buf[i];
     }
 }
 
 void sust_process(
-    struct sust * sust,
+    struct sust* sust,
     size_t frame_size,
-    float const * in,
-    float * out
-) {
-    for( size_t i = 0; i < frame_size; ++i ) {
+    float const* in,
+    float* out)
+{
+    for (size_t i = 0; i < frame_size; ++i) {
 
-        if( sust->mode == MODE_Sustain && sust->idx == 0 ) {
-            sust_swap( sust );
+        if (sust->mode == MODE_Sustain && sust->idx == 0) {
+            sust_swap(sust);
         }
 
         float out_value = in[i];
 
-        if( sust->playing ) {
+        if (sust->playing) {
             int n_voices = 5;
 
-            for( int v = 0; v < n_voices; ++v ) {
-                size_t play_idx = (sust->start_idx + sust->idx + ((v*sust->buf_len)/n_voices)) % sust->buf_len;
-                float gain = envelope( ((float) play_idx) / ((float)sust->buf_len) );
-               //printf("gain = %f\n", gain);
-                out_value += 0.5 *gain * sust->play_buf[ play_idx ];
+            for (int v = 0; v < n_voices; ++v) {
+                size_t play_idx = (sust->start_idx + sust->idx + ((v * sust->buf_len) / n_voices)) % sust->buf_len;
+                float gain = envelope(((float)play_idx) / ((float)sust->buf_len));
+                // printf("gain = %f\n", gain);
+                out_value += 0.5 * gain * sust->play_buf[play_idx];
             }
         }
 
-        if( sust->mode == MODE_Sostenuto ) {
-            sust->record_buf[ sust->idx ] = in[i];
+        if (sust->mode == MODE_Sostenuto) {
+            sust->record_buf[sust->idx] = in[i];
         }
-        if( sust->mode == MODE_Sustain ) {
-            sust->record_buf[ sust->idx ] = 0.5*out_value;
+        if (sust->mode == MODE_Sustain) {
+            sust->record_buf[sust->idx] = 0.5 * out_value;
         }
 
         sust->idx = (sust->idx + 1) % sust->buf_len;
diff --git a/sust.h b/sust.h
index 92bece8..a0472b1 100644
--- a/sust.h
+++ b/sust.h
@@ -15,18 +15,16 @@ struct sust {
     size_t start_idx;
     size_t idx;
     size_t buf_len;
-    float * record_buf;
-    float * play_buf;
+    float* record_buf;
+    float* play_buf;
 };
 
-
-void sust_init( struct sust * sust );
-void sust_resize( struct sust * sust, size_t new_len );
-void sust_swap( struct sust * sust );
+void sust_init(struct sust* sust);
+void sust_resize(struct sust* sust, size_t new_len);
+void sust_swap(struct sust* sust);
 
 void sust_process(
-    struct sust * sust,
+    struct sust* sust,
     size_t frame_size,
-    float const * in,
-    float * out
-);
+    float const* in,
+    float* out);

From 752155de328e1407bc486dd9bc5f83f577276160 Mon Sep 17 00:00:00 2001
From: Michael Sippel <micha@fragmental.art>
Date: Mon, 17 Feb 2025 18:07:53 +0100
Subject: [PATCH 4/5] add gitignore

---
 .gitignore | 2 ++
 1 file changed, 2 insertions(+)
 create mode 100644 .gitignore

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..dee53c5
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+build
+*~

From 765275ac325e46552700e051615982b936da8a78 Mon Sep 17 00:00:00 2001
From: Michael Sippel <micha@fragmental.art>
Date: Mon, 17 Feb 2025 18:59:37 +0100
Subject: [PATCH 5/5] move midi-control into separate function&file

---
 controller.c | 110 +++++++++++++++++++++++++++++++++++++++++++++
 guitfx.c     | 125 +++++++++++----------------------------------------
 guitfx.h     |  16 +++++++
 meson.build  |   1 +
 4 files changed, 153 insertions(+), 99 deletions(-)
 create mode 100644 controller.c
 create mode 100644 guitfx.h

diff --git a/controller.c b/controller.c
new file mode 100644
index 0000000..76e38b7
--- /dev/null
+++ b/controller.c
@@ -0,0 +1,110 @@
+#include "pipewire/keys.h"
+#include "pipewire/port.h"
+#include "spa/pod/iter.h"
+#include "spa/utils/defs.h"
+#include <signal.h>
+#include <stdio.h>
+
+#include <spa/control/control.h>
+#include <spa/param/latency-utils.h>
+#include <spa/pod/builder.h>
+#include <spa/pod/pod.h>
+
+#include <pipewire/filter.h>
+#include <pipewire/pipewire.h>
+
+#include "guitfx.h"
+#include "delay.h"
+#include "sust.h"
+#include "gate.h"
+
+void midi_control(
+		  struct FxData * data,
+
+		  uint64_t frame,
+		  uint64_t offset,
+		  unsigned sec,
+		  unsigned midi_size,
+		  uint8_t * midi_data,
+		  struct spa_io_position* position
+) {
+  printf("[%d] MIDI message (%d bytes) : %x, %x, %x\n", sec, midi_size,
+	 midi_data[0], midi_data[1], midi_data[2]);
+
+                        switch (midi_data[0] & 0xff) {
+                        case 0xb0:
+                            switch (midi_data[1]) {
+                            case 0x0b:
+                                // expr pedal
+                                float val_f = ((float)midi_data[2]) / 128.0;
+
+                                float thres = 0.5;
+
+                                if (val_f > thres) {
+                                    float expr_mix = (val_f - thres) / (1.0 - thres);
+                                    printf("Expr Pedal %f\n", expr_mix);
+
+                                    data->delay.mix = expr_mix;
+                                } else {
+                                    data->delay.mix = 0.0;
+                                }
+                                break;
+
+                            case 0x42:
+
+                                // noise gate calibration
+                                if (data->prog == 2) {
+                                    if (midi_data[2] >= 64) {
+                                        data->gate.threshold = data->gate.cur_block_sum * 0.8;
+                                        printf("calibrate noise gate: threshold = %f\n",
+                                            data->gate.threshold);
+                                    }
+                                }
+
+                                // sust pedal
+                                if (data->prog == 1) {
+                                    if (midi_data[2] >= 64) {
+                                        sust_swap(&data->sust);
+                                        data->sust.playing = true;
+
+                                        data->sust.start_idx = data->sust.idx;
+                                        data->sust.idx = 0;
+                                    } else {
+                                        data->sust.playing = false;
+                                    }
+                                }
+
+                                // tap tempo
+                                if (data->prog == 0) {
+                                    uint64_t cur_tap = frame + offset;
+                                    uint64_t duration = cur_tap - data->last_tap;
+                                    data->last_tap = cur_tap;
+                                    if (duration < (4 * position->clock.rate.denom)) {
+                                        delay_set_time(&data->delay, duration);
+                                    }
+
+                                    sust_resize(&data->sust, duration);
+                                }
+
+                                break;
+                            }
+
+                            break;
+
+                        case 0xc0:
+                            // program change
+                            if (midi_data[2] >= 64) {
+                                sust_swap(&data->sust);
+                                data->sust.playing = true;
+
+                                data->sust.start_idx = data->sust.idx;
+                                data->sust.idx = 0;
+                            } else {
+                                data->sust.playing = false;
+                            }
+                            printf("program change: %u\n", midi_data[1]);
+                            data->prog = midi_data[1];
+                            break;
+                        }
+}
+
diff --git a/guitfx.c b/guitfx.c
index 90d2f4f..82b53ca 100644
--- a/guitfx.c
+++ b/guitfx.c
@@ -16,6 +16,7 @@
 #include "delay.h"
 #include "gate.h"
 #include "sust.h"
+#include "guitfx.h"
 
 float envelope(float x);
 
@@ -25,23 +26,24 @@ struct port {
     struct data* data;
 };
 
+void midi_control(
+		  struct FxData * data,
+
+		  uint64_t frame,
+		  uint64_t offset,
+		  unsigned sec,
+		  unsigned midi_size,
+		  uint8_t * midi_data,
+		  struct spa_io_position* position);
+
+
 struct data {
     struct pw_main_loop* loop;
     struct pw_filter* filter;
     struct port* guit_in_port;
     struct port* midi_in_port;
     struct port* out_port;
-
-    //! effect data
-    uint64_t last_tap;
-    struct delay delay;
-    struct sust sust;
-    struct gate gate;
-
-    unsigned prog;
-
-    //! elapsed time in number of samples
-    uint64_t time;
+    struct FxData fx_data;
 };
 
 static void on_process(void* userdata, struct spa_io_position* position)
@@ -49,8 +51,8 @@ static void on_process(void* userdata, struct spa_io_position* position)
     struct data* data = userdata;
 
     uint32_t n_samples = position->clock.duration;
-    uint64_t frame = data->time;
-    data->time += n_samples;
+    uint64_t frame = data->fx_data.time;
+    data->fx_data.time += n_samples;
 
     struct pw_buffer* b = pw_filter_dequeue_buffer(data->midi_in_port);
     if (b == NULL) {
@@ -75,87 +77,12 @@ static void on_process(void* userdata, struct spa_io_position* position)
                     if (c->type == SPA_CONTROL_Midi) {
                         unsigned sec = (frame + c->offset) / (float)position->clock.rate.denom;
                         char* midi_data = SPA_POD_BODY(&c->value);
-                        unsigned size = SPA_POD_BODY_SIZE(&c->value);
+                        unsigned midi_size = SPA_POD_BODY_SIZE(&c->value);
 
-                        printf("[%d] MIDI message (%d bytes) : %x, %x, %x\n", sec, size,
-                            midi_data[0], midi_data[1], midi_data[2]);
-
-                        switch (midi_data[0] & 0xff) {
-                        case 0xb0:
-                            switch (midi_data[1]) {
-                            case 0x0b:
-                                // expr pedal
-                                float val_f = ((float)midi_data[2]) / 128.0;
-
-                                float thres = 0.5;
-
-                                if (val_f > thres) {
-                                    float expr_mix = (val_f - thres) / (1.0 - thres);
-                                    printf("Expr Pedal %f\n", expr_mix);
-                                    data->delay.mix = expr_mix;
-                                } else {
-                                    data->delay.mix = 0.0;
-                                }
-                                break;
-
-                            case 0x42:
-
-                                // noise gate calibration
-                                if (data->prog == 2) {
-                                    if (midi_data[2] >= 64) {
-                                        data->gate.threshold = data->gate.cur_block_sum * 0.8;
-                                        printf("calibrate noise gate: threshold = %f\n",
-                                            data->gate.threshold);
-                                    }
-                                }
-
-                                // sust pedal
-                                if (data->prog == 1) {
-                                    if (midi_data[2] >= 64) {
-                                        sust_swap(&data->sust);
-                                        data->sust.playing = true;
-
-                                        data->sust.start_idx = data->sust.idx;
-                                        data->sust.idx = 0;
-                                    } else {
-                                        data->sust.playing = false;
-                                    }
-                                }
-
-                                // tap tempo
-                                if (data->prog == 0) {
-                                    uint64_t cur_tap = frame + c->offset;
-                                    uint64_t duration = cur_tap - data->last_tap;
-                                    data->last_tap = cur_tap;
-                                    if (duration < (4 * position->clock.rate.denom)) {
-                                        delay_set_time(&data->delay, duration);
-                                    }
-
-                                    sust_resize(&data->sust, duration);
-                                }
-
-                                break;
-                            }
-
-                            break;
-
-                        case 0xc0:
-                            // program change
-                            if (midi_data[2] >= 64) {
-                                sust_swap(&data->sust);
-                                data->sust.playing = true;
-
-                                data->sust.start_idx = data->sust.idx;
-                                data->sust.idx = 0;
-                            } else {
-                                data->sust.playing = false;
-                            }
-                            printf("program change: %u\n", midi_data[1]);
-                            data->prog = midi_data[1];
-                            break;
-                        }
+			midi_control( &data->fx_data, frame, c->offset, sec, midi_size, midi_data, position );
                     } else {
-                        printf("on_process(): non midi-control\n");
+
+		      printf("on_process(): non midi-control\n");
                     }
                 }
             } else {
@@ -176,9 +103,9 @@ static void on_process(void* userdata, struct spa_io_position* position)
     float tmp2[n_samples];
     float* out = pw_filter_get_dsp_buffer(data->out_port, n_samples);
     if (in && out) {
-        gate_process(&data->gate, n_samples, in, tmp1);
-        sust_process(&data->sust, n_samples, tmp1, tmp2);
-        delay_process(&data->delay, n_samples, tmp2, out);
+        gate_process(&data->fx_data.gate, n_samples, in, tmp1);
+        sust_process(&data->fx_data.sust, n_samples, tmp1, tmp2);
+        delay_process(&data->fx_data.delay, n_samples, tmp2, out);
     }
 }
 
@@ -199,10 +126,10 @@ int main(int argc, char* argv[])
         0,
     };
 
-    gate_init(&data.gate);
-    delay_init(&data.delay);
-    sust_init(&data.sust);
-    data.prog = 0;
+    gate_init(&data.fx_data.gate);
+    delay_init(&data.fx_data.delay);
+    sust_init(&data.fx_data.sust);
+    data.fx_data.prog = 0;
 
     const struct spa_pod* params[1];
     uint8_t buffer[1024];
diff --git a/guitfx.h b/guitfx.h
new file mode 100644
index 0000000..4dedcdd
--- /dev/null
+++ b/guitfx.h
@@ -0,0 +1,16 @@
+
+#include "delay.h"
+#include "sust.h"
+#include "gate.h"
+
+struct FxData {
+    uint64_t last_tap;
+    struct delay delay;
+    struct sust sust;
+    struct gate gate;
+
+    unsigned prog;
+
+    //! elapsed time in number of samples
+    uint64_t time;
+};
diff --git a/meson.build b/meson.build
index d59ef2b..ab53a04 100644
--- a/meson.build
+++ b/meson.build
@@ -10,5 +10,6 @@ executable(
     'delay.c',
     'sust.c',
     'gate.c',
+    'controller.c',
     dependencies : [pipewire_dep, m_dep],
 )