From f6efcdd98b32f1cd0d5a4a52abb333437c04b44f Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Mon, 15 Jan 2024 16:06:05 +0100 Subject: [WIP] Add decay control and attack/decay params on ch3 --- src/assets.c | 4 +- src/clipboard.c | 135 +++++++++++++++++++++++----------- src/drawing.c | 225 ++++++++++++++++++++++++++++++++++++++++++++++++-------- src/main.c | 15 ++++ src/patterns.c | 105 +++++++++++++++----------- src/sequencer.c | 42 ++++++----- 6 files changed, 387 insertions(+), 139 deletions(-) (limited to 'src') diff --git a/src/assets.c b/src/assets.c index c11364e..be4b87c 100644 --- a/src/assets.c +++ b/src/assets.c @@ -97,8 +97,10 @@ enum WAVES { typedef u32 Wave[WAVE_SIZE]; static Wave wave_active = {0}; -static Wave wave_target = {0}; +// static Wave wave_target = {0}; +// TODO: wave env status: OFF, ATTACK, DECAY static int wave_env_ticks = 0; +static int wave_env_attack = 8; static int wave_env_decay = 8; static const Wave waves[][WAVE_VARS] = { diff --git a/src/clipboard.c b/src/clipboard.c index d82f576..e92d4c5 100644 --- a/src/clipboard.c +++ b/src/clipboard.c @@ -37,20 +37,25 @@ clipboard_paste(void) { case 0: { pat_dst->ch1.notes[trig_selection_loc] = pat_src->ch1.notes[clipboard.src_trig]; pat_dst->ch1.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig]; - send_notif("PASTED NOTE & PARAMS"); } break; case 1: { pat_dst->ch2.notes[trig_selection_loc] = pat_src->ch1.notes[clipboard.src_trig]; - pat_dst->ch2.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig]; - send_notif("PASTED NOTE & PARAMS"); + pat_dst->ch2.params[trig_selection_loc].env_volume = pat_src->ch1.params[clipboard.src_trig].env_volume; + pat_dst->ch2.params[trig_selection_loc].env_time = pat_src->ch1.params[clipboard.src_trig].env_time; + pat_dst->ch2.params[trig_selection_loc].env_direction = pat_src->ch1.params[clipboard.src_trig].env_direction; + pat_dst->ch2.params[trig_selection_loc].duty_cycle = pat_src->ch1.params[clipboard.src_trig].duty_cycle; + pat_dst->ch2.params[trig_selection_loc].prob = pat_src->ch1.params[clipboard.src_trig].prob; + pat_dst->ch2.params[trig_selection_loc].pan = pat_src->ch1.params[clipboard.src_trig].pan; } break; case 2: { pat_dst->ch3.notes[trig_selection_loc] = pat_src->ch1.notes[clipboard.src_trig]; - send_notif("PASTED NOTE"); + pat_dst->ch3.params[trig_selection_loc].prob = pat_src->ch1.params[clipboard.src_trig].prob; + pat_dst->ch3.params[trig_selection_loc].pan = pat_src->ch1.params[clipboard.src_trig].pan; } break; case 3: { pat_dst->ch4.notes[trig_selection_loc] = pat_src->ch1.notes[clipboard.src_trig]; - send_notif("PASTED NOTE"); + pat_dst->ch4.params[trig_selection_loc].prob = pat_src->ch1.params[clipboard.src_trig].prob; + pat_dst->ch4.params[trig_selection_loc].pan = pat_src->ch1.params[clipboard.src_trig].pan; } break; } } break; @@ -62,20 +67,22 @@ clipboard_paste(void) { pat_dst->ch1.params[trig_selection_loc].env_time = pat_src->ch2.params[clipboard.src_trig].env_time; pat_dst->ch1.params[trig_selection_loc].env_direction = pat_src->ch2.params[clipboard.src_trig].env_direction; pat_dst->ch1.params[trig_selection_loc].duty_cycle = pat_src->ch2.params[clipboard.src_trig].duty_cycle; - send_notif("PASTED NOTE & PARAMS"); + pat_dst->ch1.params[trig_selection_loc].prob = pat_src->ch2.params[clipboard.src_trig].prob; + pat_dst->ch1.params[trig_selection_loc].pan = pat_src->ch2.params[clipboard.src_trig].pan; } break; case 1: { pat_dst->ch2.notes[trig_selection_loc] = pat_src->ch2.notes[clipboard.src_trig]; pat_dst->ch2.params[trig_selection_loc] = pat_src->ch2.params[clipboard.src_trig]; - send_notif("PASTED NOTE & PARAMS"); } break; case 2: { pat_dst->ch3.notes[trig_selection_loc] = pat_src->ch2.notes[clipboard.src_trig]; - send_notif("PASTED NOTE"); + pat_dst->ch3.params[trig_selection_loc].prob = pat_src->ch2.params[clipboard.src_trig].prob; + pat_dst->ch3.params[trig_selection_loc].pan = pat_src->ch2.params[clipboard.src_trig].pan; } break; case 3: { pat_dst->ch4.notes[trig_selection_loc] = pat_src->ch2.notes[clipboard.src_trig]; - send_notif("PASTED NOTE"); + pat_dst->ch4.params[trig_selection_loc].prob = pat_src->ch2.params[clipboard.src_trig].prob; + pat_dst->ch4.params[trig_selection_loc].pan = pat_src->ch2.params[clipboard.src_trig].pan; } break; } } break; @@ -83,20 +90,22 @@ clipboard_paste(void) { switch (channel_selection_loc) { case 0: { pat_dst->ch1.notes[trig_selection_loc] = pat_src->ch3.notes[clipboard.src_trig]; - send_notif("PASTED NOTE"); + pat_dst->ch1.params[trig_selection_loc].prob = pat_src->ch3.params[clipboard.src_trig].prob; + pat_dst->ch1.params[trig_selection_loc].pan = pat_src->ch3.params[clipboard.src_trig].pan; } break; case 1: { pat_dst->ch2.notes[trig_selection_loc] = pat_src->ch3.notes[clipboard.src_trig]; - send_notif("PASTED NOTE"); + pat_dst->ch2.params[trig_selection_loc].prob = pat_src->ch3.params[clipboard.src_trig].prob; + pat_dst->ch2.params[trig_selection_loc].pan = pat_src->ch3.params[clipboard.src_trig].pan; } break; case 2: { pat_dst->ch3.notes[trig_selection_loc] = pat_src->ch3.notes[clipboard.src_trig]; pat_dst->ch3.params[trig_selection_loc] = pat_src->ch3.params[clipboard.src_trig]; - send_notif("PASTED NOTE & PARAMS"); } break; case 3: { pat_dst->ch4.notes[trig_selection_loc] = pat_src->ch3.notes[clipboard.src_trig]; - send_notif("PASTED NOTE"); + pat_dst->ch4.params[trig_selection_loc].prob = pat_src->ch3.params[clipboard.src_trig].prob; + pat_dst->ch4.params[trig_selection_loc].pan = pat_src->ch3.params[clipboard.src_trig].pan; } break; } } break; @@ -104,37 +113,44 @@ clipboard_paste(void) { switch (channel_selection_loc) { case 0: { pat_dst->ch1.notes[trig_selection_loc] = pat_src->ch4.notes[clipboard.src_trig]; - send_notif("PASTED NOTE"); + pat_dst->ch1.params[trig_selection_loc].prob = pat_src->ch4.params[clipboard.src_trig].prob; + pat_dst->ch1.params[trig_selection_loc].pan = pat_src->ch4.params[clipboard.src_trig].pan; } break; case 1: { pat_dst->ch2.notes[trig_selection_loc] = pat_src->ch4.notes[clipboard.src_trig]; - send_notif("PASTED NOTE"); + pat_dst->ch2.params[trig_selection_loc].prob = pat_src->ch4.params[clipboard.src_trig].prob; + pat_dst->ch2.params[trig_selection_loc].pan = pat_src->ch4.params[clipboard.src_trig].pan; } break; case 2: { pat_dst->ch3.notes[trig_selection_loc] = pat_src->ch4.notes[clipboard.src_trig]; - send_notif("PASTED NOTE"); + pat_dst->ch3.params[trig_selection_loc].prob = pat_src->ch4.params[clipboard.src_trig].prob; + pat_dst->ch3.params[trig_selection_loc].pan = pat_src->ch4.params[clipboard.src_trig].pan; } break; case 3: { pat_dst->ch4.notes[trig_selection_loc] = pat_src->ch4.notes[clipboard.src_trig]; pat_dst->ch4.params[trig_selection_loc] = pat_src->ch4.params[clipboard.src_trig]; - send_notif("PASTED NOTE & PARAMS"); } break; } } break; } + send_notif("PASTED NOTE & PARAMS"); } // Only paste the params for the respective trigger. if (clipboard.type == CLIP_PARAM_CH1) { switch (channel_selection_loc) { case 0: { pat_dst->ch1.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig]; - send_notif("PASTED PARAMS"); } break; case 1: { - pat_dst->ch2.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig]; - send_notif("PASTED PARAMS"); + pat_dst->ch2.params[trig_selection_loc].env_volume = pat_src->ch1.params[clipboard.src_trig].env_volume; + pat_dst->ch2.params[trig_selection_loc].env_time = pat_src->ch1.params[clipboard.src_trig].env_time; + pat_dst->ch2.params[trig_selection_loc].env_direction = pat_src->ch1.params[clipboard.src_trig].env_direction; + pat_dst->ch2.params[trig_selection_loc].duty_cycle = pat_src->ch1.params[clipboard.src_trig].duty_cycle; + pat_dst->ch2.params[trig_selection_loc].prob = pat_src->ch1.params[clipboard.src_trig].prob; + pat_dst->ch2.params[trig_selection_loc].pan = pat_src->ch1.params[clipboard.src_trig].pan; } break; } + send_notif("PASTED PARAMS"); } if (clipboard.type == CLIP_PARAM_CH2) { switch (channel_selection_loc) { @@ -143,13 +159,14 @@ clipboard_paste(void) { pat_dst->ch1.params[trig_selection_loc].env_time = pat_src->ch2.params[clipboard.src_trig].env_time; pat_dst->ch1.params[trig_selection_loc].env_direction = pat_src->ch2.params[clipboard.src_trig].env_direction; pat_dst->ch1.params[trig_selection_loc].duty_cycle = pat_src->ch2.params[clipboard.src_trig].duty_cycle; - send_notif("PASTED PARAMS"); + pat_dst->ch1.params[trig_selection_loc].prob = pat_src->ch2.params[clipboard.src_trig].prob; + pat_dst->ch1.params[trig_selection_loc].pan = pat_src->ch2.params[clipboard.src_trig].pan; } break; case 1: { pat_dst->ch2.params[trig_selection_loc] = pat_src->ch2.params[clipboard.src_trig]; - send_notif("PASTED PARAMS"); } break; } + send_notif("PASTED PARAMS"); } if (clipboard.type == CLIP_PARAM_CH3 && channel_selection_loc == clipboard.src_chan) { pat_dst->ch3.params[trig_selection_loc] = pat_src->ch3.params[clipboard.src_trig]; @@ -170,6 +187,8 @@ clipboard_paste(void) { pat_dst->ch1.params[trig_selection_loc].env_time = pat_src->ch2.params[clipboard.src_trig].env_time; pat_dst->ch1.params[trig_selection_loc].env_direction = pat_src->ch2.params[clipboard.src_trig].env_direction; pat_dst->ch1.params[trig_selection_loc].duty_cycle = pat_src->ch2.params[clipboard.src_trig].duty_cycle; + pat_dst->ch1.params[trig_selection_loc].prob = pat_src->ch2.params[clipboard.src_trig].prob; + pat_dst->ch1.params[trig_selection_loc].pan = pat_src->ch2.params[clipboard.src_trig].pan; send_notif("PASTED PARAMS"); draw_parameters(); } else if (input_handler == handle_param_selection_sq2 && clipboard.type == CLIP_PARAM_CH2) { @@ -177,7 +196,12 @@ clipboard_paste(void) { send_notif("PASTED PARAMS"); draw_parameters(); } else if (input_handler == handle_param_selection_sq2 && clipboard.type == CLIP_PARAM_CH1) { - pat_dst->ch2.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig]; + pat_dst->ch2.params[trig_selection_loc].env_volume = pat_src->ch1.params[clipboard.src_trig].env_volume; + pat_dst->ch2.params[trig_selection_loc].env_time = pat_src->ch1.params[clipboard.src_trig].env_time; + pat_dst->ch2.params[trig_selection_loc].env_direction = pat_src->ch1.params[clipboard.src_trig].env_direction; + pat_dst->ch2.params[trig_selection_loc].duty_cycle = pat_src->ch1.params[clipboard.src_trig].duty_cycle; + pat_dst->ch2.params[trig_selection_loc].prob = pat_src->ch1.params[clipboard.src_trig].prob; + pat_dst->ch2.params[trig_selection_loc].pan = pat_src->ch1.params[clipboard.src_trig].pan; send_notif("PASTED PARAMS"); draw_parameters(); } else if (input_handler == handle_param_selection_wave && clipboard.type == CLIP_PARAM_CH3) { @@ -198,7 +222,6 @@ clipboard_paste(void) { case 2: { pat_dst->ch3 = pat_src->ch3; } break; case 3: { pat_dst->ch4 = pat_src->ch4; } break; } - send_notif("PASTED NOTES & PARAMS"); } else { switch (clipboard.src_chan) { case 0: { @@ -208,26 +231,31 @@ clipboard_paste(void) { pat_dst->ch1.notes[i] = pat_src->ch1.notes[i]; pat_dst->ch1.params[i] = pat_src->ch1.params[i]; } - send_notif("PASTED NOTES & PARAMS"); } break; case 1: { for (size_t i = 0; i < 16; i++) { pat_dst->ch2.notes[i] = pat_src->ch1.notes[i]; - pat_dst->ch2.params[i] = pat_src->ch1.params[i]; + pat_dst->ch2.params[i].env_volume = pat_src->ch1.params[i].env_volume; + pat_dst->ch2.params[i].env_time = pat_src->ch1.params[i].env_time; + pat_dst->ch2.params[i].env_direction = pat_src->ch1.params[i].env_direction; + pat_dst->ch2.params[i].duty_cycle = pat_src->ch1.params[i].duty_cycle; + pat_dst->ch2.params[i].prob = pat_src->ch1.params[i].prob; + pat_dst->ch2.params[i].pan = pat_src->ch1.params[i].pan; } - send_notif("PASTED NOTES & PARAMS"); } break; case 2: { for (size_t i = 0; i < 16; i++) { pat_dst->ch3.notes[i] = pat_src->ch1.notes[i]; + pat_dst->ch3.params[i].prob = pat_src->ch1.params[i].prob; + pat_dst->ch3.params[i].pan = pat_src->ch1.params[i].pan; } - send_notif("PASTED NOTES"); } break; case 3: { for (size_t i = 0; i < 16; i++) { pat_dst->ch4.notes[i] = pat_src->ch1.notes[i]; + pat_dst->ch4.params[i].prob = pat_src->ch1.params[i].prob; + pat_dst->ch4.params[i].pan = pat_src->ch1.params[i].pan; } - send_notif("PASTED NOTES"); } break; } } break; @@ -240,27 +268,29 @@ clipboard_paste(void) { pat_dst->ch1.params[i].env_time = pat_src->ch2.params[i].env_time; pat_dst->ch1.params[i].env_direction = pat_src->ch2.params[i].env_direction; pat_dst->ch1.params[i].duty_cycle = pat_src->ch2.params[i].duty_cycle; + pat_dst->ch1.params[i].prob = pat_src->ch2.params[i].prob; + pat_dst->ch1.params[i].pan = pat_src->ch2.params[i].pan; } - send_notif("PASTED NOTES & PARAMS"); } break; case 1: { for (size_t i = 0; i < 16; i++) { pat_dst->ch2.notes[i] = pat_src->ch2.notes[i]; pat_dst->ch2.params[i] = pat_src->ch2.params[i]; } - send_notif("PASTED NOTES & PARAMS"); } break; case 2: { for (size_t i = 0; i < 16; i++) { pat_dst->ch3.notes[i] = pat_src->ch2.notes[i]; + pat_dst->ch3.params[i].prob = pat_src->ch2.params[i].prob; + pat_dst->ch3.params[i].pan = pat_src->ch2.params[i].pan; } - send_notif("PASTED NOTES"); } break; case 3: { for (size_t i = 0; i < 16; i++) { pat_dst->ch4.notes[i] = pat_src->ch2.notes[i]; + pat_dst->ch4.params[i].prob = pat_src->ch2.params[i].prob; + pat_dst->ch4.params[i].pan = pat_src->ch2.params[i].pan; } - send_notif("PASTED NOTES"); } break; } } break; @@ -269,27 +299,29 @@ clipboard_paste(void) { case 0: { for (size_t i = 0; i < 16; i++) { pat_dst->ch1.notes[i] = pat_src->ch3.notes[i]; + pat_dst->ch1.params[i].prob = pat_src->ch3.params[i].prob; + pat_dst->ch1.params[i].pan = pat_src->ch3.params[i].pan; } - send_notif("PASTED NOTES"); } break; case 1: { for (size_t i = 0; i < 16; i++) { pat_dst->ch2.notes[i] = pat_src->ch3.notes[i]; + pat_dst->ch2.params[i].prob = pat_src->ch3.params[i].prob; + pat_dst->ch2.params[i].pan = pat_src->ch3.params[i].pan; } - send_notif("PASTED NOTES"); } break; case 2: { for (size_t i = 0; i < 16; i++) { pat_dst->ch3.notes[i] = pat_src->ch3.notes[i]; pat_dst->ch3.params[i] = pat_src->ch3.params[i]; } - send_notif("PASTED NOTES & PARAMS"); } break; case 3: { for (size_t i = 0; i < 16; i++) { pat_dst->ch4.notes[i] = pat_src->ch3.notes[i]; + pat_dst->ch4.params[i].prob = pat_src->ch3.params[i].prob; + pat_dst->ch4.params[i].pan = pat_src->ch3.params[i].pan; } - send_notif("PASTED NOTES"); } break; } } break; @@ -298,32 +330,35 @@ clipboard_paste(void) { case 0: { for (size_t i = 0; i < 16; i++) { pat_dst->ch1.notes[i] = pat_src->ch4.notes[i]; + pat_dst->ch1.params[i].prob = pat_src->ch4.params[i].prob; + pat_dst->ch1.params[i].pan = pat_src->ch4.params[i].pan; } - send_notif("PASTED NOTES"); } break; case 1: { for (size_t i = 0; i < 16; i++) { pat_dst->ch2.notes[i] = pat_src->ch4.notes[i]; + pat_dst->ch2.params[i].prob = pat_src->ch4.params[i].prob; + pat_dst->ch2.params[i].pan = pat_src->ch4.params[i].pan; } - send_notif("PASTED NOTES"); } break; case 2: { for (size_t i = 0; i < 16; i++) { pat_dst->ch3.notes[i] = pat_src->ch4.notes[i]; + pat_dst->ch3.params[i].prob = pat_src->ch4.params[i].prob; + pat_dst->ch3.params[i].pan = pat_src->ch4.params[i].pan; } - send_notif("PASTED NOTES"); } break; case 3: { for (size_t i = 0; i < 16; i++) { pat_dst->ch4.notes[i] = pat_src->ch4.notes[i]; pat_dst->ch4.params[i] = pat_src->ch4.params[i]; } - send_notif("PASTED NOTES & PARAMS"); } break; } } break; } } + send_notif("PASTED NOTES & PARAMS"); draw_channels(); draw_triggers(); } else if (input_handler == handle_channel_selection) { @@ -344,11 +379,15 @@ clipboard_paste(void) { ch1_params.env_time = pat_src->ch2.params[clipboard.src_trig].env_time; ch1_params.env_direction = pat_src->ch2.params[clipboard.src_trig].env_direction; ch1_params.duty_cycle = pat_src->ch2.params[clipboard.src_trig].duty_cycle; + ch1_params.prob = pat_src->ch2.params[clipboard.src_trig].prob; + ch1_params.pan = pat_src->ch2.params[clipboard.src_trig].pan; for (size_t i = 0; i < 16; i++) { pat_dst->ch1.params[i].env_volume = pat_src->ch2.params[clipboard.src_trig].env_volume; pat_dst->ch1.params[i].env_time = pat_src->ch2.params[clipboard.src_trig].env_time; pat_dst->ch1.params[i].env_direction = pat_src->ch2.params[clipboard.src_trig].env_direction; pat_dst->ch1.params[i].duty_cycle = pat_src->ch2.params[clipboard.src_trig].duty_cycle; + pat_dst->ch1.params[i].prob = pat_src->ch2.params[clipboard.src_trig].prob; + pat_dst->ch1.params[i].pan = pat_src->ch2.params[clipboard.src_trig].pan; } send_notif("PASTED PARAMS"); } @@ -359,9 +398,19 @@ clipboard_paste(void) { clipboard.type == CLIP_PARAM_CH1 || clipboard.type == CLIP_PARAM_CH2) { if (clipboard.src_chan == 0) { - ch2_params = pat_src->ch1.params[clipboard.src_trig]; + ch2_params.env_volume = pat_src->ch1.params[clipboard.src_trig].env_volume; + ch2_params.env_time = pat_src->ch1.params[clipboard.src_trig].env_time; + ch2_params.env_direction = pat_src->ch1.params[clipboard.src_trig].env_direction; + ch2_params.duty_cycle = pat_src->ch1.params[clipboard.src_trig].duty_cycle; + ch2_params.prob = pat_src->ch1.params[clipboard.src_trig].prob; + ch2_params.pan = pat_src->ch1.params[clipboard.src_trig].pan; for (size_t i = 0; i < 16; i++) { - pat_dst->ch2.params[i] = pat_src->ch1.params[clipboard.src_trig]; + pat_dst->ch2.params[i].env_volume = pat_src->ch1.params[clipboard.src_trig].env_volume; + pat_dst->ch2.params[i].env_time = pat_src->ch1.params[clipboard.src_trig].env_time; + pat_dst->ch2.params[i].env_direction = pat_src->ch1.params[clipboard.src_trig].env_direction; + pat_dst->ch2.params[i].duty_cycle = pat_src->ch1.params[clipboard.src_trig].duty_cycle; + pat_dst->ch2.params[i].prob = pat_src->ch1.params[clipboard.src_trig].prob; + pat_dst->ch2.params[i].pan = pat_src->ch1.params[clipboard.src_trig].pan; } send_notif("PASTED PARAMS"); } diff --git a/src/drawing.c b/src/drawing.c index 2368627..f18f094 100644 --- a/src/drawing.c +++ b/src/drawing.c @@ -681,6 +681,16 @@ draw_params_cursor_wave(size_t i, u8 clr) { y += PARAMS_BOX_H - 7 + PARAMS_BOX_OFFSET_Y; txt_drawf_small("vol", x, y, COL_BG); } break; + case 7: { + x += 2 + PARAMS_BOX_OFFSET_X * 2; + y += PARAMS_BOX_H - 7 + PARAMS_BOX_OFFSET_Y; + txt_drawf_small("attack", x, y, COL_BG); + } break; + case 8: { + x += 4 + PARAMS_BOX_OFFSET_X * 3; + y += PARAMS_BOX_H - 7 + PARAMS_BOX_OFFSET_Y; + txt_drawf_small("decay", x, y, COL_BG); + } break; case 9: { x += 8 + PARAMS_BOX_OFFSET_X * 4; y += PARAMS_BOX_H - 7 + PARAMS_BOX_OFFSET_Y; @@ -1012,6 +1022,32 @@ draw_parameters_wave(ChannelWaveParams *params, bool global) { } } + // Attack. + { + size_t x = PARAMS_START_X + PARAMS_BOX_OFFSET_X * 2 + 3; + size_t y = PARAMS_START_Y + PARAMS_BOX_OFFSET_Y + 5; + if (params->wave_attack == 0) { + txt_drawf("OFF", x + 3, y, cols[6]); + } else if (params->wave_attack < 10) { + txt_drawf("%d", x + 8, y, cols[6], params->wave_attack); + } else { + txt_drawf("%d", x + 6, y, cols[6], params->wave_attack); + } + } + + // Decay. + { + size_t x = PARAMS_START_X + PARAMS_BOX_OFFSET_X * 3 + 3; + size_t y = PARAMS_START_Y + PARAMS_BOX_OFFSET_Y + 5; + if (params->wave_decay == 0) { + txt_drawf("OFF", x + 3, y, cols[6]); + } else if (params->wave_decay < 10) { + txt_drawf("%d", x + 8, y, cols[6], params->wave_decay); + } else { + txt_drawf("%d", x + 6, y, cols[6], params->wave_decay); + } + } + // Labels. { size_t x = PARAMS_START_X; @@ -1024,18 +1060,14 @@ draw_parameters_wave(ChannelWaveParams *params, bool global) { y += PARAMS_BOX_OFFSET_Y; txt_drawf_small("voice", x + 4 + PARAMS_BOX_OFFSET_X * 0, y + PARAMS_BOX_H - 7, cols[5]); txt_drawf_small("vol", x + 8 + PARAMS_BOX_OFFSET_X * 1, y + PARAMS_BOX_H - 7, cols[6]); + txt_drawf_small("attack", x + 2 + PARAMS_BOX_OFFSET_X * 2, y + PARAMS_BOX_H - 7, cols[7]); + txt_drawf_small("decay", x + 4 + PARAMS_BOX_OFFSET_X * 3, y + PARAMS_BOX_H - 7, cols[8]); txt_drawf_small("pan", x + 8 + PARAMS_BOX_OFFSET_X * 4, y + PARAMS_BOX_H - 7, cols[9]); } - - // Empty spacers. - { - draw_param_stub(7, COL_OFF); - draw_param_stub(8, COL_OFF); - } } void -draw_parameters_square(ChannelSquareParams *params, bool sweep, bool global) { +draw_parameters_square1(ChannelSquare1Params *params, bool global) { u8 cols[10] = { COL_FG, COL_FG, COL_FG, COL_FG, COL_FG, COL_FG, COL_FG, COL_FG, COL_FG, COL_FG, @@ -1044,12 +1076,8 @@ draw_parameters_square(ChannelSquareParams *params, bool sweep, bool global) { // Adjust colors for global trigger parameters. if (global && input_handler == handle_channel_selection) { for (size_t i = 0; i < 16; i++) { - ChannelSquareParams *trig_params; - if (sweep) { - trig_params = &patterns[pattern_selection_loc].ch1.params[i]; - } else { - trig_params = &patterns[pattern_selection_loc].ch2.params[i]; - } + ChannelSquare1Params *trig_params; + trig_params = &patterns[pattern_selection_loc].ch1.params[i]; if (params->duty_cycle != trig_params->duty_cycle) { cols[0] = COL_OFF; } @@ -1168,7 +1196,7 @@ draw_parameters_square(ChannelSquareParams *params, bool sweep, bool global) { draw_panning(params->pan, cols[9]); // Sweep. - if (sweep) { + { size_t x = PARAMS_START_X; size_t y = PARAMS_START_Y + PARAMS_BOX_OFFSET_Y; @@ -1229,21 +1257,156 @@ draw_parameters_square(ChannelSquareParams *params, bool sweep, bool global) { txt_drawf_small("dir", x + 8 + PARAMS_BOX_OFFSET_X * 3, y + PARAMS_BOX_H - 7, cols[3]); txt_drawf_small("prob", x + 6 + PARAMS_BOX_OFFSET_X * 4, y + PARAMS_BOX_H - 7, cols[4]); y += PARAMS_BOX_OFFSET_Y; - if (sweep) { - txt_drawf_small("sweep", x + 4 + PARAMS_BOX_OFFSET_X * 0, y + PARAMS_BOX_H - 7, cols[5]); - txt_drawf_small("time", x + 6 + PARAMS_BOX_OFFSET_X * 1, y + PARAMS_BOX_H - 7, cols[6]); - txt_drawf_small("dir", x + 8 + PARAMS_BOX_OFFSET_X * 2, y + PARAMS_BOX_H - 7, cols[7]); - } + txt_drawf_small("sweep", x + 4 + PARAMS_BOX_OFFSET_X * 0, y + PARAMS_BOX_H - 7, cols[5]); + txt_drawf_small("time", x + 6 + PARAMS_BOX_OFFSET_X * 1, y + PARAMS_BOX_H - 7, cols[6]); + txt_drawf_small("dir", x + 8 + PARAMS_BOX_OFFSET_X * 2, y + PARAMS_BOX_H - 7, cols[7]); txt_drawf_small("pan", x + 8 + PARAMS_BOX_OFFSET_X * 4, y + PARAMS_BOX_H - 7, cols[9]); } // Empty spacers. { - if (!sweep) { - draw_param_stub(5, COL_OFF); - draw_param_stub(6, COL_OFF); - draw_param_stub(7, COL_OFF); + draw_param_stub(8, COL_OFF); + } +} + +void +draw_parameters_square2(ChannelSquare2Params *params, bool global) { + u8 cols[10] = { + COL_FG, COL_FG, COL_FG, COL_FG, COL_FG, + COL_FG, COL_FG, COL_FG, COL_FG, COL_FG, + }; + + // Adjust colors for global trigger parameters. + if (global && input_handler == handle_channel_selection) { + for (size_t i = 0; i < 16; i++) { + ChannelSquare2Params *trig_params; + trig_params = &patterns[pattern_selection_loc].ch2.params[i]; + if (params->duty_cycle != trig_params->duty_cycle) { + cols[0] = COL_OFF; + } + if (params->env_volume != trig_params->env_volume) { + cols[1] = COL_OFF; + } + if (params->env_time != trig_params->env_time) { + cols[2] = COL_OFF; + } + if (params->env_direction != trig_params->env_direction) { + cols[3] = COL_OFF; + } + if (params->env_direction != trig_params->env_direction) { + cols[3] = COL_OFF; + } + if (params->prob != trig_params->prob) { + cols[4] = COL_OFF; + } + if (params->pan != trig_params->pan) { + cols[9] = COL_OFF; + } } + } + + // Duty cycle / shape. + { + size_t x = PARAMS_START_X + 3; + size_t y = PARAMS_START_Y + 1; + + size_t x0 = x + 2; + size_t x1 = x0; + size_t x2 = x0; + size_t x3 = x0; + size_t x4 = x0; + size_t x5 = x0; + size_t y0 = y + 14; + size_t y1 = y + 2; + + switch (params->duty_cycle) { + case 0: { + x1 += 4; + x2 += 6; + x3 += 13; + x4 += 15; + x5 += 20; + } break; + case 1: { + x1 += 4; + x2 += 7; + x3 += 13; + x4 += 16; + x5 += 20; + } break; + case 2: { + x1 += 3; + x2 += 8; + x3 += 12; + x4 += 17; + x5 += 20; + } break; + case 3: { + x1 += 2; + x2 += 9; + x3 += 11; + x4 += 18; + x5 += 20; + } break; + } + u8 col_shape = cols[0] != COL_OFF ? COL_ACC_1 : COL_OFF; + draw_line(x0, y0, x1, y0, col_shape); + draw_line(x1, y1, x1, y0, col_shape); + draw_line(x1, y1, x2, y1, col_shape); + draw_line(x2, y1, x2, y0, col_shape); + draw_line(x2, y0, x3, y0, col_shape); + draw_line(x3, y1, x3, y0, col_shape); + draw_line(x3, y1, x4, y1, col_shape); + draw_line(x4, y1, x4, y0, col_shape); + draw_line(x4, y0, x5, y0, col_shape); + } + + // Envelope. + { + size_t x = PARAMS_START_X + PARAMS_BOX_OFFSET_X * 1 + 1; + size_t y = PARAMS_START_Y + 1; + size_t x0 = x; + size_t y0 = y + 15 - params->env_volume; + size_t x1 = x + (3 * PARAMS_BOX_OFFSET_X) * params->env_time / 8 + 7; + size_t y1 = params->env_direction == 0 ? y + 15 : y; + size_t x2 = x + PARAMS_BOX_OFFSET_X * 3 - 5; + size_t y2 = y1; + + // Env. + u8 col_env = cols[1] != COL_OFF && cols[2] != COL_OFF && cols[3] != COL_OFF + ? COL_ACC_2 : COL_OFF; + if (params->env_time == 0) { + draw_line(x0, y0, x2, y0, col_env); + } else { + draw_line(x0, y0, x1, y1, col_env); + draw_line(x1, y1, x2, y2, col_env); + } + } + + // Trig probability. + draw_prob(params->prob, cols[4]); + + // Trig pannning. + draw_panning(params->pan, cols[9]); + + // Labels. + { + size_t x = PARAMS_START_X; + size_t y = PARAMS_START_Y; + txt_drawf_small("shape", x + 4 + PARAMS_BOX_OFFSET_X * 0, y + PARAMS_BOX_H - 7, cols[0]); + txt_drawf_small("vol", x + 8 + PARAMS_BOX_OFFSET_X * 1, y + PARAMS_BOX_H - 7, cols[1]); + txt_drawf_small("time", x + 6 + PARAMS_BOX_OFFSET_X * 2, y + PARAMS_BOX_H - 7, cols[2]); + txt_drawf_small("dir", x + 8 + PARAMS_BOX_OFFSET_X * 3, y + PARAMS_BOX_H - 7, cols[3]); + txt_drawf_small("prob", x + 6 + PARAMS_BOX_OFFSET_X * 4, y + PARAMS_BOX_H - 7, cols[4]); + y += PARAMS_BOX_OFFSET_Y; + txt_drawf_small("pan", x + 8 + PARAMS_BOX_OFFSET_X * 4, y + PARAMS_BOX_H - 7, cols[9]); + } + + // Empty spacers. + { + draw_param_stub(5, COL_OFF); + draw_param_stub(6, COL_OFF); + draw_param_stub(7, COL_OFF); draw_param_stub(8, COL_OFF); } } @@ -1358,15 +1521,15 @@ draw_parameters(void) { input_handler == handle_param_selection_noise) { if (!pat->empty) { switch (channel_selection_loc) { - case 0: { draw_parameters_square(&pat->ch1.params[trig_selection_loc], true, false); } break; - case 1: { draw_parameters_square(&pat->ch2.params[trig_selection_loc], false, false); } break; + case 0: { draw_parameters_square1(&pat->ch1.params[trig_selection_loc], false); } break; + case 1: { draw_parameters_square2(&pat->ch2.params[trig_selection_loc], false); } break; case 2: { draw_parameters_wave(&pat->ch3.params[trig_selection_loc], false); } break; case 3: { draw_parameters_noise(&pat->ch4.params[trig_selection_loc], false); } break; } } else { switch (channel_selection_loc) { - case 0: { draw_parameters_square(&default_ch1.params, true, false); } break; - case 1: { draw_parameters_square(&default_ch2.params, false, false); } break; + case 0: { draw_parameters_square1(&default_ch1.params, false); } break; + case 1: { draw_parameters_square2(&default_ch2.params, false); } break; case 2: { draw_parameters_wave(&default_ch3.params, true); } break; case 3: { draw_parameters_noise(&default_ch4.params, true); } break; } @@ -1379,8 +1542,8 @@ draw_parameters(void) { input_handler == handle_param_selection_ch3 || input_handler == handle_param_selection_ch4) { switch (channel_selection_loc) { - case 0: { draw_parameters_square(&ch1_params, true, true); } break; - case 1: { draw_parameters_square(&ch2_params, false, true); } break; + case 0: { draw_parameters_square1(&ch1_params, true); } break; + case 1: { draw_parameters_square2(&ch2_params, true); } break; case 2: { draw_parameters_wave(&ch3_params, true); } break; case 3: { draw_parameters_noise(&ch4_params, true); } break; } @@ -1640,7 +1803,7 @@ draw_notif_bar() { Pattern *pat = &patterns[pattern_selection_loc]; if (input_handler == handle_param_selection_sq1 || input_handler == handle_param_selection_ch1) { - ChannelSquareParams *params; + ChannelSquare1Params *params; if (input_handler == handle_param_selection_sq1) { params = &pat->ch1.params[trig_selection_loc]; } else { @@ -1704,7 +1867,7 @@ draw_notif_bar() { if (input_handler == handle_param_selection_sq2 || input_handler == handle_param_selection_ch2) { - ChannelSquareParams *params; + ChannelSquare2Params *params; if (input_handler == handle_param_selection_sq2) { params = &pat->ch2.params[trig_selection_loc]; } else { diff --git a/src/main.c b/src/main.c index a8c93bf..a72e5e5 100644 --- a/src/main.c +++ b/src/main.c @@ -16,6 +16,7 @@ WITH REGARD TO THIS SOFTWARE. // + Look back again at the emulator issues... (I give up) // + Sync via MIDI with the Analogue cables. // + Fix bank switching behaviour (bug) +// + Fix bug: Clipboard doesn't copy probability/pan? maybe others? // + Add more sync options // + When switching sync, play status acts wonky (bug) // + Channel params should show if there are some already on all triggers and @@ -165,6 +166,20 @@ render_settings(void) { void render(void) { + // NOTE: Debug key input + // PROF(screen_fill(COL_BG), clear_cycles); + // txt_printf("UP: %d\n", ctrl.key_up); + // txt_printf("DOWN: %d\n", ctrl.key_down); + // txt_printf("LEFT: %d\n", ctrl.key_left); + // txt_printf("RIGHT: %d\n", ctrl.key_right); + // txt_printf("A: %d\n", ctrl.key_a); + // txt_printf("B: %d\n", ctrl.key_b); + // txt_printf("L: %d\n", ctrl.key_l); + // txt_printf("R: %d\n", ctrl.key_r); + // txt_printf("SEL: %d\n", ctrl.key_select); + // txt_printf("START: %d\n", ctrl.key_start); + // txt_render(); + // txt_clear(); if (clear_screen) { PROF(screen_fill(COL_BG), clear_cycles); clear_screen = false; diff --git a/src/patterns.c b/src/patterns.c index a1f8f24..8dd0f5c 100644 --- a/src/patterns.c +++ b/src/patterns.c @@ -7,7 +7,7 @@ typedef struct TriggerNote { Note note; } TriggerNote; -typedef struct ChannelSquareParams { +typedef struct ChannelSquare1Params { u8 env_volume; u8 env_time; u8 env_direction; @@ -17,7 +17,16 @@ typedef struct ChannelSquareParams { u8 sweep_direction; u8 prob; s8 pan; -} ChannelSquareParams; +} ChannelSquare1Params; + +typedef struct ChannelSquare2Params { + u8 env_volume; + u8 env_time; + u8 env_direction; + u8 duty_cycle; + u8 prob; + s8 pan; +} ChannelSquare2Params; typedef struct ChannelWaveParams { u8 wave_volume; @@ -26,6 +35,8 @@ typedef struct ChannelWaveParams { u8 type_a; u8 shape_b; u8 type_b; + u8 wave_attack; + u8 wave_decay; u8 prob; s8 pan; } ChannelWaveParams; @@ -39,11 +50,17 @@ typedef struct ChannelNoiseParams { s8 pan; } ChannelNoiseParams; -typedef struct ChannelSquare { +typedef struct ChannelSquare1 { bool active; TriggerNote notes[16]; - ChannelSquareParams params[16]; -} ChannelSquare; + ChannelSquare1Params params[16]; +} ChannelSquare1; + +typedef struct ChannelSquare2 { + bool active; + TriggerNote notes[16]; + ChannelSquare2Params params[16]; +} ChannelSquare2; typedef struct ChannelWave { bool active; @@ -58,8 +75,8 @@ typedef struct ChannelNoise { } ChannelNoise; typedef struct Pattern { - ChannelSquare ch1; - ChannelSquare ch2; + ChannelSquare1 ch1; + ChannelSquare2 ch2; ChannelWave ch3; ChannelNoise ch4; int bpm; @@ -71,7 +88,7 @@ typedef struct Pattern { // Defaults. // -const ChannelSquare default_ch1 = { +const ChannelSquare1 default_ch1 = { .notes = { {true, NOTE_C_4}, {true, NOTE_D_SHARP_4}, @@ -111,7 +128,7 @@ const ChannelSquare default_ch1 = { .active = true, }; -const ChannelSquare default_ch2 = { +const ChannelSquare2 default_ch2 = { .notes = { {true, NOTE_C_3}, {true, NOTE_C_3}, @@ -131,22 +148,22 @@ const ChannelSquare default_ch2 = { {true, NOTE_C_3}, }, .params = { - {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}, - {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}, - {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}, - {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}, - {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}, - {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}, - {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}, - {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}, - {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}, - {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}, - {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}, - {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}, - {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}, - {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}, - {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}, - {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}, + {8, 4, 0, 2, PROB_100, 0}, + {8, 4, 0, 2, PROB_100, 0}, + {8, 4, 0, 2, PROB_100, 0}, + {8, 4, 0, 2, PROB_100, 0}, + {8, 4, 0, 2, PROB_100, 0}, + {8, 4, 0, 2, PROB_100, 0}, + {8, 4, 0, 2, PROB_100, 0}, + {8, 4, 0, 2, PROB_100, 0}, + {8, 4, 0, 2, PROB_100, 0}, + {8, 4, 0, 2, PROB_100, 0}, + {8, 4, 0, 2, PROB_100, 0}, + {8, 4, 0, 2, PROB_100, 0}, + {8, 4, 0, 2, PROB_100, 0}, + {8, 4, 0, 2, PROB_100, 0}, + {8, 4, 0, 2, PROB_100, 0}, + {8, 4, 0, 2, PROB_100, 0}, }, .active = true, }; @@ -171,22 +188,22 @@ const ChannelWave default_ch3 = { {true, NOTE_G_5}, }, .params = { - {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, PROB_100, 0}, - {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, PROB_100, 0}, - {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, PROB_100, 0}, - {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, PROB_100, 0}, - {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, PROB_100, 0}, - {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, PROB_100, 0}, - {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, PROB_100, 0}, - {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, PROB_100, 0}, - {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, PROB_100, 0}, - {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, PROB_100, 0}, - {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, PROB_100, 0}, - {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, PROB_100, 0}, - {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, PROB_100, 0}, - {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, PROB_100, 0}, - {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, PROB_100, 0}, - {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, PROB_100, 0}, + {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, 0, 0, PROB_100, 0}, + {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, 0, 0, PROB_100, 0}, + {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, 0, 0, PROB_100, 0}, + {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, 0, 0, PROB_100, 0}, + {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, 0, 0, PROB_100, 0}, + {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, 0, 0, PROB_100, 0}, + {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, 0, 0, PROB_100, 0}, + {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, 0, 0, PROB_100, 0}, + {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, 0, 0, PROB_100, 0}, + {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, 0, 0, PROB_100, 0}, + {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, 0, 0, PROB_100, 0}, + {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, 0, 0, PROB_100, 0}, + {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, 0, 0, PROB_100, 0}, + {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, 0, 0, PROB_100, 0}, + {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, 0, 0, PROB_100, 0}, + {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, 0, 0, PROB_100, 0}, }, .active = true, }; @@ -244,7 +261,7 @@ static Pattern patterns[8] = { {default_ch1, default_ch2, default_ch3, default_ch4, default_bpm, 0, true}, }; -static ChannelSquareParams ch1_params = {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}; -static ChannelSquareParams ch2_params = {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}; -static ChannelWaveParams ch3_params = {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, PROB_100, 0}; +static ChannelSquare1Params ch1_params = {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}; +static ChannelSquare2Params ch2_params = {8, 4, 0, 2, PROB_100, 0}; +static ChannelWaveParams ch3_params = {3, 0, WAVE_SIN, 0, WAVE_SAW, 0, 0, 0, PROB_100, 0}; static ChannelNoiseParams ch4_params = {0xF, 0x2, 0, 0, PROB_100, 0}; diff --git a/src/sequencer.c b/src/sequencer.c index 01b8e95..8863d14 100644 --- a/src/sequencer.c +++ b/src/sequencer.c @@ -160,7 +160,7 @@ play_step(void) { bool ch1_active = settings.global_mute ? !settings.mutes[0] : pat->ch1.active; if (ch1_active && !pat->empty) { TriggerNote *trig = &pat->ch1.notes[step_counter]; - ChannelSquareParams *params = &pat->ch1.params[step_counter]; + ChannelSquare1Params *params = &pat->ch1.params[step_counter]; if (trig->active && should_play(params->prob)) { if (params->sweep_time == 0) { SOUND_SQUARE1_SWEEP = SOUND_SWEEP_DIR(1); @@ -204,7 +204,7 @@ play_step(void) { bool ch2_active = settings.global_mute ? !settings.mutes[1] : pat->ch2.active; if (ch2_active && !pat->empty) { TriggerNote *trig = &pat->ch2.notes[step_counter]; - ChannelSquareParams *params = &pat->ch2.params[step_counter]; + ChannelSquare2Params *params = &pat->ch2.params[step_counter]; if (trig->active && should_play(params->prob)) { SOUND_SQUARE2_CTRL = SOUND_SQUARE_ENV_VOL(params->env_volume) | SOUND_SQUARE_ENV_TIME(params->env_time) @@ -252,6 +252,8 @@ play_step(void) { } 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 @@ -1075,7 +1077,7 @@ handle_pattern_selection(void) { } bool -set_param_selection_sq1(ChannelSquareParams *params, InputHandler return_handler) { +set_param_selection_sq1(ChannelSquare1Params *params, InputHandler return_handler) { // Go back to trigger selection. if (key_released(KEY_A)) { input_handler = return_handler; @@ -1159,7 +1161,7 @@ set_param_selection_sq1(ChannelSquareParams *params, InputHandler return_handler } bool -set_param_selection_sq2(ChannelSquareParams *params, InputHandler return_handler) { +set_param_selection_sq2(ChannelSquare2Params *params, InputHandler return_handler) { // Go back to trigger selection. if (key_released(KEY_A)) { input_handler = return_handler; @@ -1245,11 +1247,9 @@ set_param_selection_wave(ChannelWaveParams *params, InputHandler return_handler) if (key_retrig(KEY_RIGHT)) { if (param_selection_loc == 4) { param_selection_loc = 0; - } else if (param_selection_loc == 6) { - param_selection_loc = 9; } else if (param_selection_loc == 9) { param_selection_loc = 5; - } else if (param_selection_loc < 6) { + } else { param_selection_loc++; } } else { @@ -1257,9 +1257,7 @@ set_param_selection_wave(ChannelWaveParams *params, InputHandler return_handler) param_selection_loc = 4; } else if (param_selection_loc == 5) { param_selection_loc = 9; - } else if (param_selection_loc == 9) { - param_selection_loc = 6; - } else if (param_selection_loc > 0) { + } else { param_selection_loc--; } } @@ -1268,13 +1266,9 @@ set_param_selection_wave(ChannelWaveParams *params, InputHandler return_handler) } if (key_tap(KEY_UP) || key_tap(KEY_DOWN)) { - if (param_selection_loc == 4) { - param_selection_loc = 9; - } else if (param_selection_loc == 9) { - param_selection_loc = 4; - } else if (param_selection_loc < 2) { + if (param_selection_loc < 5) { param_selection_loc += 5; - } else if (param_selection_loc > 4) { + } else if (param_selection_loc >= 5) { param_selection_loc -= 5; } redraw_params = true; @@ -1297,6 +1291,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 9: { params->pan = CLAMP(params->pan + inc, -1, 1); } break; } redraw_params = true; @@ -1475,6 +1471,12 @@ handle_param_selection_ch3() { case 6: { pat->ch3.params[i].wave_volume = ch3_params.wave_volume; } break; + case 7: { + pat->ch3.params[i].wave_attack = ch3_params.wave_attack; + } break; + case 8: { + pat->ch3.params[i].wave_decay = ch3_params.wave_decay; + } break; case 9: { pat->ch3.params[i].pan = ch3_params.pan; } break; @@ -1516,13 +1518,13 @@ handle_param_selection_ch4() { void handle_param_selection_sq1() { - ChannelSquareParams *params = &patterns[pattern_selection_loc].ch1.params[trig_selection_loc]; + ChannelSquare1Params *params = &patterns[pattern_selection_loc].ch1.params[trig_selection_loc]; set_param_selection_sq1(params, handle_trigger_selection); } void handle_param_selection_sq2() { - ChannelSquareParams *params = &patterns[pattern_selection_loc].ch2.params[trig_selection_loc]; + ChannelSquare2Params *params = &patterns[pattern_selection_loc].ch2.params[trig_selection_loc]; set_param_selection_sq2(params, handle_trigger_selection); } @@ -1543,7 +1545,7 @@ nudge_trigs(int cur_loc, int next_loc) { Pattern *pat = &patterns[pattern_selection_loc]; switch (channel_selection_loc) { case 0: { - ChannelSquareParams cur_params = pat->ch1.params[cur_loc]; + ChannelSquare1Params cur_params = pat->ch1.params[cur_loc]; TriggerNote cur_trig = pat->ch1.notes[cur_loc]; pat->ch1.params[cur_loc] = pat->ch1.params[next_loc]; pat->ch1.notes[cur_loc] = pat->ch1.notes[next_loc]; @@ -1551,7 +1553,7 @@ nudge_trigs(int cur_loc, int next_loc) { pat->ch1.notes[next_loc] = cur_trig; } break; case 1: { - ChannelSquareParams cur_params = pat->ch2.params[cur_loc]; + ChannelSquare2Params cur_params = pat->ch2.params[cur_loc]; TriggerNote cur_trig = pat->ch2.notes[cur_loc]; pat->ch2.params[cur_loc] = pat->ch2.params[next_loc]; pat->ch2.notes[cur_loc] = pat->ch2.notes[next_loc]; -- cgit v1.2.1