summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-06-09 12:59:02 +0200
committerBad Diode <bd@badd10de.dev>2021-06-09 12:59:02 +0200
commit76791d881a007074ec34f229d01feaef5cf03794 (patch)
treefbd37b2467e857a7caf11dc06eb016cb69366ce4
parent371b4523a400d0c888dbefb7111a467e1f86c0f7 (diff)
downloadgba-sequencer-76791d881a007074ec34f229d01feaef5cf03794.tar.gz
gba-sequencer-76791d881a007074ec34f229d01feaef5cf03794.zip
Split triggers in separate channels
-rw-r--r--src/sequencer.c321
1 files changed, 220 insertions, 101 deletions
diff --git a/src/sequencer.c b/src/sequencer.c
index 526680a..fa9b674 100644
--- a/src/sequencer.c
+++ b/src/sequencer.c
@@ -141,10 +141,12 @@ int trig_selection_loc = 0;
141int param_selection_loc = 64; 141int param_selection_loc = 64;
142int channel_selection_loc = 0; 142int channel_selection_loc = 0;
143 143
144// TODO: Split into individual trigger types. 144typedef struct TriggerNote {
145typedef struct SeqTrigger { 145 bool active;
146 bool trigger;
147 Note note; 146 Note note;
147} TriggerNote;
148
149typedef struct ChannelSquareParams {
148 u8 env_volume; 150 u8 env_volume;
149 u8 env_time; 151 u8 env_time;
150 u8 env_direction; 152 u8 env_direction;
@@ -152,73 +154,146 @@ typedef struct SeqTrigger {
152 u8 sweep_number; 154 u8 sweep_number;
153 u8 sweep_time; 155 u8 sweep_time;
154 u8 sweep_direction; 156 u8 sweep_direction;
157} ChannelSquareParams;
158
159typedef struct ChannelWaveParams {
155 u8 wave_volume; 160 u8 wave_volume;
156 u8 wave_mode; 161 u8 wave_mode;
157 u8 wave_a[16]; 162 u8 wave_a[16];
158 u8 wave_b[16]; 163 u8 wave_b[16];
159} SeqTrigger; 164} ChannelWaveParams;
160 165
161static SeqTrigger sequences[3][16] = { 166typedef struct ChannelSquare {
162 // Synth 1. 167 bool active;
163 { 168 TriggerNote notes[16];
164 {true, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 169 ChannelSquareParams params[16];
165 {true, NOTE_D_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 170} ChannelSquare;
166 {false, NOTE_E_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 171
167 {false, NOTE_F_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 172typedef struct ChannelWave {
168 {true, NOTE_G_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 173 bool active;
169 {true, NOTE_A_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 174 TriggerNote notes[16];
170 {false, NOTE_B_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 175 ChannelWaveParams params[16];
171 {false, NOTE_C_5, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 176} ChannelWave;
172 {true, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 177
173 {true, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 178static ChannelSquare ch1 = {
174 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 179 .notes = {
175 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 180 {true, NOTE_C_4},
176 {true, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 181 {true, NOTE_D_4},
177 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 182 {true, NOTE_E_4},
178 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 183 {true, NOTE_F_4},
179 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 184 {true, NOTE_G_4},
185 {true, NOTE_A_4},
186 {true, NOTE_B_4},
187 {true, NOTE_C_5},
188 {true, NOTE_C_4},
189 {true, NOTE_C_4},
190 {true, NOTE_C_4},
191 {true, NOTE_C_4},
192 {true, NOTE_C_4},
193 {true, NOTE_C_4},
194 {true, NOTE_C_4},
195 {true, NOTE_C_4},
196 },
197 .params = {
198 {8, 4, 0, 2, 0, 0, 0},
199 {8, 4, 0, 2, 0, 0, 0},
200 {8, 4, 0, 2, 0, 0, 0},
201 {8, 4, 0, 2, 0, 0, 0},
202 {8, 4, 0, 2, 0, 0, 0},
203 {8, 4, 0, 2, 0, 0, 0},
204 {8, 4, 0, 2, 0, 0, 0},
205 {8, 4, 0, 2, 0, 0, 0},
206 {8, 4, 0, 2, 0, 0, 0},
207 {8, 4, 0, 2, 0, 0, 0},
208 {8, 4, 0, 2, 0, 0, 0},
209 {8, 4, 0, 2, 0, 0, 0},
210 {8, 4, 0, 2, 0, 0, 0},
211 {8, 4, 0, 2, 0, 0, 0},
212 {8, 4, 0, 2, 0, 0, 0},
213 {8, 4, 0, 2, 0, 0, 0},
180 }, 214 },
181 // Synth 2. 215 .active = true,
182 { 216};
183 {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 217
184 {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 218static ChannelSquare ch2 = {
185 {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 219 .notes = {
186 {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 220 {true, NOTE_C_4},
187 {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 221 {true, NOTE_D_4},
188 {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 222 {true, NOTE_E_4},
189 {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 223 {true, NOTE_F_4},
190 {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 224 {true, NOTE_G_4},
191 {false, NOTE_C_5, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 225 {true, NOTE_A_4},
192 {false, NOTE_B_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 226 {true, NOTE_B_4},
193 {false, NOTE_A_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 227 {true, NOTE_C_5},
194 {false, NOTE_G_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 228 {true, NOTE_C_4},
195 {false, NOTE_F_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 229 {true, NOTE_C_4},
196 {false, NOTE_E_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 230 {true, NOTE_C_4},
197 {false, NOTE_D_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 231 {true, NOTE_C_4},
198 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 232 {true, NOTE_C_4},
233 {true, NOTE_C_4},
234 {true, NOTE_C_4},
235 {true, NOTE_C_4},
199 }, 236 },
200 // Synth 3. 237 .params = {
201 { 238 {8, 4, 0, 2, 0, 0, 0},
202 {true, NOTE_C_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}}, 239 {8, 4, 0, 2, 0, 0, 0},
203 {true, NOTE_D_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}}, 240 {8, 4, 0, 2, 0, 0, 0},
204 {true, NOTE_E_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}}, 241 {8, 4, 0, 2, 0, 0, 0},
205 {true, NOTE_F_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}}, 242 {8, 4, 0, 2, 0, 0, 0},
206 {true, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}}, 243 {8, 4, 0, 2, 0, 0, 0},
207 {true, NOTE_A_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}}, 244 {8, 4, 0, 2, 0, 0, 0},
208 {true, NOTE_B_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}}, 245 {8, 4, 0, 2, 0, 0, 0},
209 {true, NOTE_C_6, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}}, 246 {8, 4, 0, 2, 0, 0, 0},
210 {true, NOTE_C_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}}, 247 {8, 4, 0, 2, 0, 0, 0},
211 {true, NOTE_D_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}}, 248 {8, 4, 0, 2, 0, 0, 0},
212 {true, NOTE_E_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}}, 249 {8, 4, 0, 2, 0, 0, 0},
213 {true, NOTE_F_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}}, 250 {8, 4, 0, 2, 0, 0, 0},
214 {true, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}}, 251 {8, 4, 0, 2, 0, 0, 0},
215 {true, NOTE_A_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}}, 252 {8, 4, 0, 2, 0, 0, 0},
216 {true, NOTE_B_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}}, 253 {8, 4, 0, 2, 0, 0, 0},
217 {true, NOTE_C_6, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}},
218 }, 254 },
255 .active = true,
219}; 256};
220 257
221static bool active_channels[4] = {true, true, true, true}; 258static ChannelWave ch3 = {
259 .notes = {
260 {true, NOTE_C_4},
261 {true, NOTE_D_4},
262 {true, NOTE_E_4},
263 {true, NOTE_F_4},
264 {true, NOTE_G_4},
265 {true, NOTE_A_4},
266 {true, NOTE_B_4},
267 {true, NOTE_C_5},
268 {true, NOTE_C_4},
269 {true, NOTE_C_4},
270 {true, NOTE_C_4},
271 {true, NOTE_C_4},
272 {true, NOTE_C_4},
273 {true, NOTE_C_4},
274 {true, NOTE_C_4},
275 {true, NOTE_C_4},
276 },
277 .params = {
278 {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}},
279 {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}},
280 {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}},
281 {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}},
282 {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}},
283 {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}},
284 {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}},
285 {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}},
286 {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}},
287 {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}},
288 {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}},
289 {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}},
290 {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}},
291 {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}},
292 {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}},
293 {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}},
294 },
295 .active = true,
296};
222 297
223// 298//
224// Trigger render functions. 299// Trigger render functions.
@@ -244,13 +319,25 @@ clear_trigger(size_t i) {
244 319
245void 320void
246draw_trigger(size_t chan, size_t i) { 321draw_trigger(size_t chan, size_t i) {
247 if (sequences[chan][i].trigger) { 322 TriggerNote trig = {0};
323 switch (chan) {
324 case 0: {
325 trig = ch1.notes[i];
326 } break;
327 case 1: {
328 trig = ch2.notes[i];
329 } break;
330 case 2: {
331 trig = ch3.notes[i];
332 } break;
333 }
334 if (trig.active) {
248 size_t offset_x = TRIG_OFFSET_X * (i % 8); 335 size_t offset_x = TRIG_OFFSET_X * (i % 8);
249 size_t offset_y = i < 8 ? 0 : TRIG_OFFSET_Y; 336 size_t offset_y = i < 8 ? 0 : TRIG_OFFSET_Y;
250 size_t x = TRIG_START_X + offset_x; 337 size_t x = TRIG_START_X + offset_x;
251 size_t y = TRIG_START_Y + offset_y; 338 size_t y = TRIG_START_Y + offset_y;
252 Tile *tiles = ASSETS_DATA; 339 Tile *tiles = ASSETS_DATA;
253 tiles += 2 * sequences[chan][i].note; 340 tiles += 2 * trig.note;
254 draw_tile(x, y, tiles, COL_FG, true); 341 draw_tile(x, y, tiles, COL_FG, true);
255 draw_tile(x + 8, y, tiles + 1, COL_FG, true); 342 draw_tile(x + 8, y, tiles + 1, COL_FG, true);
256 } else { 343 } else {
@@ -301,7 +388,19 @@ draw_channels(void) {
301 unpack_tiles(channel_buttons, channel_tiles, 3 * 4); 388 unpack_tiles(channel_buttons, channel_tiles, 3 * 4);
302 size_t k = 0; 389 size_t k = 0;
303 for (size_t i = 0; i < 4; i++) { 390 for (size_t i = 0; i < 4; i++) {
304 u8 clr = active_channels[i] ? COL_FG : COL_GREY; 391 bool active;
392 switch (i) {
393 case 0: {
394 active = ch1.active;
395 } break;
396 case 1: {
397 active = ch2.active;
398 } break;
399 case 2: {
400 active = ch3.active;
401 } break;
402 }
403 u8 clr = active ? COL_FG : COL_GREY;
305 size_t y = CHAN_START_Y + i * CHAN_OFFSET_Y; 404 size_t y = CHAN_START_Y + i * CHAN_OFFSET_Y;
306 draw_tile(CHAN_START_X, y, channel_tiles + k++, clr, false); 405 draw_tile(CHAN_START_X, y, channel_tiles + k++, clr, false);
307 draw_tile(CHAN_START_X + 8, y, channel_tiles + k++, clr, false); 406 draw_tile(CHAN_START_X + 8, y, channel_tiles + k++, clr, false);
@@ -321,55 +420,54 @@ draw_channel_cursor(size_t i, u8 clr) {
321 420
322void 421void
323irq_timer(void) { 422irq_timer(void) {
324 Note active_note; 423 if (ch1.active) {
325 if (active_channels[0]) { 424 TriggerNote *trig = &ch1.notes[step_counter];
326 SeqTrigger *trig = &sequences[0][step_counter]; 425 ChannelSquareParams *params = &ch1.params[step_counter];
327 active_note = trig->note; 426 if (trig->active) {
328 if (trig->trigger) { 427 SOUND_SQUARE1_SWEEP = SOUND_SWEEP_NUMBER(params->sweep_number)
329 SOUND_SQUARE1_SWEEP = SOUND_SWEEP_NUMBER(trig->sweep_number) 428 | SOUND_SWEEP_DIR(params->sweep_direction)
330 | SOUND_SWEEP_DIR(trig->sweep_direction) 429 | SOUND_SWEEP_TIME(params->sweep_time);
331 | SOUND_SWEEP_TIME(trig->sweep_time); 430 SOUND_SQUARE1_CTRL = SOUND_SQUARE_ENV_VOL(params->env_volume)
332 SOUND_SQUARE1_CTRL = SOUND_SQUARE_ENV_VOL(trig->env_volume) 431 | SOUND_SQUARE_ENV_TIME(params->env_time)
333 | SOUND_SQUARE_ENV_TIME(trig->env_time) 432 | SOUND_SQUARE_ENV_DIR(params->env_direction)
334 | SOUND_SQUARE_ENV_DIR(trig->env_direction) 433 | SOUND_SQUARE_DUTY(params->duty_cycle);
335 | SOUND_SQUARE_DUTY(trig->duty_cycle);
336 SOUND_SQUARE1_FREQ = SOUND_FREQ_RESET 434 SOUND_SQUARE1_FREQ = SOUND_FREQ_RESET
337 | sound_rates[active_note]; 435 | sound_rates[trig->note];
338 } 436 }
339 } else { 437 } else {
340 SOUND_SQUARE1_CTRL = 0; 438 SOUND_SQUARE1_CTRL = 0;
341 SOUND_SQUARE1_FREQ = 0; 439 SOUND_SQUARE1_FREQ = 0;
342 } 440 }
343 if (active_channels[1]) { 441 if (ch2.active) {
344 SeqTrigger *trig = &sequences[1][step_counter]; 442 TriggerNote *trig = &ch2.notes[step_counter];
345 active_note = trig->note; 443 ChannelSquareParams *params = &ch2.params[step_counter];
346 if (trig->trigger) { 444 if (trig->active) {
347 SOUND_SQUARE2_CTRL = SOUND_SQUARE_ENV_VOL(trig->env_volume) 445 SOUND_SQUARE2_CTRL = SOUND_SQUARE_ENV_VOL(params->env_volume)
348 | SOUND_SQUARE_ENV_TIME(trig->env_time) 446 | SOUND_SQUARE_ENV_TIME(params->env_time)
349 | SOUND_SQUARE_ENV_DIR(trig->env_direction) 447 | SOUND_SQUARE_ENV_DIR(params->env_direction)
350 | SOUND_SQUARE_DUTY(trig->duty_cycle); 448 | SOUND_SQUARE_DUTY(params->duty_cycle);
351 SOUND_SQUARE2_FREQ = SOUND_FREQ_RESET 449 SOUND_SQUARE2_FREQ = SOUND_FREQ_RESET
352 | sound_rates[active_note]; 450 | sound_rates[trig->note];
353 } 451 }
354 } else { 452 } else {
355 SOUND_SQUARE2_CTRL = 0; 453 SOUND_SQUARE2_CTRL = 0;
356 SOUND_SQUARE2_FREQ = 0; 454 SOUND_SQUARE2_FREQ = 0;
357 } 455 }
358 if (active_channels[2]) { 456 if (ch3.active) {
359 SeqTrigger *trig = &sequences[2][step_counter]; 457 TriggerNote *trig = &ch3.notes[step_counter];
360 active_note = trig->note; 458 ChannelWaveParams *params = &ch3.params[step_counter];
361 if (trig->trigger) { 459 if (trig->active) {
362 // Update both banks. 460 // Update both banks.
363 // TODO: Actually depends on which bank is selected, no need to 461 // TODO: Actually depends on which bank is selected, no need to
364 // update both if only one is playing. 462 // update both if only one is playing.
365 // TODO: Should we compare if previous and current wave are the 463 // TODO: Should we compare if previous and current wave are the
366 // same before updating? 464 // same before updating?
367 SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(1); 465 SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(1);
368 dma_copy(SOUND_WAVE_RAM, trig->wave_a, 16, 3); 466 dma_copy(SOUND_WAVE_RAM, params->wave_a, 16, 3);
369 SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(0); 467 SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(0);
370 dma_copy(SOUND_WAVE_RAM, trig->wave_b, 16, 3); 468 dma_copy(SOUND_WAVE_RAM, params->wave_b, 16, 3);
371 469
372 switch (trig->wave_mode) { 470 switch (params->wave_mode) {
373 case 0: { 471 case 0: {
374 SOUND_WAVE_MODE = SOUND_WAVE_BANK_MODE(0) 472 SOUND_WAVE_MODE = SOUND_WAVE_BANK_MODE(0)
375 | SOUND_WAVE_BANK_SELECT(0); 473 | SOUND_WAVE_BANK_SELECT(0);
@@ -389,7 +487,7 @@ irq_timer(void) {
389 } 487 }
390 SOUND_WAVE_MODE |= SOUND_WAVE_ENABLE; 488 SOUND_WAVE_MODE |= SOUND_WAVE_ENABLE;
391 489
392 switch (trig->wave_volume) { 490 switch (params->wave_volume) {
393 case 0: { 491 case 0: {
394 SOUND_WAVE_CTRL = SOUND_WAVE_MUTE; 492 SOUND_WAVE_CTRL = SOUND_WAVE_MUTE;
395 } break; 493 } break;
@@ -407,7 +505,7 @@ irq_timer(void) {
407 } break; 505 } break;
408 } 506 }
409 SOUND_WAVE_FREQ = SOUND_FREQ_RESET 507 SOUND_WAVE_FREQ = SOUND_FREQ_RESET
410 | sound_rates[active_note]; 508 | sound_rates[trig->note];
411 } 509 }
412 } else { 510 } else {
413 SOUND_WAVE_CTRL = 0; 511 SOUND_WAVE_CTRL = 0;
@@ -441,7 +539,17 @@ void handle_channel_cursor(void);
441void 539void
442handle_channel_cursor(void) { 540handle_channel_cursor(void) {
443 if (key_tap(KEY_B)) { 541 if (key_tap(KEY_B)) {
444 active_channels[channel_selection_loc] ^= 1; 542 switch (channel_selection_loc) {
543 case 0: {
544 ch1.active ^= 1;
545 } break;
546 case 1: {
547 ch2.active ^= 1;
548 } break;
549 case 2: {
550 ch3.active ^= 1;
551 } break;
552 }
445 draw_channels(); 553 draw_channels();
446 } 554 }
447 if (key_tap(KEY_RIGHT)) { 555 if (key_tap(KEY_RIGHT)) {
@@ -473,25 +581,36 @@ handle_channel_cursor(void) {
473 581
474void 582void
475handle_trigger_cursor(void) { 583handle_trigger_cursor(void) {
476 SeqTrigger *trig = &sequences[channel_selection_loc][trig_selection_loc]; 584 TriggerNote *trig;
585 switch (channel_selection_loc) {
586 case 0: {
587 trig = &ch1.notes[trig_selection_loc];
588 } break;
589 case 1: {
590 trig = &ch2.notes[trig_selection_loc];
591 } break;
592 case 2: {
593 trig = &ch3.notes[trig_selection_loc];
594 } break;
595 }
477 596
478 if (key_tap(KEY_B)) { 597 if (key_tap(KEY_B)) {
479 // Toggle trigger. 598 // Toggle trigger.
480 trig->trigger ^= 1; 599 trig->active ^= 1;
481 draw_trigger(channel_selection_loc, trig_selection_loc); 600 draw_trigger(channel_selection_loc, trig_selection_loc);
482 } else if (key_tap(KEY_A)) { 601 } else if (key_tap(KEY_A)) {
483 // Switch to parameter selection. 602 // Switch to parameter selection.
484 // current_selection = SEQ_SELECT_PARAMETER; 603 // current_selection = SEQ_SELECT_PARAMETER;
485 } else if (key_tap(KEY_L)) { 604 } else if (key_tap(KEY_L)) {
486 // Decrease note. 605 // Decrease note.
487 if (trig->trigger) { 606 if (trig->active) {
488 trig->note = MAX(trig->note - 1, NOTE_C_2); 607 trig->note = MAX(trig->note - 1, NOTE_C_2);
489 clear_trigger(trig_selection_loc); 608 clear_trigger(trig_selection_loc);
490 draw_trigger(channel_selection_loc, trig_selection_loc); 609 draw_trigger(channel_selection_loc, trig_selection_loc);
491 } 610 }
492 } else if (key_tap(KEY_R)) { 611 } else if (key_tap(KEY_R)) {
493 // Increase note. 612 // Increase note.
494 if (trig->trigger) { 613 if (trig->active) {
495 trig->note = MIN( trig->note + 1, NOTE_C_8); 614 trig->note = MIN( trig->note + 1, NOTE_C_8);
496 clear_trigger(trig_selection_loc); 615 clear_trigger(trig_selection_loc);
497 draw_trigger(channel_selection_loc, trig_selection_loc); 616 draw_trigger(channel_selection_loc, trig_selection_loc);
@@ -738,7 +857,7 @@ load_note_names(void) {
738 857
739void 858void
740sequencer_init(void) { 859sequencer_init(void) {
741 // TODO: Unpack non-sprite tiles directly on the VRAM. 860 // Unpack non-sprite tiles directly on the VRAM.
742 load_note_names(); 861 load_note_names();
743 862
744 // Initialize background objects and sprites. 863 // Initialize background objects and sprites.