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