src/gba/audio.c (view raw)
1/* Copyright (c) 2013-2016 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#include "audio.h"
7
8#include "core/sync.h"
9#include "gba/gba.h"
10#include "gba/io.h"
11#include "gba/serialize.h"
12#include "gba/video.h"
13
14#ifdef _3DS
15#define blip_add_delta blip_add_delta_fast
16#endif
17
18mLOG_DEFINE_CATEGORY(GBA_AUDIO, "GBA Audio");
19
20const unsigned GBA_AUDIO_SAMPLES = 2048;
21const unsigned GBA_AUDIO_FIFO_SIZE = 8 * sizeof(int32_t);
22const int GBA_AUDIO_VOLUME_MAX = 0x100;
23
24static const int CLOCKS_PER_FRAME = 0x400;
25
26static int _applyBias(struct GBAAudio* audio, int sample);
27static void _sample(struct GBAAudio* audio);
28
29void GBAAudioInit(struct GBAAudio* audio, size_t samples) {
30 audio->psg.p = NULL;
31 uint8_t* nr52 = (uint8_t*) &audio->p->memory.io[REG_SOUNDCNT_X >> 1];
32#ifdef __BIG_ENDIAN__
33 ++nr52;
34#endif
35 GBAudioInit(&audio->psg, 0, nr52, GB_AUDIO_GBA);
36 audio->samples = samples;
37 audio->psg.clockRate = GBA_ARM7TDMI_FREQUENCY;
38 // Guess too large; we hang producing extra samples if we guess too low
39 blip_set_rates(audio->psg.left, GBA_ARM7TDMI_FREQUENCY, 96000);
40 blip_set_rates(audio->psg.right, GBA_ARM7TDMI_FREQUENCY, 96000);
41 CircleBufferInit(&audio->chA.fifo, GBA_AUDIO_FIFO_SIZE);
42 CircleBufferInit(&audio->chB.fifo, GBA_AUDIO_FIFO_SIZE);
43
44 audio->forceDisableChA = false;
45 audio->forceDisableChB = false;
46 audio->masterVolume = GBA_AUDIO_VOLUME_MAX;
47}
48
49void GBAAudioReset(struct GBAAudio* audio) {
50 GBAudioReset(&audio->psg);
51 audio->nextEvent = 0;
52 audio->chA.dmaSource = 1;
53 audio->chB.dmaSource = 2;
54 audio->chA.sample = 0;
55 audio->chB.sample = 0;
56 audio->eventDiff = 0;
57 audio->nextSample = 0;
58 audio->sampleRate = 0x8000;
59 audio->soundbias = 0x200;
60 audio->volume = 0;
61 audio->volumeChA = false;
62 audio->volumeChB = false;
63 audio->chARight = false;
64 audio->chALeft = false;
65 audio->chATimer = false;
66 audio->chBRight = false;
67 audio->chBLeft = false;
68 audio->chBTimer = false;
69 audio->enable = false;
70 audio->sampleInterval = GBA_ARM7TDMI_FREQUENCY / audio->sampleRate;
71
72 blip_clear(audio->psg.left);
73 blip_clear(audio->psg.right);
74 audio->clock = 0;
75 CircleBufferClear(&audio->chA.fifo);
76 CircleBufferClear(&audio->chB.fifo);
77}
78
79void GBAAudioDeinit(struct GBAAudio* audio) {
80 GBAudioDeinit(&audio->psg);
81 CircleBufferDeinit(&audio->chA.fifo);
82 CircleBufferDeinit(&audio->chB.fifo);
83}
84
85void GBAAudioResizeBuffer(struct GBAAudio* audio, size_t samples) {
86 mCoreSyncLockAudio(audio->p->sync);
87 audio->samples = samples;
88 blip_clear(audio->psg.left);
89 blip_clear(audio->psg.right);
90 audio->clock = 0;
91 mCoreSyncConsumeAudio(audio->p->sync);
92}
93
94int32_t GBAAudioProcessEvents(struct GBAAudio* audio, int32_t cycles) {
95 audio->nextEvent -= cycles;
96 audio->eventDiff += cycles;
97 while (audio->nextEvent <= 0) {
98 audio->nextEvent = INT_MAX;
99 if (audio->enable) {
100 audio->nextEvent = GBAudioProcessEvents(&audio->psg, audio->eventDiff / 4);
101 if (audio->nextEvent != INT_MAX) {
102 audio->nextEvent *= 4;
103 }
104 }
105
106 audio->nextSample -= audio->eventDiff;
107 if (audio->nextSample <= 0) {
108 _sample(audio);
109 audio->nextSample += audio->sampleInterval;
110 }
111
112 if (audio->nextSample < audio->nextEvent) {
113 audio->nextEvent = audio->nextSample;
114 }
115 audio->eventDiff = 0;
116 }
117 return audio->nextEvent;
118}
119
120void GBAAudioScheduleFifoDma(struct GBAAudio* audio, int number, struct GBADMA* info) {
121 switch (info->dest) {
122 case BASE_IO | REG_FIFO_A_LO:
123 audio->chA.dmaSource = number;
124 break;
125 case BASE_IO | REG_FIFO_B_LO:
126 audio->chB.dmaSource = number;
127 break;
128 default:
129 if (audio->chA.dmaSource == number) {
130 audio->chA.dmaSource = -1;
131 }
132 if (audio->chB.dmaSource == number) {
133 audio->chB.dmaSource = -1;
134 }
135 mLOG(GBA_AUDIO, GAME_ERROR, "Invalid FIFO destination: 0x%08X", info->dest);
136 return;
137 }
138 info->reg = GBADMARegisterSetDestControl(info->reg, DMA_FIXED);
139}
140
141void GBAAudioWriteSOUND1CNT_LO(struct GBAAudio* audio, uint16_t value) {
142 GBAudioWriteNR10(&audio->psg, value);
143}
144
145void GBAAudioWriteSOUND1CNT_HI(struct GBAAudio* audio, uint16_t value) {
146 GBAudioWriteNR11(&audio->psg, value);
147 GBAudioWriteNR12(&audio->psg, value >> 8);
148}
149
150void GBAAudioWriteSOUND1CNT_X(struct GBAAudio* audio, uint16_t value) {
151 GBAudioWriteNR13(&audio->psg, value);
152 GBAudioWriteNR14(&audio->psg, value >> 8);
153}
154
155void GBAAudioWriteSOUND2CNT_LO(struct GBAAudio* audio, uint16_t value) {
156 GBAudioWriteNR21(&audio->psg, value);
157 GBAudioWriteNR22(&audio->psg, value >> 8);
158}
159
160void GBAAudioWriteSOUND2CNT_HI(struct GBAAudio* audio, uint16_t value) {
161 GBAudioWriteNR23(&audio->psg, value);
162 GBAudioWriteNR24(&audio->psg, value >> 8);
163}
164
165void GBAAudioWriteSOUND3CNT_LO(struct GBAAudio* audio, uint16_t value) {
166 audio->psg.ch3.size = GBAudioRegisterBankGetSize(value);
167 audio->psg.ch3.bank = GBAudioRegisterBankGetBank(value);
168 GBAudioWriteNR30(&audio->psg, value);
169}
170
171void GBAAudioWriteSOUND3CNT_HI(struct GBAAudio* audio, uint16_t value) {
172 GBAudioWriteNR31(&audio->psg, value);
173 audio->psg.ch3.volume = GBAudioRegisterBankVolumeGetVolumeGBA(value >> 8);
174}
175
176void GBAAudioWriteSOUND3CNT_X(struct GBAAudio* audio, uint16_t value) {
177 GBAudioWriteNR33(&audio->psg, value);
178 GBAudioWriteNR34(&audio->psg, value >> 8);
179}
180
181void GBAAudioWriteSOUND4CNT_LO(struct GBAAudio* audio, uint16_t value) {
182 GBAudioWriteNR41(&audio->psg, value);
183 GBAudioWriteNR42(&audio->psg, value >> 8);
184}
185
186void GBAAudioWriteSOUND4CNT_HI(struct GBAAudio* audio, uint16_t value) {
187 GBAudioWriteNR43(&audio->psg, value);
188 GBAudioWriteNR44(&audio->psg, value >> 8);
189}
190
191void GBAAudioWriteSOUNDCNT_LO(struct GBAAudio* audio, uint16_t value) {
192 GBAudioWriteNR50(&audio->psg, value);
193 GBAudioWriteNR51(&audio->psg, value >> 8);
194}
195
196void GBAAudioWriteSOUNDCNT_HI(struct GBAAudio* audio, uint16_t value) {
197 audio->volume = GBARegisterSOUNDCNT_HIGetVolume(value);
198 audio->volumeChA = GBARegisterSOUNDCNT_HIGetVolumeChA(value);
199 audio->volumeChB = GBARegisterSOUNDCNT_HIGetVolumeChB(value);
200 audio->chARight = GBARegisterSOUNDCNT_HIGetChARight(value);
201 audio->chALeft = GBARegisterSOUNDCNT_HIGetChALeft(value);
202 audio->chATimer = GBARegisterSOUNDCNT_HIGetChATimer(value);
203 audio->chBRight = GBARegisterSOUNDCNT_HIGetChBRight(value);
204 audio->chBLeft = GBARegisterSOUNDCNT_HIGetChBLeft(value);
205 audio->chBTimer = GBARegisterSOUNDCNT_HIGetChBTimer(value);
206 if (GBARegisterSOUNDCNT_HIIsChAReset(value)) {
207 CircleBufferClear(&audio->chA.fifo);
208 }
209 if (GBARegisterSOUNDCNT_HIIsChBReset(value)) {
210 CircleBufferClear(&audio->chB.fifo);
211 }
212}
213
214void GBAAudioWriteSOUNDCNT_X(struct GBAAudio* audio, uint16_t value) {
215 audio->enable = GBAudioEnableGetEnable(value);
216 GBAudioWriteNR52(&audio->psg, value);
217}
218
219void GBAAudioWriteSOUNDBIAS(struct GBAAudio* audio, uint16_t value) {
220 audio->soundbias = value;
221}
222
223void GBAAudioWriteWaveRAM(struct GBAAudio* audio, int address, uint32_t value) {
224 audio->psg.ch3.wavedata32[address | (!audio->psg.ch3.bank * 4)] = value;
225}
226
227void GBAAudioWriteFIFO(struct GBAAudio* audio, int address, uint32_t value) {
228 struct CircleBuffer* fifo;
229 switch (address) {
230 case REG_FIFO_A_LO:
231 fifo = &audio->chA.fifo;
232 break;
233 case REG_FIFO_B_LO:
234 fifo = &audio->chB.fifo;
235 break;
236 default:
237 mLOG(GBA_AUDIO, ERROR, "Bad FIFO write to address 0x%03x", address);
238 return;
239 }
240 int i;
241 for (i = 0; i < 4; ++i) {
242 while (!CircleBufferWrite8(fifo, value >> (8 * i))) {
243 int8_t dummy;
244 CircleBufferRead8(fifo, &dummy);
245 }
246 }
247}
248
249void GBAAudioSampleFIFO(struct GBAAudio* audio, int fifoId, int32_t cycles) {
250 struct GBAAudioFIFO* channel;
251 if (fifoId == 0) {
252 channel = &audio->chA;
253 } else if (fifoId == 1) {
254 channel = &audio->chB;
255 } else {
256 mLOG(GBA_AUDIO, ERROR, "Bad FIFO write to address 0x%03x", fifoId);
257 return;
258 }
259 if (CircleBufferSize(&channel->fifo) <= 4 * sizeof(int32_t) && channel->dmaSource > 0) {
260 struct GBADMA* dma = &audio->p->memory.dma[channel->dmaSource];
261 if (GBADMARegisterGetTiming(dma->reg) == DMA_TIMING_CUSTOM) {
262 dma->nextCount = 4;
263 dma->nextEvent = 0;
264 dma->reg = GBADMARegisterSetWidth(dma->reg, 1);
265 GBAMemoryUpdateDMAs(audio->p, -cycles);
266 } else {
267 channel->dmaSource = 0;
268 }
269 }
270 CircleBufferRead8(&channel->fifo, (int8_t*) &channel->sample);
271}
272
273static int _applyBias(struct GBAAudio* audio, int sample) {
274 sample += GBARegisterSOUNDBIASGetBias(audio->soundbias);
275 if (sample >= 0x400) {
276 sample = 0x3FF;
277 } else if (sample < 0) {
278 sample = 0;
279 }
280 return ((sample - GBARegisterSOUNDBIASGetBias(audio->soundbias)) * audio->masterVolume) >> 3;
281}
282
283static void _sample(struct GBAAudio* audio) {
284 int16_t sampleLeft = 0;
285 int16_t sampleRight = 0;
286 int psgShift = 5 - audio->volume;
287 GBAudioSamplePSG(&audio->psg, &sampleLeft, &sampleRight);
288 sampleLeft >>= psgShift;
289 sampleRight >>= psgShift;
290
291 if (!audio->forceDisableChA) {
292 if (audio->chALeft) {
293 sampleLeft += (audio->chA.sample << 2) >> !audio->volumeChA;
294 }
295
296 if (audio->chARight) {
297 sampleRight += (audio->chA.sample << 2) >> !audio->volumeChA;
298 }
299 }
300
301 if (!audio->forceDisableChB) {
302 if (audio->chBLeft) {
303 sampleLeft += (audio->chB.sample << 2) >> !audio->volumeChB;
304 }
305
306 if (audio->chBRight) {
307 sampleRight += (audio->chB.sample << 2) >> !audio->volumeChB;
308 }
309 }
310
311 sampleLeft = _applyBias(audio, sampleLeft);
312 sampleRight = _applyBias(audio, sampleRight);
313
314 mCoreSyncLockAudio(audio->p->sync);
315 unsigned produced;
316 if ((size_t) blip_samples_avail(audio->psg.left) < audio->samples) {
317 blip_add_delta(audio->psg.left, audio->clock, sampleLeft - audio->lastLeft);
318 blip_add_delta(audio->psg.right, audio->clock, sampleRight - audio->lastRight);
319 audio->lastLeft = sampleLeft;
320 audio->lastRight = sampleRight;
321 audio->clock += audio->sampleInterval;
322 if (audio->clock >= CLOCKS_PER_FRAME) {
323 blip_end_frame(audio->psg.left, audio->clock);
324 blip_end_frame(audio->psg.right, audio->clock);
325 audio->clock -= CLOCKS_PER_FRAME;
326 }
327 }
328 produced = blip_samples_avail(audio->psg.left);
329 if (audio->p->stream && audio->p->stream->postAudioFrame) {
330 audio->p->stream->postAudioFrame(audio->p->stream, sampleLeft, sampleRight);
331 }
332 bool wait = produced >= audio->samples;
333 mCoreSyncProduceAudio(audio->p->sync, wait);
334
335 if (wait && audio->p->stream && audio->p->stream->postAudioBuffer) {
336 audio->p->stream->postAudioBuffer(audio->p->stream, audio->psg.left, audio->psg.right);
337 }
338}
339
340void GBAAudioSerialize(const struct GBAAudio* audio, struct GBASerializedState* state) {
341 GBAudioPSGSerialize(&audio->psg, &state->audio.psg, &state->audio.flags);
342
343 CircleBufferDump(&audio->chA.fifo, state->audio.fifoA, sizeof(state->audio.fifoA));
344 CircleBufferDump(&audio->chB.fifo, state->audio.fifoB, sizeof(state->audio.fifoB));
345 uint32_t fifoSize = CircleBufferSize(&audio->chA.fifo);
346 STORE_32(fifoSize, 0, &state->audio.fifoSize);
347
348 STORE_32(audio->nextEvent, 0, &state->audio.nextEvent);
349 STORE_32(audio->eventDiff, 0, &state->audio.eventDiff);
350 STORE_32(audio->nextSample, 0, &state->audio.nextSample);
351}
352
353void GBAAudioDeserialize(struct GBAAudio* audio, const struct GBASerializedState* state) {
354 GBAudioPSGDeserialize(&audio->psg, &state->audio.psg, &state->audio.flags);
355
356 CircleBufferClear(&audio->chA.fifo);
357 CircleBufferClear(&audio->chB.fifo);
358 uint32_t fifoSize;
359 LOAD_32(fifoSize, 0, &state->audio.fifoSize);
360 if (state->audio.fifoSize > CircleBufferCapacity(&audio->chA.fifo)) {
361 fifoSize = CircleBufferCapacity(&audio->chA.fifo);
362 }
363 size_t i;
364 for (i = 0; i < fifoSize; ++i) {
365 CircleBufferWrite8(&audio->chA.fifo, state->audio.fifoA[i]);
366 CircleBufferWrite8(&audio->chB.fifo, state->audio.fifoB[i]);
367 }
368
369 LOAD_32(audio->nextEvent, 0, &state->audio.nextEvent);
370 LOAD_32(audio->eventDiff, 0, &state->audio.eventDiff);
371 LOAD_32(audio->nextSample, 0, &state->audio.nextSample);
372}
373
374float GBAAudioCalculateRatio(float inputSampleRate, float desiredFPS, float desiredSampleRate) {
375 return desiredSampleRate * GBA_ARM7TDMI_FREQUENCY / (VIDEO_TOTAL_LENGTH * desiredFPS * inputSampleRate);
376}