@@ -44,8 +44,10 @@ static void voice_note_on(picosynth_voice_t *v, uint8_t note)
4444 n -> state = 0 ;
4545 n -> out = 0 ;
4646 /* Reset filter accumulators to prevent DC offsets/pops */
47- if (n -> type == PICOSYNTH_NODE_LP || n -> type == PICOSYNTH_NODE_HP )
47+ if (n -> type == PICOSYNTH_NODE_LP || n -> type == PICOSYNTH_NODE_HP ) {
4848 n -> flt .accum = 0 ;
49+ n -> flt .coeff = n -> flt .coeff_target ;
50+ }
4951 /* Reset envelope block state to force immediate rate calculation */
5052 if (n -> type == PICOSYNTH_NODE_ENV ) {
5153 n -> env .block_counter = 0 ;
@@ -325,6 +327,7 @@ void picosynth_init_lp(picosynth_node_t *n,
325327 n -> type = PICOSYNTH_NODE_LP ;
326328 n -> flt .in = in ;
327329 n -> flt .coeff = coeff ;
330+ n -> flt .coeff_target = coeff ;
328331}
329332
330333void picosynth_init_hp (picosynth_node_t * n ,
@@ -337,6 +340,14 @@ void picosynth_init_hp(picosynth_node_t *n,
337340 n -> type = PICOSYNTH_NODE_HP ;
338341 n -> flt .in = in ;
339342 n -> flt .coeff = coeff ;
343+ n -> flt .coeff_target = coeff ;
344+ }
345+
346+ void picosynth_filter_set_coeff (picosynth_node_t * n , q15_t coeff )
347+ {
348+ if (!n || (n -> type != PICOSYNTH_NODE_LP && n -> type != PICOSYNTH_NODE_HP ))
349+ return ;
350+ n -> flt .coeff_target = q15_sat (coeff );
340351}
341352
342353void picosynth_init_mix (picosynth_node_t * n ,
@@ -504,6 +515,18 @@ q15_t picosynth_process(picosynth_t *s)
504515 }
505516 case PICOSYNTH_NODE_LP :
506517 case PICOSYNTH_NODE_HP : {
518+ /* Smooth cutoff changes to avoid zipper noise (~4ms time
519+ * constant: delta/256 per sample).
520+ */
521+ int32_t coeff_delta =
522+ (int32_t ) n -> flt .coeff_target - n -> flt .coeff ;
523+ if (coeff_delta ) {
524+ int32_t step = coeff_delta >> 8 ;
525+ if (step == 0 )
526+ step = coeff_delta > 0 ? 1 : -1 ;
527+ n -> flt .coeff = q15_sat ((int32_t ) n -> flt .coeff + step );
528+ }
529+
507530 /* Single-pole filter accumulator update:
508531 * accum += (input - output)
509532 * where output is the filtered signal from the previous sample.
0 commit comments