aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2024-01-15 14:50:21 +0100
committerBad Diode <bd@badd10de.dev>2024-01-15 14:50:21 +0100
commit65089bc6ca9e31878afd583e133cb376ef03f268 (patch)
tree3f11c40a5ddf7ac289b4e7014776dfc9a8a4f785
parente8f4708a6d809c33719ec2f773d23e05c8619b2b (diff)
downloadstepper-65089bc6ca9e31878afd583e133cb376ef03f268.tar.gz
stepper-65089bc6ca9e31878afd583e133cb376ef03f268.zip
[WIP] Initial implementation of CH3 envelope
-rw-r--r--Makefile2
-rw-r--r--src/assets.c7
-rw-r--r--src/main.c2
-rw-r--r--src/sequencer.c69
4 files changed, 69 insertions, 11 deletions
diff --git a/Makefile b/Makefile
index 4686168..6a33d16 100644
--- a/Makefile
+++ b/Makefile
@@ -27,7 +27,7 @@ INC_FLAGS := $(addprefix -I,$(INC_DIRS))
27INC_FLAGS += -I$(LIBGBA_SRC) 27INC_FLAGS += -I$(LIBGBA_SRC)
28 28
29# Output library names and executables. 29# Output library names and executables.
30TARGET := STEPPER-v1.8-dev-09 30TARGET := STEPPER-v1.8-dev-11
31ELF := $(BUILD_DIR)/$(TARGET).elf 31ELF := $(BUILD_DIR)/$(TARGET).elf
32BIN := $(BUILD_DIR)/$(TARGET).gba 32BIN := $(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
97typedef u32 Wave[WAVE_VARS]; 98typedef u32 Wave[WAVE_SIZE];
99static Wave wave_active = {0};
100static Wave wave_target = {0};
101static int wave_env_ticks = 0;
102static int wave_env_decay = 8;
98 103
99static const Wave waves[][WAVE_VARS] = { 104static const Wave waves[][WAVE_VARS] = {
100 { 105 {
diff --git a/src/main.c b/src/main.c
index 5e18396..a8c93bf 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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
353static int nseq_ticks = 0; 350static int nseq_ticks = 0;
354 351
352IWRAM_CODE
353void
354wave_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
355void 406void
356sequencer_tick(void) { 407sequencer_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 }