Optimize more by avoiding floating point

This commit is contained in:
Dejvino
2026-03-01 14:26:18 +01:00
parent 8cc8898c01
commit 534a7512c4
3 changed files with 32 additions and 27 deletions
+29 -26
View File
@@ -28,6 +28,7 @@ SynthEngine::SynthEngine(uint32_t sampleRate)
_volume(0.5f),
_waveform(SAWTOOTH),
_isGateOpen(false),
_freqToPhaseInc(0.0f),
_rngState(12345)
{
fill_sine_table();
@@ -35,6 +36,7 @@ SynthEngine::SynthEngine(uint32_t sampleRate)
setFrequency(440.0f);
// Initialize SINK
_freqToPhaseInc = 4294967296.0f / (float)_sampleRate;
grid[GRID_W / 2][GRID_H - 1].type = GridCell::SINK;
rebuildProcessingOrder();
}
@@ -92,6 +94,7 @@ int SynthEngine::importGrid(const uint8_t* buffer, size_t size) {
c.rotation = 0;
c.value = 0.0f;
c.phase = 0.0f;
c.phase_accumulator = 0;
c.next_value = 0.0f;
}
}
@@ -127,6 +130,7 @@ void SynthEngine::clearGrid() {
c.rotation = 0;
c.value = 0.0f;
c.phase = 0.0f;
c.phase_accumulator = 0;
c.next_value = 0.0f;
}
}
@@ -446,45 +450,45 @@ float SynthEngine::processGridStep() {
// Gather inputs for modulation
float mod = getInputFromTheBack(x, y, c);
// Freq 10 to 1000 Hz
// Freq 10 to 1000 Hz.
float freq = 10.0f + c.param * 990.0f + (mod * 500.0f); // 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;
val = (float)sine_table[(int)c.phase] / 32768.0f;
// Fixed point phase accumulation
uint32_t inc = (uint32_t)(freq * _freqToPhaseInc);
c.phase_accumulator += inc;
// Top 8 bits of 32-bit accumulator form the 256-entry table index
val = (float)sine_table[c.phase_accumulator >> 24] / 32768.0f;
val *= getSideInputGain(x, y, c);
} else if (c.type == GridCell::INPUT_OSCILLATOR) {
float mod = getInputFromTheBack(x, y, c);
// Freq based on current note + octave param (1-5)
float baseFreq = getFrequency();
int octave = 1 + (int)(c.param * 4.99f); // Map 0.0-1.0 to 1-5
float freq = baseFreq * (float)(1 << (octave - 1)); // 2^(octave-1)
freq += (mod * 500.0f); // Apply FM
if (freq < 1.0f) freq = 1.0f; // Protect against negative/zero freq
float inc = freq * (float)SINE_TABLE_SIZE / (float)_sampleRate;
c.phase += inc;
if (c.phase >= SINE_TABLE_SIZE) c.phase -= SINE_TABLE_SIZE;
val = (float)sine_table[(int)c.phase] / 32768.0f;
// Use the engine's global increment directly to avoid float conversion round-trip
uint32_t baseInc = _increment;
uint32_t inc = baseInc << (octave - 1);
// Apply FM (mod is float, convert to fixed point increment)
inc += (int32_t)(mod * 500.0f * _freqToPhaseInc);
c.phase_accumulator += inc;
val = (float)sine_table[c.phase_accumulator >> 24] / 32768.0f;
val *= getSideInputGain(x, y, c);
} else if (c.type == GridCell::WAVETABLE) {
float mod = getInputFromTheBack(x, y, c);
// Track current note frequency + FM
float freq = getFrequency() + (mod * 500.0f);
if (freq < 1.0f) freq = 1.0f;
// Track current note frequency + FM. Use direct increment for speed.
uint32_t inc = _increment + (int32_t)(mod * 500.0f * _freqToPhaseInc);
c.phase_accumulator += inc;
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
// 0.0 to 1.0 representation for math-based waveforms
float phase_norm = (float)c.phase_accumulator / 4294967296.0f;
int wave_select = (int)(c.param * 7.99f);
switch(wave_select) {
case 0: val = (float)sine_table[(int)c.phase] / 32768.0f; break;
case 0: val = (float)sine_table[c.phase_accumulator >> 24] / 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
@@ -535,11 +539,10 @@ float SynthEngine::processGridStep() {
} else if (c.type == GridCell::LFO) {
// Low Frequency Oscillator (0.1 Hz to 20 Hz)
float freq = 0.1f + c.param * 19.9f;
float inc = freq * (float)SINE_TABLE_SIZE / (float)_sampleRate;
c.phase += inc;
if (c.phase >= SINE_TABLE_SIZE) c.phase -= SINE_TABLE_SIZE;
uint32_t inc = (uint32_t)(freq * _freqToPhaseInc);
c.phase_accumulator += inc;
// Output full range -1.0 to 1.0
val = (float)sine_table[(int)c.phase] / 32768.0f;
val = (float)sine_table[c.phase_accumulator >> 24] / 32768.0f;
} else if (c.type == GridCell::FORK) {
// Sum inputs from "Back" (Input direction)
val = getInputFromTheBack(x, y, c);