diff options
author | Bad Diode <bd@badd10de.dev> | 2024-01-15 14:50:21 +0100 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2024-01-15 14:50:21 +0100 |
commit | 65089bc6ca9e31878afd583e133cb376ef03f268 (patch) | |
tree | 3f11c40a5ddf7ac289b4e7014776dfc9a8a4f785 | |
parent | e8f4708a6d809c33719ec2f773d23e05c8619b2b (diff) | |
download | stepper-65089bc6ca9e31878afd583e133cb376ef03f268.tar.gz stepper-65089bc6ca9e31878afd583e133cb376ef03f268.zip |
[WIP] Initial implementation of CH3 envelope
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | src/assets.c | 7 | ||||
-rw-r--r-- | src/main.c | 2 | ||||
-rw-r--r-- | src/sequencer.c | 69 |
4 files changed, 69 insertions, 11 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-09 | 30 | TARGET := STEPPER-v1.8-dev-11 |
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 | ||
diff --git a/src/assets.c b/src/assets.c index 94c9de2..c11364e 100644 --- a/src/assets.c +++ b/src/assets.c | |||
@@ -92,9 +92,14 @@ enum WAVES { | |||
92 | WAVE_MAX, | 92 | WAVE_MAX, |
93 | }; | 93 | }; |
94 | 94 | ||
95 | #define WAVE_SIZE 4 | ||
95 | #define WAVE_VARS 4 | 96 | #define WAVE_VARS 4 |
96 | 97 | ||
97 | typedef u32 Wave[WAVE_VARS]; | 98 | typedef u32 Wave[WAVE_SIZE]; |
99 | static Wave wave_active = {0}; | ||
100 | static Wave wave_target = {0}; | ||
101 | static int wave_env_ticks = 0; | ||
102 | static int wave_env_decay = 8; | ||
98 | 103 | ||
99 | static const Wave waves[][WAVE_VARS] = { | 104 | static const Wave waves[][WAVE_VARS] = { |
100 | { | 105 | { |
@@ -34,6 +34,8 @@ WITH REGARD TO THIS SOFTWARE. | |||
34 | // - 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 |
35 | // the sequence and can be reversed. | 35 | // the sequence and can be reversed. |
36 | // - Study saving overhauls for bootleg cartridges. | 36 | // - Study saving overhauls for bootleg cartridges. |
37 | // - When putting a new trigger, make sure it uses the global parameters | ||
38 | // - Bad performance when selecting patterns | ||
37 | // | 39 | // |
38 | // Low priority: | 40 | // Low priority: |
39 | // | 41 | // |
diff --git a/src/sequencer.c b/src/sequencer.c index 981bbc6..01b8e95 100644 --- a/src/sequencer.c +++ b/src/sequencer.c | |||
@@ -229,14 +229,16 @@ play_step(void) { | |||
229 | if (trig->active && should_play(params->prob)) { | 229 | if (trig->active && should_play(params->prob)) { |
230 | switch (params->wave_mode) { | 230 | switch (params->wave_mode) { |
231 | case 0: { | 231 | case 0: { |
232 | memcpy32(wave_active, waves[params->shape_a][params->type_a], 16); | ||
232 | SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(1); | 233 | SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(1); |
233 | memcpy32(SOUND_WAVE_RAM, waves[params->shape_a][params->type_a], 16); | 234 | memcpy32(SOUND_WAVE_RAM, wave_active, 16); |
234 | SOUND_WAVE_MODE = SOUND_WAVE_BANK_MODE(0) | 235 | SOUND_WAVE_MODE = SOUND_WAVE_BANK_MODE(0) |
235 | | SOUND_WAVE_BANK_SELECT(0); | 236 | | SOUND_WAVE_BANK_SELECT(0); |
236 | } break; | 237 | } break; |
237 | case 1: { | 238 | case 1: { |
239 | memcpy32(wave_active, waves[params->shape_b][params->type_b], 16); | ||
238 | SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(0); | 240 | SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(0); |
239 | memcpy32(SOUND_WAVE_RAM, waves[params->shape_b][params->type_b], 16); | 241 | memcpy32(SOUND_WAVE_RAM, wave_active, 16); |
240 | SOUND_WAVE_MODE = SOUND_WAVE_BANK_MODE(0) | 242 | SOUND_WAVE_MODE = SOUND_WAVE_BANK_MODE(0) |
241 | | SOUND_WAVE_BANK_SELECT(1); | 243 | | SOUND_WAVE_BANK_SELECT(1); |
242 | } break; | 244 | } break; |
@@ -249,6 +251,7 @@ play_step(void) { | |||
249 | | SOUND_WAVE_BANK_SELECT(0); | 251 | | SOUND_WAVE_BANK_SELECT(0); |
250 | } break; | 252 | } break; |
251 | } | 253 | } |
254 | wave_env_ticks = 0; | ||
252 | SOUND_WAVE_MODE |= SOUND_WAVE_ENABLE; | 255 | SOUND_WAVE_MODE |= SOUND_WAVE_ENABLE; |
253 | 256 | ||
254 | SOUND_WAVE_FREQ = SOUND_FREQ_RESET | 257 | SOUND_WAVE_FREQ = SOUND_FREQ_RESET |
@@ -261,12 +264,6 @@ play_step(void) { | |||
261 | case 4: { SOUND_WAVE_CTRL = SOUND_WAVE_VOL_100; } break; | 264 | case 4: { SOUND_WAVE_CTRL = SOUND_WAVE_VOL_100; } break; |
262 | } | 265 | } |
263 | pan[2] = params->pan; | 266 | pan[2] = params->pan; |
264 | } else { | ||
265 | // NOTE: Maybe in the future we want an AD, but for now this is | ||
266 | // probably better than holding the notes. Or perhaps add a hold | ||
267 | // mode? | ||
268 | SOUND_WAVE_FREQ = SOUND_FREQ_RESET; | ||
269 | SOUND_WAVE_CTRL = SOUND_WAVE_MUTE; | ||
270 | } | 267 | } |
271 | } else { | 268 | } else { |
272 | SOUND_WAVE_FREQ = SOUND_FREQ_RESET; | 269 | SOUND_WAVE_FREQ = SOUND_FREQ_RESET; |
@@ -352,11 +349,65 @@ play_step(void) { | |||
352 | 349 | ||
353 | static int nseq_ticks = 0; | 350 | static int nseq_ticks = 0; |
354 | 351 | ||
352 | IWRAM_CODE | ||
353 | void | ||
354 | wave_ad_tick(void) { | ||
355 | // Play a single step for A+B or no envelope. | ||
356 | if ((SOUND_WAVE_MODE & SOUND_WAVE_BANK_MODE(1)) || !wave_env_decay) { | ||
357 | if (wave_env_ticks++ == 24) { | ||
358 | SOUND_WAVE_FREQ = SOUND_FREQ_RESET; | ||
359 | SOUND_WAVE_CTRL = SOUND_WAVE_MUTE; | ||
360 | } | ||
361 | return; | ||
362 | } | ||
363 | |||
364 | if (wave_env_ticks++ < wave_env_decay) { | ||
365 | return; | ||
366 | } | ||
367 | wave_env_ticks = 0; | ||
368 | |||
369 | // Decay. | ||
370 | for (size_t j = 0; j < 4; j++) { | ||
371 | u32 next = 0; | ||
372 | for (size_t i = 0; i < 8; i++) { | ||
373 | u8 val = (wave_active[j] >> 4 * i) & 0xF; | ||
374 | // Operating in 24.8 fixed point: | ||
375 | // 0.9 = 230; 0.8 = 205; 0.75 = 192 | ||
376 | int power = 205; | ||
377 | if (val < 0x7) { | ||
378 | int tmp = 0x7 - val; | ||
379 | tmp *= power; | ||
380 | tmp >>= 8; | ||
381 | val = (0x7 - tmp) & 0xf; | ||
382 | } else if (val > 0x7) { | ||
383 | int tmp = (val - 0x7); | ||
384 | tmp *= power; | ||
385 | tmp >>= 8; | ||
386 | val = tmp + 0x7; | ||
387 | if (val <= 0x7) { | ||
388 | val = 0x7; | ||
389 | } | ||
390 | } | ||
391 | next |= (val << 4 * i); | ||
392 | } | ||
393 | wave_active[j] = next; | ||
394 | } | ||
395 | |||
396 | // DEBUG: | ||
397 | // int x = 50; | ||
398 | // int y = 50; | ||
399 | // draw_filled_rect(0 + x, 0 + y, 100 + x, 32 + y, COL_BG); | ||
400 | // draw_wave_pattern(&wave_active, 0 + x, 0 + y, 1); | ||
401 | |||
402 | memcpy32(SOUND_WAVE_RAM, wave_active, 16); | ||
403 | SOUND_WAVE_MODE ^= SOUND_WAVE_BANK_SELECT(1); | ||
404 | } | ||
405 | |||
355 | void | 406 | void |
356 | sequencer_tick(void) { | 407 | sequencer_tick(void) { |
408 | wave_ad_tick(); | ||
357 | if (nseq_ticks++ == 0) { | 409 | if (nseq_ticks++ == 0) { |
358 | play_step(); | 410 | play_step(); |
359 | return; | ||
360 | } else if (nseq_ticks == 24) { | 411 | } else if (nseq_ticks == 24) { |
361 | nseq_ticks = 0; | 412 | nseq_ticks = 0; |
362 | } | 413 | } |