all repos — mgba @ eac9dfb325b1fcbef9b69c87aed70094ef381e3b

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
 12static int32_t _updateChannel1(struct GBAAudioChannel1* ch);
 13static int32_t _updateChannel2(struct GBAAudioChannel2* ch);
 14static int32_t _updateChannel3(struct GBAAudioChannel3* ch);
 15static int32_t _updateChannel4(struct GBAAudioChannel4* ch);
 16static void _sample(struct GBAAudio* audio);
 17
 18void GBAAudioInit(struct GBAAudio* audio) {
 19	audio->nextEvent = 0;
 20	audio->nextCh1 = 0;
 21	audio->nextCh2 = 0;
 22	audio->nextCh3 = 0;
 23	audio->nextCh4 = 0;
 24	audio->eventDiff = 0;
 25	audio->nextSample = 0;
 26	audio->sampleRate = 0x8000;
 27	audio->sampleInterval = GBA_ARM7TDMI_FREQUENCY / audio->sampleRate;
 28
 29	CircleBufferInit(&audio->left, GBA_AUDIO_SAMPLES * sizeof(int32_t));
 30	CircleBufferInit(&audio->right, GBA_AUDIO_SAMPLES * sizeof(int32_t));
 31	CircleBufferInit(&audio->chA.fifo, GBA_AUDIO_FIFO_SIZE);
 32	CircleBufferInit(&audio->chB.fifo, GBA_AUDIO_FIFO_SIZE);
 33
 34	pthread_mutex_init(&audio->bufferMutex, 0);
 35}
 36
 37void GBAAudioDeinit(struct GBAAudio* audio) {
 38	CircleBufferDeinit(&audio->left);
 39	CircleBufferDeinit(&audio->right);
 40	CircleBufferDeinit(&audio->chA.fifo);
 41	CircleBufferDeinit(&audio->chB.fifo);
 42
 43	pthread_mutex_destroy(&audio->bufferMutex);
 44}
 45
 46int32_t GBAAudioProcessEvents(struct GBAAudio* audio, int32_t cycles) {
 47	audio->nextEvent -= cycles;
 48	if (audio->nextEvent <= 0) {
 49		audio->nextCh1 -= audio->eventDiff;
 50		audio->nextCh2 -= audio->eventDiff;
 51		audio->nextCh3 -= audio->eventDiff;
 52		audio->nextCh4 -= audio->eventDiff;
 53
 54		if ((audio->ch1Right || audio->ch1Left) && audio->nextCh1 <= 0) {
 55			audio->nextCh1 += _updateChannel1(&audio->ch1);
 56		}
 57
 58		if ((audio->ch2Right || audio->ch2Left) && audio->nextCh2 <= 0) {
 59			audio->nextCh2 += _updateChannel2(&audio->ch2);
 60		}
 61
 62		if ((audio->ch3Right || audio->ch3Left) && audio->nextCh3 <= 0) {
 63			audio->nextCh3 += _updateChannel3(&audio->ch3);
 64		}
 65
 66		if ((audio->ch4Right || audio->ch4Left) && audio->nextCh4 <= 0) {
 67			audio->nextCh4 += _updateChannel4(&audio->ch4);
 68		}
 69
 70		audio->nextSample -= audio->eventDiff;
 71		if (audio->nextSample <= 0) {
 72			_sample(audio);
 73			audio->nextSample += audio->sampleInterval;
 74		}
 75
 76		audio->nextEvent = audio->nextSample;
 77		audio->eventDiff = audio->nextEvent;
 78	}
 79	return audio->nextEvent;
 80}
 81
 82void GBAAudioScheduleFifoDma(struct GBAAudio* audio, int number, struct GBADMA* info) {
 83	switch (info->dest) {
 84	case BASE_IO | REG_FIFO_A_LO:
 85		audio->chA.dmaSource = number;
 86		break;
 87	case BASE_IO | REG_FIFO_B_LO:
 88		audio->chB.dmaSource = number;
 89		break;
 90	default:
 91		GBALog(audio->p, GBA_LOG_GAME_ERROR, "Invalid FIFO destination: 0x%08X", info->dest);
 92		return;
 93	}
 94	info->dstControl = DMA_FIXED;
 95}
 96
 97void GBAAudioWriteSOUND1CNT_LO(struct GBAAudio* audio, uint16_t value) {
 98	audio->ch1.sweep.packed = value;
 99}
