guitfx/sust.c

92 lines
2.1 KiB
C
Raw Normal View History

2024-12-08 20:02:05 +01:00
#include "sust.h"
#include <math.h>
#include <stdio.h>
2025-02-17 18:06:56 +01:00
#include <stdlib.h>
2024-12-08 20:02:05 +01:00
2025-02-17 18:06:56 +01:00
void sust_init(struct sust* sust)
{
2024-12-08 20:02:05 +01:00
sust->mode = MODE_Sostenuto;
sust->playing = false;
sust->start_idx = 0;
sust->idx = 0;
2024-12-13 12:59:33 +01:00
sust->buf_len = 51200;
2025-02-17 18:06:56 +01:00
sust->record_buf = malloc(sizeof(float) * sust->buf_len);
sust->play_buf = malloc(sizeof(float) * sust->buf_len);
2024-12-08 20:02:05 +01:00
}
2025-02-17 18:06:56 +01:00
float envelope(float x)
{
if (x < 0.4)
2024-12-08 20:02:05 +01:00
return (x / 0.4) * (x / 0.4);
2025-02-17 18:06:56 +01:00
if (x < 0.6)
2024-12-08 20:02:05 +01:00
return 1.0;
2025-02-17 18:06:56 +01:00
float v = 1.0 - ((x - 0.6) / 0.4);
return v * v;
2024-12-08 20:02:05 +01:00
}
2025-02-17 18:06:56 +01:00
float softcos(float x)
{
return sin(x * (3.141 / 2.0));
2024-12-08 20:02:05 +01:00
}
2025-02-17 18:06:56 +01:00
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;
2024-12-13 12:59:33 +01:00
}
2024-12-08 20:02:05 +01:00
void sust_swap(
2025-02-17 18:06:56 +01:00
struct sust* sust)
{
float* tmp = sust->play_buf;
2024-12-08 20:02:05 +01:00
sust->play_buf = sust->record_buf;
sust->record_buf = tmp;
2025-02-17 18:06:56 +01:00
for (int i = 0; i < sust->buf_len; ++i) {
2024-12-08 20:02:05 +01:00
sust->record_buf[i] = sust->play_buf[i];
}
}
void sust_process(
2025-02-17 18:06:56 +01:00
struct sust* sust,
2024-12-08 20:02:05 +01:00
size_t frame_size,
2025-02-17 18:06:56 +01:00
float const* in,
float* out)
{
for (size_t i = 0; i < frame_size; ++i) {
2024-12-08 20:02:05 +01:00
2025-02-17 18:06:56 +01:00
if (sust->mode == MODE_Sustain && sust->idx == 0) {
sust_swap(sust);
2024-12-08 20:02:05 +01:00
}
float out_value = in[i];
2025-02-17 18:06:56 +01:00
if (sust->playing) {
2024-12-08 20:02:05 +01:00
int n_voices = 5;
2025-02-17 18:06:56 +01:00
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];
2024-12-08 20:02:05 +01:00
}
}
2025-02-17 18:06:56 +01:00
if (sust->mode == MODE_Sostenuto) {
sust->record_buf[sust->idx] = in[i];
2024-12-08 20:02:05 +01:00
}
2025-02-17 18:06:56 +01:00
if (sust->mode == MODE_Sustain) {
sust->record_buf[sust->idx] = 0.5 * out_value;
2024-12-08 20:02:05 +01:00
}
sust->idx = (sust->idx + 1) % sust->buf_len;
out[i] = out_value;
}
}