src/gba/gba-audio.c (view raw)
1#include "gba-audio.h"
2
3#include "gba.h"
4#include "gba-io.h"
5#include "gba-thread.h"
6
7#include <limits.h>
8
9const unsigned GBA_AUDIO_SAMPLES = 512;
10const unsigned GBA_AUDIO_FIFO_SIZE = 8 * sizeof(int32_t);
11#define SWEEP_CYCLES (GBA_ARM7TDMI_FREQUENCY / 128)
12
13static int32_t _updateSquareChannel(struct GBAAudioSquareControl* envelope, int duty);
14static void _updateEnvelope(struct GBAAudioEnvelope* envelope);
15static void _updateSweep(struct GBAAudioChannel1* ch);
16static int32_t _updateChannel1(struct GBAAudioChannel1* ch);
17static int32_t _updateChannel2(struct GBAAudioChannel2* ch);
18static int32_t _updateChannel3(struct GBAAudioChannel3* ch);
19static int32_t _updateChannel4(struct GBAAudioChannel4* ch);
20static void _sample(struct GBAAudio* audio);
21
22void GBAAudioInit(struct GBAAudio* audio) {
23 audio->nextEvent = 0;
24 audio->nextCh1 = 0;
25 audio->nextCh2 = 0;
26 audio->nextCh3 = 0;
27 audio->nextCh4 = 0;
28 audio->ch1.envelope.nextStep = INT_MAX;
29 audio->ch1.control.nextStep = 0;
30 audio->ch1.nextSweep = INT_MAX;
31 audio->ch1.playing = 0;
32 audio->ch1.sample = 0;
33 audio->ch2.envelope.nextStep = INT_MAX;
34 audio->ch2.control.nextStep = 0;
35 audio->ch2.sample = 0;
36 audio->ch3.bank.packed = 0;
37 audio->ch3.sample = 0;
38 audio->ch4.sample = 0;
39 audio->ch4.envelope.nextStep = INT_MAX;
40 audio->eventDiff = 0;
41 audio->nextSample = 0;
42 audio->sampleRate = 0x8000;
43 audio->soundcntLo = 0;
44 audio->soundcntHi = 0;
45 audio->soundcntX = 0;
46 audio->sampleInterval = GBA_ARM7TDMI_FREQUENCY / audio->sampleRate;
47
48 CircleBufferInit(&audio->left, GBA_AUDIO_SAMPLES * sizeof(int32_t));
49 CircleBufferInit(&audio->right, GBA_AUDIO_SAMPLES * sizeof(int32_t));
50 CircleBufferInit(&audio->chA.fifo, GBA_AUDIO_FIFO_SIZE);
51 CircleBufferInit(&audio->chB.fifo, GBA_AUDIO_FIFO_SIZE);
52
53 pthread_mutex_init(&audio->bufferMutex, 0);
54}
55
56void GBAAudioDeinit(struct GBAAudio* audio) {
57 CircleBufferDeinit(&audio->left);
58 CircleBufferDeinit(&audio->right);
59 CircleBufferDeinit(&audio->chA.fifo);
60 CircleBufferDeinit(&audio->chB.fifo);
61
62 pthread_mutex_lock(&audio->bufferMutex);
63 pthread_mutex_destroy(&audio->bufferMutex);
64}
65
66int32_t GBAAudioProcessEvents(struct GBAAudio* audio, int32_t cycles) {
67 audio->nextEvent -= cycles;
68 audio->eventDiff += cycles;
69 while (audio->nextEvent <= 0) {
70 audio->nextEvent = INT_MAX;
71 if (audio->enable) {
72 audio->nextCh1 -= audio->eventDiff;
73 audio->nextCh2 -= audio->eventDiff;
74 audio->nextCh3 -= audio->eventDiff;
75 audio->nextCh4 -= audio->eventDiff;
76
77 if (audio->ch1.envelope.nextStep != INT_MAX) {
78 audio->ch1.envelope.nextStep -= audio->eventDiff;
79 if (audio->ch1.envelope.nextStep <= 0) {
80 _updateEnvelope(&audio->ch1.envelope);
81 if (audio->ch1.envelope.nextStep < audio->nextEvent) {
82 audio->nextEvent = audio->ch1.envelope.nextStep;
83 }
84 }
85 }
86
87 if (audio->ch1.nextSweep != INT_MAX) {
88 audio->ch1.nextSweep -= audio->eventDiff;
89 if (audio->ch1.nextSweep <= 0) {
90 _updateSweep(&audio->ch1);
91 if (audio->ch1.nextSweep < audio->nextEvent) {
92 audio->nextEvent = audio->ch1.nextSweep;
93 }
94 }
95 }
96
97 if (audio->ch2.envelope.nextStep != INT_MAX) {
98 audio->ch2.envelope.nextStep -= audio->eventDiff;
99 if (audio->ch2.envelope.nextStep <= 0) {
100 _updateEnvelope(&audio->ch2.envelope);
101 if (audio->ch2.envelope.nextStep < audio->nextEvent) {
102 audio->nextEvent = audio->ch2.envelope.nextStep;
103 }
104 }
105 }
106
107 if (audio->ch4.envelope.nextStep != INT_MAX) {
108 audio->ch4.envelope.nextStep -= audio->eventDiff;
109 if (audio->ch4.envelope.nextStep <= 0) {
110 _updateEnvelope(&audio->ch4.envelope);
111 if (audio->ch4.envelope.nextStep < audio->nextEvent) {
112 audio->nextEvent = audio->ch4.envelope.nextStep;
113 }
114 }
115 }
116
117 if ((audio->ch1Right || audio->ch1Left) && audio->nextCh1 <= 0) {
118 audio->nextCh1 += _updateChannel1(&audio->ch1);
119 if (audio->nextCh1 < audio->nextEvent) {
120 audio->nextEvent = audio->nextCh1;
121 }
122 }
123
124 if ((audio->ch2Right || audio->ch2Left) && audio->nextCh2 <= 0) {
125 audio->nextCh2 += _updateChannel2(&audio->ch2);
126 if (audio->nextCh2 < audio->nextEvent) {
127 audio->nextEvent = audio->nextCh2;
128 }
129 }
130
131 if ((audio->ch3Right || audio->ch3Left) && audio->nextCh3 <= 0) {
132 audio->nextCh3 += _updateChannel3(&audio->ch3);
133 if (audio->nextCh3 < audio->nextEvent) {
134 audio->nextEvent = audio->nextCh3;
135 }
136 }
137
138 if ((audio->ch4Right || audio->ch4Left) && audio->nextCh4 <= 0) {
139 audio->nextCh4 += _updateChannel4(&audio->ch4);
140 if (audio->nextCh4 < audio->nextEvent) {
141 audio->nextEvent = audio->nextCh4;
142 }
143 }
144 }
145
146 audio->nextSample -= audio->eventDiff;
147 if (audio->nextSample <= 0) {
148 _sample(audio);
149 audio->nextSample += audio->sampleInterval;
150 }
151
152 if (audio->nextSample < audio->nextEvent) {
153 audio->nextEvent = audio->nextSample;
154 }
155 audio->eventDiff = 0;
156 }
157 return audio->nextEvent;
158}
159
160void GBAAudioScheduleFifoDma(struct GBAAudio* audio, int number, struct GBADMA* info) {
161 switch (info->dest) {
162 case BASE_IO | REG_FIFO_A_LO:
163 audio->chA.dmaSource = number;
164 break;
165 case BASE_IO | REG_FIFO_B_LO:
166 audio->chB.dmaSource = number;
167 break;
168 default:
169 GBALog(audio->p, GBA_LOG_GAME_ERROR, "Invalid FIFO destination: 0x%08X", info->dest);
170 return;
171 }
172 info->dstControl = DMA_FIXED;
173}
174
175void GBAAudioWriteSOUND1CNT_LO(struct GBAAudio* audio, uint16_t value) {
176 audio->ch1.sweep.packed = value;
177 if (audio->ch1.sweep.time) {
178 audio->ch1.nextSweep = audio->ch1.sweep.time * SWEEP_CYCLES;
179 } else {
180 audio->ch1.nextSweep = INT_MAX;
181 }
182}
183
184void GBAAudioWriteSOUND1CNT_HI(struct GBAAudio* audio, uint16_t value) {
185 audio->ch1.envelope.packed = value;
186}
187
188void GBAAudioWriteSOUND1CNT_X(struct GBAAudio* audio, uint16_t value) {
189 audio->ch1.control.packed = value;
190 if (audio->ch1.control.restart) {
191 if (audio->ch1.sweep.time) {
192 audio->ch1.nextSweep = audio->ch1.sweep.time * SWEEP_CYCLES;
193 } else {
194 audio->ch1.nextSweep = INT_MAX;
195 }
196 if (!audio->ch1.playing) {
197 audio->nextCh1 = 0;
198 }
199 audio->ch1.playing = 1;
200 if (audio->ch1.envelope.stepTime) {
201 audio->ch1.envelope.nextStep = 0;
202 } else {
203 audio->ch1.envelope.nextStep = INT_MAX;
204 }
205 audio->ch1.envelope.currentVolume = audio->ch1.envelope.initialVolume;
206 if (audio->ch1.envelope.stepTime) {
207 audio->ch1.envelope.nextStep = 0;
208 } else {
209 audio->ch1.envelope.nextStep = INT_MAX;
210 }
211 }
212}
213
214void GBAAudioWriteSOUND2CNT_LO(struct GBAAudio* audio, uint16_t value) {
215 audio->ch2.envelope.packed = value;
216 if (audio->ch2.envelope.stepTime) {
217 audio->ch2.envelope.nextStep = 0;
218 } else {
219 audio->ch2.envelope.nextStep = INT_MAX;
220 }
221}
222
223void GBAAudioWriteSOUND2CNT_HI(struct GBAAudio* audio, uint16_t value) {
224 audio->ch2.control.packed = value;
225 if (audio->ch2.control.restart) {
226 audio->ch2.envelope.currentVolume = audio->ch2.envelope.initialVolume;
227 if (audio->ch2.envelope.stepTime) {
228 audio->ch2.envelope.nextStep = 0;
229 } else {
230 audio->ch2.envelope.nextStep = INT_MAX;
231 }
232 audio->nextCh2 = 0;
233 }
234}
235
236void GBAAudioWriteSOUND3CNT_LO(struct GBAAudio* audio, uint16_t value) {
237 audio->ch3.bank.packed = value;
238}
239
240void GBAAudioWriteSOUND3CNT_HI(struct GBAAudio* audio, uint16_t value) {
241 audio->ch3.wave.packed = value;
242}
243
244void GBAAudioWriteSOUND3CNT_X(struct GBAAudio* audio, uint16_t value) {
245 audio->ch3.control.packed = value;
246}
247
248void GBAAudioWriteSOUND4CNT_LO(struct GBAAudio* audio, uint16_t value) {
249 audio->ch4.envelope.packed = value;
250 if (audio->ch4.envelope.stepTime) {
251 audio->ch4.envelope.nextStep = 0;
252 } else {
253 audio->ch4.envelope.nextStep = INT_MAX;
254 }
255}
256
257void GBAAudioWriteSOUND4CNT_HI(struct GBAAudio* audio, uint16_t value) {
258 audio->ch4.control.packed = value;
259 if (audio->ch4.control.restart) {
260 audio->ch4.envelope.currentVolume = audio->ch4.envelope.initialVolume;
261 if (audio->ch4.envelope.stepTime) {
262 audio->ch4.envelope.nextStep = 0;
263 } else {
264 audio->ch4.envelope.nextStep = INT_MAX;
265 }
266 if (audio->ch4.control.power) {
267 audio->ch4.lfsr = 0x40;
268 } else {
269 audio->ch4.lfsr = 0x4000;
270 }
271 audio->nextCh4 = 0;
272 }
273}
274
275void GBAAudioWriteSOUNDCNT_LO(struct GBAAudio* audio, uint16_t value) {
276 audio->soundcntLo = value;
277}
278
279void GBAAudioWriteSOUNDCNT_HI(struct GBAAudio* audio, uint16_t value) {
280 audio->soundcntHi = value;
281}
282
283void GBAAudioWriteSOUNDCNT_X(struct GBAAudio* audio, uint16_t value) {
284 audio->soundcntX = (value & 0xF0) | (audio->soundcntX & 0x0F);
285}
286
287void GBAAudioWriteWaveRAM(struct GBAAudio* audio, int address, uint32_t value) {
288 audio->ch3.wavedata[address | (!audio->ch3.bank.bank * 4)] = value;
289}
290
291void GBAAudioWriteFIFO(struct GBAAudio* audio, int address, uint32_t value) {
292 struct CircleBuffer* fifo;
293 switch (address) {
294 case REG_FIFO_A_LO:
295 fifo = &audio->chA.fifo;
296 break;
297 case REG_FIFO_B_LO:
298 fifo = &audio->chB.fifo;
299 break;
300 default:
301 GBALog(audio->p, GBA_LOG_ERROR, "Bad FIFO write to address 0x%03x", address);
302 return;
303 }
304 while (!CircleBufferWrite32(fifo, value)) {
305 int32_t dummy;
306 CircleBufferRead32(fifo, &dummy);
307 }
308}
309
310void GBAAudioSampleFIFO(struct GBAAudio* audio, int fifoId) {
311 struct GBAAudioFIFO* channel;
312 if (fifoId == 0) {
313 channel = &audio->chA;
314 } else if (fifoId == 1) {
315 channel = &audio->chB;
316 } else {
317 GBALog(audio->p, GBA_LOG_ERROR, "Bad FIFO write to address 0x%03x", fifoId);
318 return;
319 }
320 if (CircleBufferSize(&channel->fifo) <= 4 * sizeof(int32_t)) {
321 struct GBADMA* dma = &audio->p->memory.dma[channel->dmaSource];
322 dma->nextCount = 4;
323 GBAMemoryServiceDMA(&audio->p->memory, channel->dmaSource, dma);
324 }
325 CircleBufferRead8(&channel->fifo, &channel->sample);
326}
327
328static int32_t _updateSquareChannel(struct GBAAudioSquareControl* control, int duty) {
329 control->hi = !control->hi;
330 int period = 16 * (2048 - control->frequency);
331 switch (duty) {
332 case 0:
333 return control->hi ? period : period * 7;
334 case 1:
335 return control->hi ? period * 2 : period * 6;
336 case 2:
337 return period * 4;
338 case 3:
339 return control->hi ? period * 6 : period * 2;
340 default:
341 // This should never be hit
342 return period * 4;
343 }
344}
345
346static void _updateEnvelope(struct GBAAudioEnvelope* envelope) {
347 if (envelope->direction) {
348 ++envelope->currentVolume;
349 } else {
350 --envelope->currentVolume;
351 }
352 if (envelope->currentVolume >= 15) {
353 envelope->currentVolume = 15;
354 envelope->nextStep = INT_MAX;
355 } else if (envelope->currentVolume <= 0) {
356 envelope->currentVolume = 0;
357 envelope->nextStep = INT_MAX;
358 } else {
359 envelope->nextStep += envelope->stepTime * (GBA_ARM7TDMI_FREQUENCY >> 6);
360 }
361}
362
363static void _updateSweep(struct GBAAudioChannel1* ch) {
364 if (ch->sweep.direction) {
365 int frequency = ch->control.frequency;
366 frequency -= frequency >> ch->sweep.shift;
367 if (frequency >= 0) {
368 ch->control.frequency = frequency;
369 }
370 } else {
371 int frequency = ch->control.frequency;
372 frequency += frequency >> ch->sweep.shift;
373 if (frequency < 2048) {
374 ch->control.frequency = frequency;
375 } else {
376 ch->playing = 0;
377 }
378 }
379 ch->nextSweep += ch->sweep.time * SWEEP_CYCLES;
380}
381
382static int32_t _updateChannel1(struct GBAAudioChannel1* ch) {
383 int timing = _updateSquareChannel(&ch->control, ch->envelope.duty);
384 ch->sample = ch->control.hi * 0x10 - 0x8;
385 ch->sample *= ch->envelope.currentVolume;
386 return timing;
387}
388
389static int32_t _updateChannel2(struct GBAAudioChannel2* ch) {
390 int timing = _updateSquareChannel(&ch->control, ch->envelope.duty);
391 ch->sample = ch->control.hi * 0x10 - 0x8;
392 ch->sample *= ch->envelope.currentVolume;
393 return timing;
394}
395
396static int32_t _updateChannel3(struct GBAAudioChannel3* ch) {
397 int i;
398 int start;
399 int end;
400 int volume;
401 switch (ch->wave.volume) {
402 case 0:
403 volume = 0;
404 break;
405 case 1:
406 volume = 4;
407 break;
408 case 2:
409 volume = 2;
410 break;
411 case 3:
412 volume = 1;
413 break;
414 default:
415 volume = 3;
416 break;
417 }
418 if (ch->bank.size) {
419 start = 7;
420 end = 0;
421 } else if (ch->bank.bank) {
422 start = 7;
423 end = 4;
424 } else {
425 start = 3;
426 end = 0;
427 }
428 uint32_t bitsCarry = ch->wavedata[end] & 0xF0000000;
429 uint32_t bits;
430 for (i = start; i >= end; --i) {
431 bits = ch->wavedata[i] & 0xF0000000;
432 ch->wavedata[i] <<= 4;
433 ch->wavedata[i] |= bitsCarry >> 28;
434 bitsCarry = bits;
435 }
436 ch->sample = ((bitsCarry >> 26) - 0x20) * volume;
437 return 8 * (2048 - ch->control.rate);
438}
439
440static int32_t _updateChannel4(struct GBAAudioChannel4* ch) {
441 int lsb = ch->lfsr & 1;
442 ch->sample = lsb * 0x10 - 0x8;
443 ch->sample *= ch->envelope.currentVolume;
444 ch->lfsr >>= 1;
445 ch->lfsr ^= (lsb * 0x60) << (ch->control.power ? 0 : 8);
446 int timing = ch->control.ratio ? 2 * ch->control.ratio : 1;
447 timing <<= ch->control.frequency;
448 timing *= 32;
449 return timing;
450}
451
452static void _sample(struct GBAAudio* audio) {
453 int32_t sampleLeft = 0;
454 int32_t sampleRight = 0;
455 int psgShift = 1 + audio->volume;
456
457 if (audio->ch1Left) {
458 sampleLeft += audio->ch1.sample;
459 }
460
461 if (audio->ch1Right) {
462 sampleRight += audio->ch1.sample;
463 }
464
465 if (audio->ch2Left) {
466 sampleLeft += audio->ch2.sample;
467 }
468
469 if (audio->ch2Right) {
470 sampleRight += audio->ch2.sample;
471 }
472
473 if (audio->ch3Left) {
474 sampleLeft += audio->ch3.sample;
475 }
476
477 if (audio->ch3Right) {
478 sampleRight += audio->ch3.sample;
479 }
480
481 if (audio->ch4Left) {
482 sampleLeft += audio->ch4.sample;
483 }
484
485 if (audio->ch4Right) {
486 sampleRight += audio->ch4.sample;
487 }
488
489 sampleLeft = (sampleLeft * (1 + audio->volumeLeft)) >> psgShift;
490 sampleRight = (sampleRight * (1 + audio->volumeRight)) >> psgShift;
491
492 if (audio->chALeft) {
493 sampleLeft += (audio->chA.sample << 2) >> !audio->volumeChA;
494 }
495
496 if (audio->chARight) {
497 sampleRight += (audio->chA.sample << 2) >> !audio->volumeChA;
498 }
499
500 if (audio->chBLeft) {
501 sampleLeft += (audio->chB.sample << 2) >> !audio->volumeChB;
502 }
503
504 if (audio->chBRight) {
505 sampleRight += (audio->chB.sample << 2) >> !audio->volumeChB;
506 }
507
508 pthread_mutex_lock(&audio->bufferMutex);
509 while (CircleBufferSize(&audio->left) + (GBA_AUDIO_SAMPLES * 2 / 5) >= audio->left.capacity) {
510 if (!audio->p->sync->audioWait) {
511 break;
512 }
513 GBASyncProduceAudio(audio->p->sync, &audio->bufferMutex);
514 }
515 CircleBufferWrite32(&audio->left, sampleLeft);
516 CircleBufferWrite32(&audio->right, sampleRight);
517 pthread_mutex_unlock(&audio->bufferMutex);
518}