100
101void GBAAudioWriteSOUND1CNT_HI(struct GBAAudio* audio, uint16_t value) {
102	audio->ch1.wave.packed = value;
103}
104
105void GBAAudioWriteSOUND1CNT_X(struct GBAAudio* audio, uint16_t value) {
106	audio->ch1.control.packed = value;
107}
108
109void GBAAudioWriteSOUND2CNT_LO(struct GBAAudio* audio, uint16_t value) {
110	audio->ch2.wave.packed = value;
111}
112
113void GBAAudioWriteSOUND2CNT_HI(struct GBAAudio* audio, uint16_t value) {
114	audio->ch2.control.packed = value;
115}
116
117void GBAAudioWriteSOUND3CNT_LO(struct GBAAudio* audio, uint16_t value) {
118	audio->ch3.bank.packed = value;
119}
120
121void GBAAudioWriteSOUND3CNT_HI(struct GBAAudio* audio, uint16_t value) {
122	audio->ch3.wave.packed = value;
123}
124
125void GBAAudioWriteSOUND3CNT_X(struct GBAAudio* audio, uint16_t value) {
126	audio->ch3.control.packed = value;
127}
128
129void GBAAudioWriteSOUND4CNT_LO(struct GBAAudio* audio, uint16_t value) {
130	audio->ch4.wave.packed = value;
131}
132
133void GBAAudioWriteSOUND4CNT_HI(struct GBAAudio* audio, uint16_t value) {
134	audio->ch4.control.packed = value;
135}
136
137void GBAAudioWriteSOUNDCNT_LO(struct GBAAudio* audio, uint16_t value) {
138	audio->soundcntLo = value;
139}
140
141void GBAAudioWriteSOUNDCNT_HI(struct GBAAudio* audio, uint16_t value) {
142	audio->soundcntHi = value;
143}
144
145void GBAAudioWriteSOUNDCNT_X(struct GBAAudio* audio, uint16_t value) {
146	audio->soundcntX = (value & 0xF0) | (audio->soundcntX & 0x0F);
147}
148
149void GBAAudioWriteWaveRAM(struct GBAAudio* audio, int address, uint32_t value) {
150	GBALog(audio->p, GBA_LOG_STUB, "Audio unimplemented");
151}
152
153void GBAAudioWriteFIFO(struct GBAAudio* audio, int address, uint32_t value) {
154	struct CircleBuffer* fifo;
155	switch (address) {
156	case REG_FIFO_A_LO:
157		fifo = &audio->chA.fifo;
158		break;
159	case REG_FIFO_B_LO:
160		fifo = &audio->chB.fifo;
161		break;
162	default:
163		GBALog(audio->p, GBA_LOG_ERROR, "Bad FIFO write to address 0x%03x", address);
164		return;
165	}
166	while (!CircleBufferWrite32(fifo, value)) {
167		int32_t dummy;
168		CircleBufferRead32(fifo, &dummy);
169	}
170}
171
172void GBAAudioSampleFIFO(struct GBAAudio* audio, int fifoId) {
173	struct GBAAudioFIFO* channel;
174	if (fifoId == 0) {
175		channel = &audio->chA;
176	} else if (fifoId == 1) {
177		channel = &audio->chB;
178	} else {
179		GBALog(audio->p, GBA_LOG_ERROR, "Bad FIFO write to address 0x%03x", fifoId);
180		return;
181	}
182	if (CircleBufferSize(&channel->fifo) <= 4 * sizeof(int32_t)) {
183		struct GBADMA* dma = &audio->p->memory.dma[channel->dmaSource];
184		dma->nextCount = 4;
185		GBAMemoryServiceDMA(&audio->p->memory, channel->dmaSource, dma);
186	}
187	CircleBufferRead8(&channel->fifo, &channel->sample);
188}
189
190static int32_t _updateChannel1(struct GBAAudioChannel1* ch) {
191	return INT_MAX / 4;
192}
193
194static int32_t _updateChannel2(struct GBAAudioChannel2* ch) {
195	return INT_MAX / 4;
196}
197
198static int32_t _updateChannel3(struct GBAAudioChannel3* ch) {
199	return INT_MAX / 4;
200}
201
202static int32_t _updateChannel4(struct GBAAudioChannel4* ch) {
203	return INT_MAX / 4;
204}
205
206static void _sample(struct GBAAudio* audio) {
207	int32_t sampleLeft = 0;
208	int32_t sampleRight = 0;
209
210	if (audio->chALeft) {
211		sampleLeft += audio->chA.sample;
212	}
213
214	if (audio->chARight) {
215		sampleRight += audio->chA.sample;
216	}
217
218	if (audio->chBLeft) {
219		sampleLeft += audio->chB.sample;
220	}
221
222	if (audio->chBRight) {
223		sampleRight += audio->chB.sample;
224	}
225
226	pthread_mutex_lock(&audio->bufferMutex);
227	while (CircleBufferSize(&audio->left) + (GBA_AUDIO_SAMPLES * 2 / 5) >= audio->left.capacity) {
228		if (!audio->p->sync->audioWait) {
229			break;
230		}
231		GBASyncProduceAudio(audio->p->sync, &audio->bufferMutex);
232	}
233	CircleBufferWrite32(&audio->left, sampleLeft);
234	CircleBufferWrite32(&audio->right, sampleRight);
235	pthread_mutex_unlock(&audio->bufferMutex);
236}