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