diff options
author | Bad Diode <bd@badd10de.dev> | 2021-04-30 11:56:31 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2021-04-30 11:56:31 +0200 |
commit | c2edce15ca79b8a841c187fcacd184ee6c713b82 (patch) | |
tree | 6bf0e6c7f7c993fb494ad7489f527c52db3ce821 | |
parent | 3ec91ad217fb77ae1980b0b935e76307edf63ae1 (diff) | |
download | gba-experiments-c2edce15ca79b8a841c187fcacd184ee6c713b82.tar.gz gba-experiments-c2edce15ca79b8a841c187fcacd184ee6c713b82.zip |
Add fixed rates for all notes in the sound range
From C2 to C8
-rw-r--r-- | src/common.h | 64 | ||||
-rw-r--r-- | src/main.c | 72 |
2 files changed, 64 insertions, 72 deletions
diff --git a/src/common.h b/src/common.h index 7a0c50c..e864a71 100644 --- a/src/common.h +++ b/src/common.h | |||
@@ -601,29 +601,46 @@ sound_volume(SoundChannel channels, u8 volume) { | |||
601 | #define SOUND_SQUARE_RESET (1 << 0xF) | 601 | #define SOUND_SQUARE_RESET (1 << 0xF) |
602 | 602 | ||
603 | typedef enum { | 603 | typedef enum { |
604 | NOTE_C, | 604 | NOTE_C_2 , NOTE_C_SHARP_2 , NOTE_D_2 , NOTE_D_SHARP_2 , |
605 | NOTE_C_SHARP, | 605 | NOTE_E_2 , NOTE_F_2 , NOTE_F_SHARP_2 , NOTE_G_2 , |
606 | NOTE_D, | 606 | NOTE_G_SHARP_2 , NOTE_A_2 , NOTE_A_SHARP_2 , NOTE_B_2 , |
607 | NOTE_D_SHARP, | 607 | NOTE_C_3 , NOTE_C_SHARP_3 , NOTE_D_3 , NOTE_D_SHARP_3 , |
608 | NOTE_E, | 608 | NOTE_E_3 , NOTE_F_3 , NOTE_F_SHARP_3 , NOTE_G_3 , |
609 | NOTE_F, | 609 | NOTE_G_SHARP_3 , NOTE_A_3 , NOTE_A_SHARP_3 , NOTE_B_3 , |
610 | NOTE_F_SHARP, | 610 | NOTE_C_4 , NOTE_C_SHARP_4 , NOTE_D_4 , NOTE_D_SHARP_4 , |
611 | NOTE_G, | 611 | NOTE_E_4 , NOTE_F_4 , NOTE_F_SHARP_4 , NOTE_G_4 , |
612 | NOTE_G_SHARP, | 612 | NOTE_G_SHARP_4 , NOTE_A_4 , NOTE_A_SHARP_4 , NOTE_B_4 , |
613 | NOTE_A, | 613 | NOTE_C_5 , NOTE_C_SHARP_5 , NOTE_D_5 , NOTE_D_SHARP_5 , |
614 | NOTE_A_SHARP, | 614 | NOTE_E_5 , NOTE_F_5 , NOTE_F_SHARP_5 , NOTE_G_5 , |
615 | NOTE_B, | 615 | NOTE_G_SHARP_5 , NOTE_A_5 , NOTE_A_SHARP_5 , NOTE_B_5 , |
616 | NOTE_C_6 , NOTE_C_SHARP_6 , NOTE_D_6 , NOTE_D_SHARP_6 , | ||
617 | NOTE_E_6 , NOTE_F_6 , NOTE_F_SHARP_6 , NOTE_G_6 , | ||
618 | NOTE_G_SHARP_6 , NOTE_A_6 , NOTE_A_SHARP_6 , NOTE_B_6 , | ||
619 | NOTE_C_7 , NOTE_C_SHARP_7 , NOTE_D_7 , NOTE_D_SHARP_7 , | ||
620 | NOTE_E_7 , NOTE_F_7 , NOTE_F_SHARP_7 , NOTE_G_7 , | ||
621 | NOTE_G_SHARP_7 , NOTE_A_7 , NOTE_A_SHARP_7 , NOTE_B_7 , | ||
622 | NOTE_C_8 | ||
616 | } Note; | 623 | } Note; |
617 | 624 | ||
618 | u32 | 625 | static char * note_names[] = { |
619 | sound_rate(Note note, u32 octave) { | 626 | "C2", "C#2", "D2", "D#2", "E2", "F2", "F#2", "G2", "G#2", "A2", "A#2", "B2", |
620 | const u32 base_rate[12] = { | 627 | "C3", "C#3", "D3", "D#3", "E3", "F3", "F#3", "G3", "G#3", "A3", "A#3", "B3", |
621 | 8013, 7566, 7144, 6742, // C , C#, D , D# | 628 | "C4", "C#4", "D4", "D#4", "E4", "F4", "F#4", "G4", "G#4", "A4", "A#4", "B4", |
622 | 6362, 6005, 5666, 5346, // E , F , F#, G | 629 | "C5", "C#5", "D5", "D#5", "E5", "F5", "F#5", "G5", "G#5", "A5", "A#5", "B5", |
623 | 5048, 4766, 4499, 4246 // G#, A , A#, B | 630 | "C6", "C#6", "D6", "D#6", "E6", "F6", "F#6", "G6", "G#6", "A6", "A#6", "B6", |
624 | }; | 631 | "C7", "C#7", "D7", "D#7", "E7", "F7", "F#7", "G7", "G#7", "A7", "A#7", "B7", |
625 | return 2048 - (base_rate[note] >> (4 + octave)); | 632 | "C8" |
626 | } | 633 | }; |
634 | |||
635 | const u32 sound_rates[] = { | ||
636 | 44 , 156 , 262 , 363 , 457 , 547 , 631 , 710 , 785 , 856 , 923 , 986 , | ||
637 | 1046, 1102, 1155, 1205, 1252, 1297, 1339, 1379, 1416, 1452, 1485, 1517, | ||
638 | 1547, 1575, 1601, 1626, 1650, 1672, 1693, 1713, 1732, 1750, 1766, 1782, | ||
639 | 1797, 1811, 1824, 1837, 1849, 1860, 1870, 1880, 1890, 1899, 1907, 1915, | ||
640 | 1922, 1929, 1936, 1942, 1948, 1954, 1959, 1964, 1969, 1973, 1977, 1981, | ||
641 | 1985, 1988, 1992, 1995, 1998, 2001, 2003, 2006, 2008, 2010, 2012, 2014, | ||
642 | 2016, | ||
643 | }; | ||
627 | 644 | ||
628 | // | 645 | // |
629 | // Misc. | 646 | // Misc. |
@@ -638,4 +655,9 @@ wait_vsync(void) { | |||
638 | while(DISP_VCOUNT < 160); | 655 | while(DISP_VCOUNT < 160); |
639 | } | 656 | } |
640 | 657 | ||
658 | // General utility functions. Min/Max/Clamp | ||
659 | #define MIN(A, B) ((A) <= (B) ? (A) : (B)) | ||
660 | #define MAX(A, B) ((A) >= (B) ? (A) : (B)) | ||
661 | #define CLAMP(X, MIN, MAX) ((X) <= (MIN) ? (MIN) : (X) > (MAX) ? (MAX): (X)) | ||
662 | |||
641 | #endif // GBAEXP_COMMON_H | 663 | #endif // GBAEXP_COMMON_H |
@@ -13,23 +13,6 @@ | |||
13 | // TODO: Cleanup OBJ/OAM memory copying and access. | 13 | // TODO: Cleanup OBJ/OAM memory copying and access. |
14 | // | 14 | // |
15 | 15 | ||
16 | // | ||
17 | // BIOS calls | ||
18 | // | ||
19 | |||
20 | int hblank_counter = 0; | ||
21 | |||
22 | void | ||
23 | irs_hblank_func() { | ||
24 | hblank_counter++; | ||
25 | if (DISP_VCOUNT >= 160) { | ||
26 | PAL_BUFFER_BG[0] = rgb15(0, 0, 0); | ||
27 | } else { | ||
28 | u16 clr = (DISP_VCOUNT / 8); | ||
29 | PAL_BUFFER_BG[0] = rgb15(clr, 0, 31 - clr); | ||
30 | } | ||
31 | } | ||
32 | |||
33 | int main(void) { | 16 | int main(void) { |
34 | // Configure the display in mode 0 to show OBJs, where tile memory is | 17 | // Configure the display in mode 0 to show OBJs, where tile memory is |
35 | // sequential. | 18 | // sequential. |
@@ -46,24 +29,18 @@ int main(void) { | |||
46 | // Register interrupts. | 29 | // Register interrupts. |
47 | irq_init(); | 30 | irq_init(); |
48 | irs_set(IRQ_VBLANK, irs_stub); | 31 | irs_set(IRQ_VBLANK, irs_stub); |
49 | irs_set(IRQ_HBLANK, irs_hblank_func); | ||
50 | 32 | ||
51 | // turn sound on | 33 | // turn sound on |
52 | SOUND_STATUS = SOUND_ENABLE; | 34 | SOUND_STATUS = SOUND_ENABLE; |
53 | SOUND_DMG_MASTER = sound_volume(SOUND_SQUARE1 | SOUND_SQUARE2, 7); | 35 | SOUND_DMG_MASTER = sound_volume(SOUND_SQUARE1 | SOUND_SQUARE2, 7); |
54 | SOUND_DSOUND_MASTER = SOUND_DMG100; | 36 | SOUND_DSOUND_MASTER = SOUND_DMG100; |
55 | 37 | ||
56 | char *note_names[] = { | ||
57 | "C" , "C#" , "D" , "D#" , | ||
58 | "E" , "F" , "F#" , "G" , | ||
59 | "G#" , "A" , "A#" , "B" | ||
60 | }; | ||
61 | int frame_counter = 0; | 38 | int frame_counter = 0; |
62 | Note active_note = NOTE_C; | 39 | Note active_note = NOTE_C_4; |
63 | u8 octave = 0; | 40 | int octave_diff = 0; |
64 | bool playing = false; | 41 | bool playing = false; |
65 | bool new_note = false; | 42 | bool new_note = false; |
66 | u8 interval = 1; | 43 | u8 interval = 4; |
67 | while(true) { | 44 | while(true) { |
68 | bios_vblank_wait(); | 45 | bios_vblank_wait(); |
69 | poll_keys(); | 46 | poll_keys(); |
@@ -72,49 +49,39 @@ int main(void) { | |||
72 | txt_clear_line(); | 49 | txt_clear_line(); |
73 | 50 | ||
74 | if (key_pressed(KEY_B)) { | 51 | if (key_pressed(KEY_B)) { |
75 | active_note = NOTE_C; | 52 | active_note = NOTE_C_4 + 12 * octave_diff; |
76 | new_note = true; | 53 | new_note = true; |
77 | octave = 0; | ||
78 | } else if (key_pressed(KEY_A)) { | 54 | } else if (key_pressed(KEY_A)) { |
79 | active_note = NOTE_D; | 55 | active_note = NOTE_D_4 + 12 * octave_diff; |
80 | new_note = true; | 56 | new_note = true; |
81 | octave = 0; | ||
82 | } else if (key_pressed(KEY_LEFT)) { | 57 | } else if (key_pressed(KEY_LEFT)) { |
83 | active_note = NOTE_E; | 58 | active_note = NOTE_E_4 + 12 * octave_diff; |
84 | new_note = true; | 59 | new_note = true; |
85 | octave = 0; | ||
86 | } else if (key_pressed(KEY_DOWN)) { | 60 | } else if (key_pressed(KEY_DOWN)) { |
87 | active_note = NOTE_F; | 61 | active_note = NOTE_F_4 + 12 * octave_diff; |
88 | new_note = true; | 62 | new_note = true; |
89 | octave = 0; | ||
90 | } else if (key_pressed(KEY_RIGHT)) { | 63 | } else if (key_pressed(KEY_RIGHT)) { |
91 | active_note = NOTE_G; | 64 | active_note = NOTE_G_4 + 12 * octave_diff; |
92 | new_note = true; | 65 | new_note = true; |
93 | octave = 0; | ||
94 | } else if (key_pressed(KEY_UP)) { | 66 | } else if (key_pressed(KEY_UP)) { |
95 | active_note = NOTE_A; | 67 | active_note = NOTE_A_4 + 12 * octave_diff; |
96 | new_note = true; | 68 | new_note = true; |
97 | octave = 0; | ||
98 | } else if (key_pressed(KEY_L)) { | 69 | } else if (key_pressed(KEY_L)) { |
99 | active_note = NOTE_B; | 70 | active_note = NOTE_B_4 + 12 * octave_diff; |
100 | new_note = true; | 71 | new_note = true; |
101 | octave = 0; | ||
102 | } else if (key_pressed(KEY_R)) { | 72 | } else if (key_pressed(KEY_R)) { |
103 | active_note = NOTE_C; | 73 | active_note = NOTE_C_5 + 12 * octave_diff; |
104 | new_note = true; | 74 | new_note = true; |
105 | octave = 1; | ||
106 | } | 75 | } |
107 | if (key_pressed(KEY_START)) { | 76 | if (key_pressed(KEY_START)) { |
108 | interval++; | 77 | octave_diff = CLAMP(octave_diff + 1, -2, 3); |
109 | } | 78 | } |
110 | if (key_pressed(KEY_SELECT)) { | 79 | if (key_pressed(KEY_SELECT)) { |
111 | interval--; | 80 | octave_diff = CLAMP(octave_diff - 1, -2, 3); |
112 | } | 81 | } |
113 | 82 | ||
114 | if (key_curr > 0) { | 83 | if (key_curr > 0) { |
115 | txt_printf(" Playing: %s + %s\n", | 84 | txt_printf(" Playing: %s\n", note_names[active_note]); |
116 | note_names[active_note], | ||
117 | (note_names[(active_note + interval) % 12])); | ||
118 | playing = true; | 85 | playing = true; |
119 | } else { | 86 | } else { |
120 | playing = false; | 87 | playing = false; |
@@ -122,10 +89,13 @@ int main(void) { | |||
122 | 89 | ||
123 | if (playing) { | 90 | if (playing) { |
124 | if (new_note) { | 91 | if (new_note) { |
125 | SOUND_SQUARE1_CTRL = SOUND_SQUARE_ENV_VOL(4) | SOUND_SQUARE_ENV_TIME(0); | 92 | // SOUND_SQUARE1_SWEEP = 3 | (1 << 3) | (2 << 4); |
126 | SOUND_SQUARE2_CTRL = SOUND_SQUARE_ENV_VOL(4) | SOUND_SQUARE_ENV_TIME(0); | 93 | // SOUND_SQUARE1_CTRL = SOUND_SQUARE_ENV_VOL(15) | SOUND_SQUARE_ENV_TIME(0x7); |
127 | SOUND_SQUARE1_FREQ = SOUND_SQUARE_RESET | sound_rate(active_note, octave); | 94 | // SOUND_SQUARE2_CTRL = SOUND_SQUARE_ENV_VOL(15) | SOUND_SQUARE_ENV_TIME(0); |
128 | SOUND_SQUARE2_FREQ = SOUND_SQUARE_RESET | sound_rate((active_note + interval) % 12, octave); | 95 | SOUND_SQUARE1_CTRL = SOUND_SQUARE_ENV_VOL(15) | SOUND_SQUARE_ENV_TIME(4) | SOUND_SQUARE_ENV_INC | SOUND_SQUARE_DUTY(3); |
96 | // SOUND_SQUARE2_CTRL = SOUND_SQUARE_ENV_VOL(15) | SOUND_SQUARE_ENV_TIME(4) | SOUND_SQUARE_ENV_INC; | ||
97 | SOUND_SQUARE1_FREQ = SOUND_SQUARE_RESET | sound_rates[active_note]; | ||
98 | // SOUND_SQUARE2_FREQ = SOUND_SQUARE_RESET | sound_rate((active_note + interval) % 12, octave); | ||
129 | } | 99 | } |
130 | new_note = false; | 100 | new_note = false; |
131 | } else { | 101 | } else { |