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 int GBA_AUDIO_VOLUME_MAX = 0x100;
27
28static const int CLOCKS_PER_FRAME = 0x800;
29
30static int _applyBias(struct GBAAudio* audio, int sample);
31static void _sample(struct mTiming* timing, void* user, uint32_t cyclesLate);
32
33void GBAAudioInit(struct GBAAudio* audio, size_t samples) {
34 audio->sampleEvent.context = audio;
35 audio->sampleEvent.name = "GBA Audio Sample";
36 audio->sampleEvent.callback = _sample;
37 audio->sampleEvent.priority = 0x18;
38 audio->psg.p = NULL;
39 uint8_t* nr52 = (uint8_t*) &audio->p->memory.io[REG_SOUNDCNT_X >> 1];
40#ifdef __BIG_ENDIAN__
41 ++nr52;
42#endif
43 GBAudioInit(&audio->psg, 0, nr52, GB_AUDIO_GBA);
44 audio->psg.timing = &audio->p->timing;
45 audio->psg.clockRate = GBA_ARM7TDMI_FREQUENCY;
46 audio->samples = samples;
47 // Guess too large; we hang producing extra samples if we guess too low
48 blip_set_rates(audio->psg.left, GBA_ARM7TDMI_FREQUENCY, 96000);
49 blip_set_rates(audio->psg.right, GBA_ARM7TDMI_FREQUENCY, 96000);
50
51 audio->externalMixing = false;
52 audio->forceDisableChA = false;
53 audio->forceDisableChB = false;
54 audio->masterVolume = GBA_AUDIO_VOLUME_MAX;
55 audio->mixer = NULL;
56}
57
58void GBAAudioReset(struct GBAAudio* audio) {
59 GBAudioReset(&audio->psg);
60 mTimingDeschedule(&audio->p->timing, &audio->sampleEvent);
61 mTimingSchedule(&audio->p->timing, &audio->sampleEvent, 0);
62 audio->chA.dmaSource = 1;
63 audio->chB.dmaSource = 2;
64 audio->chA.fifoWrite = 0;
65 audio->chA.fifoRead = 0;
66 audio->chA.internalSample = 0;
67 audio->chA.internalRemaining = 0;
68 memset(audio->chA.fifo, 0, sizeof(audio->chA.fifo));
69 audio->chA.sample = 0;
70 audio->chB.fifoWrite = 0;
71 audio->chB.fifoRead = 0;
72 audio->chB.internalSample = 0;
73 audio->chB.internalRemaining = 0;
74 memset(audio->chB.fifo, 0, sizeof(audio->chB.fifo));
75 audio->chB.sample = 0;
76 audio->sampleRate = 0x8000;
77 audio->soundbias = 0x200;
78 audio->volume = 0;
79 audio->volumeChA = false;
80 audio->volumeChB = false;
81 audio->chARight = false;
82 audio->chALeft = false;
83 audio->chATimer = false;
84 audio->chBRight = false;
85 audio->chBLeft = false;
86 audio->chBTimer = false;
87 audio->enable = false;
88 audio->sampleInterval = GBA_ARM7TDMI_FREQUENCY / audio->sampleRate;
89 audio->psg.sampleInterval = audio->sampleInterval;
90
91 blip_clear(audio->psg.left);
92 blip_clear(audio->psg.right);
93 audio->clock = 0;
94}
95
96void GBAAudioDeinit(struct GBAAudio* audio) {
97 GBAudioDeinit(&audio->psg);
98}
99
100void GBAAudioResizeBuffer(struct GBAAudio* audio, size_t samples) {
101 mCoreSyncLockAudio(audio->p->sync);
102 audio->samples = samples;
103 blip_clear(audio->psg.left);
104 blip_clear(audio->psg.right);
105 audio->clock = 0;
106 mCoreSyncConsumeAudio(audio->p->sync);
107}
108
109void GBAAudioScheduleFifoDma(struct GBAAudio* audio, int number, struct GBADMA* info) {
110 info->reg = GBADMARegisterSetDestControl(info->reg, GBA_DMA_FIXED);
111 info->reg = GBADMARegisterSetWidth(info->reg, 1);
112 switch (info->dest) {
113 case BASE_IO | REG_FIFO_A_LO:
114 audio->chA.dmaSource = number;
115 break;
116 case BASE_IO | REG_FIFO_B_LO:
117 audio->chB.dmaSource = number;
118 break;
119 default:
120 mLOG(GBA_AUDIO, GAME_ERROR, "Invalid FIFO destination: 0x%08X", info->dest);
121 return;
122 }
123 uint32_t source = info->source;
124 uint32_t magic[2] = {
125 audio->p->cpu->memory.load32(audio->p->cpu, source - 0x350, NULL),
126 audio->p->cpu->memory.load32(audio->p->cpu, source - 0x980, NULL)
127 };
128 if (audio->mixer) {
129 if (magic[0] - MP2K_MAGIC <= MP2K_LOCK_MAX) {
130 audio->mixer->engage(audio->mixer, source - 0x350);
131 } else if (magic[1] - MP2K_MAGIC <= MP2K_LOCK_MAX) {
132 audio->mixer->engage(audio->mixer, source - 0x980);
133 } else {
134 audio->externalMixing = false;
135 }
136 }
137}
138
139void GBAAudioWriteSOUND1CNT_LO(struct GBAAudio* audio, uint16_t value) {
140 GBAudioWriteNR10(&audio->psg, value);
141}
142
143void GBAAudioWriteSOUND1CNT_HI(struct GBAAudio* audio, uint16_t value) {
144 GBAudioWriteNR11(&audio->psg, value);
145 GBAudioWriteNR12(&audio->psg, value >> 8);
146}
147
148void GBAAudioWriteSOUND1CNT_X(struct GBAAudio* audio, uint16_t value) {
149 GBAudioWriteNR13(&audio->psg, value);
150 GBAudioWriteNR14(&audio->psg, value >> 8);
151}
152
153void GBAAudioWriteSOUND2CNT_LO(struct GBAAudio* audio, uint16_t value) {
154 GBAudioWriteNR21(&audio->psg, value);
155 GBAudioWriteNR22(&audio->psg, value >> 8);
156}
157
158void GBAAudioWriteSOUND2CNT_HI(struct GBAAudio* audio, uint16_t value) {
159 GBAudioWriteNR23(&audio->psg, value);
160 GBAudioWriteNR24(&audio->psg, value >> 8);
161}
162
163void GBAAudioWriteSOUND3CNT_LO(struct GBAAudio* audio, uint16_t value) {
164 audio->psg.ch3.size = GBAudioRegisterBankGetSize(value);
165 audio->psg.ch3.bank = GBAudioRegisterBankGetBank(value);
166 GBAudioWriteNR30(&audio->psg, value);
167}
168
169void GBAAudioWriteSOUND3CNT_HI(struct GBAAudio* audio, uint16_t value) {
170 GBAudioWriteNR31(&audio->psg, value);
171 audio->psg.ch3.volume = GBAudioRegisterBankVolumeGetVolumeGBA(value >> 8);
172}
173
174void GBAAudioWriteSOUND3CNT_X(struct GBAAudio* audio, uint16_t value) {
175 GBAudioWriteNR33(&audio->psg, value);
176 GBAudioWriteNR34(&audio->psg, value >> 8);
177}
178
179void GBAAudioWriteSOUND4CNT_LO(struct GBAAudio* audio, uint16_t value) {
180 GBAudioWriteNR41(&audio->psg, value);
181 GBAudioWriteNR42(&audio->psg, value >> 8);
182}
183
184void GBAAudioWriteSOUND4CNT_HI(struct GBAAudio* audio, uint16_t value) {
185 GBAudioWriteNR43(&audio->psg, value);
186 GBAudioWriteNR44(&audio->psg, value >> 8);
187}
188
189void GBAAudioWriteSOUNDCNT_LO(struct GBAAudio* audio, uint16_t value) {
190 GBAudioWriteNR50(&audio->psg, value);
191 GBAudioWriteNR51(&audio->psg, value >> 8);
192}
193
194void GBAAudioWriteSOUNDCNT_HI(struct GBAAudio* audio, uint16_t value) {
195 audio->volume = GBARegisterSOUNDCNT_HIGetVolume(value);
196 audio->volumeChA = GBARegisterSOUNDCNT_HIGetVolumeChA(value);
197 audio->volumeChB = GBARegisterSOUNDCNT_HIGetVolumeChB(value);
198 audio->chARight = GBARegisterSOUNDCNT_HIGetChARight(value);
199 audio->chALeft = GBARegisterSOUNDCNT_HIGetChALeft(value);
200 audio->chATimer = GBARegisterSOUNDCNT_HIGetChATimer(value);
201 audio->chBRight = GBARegisterSOUNDCNT_HIGetChBRight(value);
202 audio->chBLeft = GBARegisterSOUNDCNT_HIGetChBLeft(value);
203 audio->chBTimer = GBARegisterSOUNDCNT_HIGetChBTimer(value);
204 if (GBARegisterSOUNDCNT_HIIsChAReset(value)) {
205 audio->chA.fifoWrite = 0;
206 audio->chA.fifoRead = 0;
207 }
208 if (GBARegisterSOUNDCNT_HIIsChBReset(value)) {
209 audio->chB.fifoWrite = 0;
210 audio->chB.fifoRead = 0;
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 int bank = !audio->psg.ch3.bank;
225
226 // When the audio hardware is turned off, it acts like bank 0 has been
227 // selected in SOUND3CNT_L, so any read comes from bank 1.
228 if (!audio->enable) {
229 bank = 1;
230 }
231
232 audio->psg.ch3.wavedata32[address | (bank * 4)] = value;
233}
234
235uint32_t GBAAudioReadWaveRAM(struct GBAAudio* audio, int address) {
236 int bank = !audio->psg.ch3.bank;
237
238 // When the audio hardware is turned off, it acts like bank 0 has been
239 // selected in SOUND3CNT_L, so any read comes from bank 1.
240 if (!audio->enable) {
241 bank = 1;
242 }
243
244 return audio->psg.ch3.wavedata32[address | (bank * 4)];
245}
246
247uint32_t GBAAudioWriteFIFO(struct GBAAudio* audio, int address, uint32_t value) {
248 struct GBAAudioFIFO* channel;
249 switch (address) {
250 case REG_FIFO_A_LO:
251 channel = &audio->chA;
252 break;
253 case REG_FIFO_B_LO:
254 channel = &audio->chB;
255 break;
256 default:
257 mLOG(GBA_AUDIO, ERROR, "Bad FIFO write to address 0x%03x", address);
258 return value;
259 }
260 channel->fifo[channel->fifoWrite] = value;
261 ++channel->fifoWrite;
262 if (channel->fifoWrite == GBA_AUDIO_FIFO_SIZE) {
263 channel->fifoWrite = 0;
264 }
265 return channel->fifo[channel->fifoWrite];
266}
267
268void GBAAudioSampleFIFO(struct GBAAudio* audio, int fifoId, int32_t cycles) {
269 struct GBAAudioFIFO* channel;
270 if (fifoId == 0) {
271 channel = &audio->chA;
272 } else if (fifoId == 1) {
273 channel = &audio->chB;
274 } else {
275 mLOG(GBA_AUDIO, ERROR, "Bad FIFO write to address 0x%03x", fifoId);
276 return;
277 }
278 int fifoSize;
279 if (channel->fifoWrite >= channel->fifoRead) {
280 fifoSize = channel->fifoWrite - channel->fifoRead;
281 } else {
282 fifoSize = GBA_AUDIO_FIFO_SIZE - channel->fifoRead + channel->fifoWrite;
283 }
284 if (GBA_AUDIO_FIFO_SIZE - fifoSize > 4 && channel->dmaSource > 0) {
285 struct GBADMA* dma = &audio->p->memory.dma[channel->dmaSource];
286 if (GBADMARegisterGetTiming(dma->reg) == GBA_DMA_TIMING_CUSTOM) {
287 dma->when = mTimingCurrentTime(&audio->p->timing) - cycles;
288 dma->nextCount = 4;
289 GBADMASchedule(audio->p, channel->dmaSource, dma);
290 }
291 }
292 if (!channel->internalRemaining && fifoSize) {
293 channel->internalSample = channel->fifo[channel->fifoRead];
294 channel->internalRemaining = 4;
295 ++channel->fifoRead;
296 if (channel->fifoRead == GBA_AUDIO_FIFO_SIZE) {
297 channel->fifoRead = 0;
298 }
299 }
300 channel->sample = channel->internalSample;
301 if (channel->internalRemaining) {
302 channel->internalSample >>= 8;
303 --channel->internalRemaining;
304 }
305}
306
307static int _applyBias(struct GBAAudio* audio, int sample) {
308 sample += GBARegisterSOUNDBIASGetBias(audio->soundbias);
309 if (sample >= 0x400) {
310 sample = 0x3FF;
311 } else if (sample < 0) {
312 sample = 0;
313 }
314 return ((sample - GBARegisterSOUNDBIASGetBias(audio->soundbias)) * audio->masterVolume * 3) >> 4;
315}
316
317static void _sample(struct mTiming* timing, void* user, uint32_t cyclesLate) {
318 struct GBAAudio* audio = user;
319 int16_t sampleLeft = 0;
320 int16_t sampleRight = 0;
321 int psgShift = 4 - audio->volume;
322 GBAudioSamplePSG(&audio->psg, &sampleLeft, &sampleRight);
323 sampleLeft >>= psgShift;
324 sampleRight >>= psgShift;
325
326 if (audio->mixer) {
327 audio->mixer->step(audio->mixer);
328 }
329 if (!audio->externalMixing) {
330 if (!audio->forceDisableChA) {
331 if (audio->chALeft) {
332 sampleLeft += (audio->chA.sample << 2) >> !audio->volumeChA;
333 }
334
335 if (audio->chARight) {
336 sampleRight += (audio->chA.sample << 2) >> !audio->volumeChA;
337 }
338 }
339
340 if (!audio->forceDisableChB) {
341 if (audio->chBLeft) {
342 sampleLeft += (audio->chB.sample << 2) >> !audio->volumeChB;
343 }
344
345 if (audio->chBRight) {
346 sampleRight += (audio->chB.sample << 2) >> !audio->volumeChB;
347 }
348 }
349 }
350
351 sampleLeft = _applyBias(audio, sampleLeft);
352 sampleRight = _applyBias(audio, sampleRight);
353
354 mCoreSyncLockAudio(audio->p->sync);
355 unsigned produced;
356 if ((size_t) blip_samples_avail(audio->psg.left) < audio->samples) {
357 blip_add_delta(audio->psg.left, audio->clock, sampleLeft - audio->lastLeft);
358 blip_add_delta(audio->psg.right, audio->clock, sampleRight - audio->lastRight);
359 audio->lastLeft = sampleLeft;
360 audio->lastRight = sampleRight;
361 audio->clock += audio->sampleInterval;
362 if (audio->clock >= CLOCKS_PER_FRAME) {
363 blip_end_frame(audio->psg.left, CLOCKS_PER_FRAME);
364 blip_end_frame(audio->psg.right, CLOCKS_PER_FRAME);
365 audio->clock -= CLOCKS_PER_FRAME;
366 }
367 }
368 produced = blip_samples_avail(audio->psg.left);
369 if (audio->p->stream && audio->p->stream->postAudioFrame) {
370 audio->p->stream->postAudioFrame(audio->p->stream, sampleLeft, sampleRight);
371 }
372 bool wait = produced >= audio->samples;
373 if (!mCoreSyncProduceAudio(audio->p->sync, audio->psg.left, audio->samples)) {
374 // Interrupted
375 audio->p->earlyExit = true;
376 }
377
378 if (wait && audio->p->stream && audio->p->stream->postAudioBuffer) {
379 audio->p->stream->postAudioBuffer(audio->p->stream, audio->psg.left, audio->psg.right);
380 }
381
382 mTimingSchedule(timing, &audio->sampleEvent, audio->sampleInterval - cyclesLate);
383}
384
385void GBAAudioSerialize(const struct GBAAudio* audio, struct GBASerializedState* state) {
386 GBAudioPSGSerialize(&audio->psg, &state->audio.psg, &state->audio.flags);
387
388 STORE_32(audio->chA.internalSample, 0, &state->audio.internalA);
389 STORE_32(audio->chB.internalSample, 0, &state->audio.internalB);
390 state->audio.sampleA = audio->chA.sample;
391 state->audio.sampleB = audio->chB.sample;
392
393 int readA = audio->chA.fifoRead;
394 int readB = audio->chB.fifoRead;
395 size_t i;
396 for (i = 0; i < GBA_AUDIO_FIFO_SIZE; ++i) {
397 STORE_32(audio->chA.fifo[readA], i << 2, state->audio.fifoA);
398 STORE_32(audio->chB.fifo[readB], i << 2, state->audio.fifoB);
399 ++readA;
400 if (readA == GBA_AUDIO_FIFO_SIZE) {
401 readA = 0;
402 }
403 ++readB;
404 if (readB == GBA_AUDIO_FIFO_SIZE) {
405 readB = 0;
406 }
407 }
408
409 int fifoSizeA;
410 if (audio->chA.fifoWrite >= audio->chA.fifoRead) {
411 fifoSizeA = audio->chA.fifoWrite - audio->chA.fifoRead;
412 } else {
413 fifoSizeA = GBA_AUDIO_FIFO_SIZE - audio->chA.fifoRead + audio->chA.fifoWrite;
414 }
415
416 int fifoSizeB;
417 if (audio->chB.fifoWrite >= audio->chB.fifoRead) {
418 fifoSizeB = audio->chB.fifoWrite - audio->chB.fifoRead;
419 } else {
420 fifoSizeB = GBA_AUDIO_FIFO_SIZE - audio->chB.fifoRead + audio->chB.fifoWrite;
421 }
422
423 GBASerializedAudioFlags flags = 0;
424 flags = GBASerializedAudioFlagsSetFIFOSamplesA(flags, fifoSizeA);
425 flags = GBASerializedAudioFlagsSetFIFOSamplesB(flags, fifoSizeB);
426 flags = GBASerializedAudioFlagsSetFIFOInternalSamplesA(flags, audio->chA.internalRemaining);
427 flags = GBASerializedAudioFlagsSetFIFOInternalSamplesB(flags, audio->chB.internalRemaining);
428 STORE_16(flags, 0, &state->audio.gbaFlags);
429 STORE_32(audio->sampleEvent.when - mTimingCurrentTime(&audio->p->timing), 0, &state->audio.nextSample);
430}
431
432void GBAAudioDeserialize(struct GBAAudio* audio, const struct GBASerializedState* state) {
433 GBAudioPSGDeserialize(&audio->psg, &state->audio.psg, &state->audio.flags);
434
435 LOAD_32(audio->chA.internalSample, 0, &state->audio.internalA);
436 LOAD_32(audio->chB.internalSample, 0, &state->audio.internalB);
437 audio->chA.sample = state->audio.sampleA;
438 audio->chB.sample = state->audio.sampleB;
439
440 int readA = 0;
441 int readB = 0;
442 size_t i;
443 for (i = 0; i < GBA_AUDIO_FIFO_SIZE; ++i) {
444 LOAD_32(audio->chA.fifo[readA], i << 2, state->audio.fifoA);
445 LOAD_32(audio->chB.fifo[readB], i << 2, state->audio.fifoB);
446 ++readA;
447 ++readB;
448 }
449 audio->chA.fifoRead = 0;
450 audio->chB.fifoRead = 0;
451
452 GBASerializedAudioFlags flags;
453 LOAD_16(flags, 0, &state->audio.gbaFlags);
454 audio->chA.fifoWrite = GBASerializedAudioFlagsGetFIFOSamplesA(flags);
455 audio->chB.fifoWrite = GBASerializedAudioFlagsGetFIFOSamplesB(flags);
456 audio->chA.internalRemaining = GBASerializedAudioFlagsGetFIFOInternalSamplesA(flags);
457 audio->chB.internalRemaining = GBASerializedAudioFlagsGetFIFOInternalSamplesB(flags);
458
459 uint32_t when;
460 LOAD_32(when, 0, &state->audio.nextSample);
461 mTimingSchedule(&audio->p->timing, &audio->sampleEvent, when);
462}
463
464float GBAAudioCalculateRatio(float inputSampleRate, float desiredFPS, float desiredSampleRate) {
465 return desiredSampleRate * GBA_ARM7TDMI_FREQUENCY / (VIDEO_TOTAL_LENGTH * desiredFPS * inputSampleRate);
466}