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