diff options
author | Bad Diode <bd@badd10de.dev> | 2024-01-16 10:32:28 +0100 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2024-01-16 10:32:28 +0100 |
commit | 8c33aeda7cd65a5797930340c2728a9464e98b9f (patch) | |
tree | f7e9548d326fac18d1e7f778a6681fa8da9a4981 | |
parent | 77374dacdee448b9dea733c0e444da07942b3238 (diff) | |
download | stepper-8c33aeda7cd65a5797930340c2728a9464e98b9f.tar.gz stepper-8c33aeda7cd65a5797930340c2728a9464e98b9f.zip |
[WIP] Full implementation of attack/decay for ch3 (bugs?)
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | src/main.c | 4 | ||||
-rw-r--r-- | src/sequencer.c | 84 |
3 files changed, 65 insertions, 25 deletions
@@ -27,7 +27,7 @@ INC_FLAGS := $(addprefix -I,$(INC_DIRS)) | |||
27 | INC_FLAGS += -I$(LIBGBA_SRC) | 27 | INC_FLAGS += -I$(LIBGBA_SRC) |
28 | 28 | ||
29 | # Output library names and executables. | 29 | # Output library names and executables. |
30 | TARGET := STEPPER-v1.8-dev-15 | 30 | TARGET := STEPPER-v1.8-dev-16 |
31 | ELF := $(BUILD_DIR)/$(TARGET).elf | 31 | ELF := $(BUILD_DIR)/$(TARGET).elf |
32 | BIN := $(BUILD_DIR)/$(TARGET).gba | 32 | BIN := $(BUILD_DIR)/$(TARGET).gba |
33 | 33 | ||
@@ -28,9 +28,8 @@ WITH REGARD TO THIS SOFTWARE. | |||
28 | // + Hold L/R retriggers at short intervals? | 28 | // + Hold L/R retriggers at short intervals? |
29 | // to key release to enable trigs. | 29 | // to key release to enable trigs. |
30 | // + Fix bug with not being able to stop the sound when synced | 30 | // + Fix bug with not being able to stop the sound when synced |
31 | // + Add attack and decay envelope for ch3 (synced to tempo) | ||
31 | // - Fix any bugs we currently have | 32 | // - Fix any bugs we currently have |
32 | // - Add an envelope to ch3, would need to work with a timer in order to make | ||
33 | // it work I think (Can reuse the 96bpq sequencer timer for this). | ||
34 | // - Add clipboard sharing between banks. | 33 | // - Add clipboard sharing between banks. |
35 | // - Make sure transposing a sequence past the keyboard limit doesn't affect | 34 | // - Make sure transposing a sequence past the keyboard limit doesn't affect |
36 | // the sequence and can be reversed. | 35 | // the sequence and can be reversed. |
@@ -38,6 +37,7 @@ WITH REGARD TO THIS SOFTWARE. | |||
38 | // - When putting a new trigger, make sure it uses the global parameters | 37 | // - When putting a new trigger, make sure it uses the global parameters |
39 | // - Bad performance when selecting patterns | 38 | // - Bad performance when selecting patterns |
40 | // - Add help for attack/decay on ch3 | 39 | // - Add help for attack/decay on ch3 |
40 | // - Fix A+B on ch3 | ||
41 | // | 41 | // |
42 | // Low priority: | 42 | // Low priority: |
43 | // | 43 | // |
diff --git a/src/sequencer.c b/src/sequencer.c index 4b5f34f..66f1d24 100644 --- a/src/sequencer.c +++ b/src/sequencer.c | |||
@@ -227,33 +227,18 @@ play_step(void) { | |||
227 | TriggerNote *trig = &pat->ch3.notes[step_counter]; | 227 | TriggerNote *trig = &pat->ch3.notes[step_counter]; |
228 | ChannelWaveParams *params = &pat->ch3.params[step_counter]; | 228 | ChannelWaveParams *params = &pat->ch3.params[step_counter]; |
229 | if (trig->active && should_play(params->prob)) { | 229 | if (trig->active && should_play(params->prob)) { |
230 | Wave wave_zero = { | ||
231 | 0x77777777, 0x77777777, 0x77777777, 0x77777777, | ||
232 | }; | ||
233 | switch (params->wave_mode) { | 230 | switch (params->wave_mode) { |
234 | case 0: { | 231 | case 0: { |
235 | wave_target = &waves[params->shape_a][params->type_a]; | 232 | wave_target = &waves[params->shape_a][params->type_a]; |
236 | wave_env_attack = params->wave_attack; | 233 | wave_env_attack = params->wave_attack; |
237 | wave_env_decay = params->wave_decay; | 234 | wave_env_decay = params->wave_decay; |
238 | wave_env = WAV_ENV_START; | 235 | wave_env = WAV_ENV_START; |
239 | SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(0); | ||
240 | memcpy32(SOUND_WAVE_RAM, wave_zero, 16); | ||
241 | SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(1); | ||
242 | memcpy32(SOUND_WAVE_RAM, wave_zero, 16); | ||
243 | SOUND_WAVE_MODE = SOUND_WAVE_BANK_MODE(0) | ||
244 | | SOUND_WAVE_BANK_SELECT(0); | ||
245 | } break; | 236 | } break; |
246 | case 1: { | 237 | case 1: { |
247 | wave_target = &waves[params->shape_b][params->type_b]; | 238 | wave_target = &waves[params->shape_b][params->type_b]; |
248 | wave_env_attack = params->wave_attack; | 239 | wave_env_attack = params->wave_attack; |
249 | wave_env_decay = params->wave_decay; | 240 | wave_env_decay = params->wave_decay; |
250 | wave_env = WAV_ENV_START; | 241 | wave_env = WAV_ENV_START; |
251 | SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(0); | ||
252 | memcpy32(SOUND_WAVE_RAM, wave_zero, 16); | ||
253 | SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(1); | ||
254 | memcpy32(SOUND_WAVE_RAM, wave_zero, 16); | ||
255 | SOUND_WAVE_MODE = SOUND_WAVE_BANK_MODE(0) | ||
256 | | SOUND_WAVE_BANK_SELECT(0); | ||
257 | } break; | 242 | } break; |
258 | case 2: { | 243 | case 2: { |
259 | SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(0); | 244 | SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(0); |
@@ -361,21 +346,30 @@ play_step(void) { | |||
361 | 346 | ||
362 | static int nseq_ticks = 0; | 347 | static int nseq_ticks = 0; |
363 | 348 | ||
349 | UNROLL_LOOPS | ||
364 | IWRAM_CODE | 350 | IWRAM_CODE |
365 | void | 351 | void |
366 | wave_ad_tick(void) { | 352 | wave_ad_tick(void) { |
367 | Wave wave_active = {0}; | 353 | Wave wave_active = {0}; |
354 | Wave wave_zero = { | ||
355 | 0x77777777, 0x77777777, 0x77777777, 0x77777777, | ||
356 | }; | ||
368 | env_start: | 357 | env_start: |
369 | switch (wave_env) { | 358 | switch (wave_env) { |
370 | case WAV_ENV_START: { | 359 | case WAV_ENV_START: { |
371 | wave_env_ticks = 0; | 360 | wave_env_ticks = 0; |
372 | wave_env_prog = 0; | 361 | wave_env_prog = 0; |
362 | SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(0); | ||
363 | memcpy32(SOUND_WAVE_RAM, wave_zero, 16); | ||
364 | SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(1); | ||
365 | memcpy32(SOUND_WAVE_RAM, wave_zero, 16); | ||
366 | SOUND_WAVE_MODE = SOUND_WAVE_BANK_MODE(0) | ||
367 | | SOUND_WAVE_BANK_SELECT(0); | ||
373 | SOUND_WAVE_MODE |= SOUND_WAVE_ENABLE; | 368 | SOUND_WAVE_MODE |= SOUND_WAVE_ENABLE; |
374 | SOUND_WAVE_FREQ = SOUND_FREQ_RESET | wave_freq; | 369 | SOUND_WAVE_FREQ = SOUND_FREQ_RESET | wave_freq; |
375 | 370 | ||
376 | if (wave_env_attack == 0) { | 371 | if (wave_env_attack == 0) { |
377 | memcpy32(wave_active, wave_target, 16); | 372 | memcpy32(SOUND_WAVE_RAM, wave_target, 16); |
378 | memcpy32(SOUND_WAVE_RAM, wave_active, 16); | ||
379 | SOUND_WAVE_MODE ^= SOUND_WAVE_BANK_SELECT(1); | 373 | SOUND_WAVE_MODE ^= SOUND_WAVE_BANK_SELECT(1); |
380 | } else { | 374 | } else { |
381 | wave_env = WAV_ENV_ATTACK; | 375 | wave_env = WAV_ENV_ATTACK; |
@@ -391,7 +385,57 @@ env_start: | |||
391 | return; | 385 | return; |
392 | } break; | 386 | } break; |
393 | case WAV_ENV_ATTACK: { | 387 | case WAV_ENV_ATTACK: { |
394 | // TODO: Attack envelope | 388 | if (wave_env_ticks++ < wave_env_attack) { |
389 | return; | ||
390 | } | ||
391 | wave_env_ticks = 0; | ||
392 | |||
393 | // Attack. | ||
394 | int powers[] = { | ||
395 | 20, 57, 104, 143, 177, 208, 235, 256, | ||
396 | }; | ||
397 | int power = powers[wave_env_prog]; | ||
398 | if (++wave_env_prog >= 8) { | ||
399 | if (wave_env_decay == 0) { | ||
400 | wave_env = WAV_ENV_OFF; | ||
401 | } else { | ||
402 | wave_env_prog = 0; | ||
403 | wave_env = WAV_ENV_DECAY; | ||
404 | } | ||
405 | } | ||
406 | for (size_t j = 0; j < 4; j++) { | ||
407 | u32 next = 0; | ||
408 | u32 prev = (*wave_target)[j]; | ||
409 | for (size_t i = 0; i < 8; i++) { | ||
410 | u8 val = (prev >> 4 * i) & 0xF; | ||
411 | // Operating in 24.8 fixed point: | ||
412 | if (val < 0x7) { | ||
413 | int tmp = 0x7 - val; | ||
414 | tmp *= power; | ||
415 | tmp >>= 8; | ||
416 | val = (0x7 - tmp) & 0xf; | ||
417 | } else if (val > 0x7) { | ||
418 | int tmp = (val - 0x7); | ||
419 | tmp *= power; | ||
420 | tmp >>= 8; | ||
421 | val = tmp + 0x7; | ||
422 | if (val <= 0x7) { | ||
423 | val = 0x7; | ||
424 | } | ||
425 | } | ||
426 | next |= (val << 4 * i); | ||
427 | } | ||
428 | wave_active[j] = next; | ||
429 | } | ||
430 | |||
431 | // DEBUG: | ||
432 | // int x = 50; | ||
433 | // int y = 50; | ||
434 | // draw_filled_rect(0 + x, 0 + y, 100 + x, 32 + y, COL_BG); | ||
435 | // draw_wave_pattern(&wave_active, 0 + x, 0 + y, 1); | ||
436 | |||
437 | memcpy32(SOUND_WAVE_RAM, wave_active, 16); | ||
438 | SOUND_WAVE_MODE ^= SOUND_WAVE_BANK_SELECT(1); | ||
395 | } break; | 439 | } break; |
396 | case WAV_ENV_DECAY: { | 440 | case WAV_ENV_DECAY: { |
397 | if (wave_env_ticks++ < wave_env_decay) { | 441 | if (wave_env_ticks++ < wave_env_decay) { |
@@ -401,11 +445,7 @@ env_start: | |||
401 | 445 | ||
402 | // Decay. | 446 | // Decay. |
403 | int powers[] = { | 447 | int powers[] = { |
404 | // FP_NUM(1,8), 230, 205, 192, 150, 100, 50, 0 | ||
405 | // 256, 128, 85, 64, 51, 43, 37, 32, 28, 0 | ||
406 | // Logarithmic volume range. | 448 | // Logarithmic volume range. |
407 | // 256, 245, 224, 202, 177, 150, 120, 86, 47, 0, | ||
408 | // 0., 57., 104., 143., 177., 208., 235., 259. | ||
409 | 256, 235, 208, 177, 143, 104, 57, 0 | 449 | 256, 235, 208, 177, 143, 104, 57, 0 |
410 | }; | 450 | }; |
411 | int power = powers[wave_env_prog]; | 451 | int power = powers[wave_env_prog]; |