diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/apu.c | 125 |
1 files changed, 85 insertions, 40 deletions
@@ -1,23 +1,89 @@ | |||
1 | /* | ||
2 | Copyright (c) 2021 Bad Diode | ||
3 | |||
4 | Permission to use, copy, modify, and distribute this software for any | ||
5 | purpose with or without fee is hereby granted, provided that the above | ||
6 | copyright notice and this permission notice appear in all copies. | ||
7 | |||
8 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | WITH REGARD TO THIS SOFTWARE. | ||
10 | */ | ||
11 | |||
1 | // | 12 | // |
2 | // REG_TM0D frequency buffer size | 13 | // Audio quality configuration. |
3 | // | | | | ||
4 | // V V V | ||
5 | // | ||
6 | // Timer = 62610 = 65536 - (16777216 / 5734), buf = 96 | ||
7 | // Timer = 63940 = 65536 - (16777216 / 10512), buf = 176 | ||
8 | // Timer = 64282 = 65536 - (16777216 / 13379), buf = 224 | ||
9 | // Timer = 64612 = 65536 - (16777216 / 18157), buf = 304 | ||
10 | // Timer = 64738 = 65536 - (16777216 / 21024), buf = 352 | ||
11 | // Timer = 64909 = 65536 - (16777216 / 26758), buf = 448 | ||
12 | // Timer = 65004 = 65536 - (16777216 / 31536), buf = 528 | ||
13 | // Timer = 65073 = 65536 - (16777216 / 36314), buf = 608 | ||
14 | // Timer = 65118 = 65536 - (16777216 / 40137), buf = 672 | ||
15 | // Timer = 65137 = 65536 - (16777216 / 42048), buf = 704 | ||
16 | // | 14 | // |
17 | // Source: https://deku.gbadev.org/program/sound1.html | 15 | // The AUDIO_FREQ, AUDIO_BUF_LEN and AUDIO_TIMER depend on each other. The pitch |
18 | #define AUDIO_FREQ 18157 | 16 | // table is generated such as the samples are pitched with respect to C4. When |
19 | #define AUDIO_BUF_LEN 304 | 17 | // the pitch table is multiplied by the sampling rate of the original sample, |
20 | #define AUDIO_TIMER 64612 | 18 | // the resulting value will be the increment per VSYNC, which must be shifted |
19 | // AUDIO_INC_PRECISION to obtain a (20.12) fixed-point increment value. | ||
20 | #if defined(AUDIO_HIFI) | ||
21 | #define AUDIO_FREQ 40137 | ||
22 | #define AUDIO_BUF_LEN 672 | ||
23 | #define AUDIO_TIMER 65118 | ||
24 | #define AUDIO_INC_PRECISION 6 | ||
25 | static u16 pitch_table[120] = { | ||
26 | 53, 56, 59, 63, 67, 71, 75, 79, | ||
27 | 84, 89, 95, 100, 106, 113, 119, 126, | ||
28 | 134, 142, 151, 159, 169, 179, 190, 201, | ||
29 | 213, 226, 239, 253, 269, 285, 302, 319, | ||
30 | 339, 359, 380, 403, 427, 452, 479, 507, | ||
31 | 538, 570, 604, 639, 678, 718, 761, 806, | ||
32 | 854, 905, 958, 1015, 1076, 1140, 1208, 1279, | ||
33 | 1356, 1436, 1522, 1612, 1708, 1810, 1917, 2031, | ||
34 | 2152, 2280, 2416, 2559, 2712, 2873, 3044, 3225, | ||
35 | 3417, 3620, 3835, 4063, 4305, 4561, 4832, 5119, | ||
36 | 5424, 5746, 6088, 6450, 6834, 7240, 7671, 8127, | ||
37 | 8610, 9122, 9665, 10239, 10848, 11493, 12177, 12901, | ||
38 | 13668, 14481, 15342, 16254, 17221, 18245, 19330, 20479, | ||
39 | 21697, 22987, 24354, 25802, 27337, 28962, 30684, 32509, | ||
40 | 34442, 36490, 38660, 40959, 43394, 45975, 48709, 51605, | ||
41 | }; | ||
42 | #elif defined(AUDIO_LOWFI) | ||
43 | #define AUDIO_FREQ 5734 | ||
44 | #define AUDIO_BUF_LEN 96 | ||
45 | #define AUDIO_TIMER 62610 | ||
46 | #define AUDIO_INC_PRECISION 4 | ||
47 | static u16 pitch_table[120] = { | ||
48 | 93, 98, 104, 111, 117, 124, 132, 139, | ||
49 | 148, 157, 166, 176, 186, 197, 209, 222, | ||
50 | 235, 249, 264, 279, 296, 314, 332, 352, | ||
51 | 373, 395, 419, 444, 470, 498, 528, 559, | ||
52 | 593, 628, 665, 705, 747, 791, 839, 888, | ||
53 | 941, 997, 1057, 1119, 1186, 1257, 1331, 1411, | ||
54 | 1494, 1583, 1678, 1777, 1883, 1995, 2114, 2239, | ||
55 | 2373, 2514, 2663, 2822, 2989, 3167, 3356, 3555, | ||
56 | 3767, 3991, 4228, 4479, 4746, 5028, 5327, 5644, | ||
57 | 5979, 6335, 6712, 7111, 7534, 7982, 8456, 8959, | ||
58 | 9492, 10056, 10654, 11288, 11959, 12670, 13424, 14222, | ||
59 | 15068, 15964, 16913, 17919, 18984, 20113, 21309, 22576, | ||
60 | 23919, 25341, 26848, 28445, 30136, 31928, 33827, 35838, | ||
61 | 37969, 40227, 42619, 45153, 47838, 50683, 53697, 56890, | ||
62 | 60273, 63857, 67654, 71677, 75939, 80454, 85238, 90307, | ||
63 | }; | ||
64 | #else | ||
65 | #define AUDIO_FREQ 18157 | ||
66 | #define AUDIO_BUF_LEN 304 | ||
67 | #define AUDIO_TIMER 64612 | ||
68 | #define AUDIO_INC_PRECISION 5 | ||
69 | static u16 pitch_table[120] = { | ||
70 | 59, 62, 66, 70, 74, 78, 83, 88, | ||
71 | 93, 99, 105, 111, 118, 125, 132, 140, | ||
72 | 148, 157, 166, 176, 187, 198, 210, 222, | ||
73 | 236, 250, 264, 280, 297, 315, 333, 353, | ||
74 | 374, 396, 420, 445, 472, 500, 529, 561, | ||
75 | 594, 630, 667, 707, 749, 793, 841, 891, | ||
76 | 944, 1000, 1059, 1122, 1189, 1260, 1335, 1414, | ||
77 | 1498, 1587, 1682, 1782, 1888, 2000, 2119, 2245, | ||
78 | 2379, 2520, 2670, 2829, 2997, 3175, 3364, 3564, | ||
79 | 3776, 4001, 4239, 4491, 4758, 5041, 5341, 5658, | ||
80 | 5995, 6351, 6729, 7129, 7553, 8002, 8478, 8982, | ||
81 | 9517, 10083, 10682, 11317, 11990, 12703, 13459, 14259, | ||
82 | 15107, 16005, 16957, 17965, 19034, 20166, 21365, 22635, | ||
83 | 23981, 25407, 26918, 28519, 30215, 32011, 33915, 35931, | ||
84 | 38068, 40332, 42730, 45271, 47963, 50815, 53837, 57038, | ||
85 | }; | ||
86 | #endif | ||
21 | 87 | ||
22 | typedef struct Audio { | 88 | typedef struct Audio { |
23 | s8 mix_buffer[AUDIO_BUF_LEN * 2]; | 89 | s8 mix_buffer[AUDIO_BUF_LEN * 2]; |
@@ -51,27 +117,6 @@ typedef struct AudioChannel { | |||
51 | u8 filter_len; | 117 | u8 filter_len; |
52 | } AudioChannel; | 118 | } AudioChannel; |
53 | 119 | ||
54 | // Calculated as ((261.6 / 18157) << 17) for C4. If multiplied by sampling rate | ||
55 | // we will have a u32 (15.17) fixed-point number. This should be enough to | ||
56 | // accurately portray samples up to 75300 Hz. | ||
57 | static u16 pitch_table[120] = { | ||
58 | 59, 62, 66, 70, 74, 78, 83, 88, | ||
59 | 93, 99, 105, 111, 118, 125, 132, 140, | ||
60 | 148, 157, 166, 176, 187, 198, 210, 222, | ||
61 | 236, 250, 264, 280, 297, 315, 333, 353, | ||
62 | 374, 396, 420, 445, 472, 500, 529, 561, | ||
63 | 594, 630, 667, 707, 749, 793, 841, 891, | ||
64 | 944, 1000, 1059, 1122, 1189, 1260, 1335, 1414, | ||
65 | 1498, 1587, 1682, 1782, 1888, 2000, 2119, 2245, | ||
66 | 2379, 2520, 2670, 2829, 2997, 3175, 3364, 3564, | ||
67 | 3776, 4001, 4239, 4491, 4758, 5041, 5341, 5658, | ||
68 | 5995, 6351, 6729, 7129, 7553, 8002, 8478, 8982, | ||
69 | 9517, 10083, 10682, 11317, 11990, 12703, 13459, 14259, | ||
70 | 15107, 16005, 16957, 17965, 19034, 20166, 21365, 22635, | ||
71 | 23981, 25407, 26918, 28519, 30215, 32011, 33915, 35931, | ||
72 | 38068, 40332, 42730, 45271, 47963, 50815, 53837, 57038, | ||
73 | }; | ||
74 | |||
75 | IWRAM_CODE | 120 | IWRAM_CODE |
76 | void | 121 | void |
77 | build_adsr(AudioChannel *chan, u16 adsr) { | 122 | build_adsr(AudioChannel *chan, u16 adsr) { |
@@ -177,7 +222,7 @@ update_channel(AudioChannel *c, u8 *data, u16 length, u8 pitch, u16 adsr, | |||
177 | if (length > 256) { | 222 | if (length > 256) { |
178 | sampling_rate = 44100; | 223 | sampling_rate = 44100; |
179 | } | 224 | } |
180 | c->inc = (pitch_table[c->pitch] * sampling_rate) >> 5; | 225 | c->inc = (pitch_table[c->pitch] * sampling_rate) >> AUDIO_INC_PRECISION; |
181 | 226 | ||
182 | build_adsr(c, adsr); | 227 | build_adsr(c, adsr); |
183 | } | 228 | } |