From 77374dacdee448b9dea733c0e444da07942b3238 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Tue, 16 Jan 2024 09:31:31 +0100 Subject: [WIP] Refactor ch3 envelope --- src/globals.c | 39 ++++++++----- src/main.c | 1 + src/sequencer.c | 175 +++++++++++++++++++++++++++++++++++++------------------- 3 files changed, 141 insertions(+), 74 deletions(-) (limited to 'src') diff --git a/src/globals.c b/src/globals.c index 5063d69..c040585 100644 --- a/src/globals.c +++ b/src/globals.c @@ -1,15 +1,3 @@ -enum WAVES { - WAVE_SIN, - WAVE_SAW, - WAVE_SQUARE, - WAVE_MAX, -}; - -#define WAVE_SIZE 4 -#define WAVE_VARS 4 - -typedef u32 Wave[WAVE_SIZE]; - // // Globals. // @@ -221,9 +209,30 @@ bool redraw_scale = true; bool update_bpm = false; u8 bar_counter = 0; -static Wave wave_active = {0}; -// static Wave wave_target = {0}; -// TODO: wave env status: OFF, ATTACK, DECAY +typedef enum WaveEnv { + WAV_ENV_START, + WAV_ENV_ATTACK, + WAV_ENV_DECAY, + WAV_ENV_END, + WAV_ENV_OFF, +} WaveEnv; + +enum WAVES { + WAVE_SIN, + WAVE_SAW, + WAVE_SQUARE, + WAVE_MAX, +}; + +#define WAVE_SIZE 4 +#define WAVE_VARS 4 + +typedef u32 Wave[WAVE_SIZE]; + +static WaveEnv wave_env = WAV_ENV_OFF; +static const Wave *wave_target; +static u32 wave_freq; static int wave_env_ticks = 0; static int wave_env_attack = 8; static int wave_env_decay = 8; +static int wave_env_prog = 0; diff --git a/src/main.c b/src/main.c index a72e5e5..cea35f6 100644 --- a/src/main.c +++ b/src/main.c @@ -37,6 +37,7 @@ WITH REGARD TO THIS SOFTWARE. // - Study saving overhauls for bootleg cartridges. // - When putting a new trigger, make sure it uses the global parameters // - Bad performance when selecting patterns +// - Add help for attack/decay on ch3 // // Low priority: // diff --git a/src/sequencer.c b/src/sequencer.c index 8863d14..4b5f34f 100644 --- a/src/sequencer.c +++ b/src/sequencer.c @@ -227,20 +227,33 @@ play_step(void) { TriggerNote *trig = &pat->ch3.notes[step_counter]; ChannelWaveParams *params = &pat->ch3.params[step_counter]; if (trig->active && should_play(params->prob)) { + Wave wave_zero = { + 0x77777777, 0x77777777, 0x77777777, 0x77777777, + }; switch (params->wave_mode) { case 0: { - memcpy32(wave_active, waves[params->shape_a][params->type_a], 16); + wave_target = &waves[params->shape_a][params->type_a]; + wave_env_attack = params->wave_attack; + wave_env_decay = params->wave_decay; + wave_env = WAV_ENV_START; + SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(0); + memcpy32(SOUND_WAVE_RAM, wave_zero, 16); SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(1); - memcpy32(SOUND_WAVE_RAM, wave_active, 16); + memcpy32(SOUND_WAVE_RAM, wave_zero, 16); SOUND_WAVE_MODE = SOUND_WAVE_BANK_MODE(0) | SOUND_WAVE_BANK_SELECT(0); } break; case 1: { - memcpy32(wave_active, waves[params->shape_b][params->type_b], 16); + wave_target = &waves[params->shape_b][params->type_b]; + wave_env_attack = params->wave_attack; + wave_env_decay = params->wave_decay; + wave_env = WAV_ENV_START; SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(0); - memcpy32(SOUND_WAVE_RAM, wave_active, 16); + memcpy32(SOUND_WAVE_RAM, wave_zero, 16); + SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(1); + memcpy32(SOUND_WAVE_RAM, wave_zero, 16); SOUND_WAVE_MODE = SOUND_WAVE_BANK_MODE(0) - | SOUND_WAVE_BANK_SELECT(1); + | SOUND_WAVE_BANK_SELECT(0); } break; case 2: { SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(0); @@ -249,15 +262,12 @@ play_step(void) { memcpy32(SOUND_WAVE_RAM, waves[params->shape_a][params->type_a], 16); SOUND_WAVE_MODE = SOUND_WAVE_BANK_MODE(1) | SOUND_WAVE_BANK_SELECT(0); + wave_env = WAV_ENV_OFF; + SOUND_WAVE_MODE |= SOUND_WAVE_ENABLE; + SOUND_WAVE_FREQ = SOUND_FREQ_RESET | sound_rates[trig->note]; } break; } - wave_env_ticks = 0; - wave_env_attack = params->wave_attack; - wave_env_decay = params->wave_decay; - SOUND_WAVE_MODE |= SOUND_WAVE_ENABLE; - - SOUND_WAVE_FREQ = SOUND_FREQ_RESET - | sound_rates[trig->note]; + wave_freq = sound_rates[trig->note]; switch (params->wave_volume) { case 0: { SOUND_WAVE_CTRL = SOUND_WAVE_MUTE; } break; case 1: { SOUND_WAVE_CTRL = SOUND_WAVE_VOL_25; } break; @@ -354,65 +364,112 @@ static int nseq_ticks = 0; IWRAM_CODE void wave_ad_tick(void) { - // Play a single step for A+B or no envelope. - if ((SOUND_WAVE_MODE & SOUND_WAVE_BANK_MODE(1)) || !wave_env_decay) { - if (wave_env_ticks++ == 24) { - SOUND_WAVE_FREQ = SOUND_FREQ_RESET; - SOUND_WAVE_CTRL = SOUND_WAVE_MUTE; - } - return; - } + Wave wave_active = {0}; +env_start: + switch (wave_env) { + case WAV_ENV_START: { + wave_env_ticks = 0; + wave_env_prog = 0; + SOUND_WAVE_MODE |= SOUND_WAVE_ENABLE; + SOUND_WAVE_FREQ = SOUND_FREQ_RESET | wave_freq; - if (wave_env_ticks++ < wave_env_decay) { - return; - } - wave_env_ticks = 0; - - // Decay. - for (size_t j = 0; j < 4; j++) { - u32 next = 0; - for (size_t i = 0; i < 8; i++) { - u8 val = (wave_active[j] >> 4 * i) & 0xF; - // Operating in 24.8 fixed point: - // 0.9 = 230; 0.8 = 205; 0.75 = 192 - int power = 205; - if (val < 0x7) { - int tmp = 0x7 - val; - tmp *= power; - tmp >>= 8; - val = (0x7 - tmp) & 0xf; - } else if (val > 0x7) { - int tmp = (val - 0x7); - tmp *= power; - tmp >>= 8; - val = tmp + 0x7; - if (val <= 0x7) { - val = 0x7; + if (wave_env_attack == 0) { + memcpy32(wave_active, wave_target, 16); + memcpy32(SOUND_WAVE_RAM, wave_active, 16); + SOUND_WAVE_MODE ^= SOUND_WAVE_BANK_SELECT(1); + } else { + wave_env = WAV_ENV_ATTACK; + goto env_start; + } + + if (wave_env_decay == 0) { + wave_env = WAV_ENV_OFF; + goto env_start; + } else { + wave_env = WAV_ENV_DECAY; + } + return; + } break; + case WAV_ENV_ATTACK: { + // TODO: Attack envelope + } break; + case WAV_ENV_DECAY: { + if (wave_env_ticks++ < wave_env_decay) { + return; + } + wave_env_ticks = 0; + + // Decay. + int powers[] = { + // FP_NUM(1,8), 230, 205, 192, 150, 100, 50, 0 + // 256, 128, 85, 64, 51, 43, 37, 32, 28, 0 + // Logarithmic volume range. + // 256, 245, 224, 202, 177, 150, 120, 86, 47, 0, + // 0., 57., 104., 143., 177., 208., 235., 259. + 256, 235, 208, 177, 143, 104, 57, 0 + }; + int power = powers[wave_env_prog]; + if (++wave_env_prog >= 8) { + wave_env = WAV_ENV_END; + } + for (size_t j = 0; j < 4; j++) { + u32 next = 0; + u32 prev = (*wave_target)[j]; + for (size_t i = 0; i < 8; i++) { + u8 val = (prev >> 4 * i) & 0xF; + // Operating in 24.8 fixed point: + if (val < 0x7) { + int tmp = 0x7 - val; + tmp *= power; + tmp >>= 8; + val = (0x7 - tmp) & 0xf; + } else if (val > 0x7) { + int tmp = (val - 0x7); + tmp *= power; + tmp >>= 8; + val = tmp + 0x7; + if (val <= 0x7) { + val = 0x7; + } + } + next |= (val << 4 * i); } + wave_active[j] = next; } - next |= (val << 4 * i); - } - wave_active[j] = next; - } - // DEBUG: - // int x = 50; - // int y = 50; - // draw_filled_rect(0 + x, 0 + y, 100 + x, 32 + y, COL_BG); - // draw_wave_pattern(&wave_active, 0 + x, 0 + y, 1); + // DEBUG: + // int x = 50; + // int y = 50; + // draw_filled_rect(0 + x, 0 + y, 100 + x, 32 + y, COL_BG); + // draw_wave_pattern(&wave_active, 0 + x, 0 + y, 1); - memcpy32(SOUND_WAVE_RAM, wave_active, 16); - SOUND_WAVE_MODE ^= SOUND_WAVE_BANK_SELECT(1); + memcpy32(SOUND_WAVE_RAM, wave_active, 16); + SOUND_WAVE_MODE ^= SOUND_WAVE_BANK_SELECT(1); + } break; + case WAV_ENV_OFF: { + if (wave_env_ticks++ == 24) { + SOUND_WAVE_FREQ = SOUND_FREQ_RESET; + SOUND_WAVE_CTRL = SOUND_WAVE_MUTE; + wave_env = WAV_ENV_END; + } + return; + } break; + case WAV_ENV_END: { + SOUND_WAVE_FREQ = SOUND_FREQ_RESET; + SOUND_WAVE_CTRL = SOUND_WAVE_MUTE; + return; + } break; + } } void sequencer_tick(void) { - wave_ad_tick(); if (nseq_ticks++ == 0) { play_step(); } else if (nseq_ticks == 24) { nseq_ticks = 0; } + wave_ad_tick(); } void @@ -1291,8 +1348,8 @@ set_param_selection_wave(ChannelWaveParams *params, InputHandler return_handler) case 4: { params->prob = CLAMP(params->prob + inc * -1, 0, PROB_NUM - 1); } break; case 5: { params->wave_mode = CLAMP(params->wave_mode + inc, 0, 2); } break; case 6: { params->wave_volume = CLAMP(params->wave_volume + inc, 0, 4); } break; - case 7: { params->wave_attack = CLAMP(params->wave_attack + inc, 0, 24); } break; - case 8: { params->wave_decay = CLAMP(params->wave_decay + inc, 0, 24); } break; + case 7: { params->wave_attack = CLAMP(params->wave_attack + inc, 0, 16); } break; + case 8: { params->wave_decay = CLAMP(params->wave_decay + inc, 0, 16); } break; case 9: { params->pan = CLAMP(params->pan + inc, -1, 1); } break; } redraw_params = true; -- cgit v1.2.1