Tuesday, February 3, 2026

Confirming that the code is correct

This post shows the verification of the code in the previous post.


int24_t saw[7] = {0,0,0,0,0,0,0};

const int24_t detune_table[7] = {0, 128, -128, 408, -412, 704, -720};

int24_t next(int24_t pitch, int24_t mix, int24_t detune) {

int24_t sum = 0;

for (int i = 0; i < 7; i++) {
int24_t detunePitch = ((int48_t) pitch * detune) >> 23;
int24_t voice_detune = ((int48_t) detune_table[i] * detunePitch) >> 7;
saw[i] += pitch + voice_detune;

if (i == 0) {
sum += ((int48_t) saw[i] * 25) >> 7;
} else {
sum += ((int48_t) saw[i] * (mix >> 16)) >> 7;
}
}
return high_pass(sum);
}


Pitch

Pitch arrives at program memory location 0x0424, after some calculations pitch is stored at iram[0x65]. The same value arrives unchanged at the first oscillator calculation at 0x0455.
 
Pitch code is correct.


Detune

Detune arrives at 0x043f. The same value minus one arrives at the first oscillator calculation at 0x0455. Detune is stored in mulcoeffs[0]. 

With detune = midi 127 and pitch = midi 97, we get 

pitch = 421800 

detune = 164352

(pitch * detune) >> 23 = 8237

Test:

Osc 4 detune 8237 * 408 / 128 = 26255.4, from debugger: 26255

Osc 5 detune  8237 * -412 / 128 = -26512.8, from debugger: -26513

Osc 6 detune: 8237 * 704 / 128 = 45303.5, from debugger: 45303

Osc 7 detune: , 8237 * -720 / 128 = 46333.13, from debugger: -46334

 

Detune code is correct.

 

Mix

Mix arrives at 0x043c. The same value minus one arrives at the oscillator mixing code at 0x47a. Mix is stored in mulcoeffs[1] 

With mix = midi 127:

mix = mulcoeffs[1] = 2183167 (input - 1) 

mix >> 16 =  2183167 >> 16 = 33

 

Results below are found by stepping through the debugger. Iram contains the raw values for each saws.

Step 1: 

Iram 11 = -7537654

Result  = -1943302

Control: 

 -7537654 * 33 / 128 = - 1943301.4 // OK!

 

Step 2: 

Iram 6 = -8000810

Result = -4006011

Control: 

-8000810 * 33 / 128 = -2062708.8 // contrib from this osc

-2062708.8 - 1943302 = -4006011.8 // OK!


Step 3:

Iram 9 = 92969

Result = -3982043

Control: 

92969 * 33 / 128 = 23968.57 // contrib from this osc

23968.57 - 4006011.8 = -3982043.23 // OK! 


Step 4:

Iram 5 = -4968160

Result = -4952387

Control:  

-4968160 *25 / 128 = -907343.75 // center oscillator

-3982043 -907343.75 = -4952386.75 // OK!

 

Step 5: 

Iram 7 = 6361263

Result = -3312374

Control:  

6361263 * 33 / 128 = 1640013.12 // contrib from this osc

1640013.12 - 4952386.75 = -3312373.6 // OK!

 

Step 6: 

Iram 0b = 3650948

Result = -2371114

Control: 

3650948 * 33 / 128 = 941260.03 // contrib from this osc

941260.03 - 3312374 = -2371113.96 // OK!


Step 7:

Iram 0f is 6940947

Result = -581652

Control: 

6940947 * 33 / 128 = 1789462.0 // contrib from this osc

1789462.0 - 2371114 = -581651.1 // OK!

 

Summing code is correct.

 

Checking the detune coefficients

The integer coefficients we found:

[0, 128, -128, 408, -412, 704, -720]

The decimal coefficients in the presentation, that match Adam Szabo's detected ones:

[0, 0.01953125, -0.01953125, 0.06225585, -0.0628662, 0.107421875, -0.10986328125] 

These are 10/65536 times the integer coefficients (or 10 * (integer coefficient) >> 16). This holds true for all of the coefficients.

 

The coefficients are correct. 

 

No comments:

Post a Comment