aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2024-01-16 09:31:31 +0100
committerBad Diode <bd@badd10de.dev>2024-01-16 09:31:31 +0100
commit77374dacdee448b9dea733c0e444da07942b3238 (patch)
tree1fcb19f8e81c59a8ff5a48205b19a7eff052f0fe
parent22ddbd9d1688aed3220122ac7a513742140ed3b6 (diff)
downloadstepper-77374dacdee448b9dea733c0e444da07942b3238.tar.gz
stepper-77374dacdee448b9dea733c0e444da07942b3238.zip
[WIP] Refactor ch3 envelope
-rw-r--r--Makefile2
-rw-r--r--src/globals.c39
-rw-r--r--src/main.c1
-rw-r--r--src/sequencer.c175
4 files changed, 142 insertions, 75 deletions
diff --git a/Makefile b/Makefile
index 9894173..7afaf9d 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-14 30TARGET := STEPPER-v1.8-dev-15
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/globals.c b/src/globals.c
index 5063d69..c040585 100644
--- a/src/globals.c
+++ b/src/globals.c
@@ -1,15 +1,3 @@
1enum WAVES {
2 WAVE_SIN,
3 WAVE_SAW,
4 WAVE_SQUARE,
5 WAVE_MAX,
6};
7
8#define WAVE_SIZE 4
9#define WAVE_VARS 4
10
11typedef u32 Wave[WAVE_SIZE];
12
13// 1//
14// Globals. 2// Globals.
15// 3//
@@ -221,9 +209,30 @@ bool redraw_scale = true;
221bool update_bpm = false; 209bool update_bpm = false;
222u8 bar_counter = 0; 210u8 bar_counter = 0;
223 211
224static Wave wave_active = {0}; 212typedef enum WaveEnv {
225// static Wave wave_target = {0}; 213 WAV_ENV_START,
226// TODO: wave env status: OFF, ATTACK, DECAY 214 WAV_ENV_ATTACK,
215 WAV_ENV_DECAY,
216 WAV_ENV_END,
217 WAV_ENV_OFF,
218} WaveEnv;
219
220enum WAVES {
221 WAVE_SIN,
222 WAVE_SAW,
223 WAVE_SQUARE,
224 WAVE_MAX,
225};
226
227#define WAVE_SIZE 4
228#define WAVE_VARS 4
229
230typedef u32 Wave[WAVE_SIZE];
231
232static WaveEnv wave_env = WAV_ENV_OFF;
233static const Wave *wave_target;
234static u32 wave_freq;
227static int wave_env_ticks = 0; 235static int wave_env_ticks = 0;
228static int wave_env_attack = 8; 236static int wave_env_attack = 8;
229static int wave_env_decay = 8; 237static int wave_env_decay = 8;
238static int wave_env_prog = 0;
diff --git a/src/main.c b/src/main.c
index a72e5e5..cea35f6 100644
--- a/src/main.c
+++ b/src/main.c
@@ -37,6 +37,7 @@ WITH REGARD TO THIS SOFTWARE.
37// - Study saving overhauls for bootleg cartridges. 37// - Study saving overhauls for bootleg cartridges.
38// - When putting a new trigger, make sure it uses the global parameters 38// - When putting a new trigger, make sure it uses the global parameters
39// - Bad performance when selecting patterns 39// - Bad performance when selecting patterns
40// - Add help for attack/decay on ch3
40// 41//
41// Low priority: 42// Low priority:
42// 43//
diff --git a/src/sequencer.c b/src/sequencer.c
index 8863d14..4b5f34f 100644
--- a/src/sequencer.c
+++ b/src/sequencer.c
@@ -227,20 +227,33 @@ 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 };
230 switch (params->wave_mode) { 233 switch (params->wave_mode) {
231 case 0: { 234 case 0: {
232 memcpy32(wave_active, waves[params->shape_a][params->type_a], 16); 235 wave_target = &waves[params->shape_a][params->type_a];
236 wave_env_attack = params->wave_attack;
237 wave_env_decay = params->wave_decay;
238 wave_env = WAV_ENV_START;
239 SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(0);
240 memcpy32(SOUND_WAVE_RAM, wave_zero, 16);
233 SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(1); 241 SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(1);
234 memcpy32(SOUND_WAVE_RAM, wave_active, 16); 242 memcpy32(SOUND_WAVE_RAM, wave_zero, 16);
235 SOUND_WAVE_MODE = SOUND_WAVE_BANK_MODE(0) 243 SOUND_WAVE_MODE = SOUND_WAVE_BANK_MODE(0)
236 | SOUND_WAVE_BANK_SELECT(0); 244 | SOUND_WAVE_BANK_SELECT(0);
237 } break; 245 } break;
238 case 1: { 246 case 1: {
239 memcpy32(wave_active, waves[params->shape_b][params->type_b], 16); 247 wave_target = &waves[params->shape_b][params->type_b];
248 wave_env_attack = params->wave_attack;
249 wave_env_decay = params->wave_decay;
250 wave_env = WAV_ENV_START;
240 SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(0); 251 SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(0);
241 memcpy32(SOUND_WAVE_RAM, wave_active, 16); 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);
242 SOUND_WAVE_MODE = SOUND_WAVE_BANK_MODE(0) 255 SOUND_WAVE_MODE = SOUND_WAVE_BANK_MODE(0)
243 | SOUND_WAVE_BANK_SELECT(1); 256 | SOUND_WAVE_BANK_SELECT(0);
244 } break; 257 } break;
245 case 2: { 258 case 2: {
246 SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(0); 259 SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(0);
@@ -249,15 +262,12 @@ play_step(void) {
249 memcpy32(SOUND_WAVE_RAM, waves[params->shape_a][params->type_a], 16); 262 memcpy32(SOUND_WAVE_RAM, waves[params->shape_a][params->type_a], 16);
250 SOUND_WAVE_MODE = SOUND_WAVE_BANK_MODE(1) 263 SOUND_WAVE_MODE = SOUND_WAVE_BANK_MODE(1)
251 | SOUND_WAVE_BANK_SELECT(0); 264 | SOUND_WAVE_BANK_SELECT(0);
265 wave_env = WAV_ENV_OFF;
266 SOUND_WAVE_MODE |= SOUND_WAVE_ENABLE;
267 SOUND_WAVE_FREQ = SOUND_FREQ_RESET | sound_rates[trig->note];
252 } break; 268 } break;
253 } 269 }
254 wave_env_ticks = 0; 270 wave_freq = sound_rates[trig->note];
255 wave_env_attack = params->wave_attack;
256 wave_env_decay = params->wave_decay;
257 SOUND_WAVE_MODE |= SOUND_WAVE_ENABLE;
258
259 SOUND_WAVE_FREQ = SOUND_FREQ_RESET
260 | sound_rates[trig->note];
261 switch (params->wave_volume) { 271 switch (params->wave_volume) {
262 case 0: { SOUND_WAVE_CTRL = SOUND_WAVE_MUTE; } break; 272 case 0: { SOUND_WAVE_CTRL = SOUND_WAVE_MUTE; } break;
263 case 1: { SOUND_WAVE_CTRL = SOUND_WAVE_VOL_25; } break; 273 case 1: { SOUND_WAVE_CTRL = SOUND_WAVE_VOL_25; } break;
@@ -354,65 +364,112 @@ static int nseq_ticks = 0;
354IWRAM_CODE 364IWRAM_CODE
355void 365void
356wave_ad_tick(void) { 366wave_ad_tick(void) {
357 // Play a single step for A+B or no envelope. 367 Wave wave_active = {0};
358 if ((SOUND_WAVE_MODE & SOUND_WAVE_BANK_MODE(1)) || !wave_env_decay) { 368env_start:
359 if (wave_env_ticks++ == 24) { 369 switch (wave_env) {
360 SOUND_WAVE_FREQ = SOUND_FREQ_RESET; 370 case WAV_ENV_START: {
361 SOUND_WAVE_CTRL = SOUND_WAVE_MUTE; 371 wave_env_ticks = 0;
362 } 372 wave_env_prog = 0;
363 return; 373 SOUND_WAVE_MODE |= SOUND_WAVE_ENABLE;
364 } 374 SOUND_WAVE_FREQ = SOUND_FREQ_RESET | wave_freq;
365 375
366 if (wave_env_ticks++ < wave_env_decay) { 376 if (wave_env_attack == 0) {
367 return; 377 memcpy32(wave_active, wave_target, 16);
368 } 378 memcpy32(SOUND_WAVE_RAM, wave_active, 16);
369 wave_env_ticks = 0; 379 SOUND_WAVE_MODE ^= SOUND_WAVE_BANK_SELECT(1);
370 380 } else {
371 // Decay. 381 wave_env = WAV_ENV_ATTACK;
372 for (size_t j = 0; j < 4; j++) { 382 goto env_start;
373 u32 next = 0; 383 }
374 for (size_t i = 0; i < 8; i++) { 384
375 u8 val = (wave_active[j] >> 4 * i) & 0xF; 385 if (wave_env_decay == 0) {
376 // Operating in 24.8 fixed point: 386 wave_env = WAV_ENV_OFF;
377 // 0.9 = 230; 0.8 = 205; 0.75 = 192 387 goto env_start;
378 int power = 205; 388 } else {
379 if (val < 0x7) { 389 wave_env = WAV_ENV_DECAY;
380 int tmp = 0x7 - val; 390 }
381 tmp *= power; 391 return;
382 tmp >>= 8; 392 } break;
383 val = (0x7 - tmp) & 0xf; 393 case WAV_ENV_ATTACK: {
384 } else if (val > 0x7) { 394 // TODO: Attack envelope
385 int tmp = (val - 0x7); 395 } break;
386 tmp *= power; 396 case WAV_ENV_DECAY: {
387 tmp >>= 8; 397 if (wave_env_ticks++ < wave_env_decay) {
388 val = tmp + 0x7; 398 return;
389 if (val <= 0x7) { 399 }
390 val = 0x7; 400 wave_env_ticks = 0;
401
402 // Decay.
403 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.
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
410 };
411 int power = powers[wave_env_prog];
412 if (++wave_env_prog >= 8) {
413 wave_env = WAV_ENV_END;
414 }
415 for (size_t j = 0; j < 4; j++) {
416 u32 next = 0;
417 u32 prev = (*wave_target)[j];
418 for (size_t i = 0; i < 8; i++) {
419 u8 val = (prev >> 4 * i) & 0xF;
420 // Operating in 24.8 fixed point:
421 if (val < 0x7) {
422 int tmp = 0x7 - val;
423 tmp *= power;
424 tmp >>= 8;
425 val = (0x7 - tmp) & 0xf;
426 } else if (val > 0x7) {
427 int tmp = (val - 0x7);
428 tmp *= power;
429 tmp >>= 8;
430 val = tmp + 0x7;
431 if (val <= 0x7) {
432 val = 0x7;
433 }
434 }
435 next |= (val << 4 * i);
391 } 436 }
437 wave_active[j] = next;
392 } 438 }
393 next |= (val << 4 * i);
394 }
395 wave_active[j] = next;
396 }
397 439
398 // DEBUG: 440 // DEBUG:
399 // int x = 50; 441 // int x = 50;
400 // int y = 50; 442 // int y = 50;
401 // draw_filled_rect(0 + x, 0 + y, 100 + x, 32 + y, COL_BG); 443 // draw_filled_rect(0 + x, 0 + y, 100 + x, 32 + y, COL_BG);
402 // draw_wave_pattern(&wave_active, 0 + x, 0 + y, 1); 444 // draw_wave_pattern(&wave_active, 0 + x, 0 + y, 1);
403 445
404 memcpy32(SOUND_WAVE_RAM, wave_active, 16); 446 memcpy32(SOUND_WAVE_RAM, wave_active, 16);
405 SOUND_WAVE_MODE ^= SOUND_WAVE_BANK_SELECT(1); 447 SOUND_WAVE_MODE ^= SOUND_WAVE_BANK_SELECT(1);
448 } break;
449 case WAV_ENV_OFF: {
450 if (wave_env_ticks++ == 24) {
451 SOUND_WAVE_FREQ = SOUND_FREQ_RESET;
452 SOUND_WAVE_CTRL = SOUND_WAVE_MUTE;
453 wave_env = WAV_ENV_END;
454 }
455 return;
456 } break;
457 case WAV_ENV_END: {
458 SOUND_WAVE_FREQ = SOUND_FREQ_RESET;
459 SOUND_WAVE_CTRL = SOUND_WAVE_MUTE;
460 return;
461 } break;
462 }
406} 463}
407 464
408void 465void
409sequencer_tick(void) { 466sequencer_tick(void) {
410 wave_ad_tick();
411 if (nseq_ticks++ == 0) { 467 if (nseq_ticks++ == 0) {
412 play_step(); 468 play_step();
413 } else if (nseq_ticks == 24) { 469 } else if (nseq_ticks == 24) {
414 nseq_ticks = 0; 470 nseq_ticks = 0;
415 } 471 }
472 wave_ad_tick();
416} 473}
417 474
418void 475void
@@ -1291,8 +1348,8 @@ set_param_selection_wave(ChannelWaveParams *params, InputHandler return_handler)
1291 case 4: { params->prob = CLAMP(params->prob + inc * -1, 0, PROB_NUM - 1); } break; 1348 case 4: { params->prob = CLAMP(params->prob + inc * -1, 0, PROB_NUM - 1); } break;
1292 case 5: { params->wave_mode = CLAMP(params->wave_mode + inc, 0, 2); } break; 1349 case 5: { params->wave_mode = CLAMP(params->wave_mode + inc, 0, 2); } break;
1293 case 6: { params->wave_volume = CLAMP(params->wave_volume + inc, 0, 4); } break; 1350 case 6: { params->wave_volume = CLAMP(params->wave_volume + inc, 0, 4); } break;
1294 case 7: { params->wave_attack = CLAMP(params->wave_attack + inc, 0, 24); } break; 1351 case 7: { params->wave_attack = CLAMP(params->wave_attack + inc, 0, 16); } break;
1295 case 8: { params->wave_decay = CLAMP(params->wave_decay + inc, 0, 24); } break; 1352 case 8: { params->wave_decay = CLAMP(params->wave_decay + inc, 0, 16); } break;
1296 case 9: { params->pan = CLAMP(params->pan + inc, -1, 1); } break; 1353 case 9: { params->pan = CLAMP(params->pan + inc, -1, 1); } break;
1297 } 1354 }
1298 redraw_params = true; 1355 redraw_params = true;