# HG changeset patch # User Josef 'Jeff' Sipek # Date 1672377094 18000 # Fri Dec 30 00:11:34 2022 -0500 # Node ID 0cce8e4cf6f402917b9044f4487d1060b20c534d # Parent 0988c0811f93133fbd07c2a2335edb3a5d962af2 main: do phase math using a uint16_t fixed point Using integer math for the phase calculation limits the tone frequencies to rather large discrete steps. When we represent a frequency as how many wave array steps we make per sample relative to 1 Hz, we get about 64 possible frequencies (assuming 16384 Hz sample rate and 256 entry wave array): > c(0:64)*(16384/256) [1] 0 64 128 192 256 320 384 448 512 576 640 704 768 832 896 [16] 960 1024 1088 1152 1216 1280 1344 1408 1472 1536 1600 1664 1728 1792 1856 [31] 1920 1984 2048 2112 2176 2240 2304 2368 2432 2496 2560 2624 2688 2752 2816 [46] 2880 2944 3008 3072 3136 3200 3264 3328 3392 3456 3520 3584 3648 3712 3776 [61] 3840 3904 3968 4032 4096 That is, we get frequencies that are multiples of 64 Hz. This are pretty substantial steps and makes many musical patterns sound out of tune. Instead of using a uint8_t to describe the frequency and the current phase, we could use more bits with an implied decimal point some number of bits in. This would allow us to calculate more accurately, and then simply round the index or interpolate between two values when doing the wave array lookup. This commit switches the phase calculation to uint16_t used as a 8.8 fixed point number. That is, given a phase x, the real world phase is x / 256. Signed-off-by: Josef 'Jeff' Sipek diff --git a/main.c b/main.c --- a/main.c +++ b/main.c @@ -139,10 +139,17 @@ * Audio */ -static inline uint8_t get_wave(uint8_t idx) +static inline uint8_t get_wave(uint16_t _idx) { bool reverse; bool negate; + uint8_t idx; + + /* convert 8.8 fixed point index to a 8.0 index */ + if ((_idx & 0xff) < 0x80) + idx = _idx >> 8; + else + idx = (_idx >> 8) + 1; if (idx < (1 * WAVE_STEPS / 4)) { reverse = false; @@ -226,9 +233,9 @@ static uint16_t steps; /* samples per tone */ static uint8_t overflows = 1; /* number of overflows before starting */ static uint8_t ntones; /* number of tones to play before stopping */ - static uint8_t phase; + static uint16_t phase; static uint8_t tone; - uint8_t dphase; + uint16_t dphase; /* * Note: We send out the sample now (asynchronously) but it will be @@ -371,7 +378,7 @@ tone = next_fixed_tone(tone); } - dphase = tones_fixed[tone]; + dphase = tones_fixed[tone] << 8; break; case STATE_PLAYING_LFSR: if (!steps) { @@ -379,7 +386,7 @@ tone = next_lfsr_tone(tone); } - dphase = tones_lfsr[tone]; + dphase = tones_lfsr[tone] << 8; break; case STATE_PLAYING_IDENT: if (!steps) { @@ -394,7 +401,7 @@ phase = 0; } - dphase = tones_morse[tone]; + dphase = tones_morse[tone] << 8; break; }