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