Wavetable and reverb

This commit is contained in:
Dejvino
2026-02-28 00:24:17 +01:00
parent e86c06e05f
commit 58af6bd3dc
3 changed files with 261 additions and 8 deletions
+63 -1
View File
@@ -118,7 +118,7 @@ float SynthEngine::processGridStep() {
// Check if neighbor outputs to (tx, ty)
bool connects = false;
if (n.type == GridCell::WIRE || n.type == GridCell::FIXED_OSCILLATOR || n.type == GridCell::INPUT_OSCILLATOR || n.type == GridCell::OPERATOR || n.type == GridCell::NOISE || n.type == GridCell::DELAY) {
if (n.type == GridCell::WIRE || n.type == GridCell::FIXED_OSCILLATOR || n.type == GridCell::INPUT_OSCILLATOR || n.type == GridCell::WAVETABLE || n.type == GridCell::OPERATOR || n.type == GridCell::NOISE || n.type == GridCell::DELAY || n.type == GridCell::REVERB) {
// Check rotation
// 0:N (y-1), 1:E (x+1), 2:S (y+1), 3:W (x-1)
if (n.rotation == 0 && from_y - 1 == ty && from_x == tx) connects = true;
@@ -184,6 +184,41 @@ float SynthEngine::processGridStep() {
c.phase += inc;
if (c.phase >= SINE_TABLE_SIZE) c.phase -= SINE_TABLE_SIZE;
val = (float)sine_table[(int)c.phase] / 32768.0f;
} else if (c.type == GridCell::WAVETABLE) {
float mod = 0.0f;
mod += getInput(x, y, x, y-1);
mod += getInput(x, y, x+1, y);
mod += getInput(x, y, x, y+1);
mod += getInput(x, y, x-1, y);
float freq = 440.0f + (mod * 500.0f); // Fixed base freq + FM
if (freq < 1.0f) freq = 1.0f;
float inc = freq * (float)SINE_TABLE_SIZE / (float)_sampleRate;
c.phase += inc;
if (c.phase >= SINE_TABLE_SIZE) c.phase -= SINE_TABLE_SIZE;
float phase_norm = c.phase / (float)SINE_TABLE_SIZE; // 0.0 to 1.0
int wave_select = (int)(c.param * 7.99f);
switch(wave_select) {
case 0: val = (float)sine_table[(int)c.phase] / 32768.0f; break;
case 1: val = (phase_norm * 2.0f) - 1.0f; break; // Saw
case 2: val = (phase_norm < 0.5f) ? 1.0f : -1.0f; break; // Square
case 3: val = (phase_norm < 0.5f) ? (phase_norm * 4.0f - 1.0f) : (3.0f - phase_norm * 4.0f); break; // Triangle
case 4: val = 1.0f - (phase_norm * 2.0f); break; // Ramp
case 5: val = (phase_norm < 0.25f) ? 1.0f : -1.0f; break; // Pulse 25%
case 6: // Distorted Sine
val = sin(phase_norm * 2.0 * M_PI) + sin(phase_norm * 4.0 * M_PI) * 0.3f;
val /= 1.3f; // Normalize
break;
case 7: // Organ-like
val = sin(phase_norm * 2.0 * M_PI) * 0.6f +
sin(phase_norm * 4.0 * M_PI) * 0.2f +
sin(phase_norm * 8.0 * M_PI) * 0.1f;
val /= 0.9f; // Normalize
break;
}
} else if (c.type == GridCell::NOISE) {
float white = (float)rand() / (float)RAND_MAX * 2.0f - 1.0f;
int shade = (int)(c.param * 4.99f);
@@ -252,6 +287,33 @@ float SynthEngine::processGridStep() {
} else {
val = 0.0f; // No buffer, no output
}
} else if (c.type == GridCell::REVERB) {
// Input is from the "Back" (rot+2)
int inDir = (c.rotation + 2) % 4;
int dx=0, dy=0;
if(inDir==0) dy=-1; else if(inDir==1) dx=1; else if(inDir==2) dy=1; else dx=-1;
float input_val = getInput(x, y, x+dx, y+dy);
if (c.buffer && c.buffer_size > 0) {
// Fixed delay for reverb effect (e.g. 50ms)
uint32_t delay_samples = (uint32_t)(0.05f * _sampleRate);
if (delay_samples >= c.buffer_size) delay_samples = c.buffer_size - 1;
int read_idx = (int)c.write_idx - (int)delay_samples;
if (read_idx < 0) read_idx += c.buffer_size;
float delayed = c.buffer[read_idx];
// Feedback controlled by param (0.0 to 0.95)
float feedback = c.param * 0.95f;
float newValue = input_val + delayed * feedback;
c.buffer[c.write_idx] = newValue;
val = newValue;
c.write_idx = (c.write_idx + 1) % c.buffer_size;
} else {
val = 0.0f;
}
} else if (c.type == GridCell::OPERATOR || c.type == GridCell::SINK) {
// Gather inputs
float inputs[4];