all repos — mgba @ 2db6d27496dcd66af0ab45a51a6bf94a4862b59d

mGBA Game Boy Advance Emulator

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