src/gb/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/gb/audio.h>
7
8#include <mgba/core/blip_buf.h>
9#include <mgba/core/interface.h>
10#include <mgba/core/sync.h>
11#include <mgba/internal/gb/gb.h>
12#include <mgba/internal/gb/serialize.h>
13#include <mgba/internal/gb/io.h>
14
15#ifdef _3DS
16#define blip_add_delta blip_add_delta_fast
17#endif
18
19#define FRAME_CYCLES (DMG_LR35902_FREQUENCY >> 9)
20
21const uint32_t DMG_LR35902_FREQUENCY = 0x400000;
22static const int CLOCKS_PER_BLIP_FRAME = 0x1000;
23static const unsigned BLIP_BUFFER_SIZE = 0x4000;
24const int GB_AUDIO_VOLUME_MAX = 0x100;
25
26static bool _writeSweep(struct GBAudioSweep* sweep, uint8_t value);
27static void _writeDuty(struct GBAudioEnvelope* envelope, uint8_t value);
28static bool _writeEnvelope(struct GBAudioEnvelope* envelope, uint8_t value, enum GBAudioStyle style);
29
30static void _resetSweep(struct GBAudioSweep* sweep);
31static bool _resetEnvelope(struct GBAudioEnvelope* sweep);
32
33static void _updateEnvelope(struct GBAudioEnvelope* envelope);
34static void _updateEnvelopeDead(struct GBAudioEnvelope* envelope);
35static bool _updateSweep(struct GBAudioSquareChannel* sweep, bool initial);
36
37static void _updateSquareSample(struct GBAudioSquareChannel* ch);
38static int32_t _updateSquareChannel(struct GBAudioSquareChannel* ch);
39
40static int8_t _coalesceNoiseChannel(struct GBAudioNoiseChannel* ch);
41
42static void _updateFrame(struct mTiming* timing, void* user, uint32_t cyclesLate);
43static void _updateChannel1(struct mTiming* timing, void* user, uint32_t cyclesLate);
44static void _updateChannel2(struct mTiming* timing, void* user, uint32_t cyclesLate);
45static void _updateChannel3(struct mTiming* timing, void* user, uint32_t cyclesLate);
46static void _fadeChannel3(struct mTiming* timing, void* user, uint32_t cyclesLate);
47static void _updateChannel4(struct mTiming* timing, void* user, uint32_t cyclesLate);
48static void _sample(struct mTiming* timing, void* user, uint32_t cyclesLate);
49
50void GBAudioInit(struct GBAudio* audio, size_t samples, uint8_t* nr52, enum GBAudioStyle style) {
51 audio->samples = samples;
52 audio->left = blip_new(BLIP_BUFFER_SIZE);
53 audio->right = blip_new(BLIP_BUFFER_SIZE);
54 audio->clockRate = DMG_LR35902_FREQUENCY;
55 // Guess too large; we hang producing extra samples if we guess too low
56 blip_set_rates(audio->left, DMG_LR35902_FREQUENCY, 96000);
57 blip_set_rates(audio->right, DMG_LR35902_FREQUENCY, 96000);
58 audio->forceDisableCh[0] = false;
59 audio->forceDisableCh[1] = false;
60 audio->forceDisableCh[2] = false;
61 audio->forceDisableCh[3] = false;
62 audio->masterVolume = GB_AUDIO_VOLUME_MAX;
63 audio->nr52 = nr52;
64 audio->style = style;
65 if (style == GB_AUDIO_GBA) {
66 audio->timingFactor = 4;
67 } else {
68 audio->timingFactor = 1;
69 }
70
71 audio->frameEvent.context = audio;
72 audio->frameEvent.name = "GB Audio Frame Sequencer";
73 audio->frameEvent.callback = _updateFrame;
74 audio->frameEvent.priority = 0x10;
75 audio->ch1Event.context = audio;
76 audio->ch1Event.name = "GB Audio Channel 1";
77 audio->ch1Event.callback = _updateChannel1;
78 audio->ch1Event.priority = 0x11;
79 audio->ch2Event.context = audio;
80 audio->ch2Event.name = "GB Audio Channel 2";
81 audio->ch2Event.callback = _updateChannel2;
82 audio->ch2Event.priority = 0x12;
83 audio->ch3Event.context = audio;
84 audio->ch3Event.name = "GB Audio Channel 3";
85 audio->ch3Event.callback = _updateChannel3;
86 audio->ch3Event.priority = 0x13;
87 audio->ch3Fade.context = audio;
88 audio->ch3Fade.name = "GB Audio Channel 3 Memory";
89 audio->ch3Fade.callback = _fadeChannel3;
90 audio->ch3Fade.priority = 0x14;
91 audio->ch4Event.context = audio;
92 audio->ch4Event.name = "GB Audio Channel 4";
93 audio->ch4Event.callback = _updateChannel4;
94 audio->ch4Event.priority = 0x15;
95 audio->sampleEvent.context = audio;
96 audio->sampleEvent.name = "GB Audio Sample";
97 audio->sampleEvent.callback = _sample;
98 audio->sampleEvent.priority = 0x18;
99}
100
101void GBAudioDeinit(struct GBAudio* audio) {
102 blip_delete(audio->left);
103 blip_delete(audio->right);
104}
105
106void GBAudioReset(struct GBAudio* audio) {
107 mTimingDeschedule(audio->timing, &audio->frameEvent);
108 mTimingDeschedule(audio->timing, &audio->ch1Event);
109 mTimingDeschedule(audio->timing, &audio->ch2Event);
110 mTimingDeschedule(audio->timing, &audio->ch3Event);
111 mTimingDeschedule(audio->timing, &audio->ch3Fade);
112 mTimingDeschedule(audio->timing, &audio->ch4Event);
113 mTimingDeschedule(audio->timing, &audio->sampleEvent);
114 if (audio->style != GB_AUDIO_GBA) {
115 mTimingSchedule(audio->timing, &audio->sampleEvent, 0);
116 }
117 if (audio->style == GB_AUDIO_GBA) {
118 mTimingSchedule(audio->timing, &audio->frameEvent, 0);
119 }
120 audio->ch1 = (struct GBAudioSquareChannel) { .envelope = { .dead = 2 } };
121 audio->ch2 = (struct GBAudioSquareChannel) { .envelope = { .dead = 2 } };
122 audio->ch3 = (struct GBAudioWaveChannel) { .bank = 0 };
123 audio->ch4 = (struct GBAudioNoiseChannel) { .nSamples = 0 };
124 // TODO: DMG randomness
125 audio->ch3.wavedata8[0] = 0x00;
126 audio->ch3.wavedata8[1] = 0xFF;
127 audio->ch3.wavedata8[2] = 0x00;
128 audio->ch3.wavedata8[3] = 0xFF;
129 audio->ch3.wavedata8[4] = 0x00;
130 audio->ch3.wavedata8[5] = 0xFF;
131 audio->ch3.wavedata8[6] = 0x00;
132 audio->ch3.wavedata8[7] = 0xFF;
133 audio->ch3.wavedata8[8] = 0x00;
134 audio->ch3.wavedata8[9] = 0xFF;
135 audio->ch3.wavedata8[10] = 0x00;
136 audio->ch3.wavedata8[11] = 0xFF;
137 audio->ch3.wavedata8[12] = 0x00;
138 audio->ch3.wavedata8[13] = 0xFF;
139 audio->ch3.wavedata8[14] = 0x00;
140 audio->ch3.wavedata8[15] = 0xFF;
141 audio->ch4 = (struct GBAudioNoiseChannel) { .envelope = { .dead = 2 } };
142 audio->frame = 0;
143 audio->sampleInterval = 128;
144 audio->lastLeft = 0;
145 audio->lastRight = 0;
146 audio->capLeft = 0;
147 audio->capRight = 0;
148 audio->clock = 0;
149 audio->playingCh1 = false;
150 audio->playingCh2 = false;
151 audio->playingCh3 = false;
152 audio->playingCh4 = false;
153 if (audio->p && !(audio->p->model & GB_MODEL_SGB)) {
154 audio->playingCh1 = true;
155 audio->enable = true;
156 *audio->nr52 |= 0x01;
157 }
158}
159
160void GBAudioResizeBuffer(struct GBAudio* audio, size_t samples) {
161 mCoreSyncLockAudio(audio->p->sync);
162 audio->samples = samples;
163 blip_clear(audio->left);
164 blip_clear(audio->right);
165 audio->clock = 0;
166 mCoreSyncConsumeAudio(audio->p->sync);
167}
168
169void GBAudioWriteNR10(struct GBAudio* audio, uint8_t value) {
170 if (!_writeSweep(&audio->ch1.sweep, value)) {
171 mTimingDeschedule(audio->timing, &audio->ch1Event);
172 audio->playingCh1 = false;
173 *audio->nr52 &= ~0x0001;
174 }
175}
176
177void GBAudioWriteNR11(struct GBAudio* audio, uint8_t value) {
178 _writeDuty(&audio->ch1.envelope, value);
179 audio->ch1.control.length = 64 - audio->ch1.envelope.length;
180}
181
182void GBAudioWriteNR12(struct GBAudio* audio, uint8_t value) {
183 if (!_writeEnvelope(&audio->ch1.envelope, value, audio->style)) {
184 mTimingDeschedule(audio->timing, &audio->ch1Event);
185 audio->playingCh1 = false;
186 *audio->nr52 &= ~0x0001;
187 }
188}
189
190void GBAudioWriteNR13(struct GBAudio* audio, uint8_t value) {
191 audio->ch1.control.frequency &= 0x700;
192 audio->ch1.control.frequency |= GBAudioRegisterControlGetFrequency(value);
193}
194
195void GBAudioWriteNR14(struct GBAudio* audio, uint8_t value) {
196 audio->ch1.control.frequency &= 0xFF;
197 audio->ch1.control.frequency |= GBAudioRegisterControlGetFrequency(value << 8);
198 bool wasStop = audio->ch1.control.stop;
199 audio->ch1.control.stop = GBAudioRegisterControlGetStop(value << 8);
200 if (!wasStop && audio->ch1.control.stop && audio->ch1.control.length && !(audio->frame & 1)) {
201 --audio->ch1.control.length;
202 if (audio->ch1.control.length == 0) {
203 mTimingDeschedule(audio->timing, &audio->ch1Event);
204 audio->playingCh1 = false;
205 }
206 }
207 if (GBAudioRegisterControlIsRestart(value << 8)) {
208 audio->playingCh1 = _resetEnvelope(&audio->ch1.envelope);
209 audio->ch1.sweep.realFrequency = audio->ch1.control.frequency;
210 _resetSweep(&audio->ch1.sweep);
211 if (audio->playingCh1 && audio->ch1.sweep.shift) {
212 audio->playingCh1 = _updateSweep(&audio->ch1, true);
213 }
214 if (!audio->ch1.control.length) {
215 audio->ch1.control.length = 64;
216 if (audio->ch1.control.stop && !(audio->frame & 1)) {
217 --audio->ch1.control.length;
218 }
219 }
220 if (audio->playingCh1 && audio->ch1.envelope.dead != 2) {
221 _updateSquareChannel(&audio->ch1);
222 mTimingDeschedule(audio->timing, &audio->ch1Event);
223 mTimingSchedule(audio->timing, &audio->ch1Event, 0);
224 }
225 }
226 *audio->nr52 &= ~0x0001;
227 *audio->nr52 |= audio->playingCh1;
228}
229
230void GBAudioWriteNR21(struct GBAudio* audio, uint8_t value) {
231 _writeDuty(&audio->ch2.envelope, value);
232 audio->ch2.control.length = 64 - audio->ch2.envelope.length;
233}
234
235void GBAudioWriteNR22(struct GBAudio* audio, uint8_t value) {
236 if (!_writeEnvelope(&audio->ch2.envelope, value, audio->style)) {
237 mTimingDeschedule(audio->timing, &audio->ch2Event);
238 audio->playingCh2 = false;
239 *audio->nr52 &= ~0x0002;
240 }
241}
242
243void GBAudioWriteNR23(struct GBAudio* audio, uint8_t value) {
244 audio->ch2.control.frequency &= 0x700;
245 audio->ch2.control.frequency |= GBAudioRegisterControlGetFrequency(value);
246}
247
248void GBAudioWriteNR24(struct GBAudio* audio, uint8_t value) {
249 audio->ch2.control.frequency &= 0xFF;
250 audio->ch2.control.frequency |= GBAudioRegisterControlGetFrequency(value << 8);
251 bool wasStop = audio->ch2.control.stop;
252 audio->ch2.control.stop = GBAudioRegisterControlGetStop(value << 8);
253 if (!wasStop && audio->ch2.control.stop && audio->ch2.control.length && !(audio->frame & 1)) {
254 --audio->ch2.control.length;
255 if (audio->ch2.control.length == 0) {
256 mTimingDeschedule(audio->timing, &audio->ch2Event);
257 audio->playingCh2 = false;
258 }
259 }
260 if (GBAudioRegisterControlIsRestart(value << 8)) {
261 audio->playingCh2 = _resetEnvelope(&audio->ch2.envelope);
262
263 if (!audio->ch2.control.length) {
264 audio->ch2.control.length = 64;
265 if (audio->ch2.control.stop && !(audio->frame & 1)) {
266 --audio->ch2.control.length;
267 }
268 }
269 if (audio->playingCh2 && audio->ch2.envelope.dead != 2) {
270 _updateSquareChannel(&audio->ch2);
271 mTimingDeschedule(audio->timing, &audio->ch2Event);
272 mTimingSchedule(audio->timing, &audio->ch2Event, 0);
273 }
274 }
275 *audio->nr52 &= ~0x0002;
276 *audio->nr52 |= audio->playingCh2 << 1;
277}
278
279void GBAudioWriteNR30(struct GBAudio* audio, uint8_t value) {
280 audio->ch3.enable = GBAudioRegisterBankGetEnable(value);
281 if (!audio->ch3.enable) {
282 mTimingDeschedule(audio->timing, &audio->ch3Event);
283 audio->playingCh3 = false;
284 *audio->nr52 &= ~0x0004;
285 }
286}
287
288void GBAudioWriteNR31(struct GBAudio* audio, uint8_t value) {
289 audio->ch3.length = 256 - value;
290}
291
292void GBAudioWriteNR32(struct GBAudio* audio, uint8_t value) {
293 audio->ch3.volume = GBAudioRegisterBankVolumeGetVolumeGB(value);
294}
295
296void GBAudioWriteNR33(struct GBAudio* audio, uint8_t value) {
297 audio->ch3.rate &= 0x700;
298 audio->ch3.rate |= GBAudioRegisterControlGetRate(value);
299}
300
301void GBAudioWriteNR34(struct GBAudio* audio, uint8_t value) {
302 audio->ch3.rate &= 0xFF;
303 audio->ch3.rate |= GBAudioRegisterControlGetRate(value << 8);
304 bool wasStop = audio->ch3.stop;
305 audio->ch3.stop = GBAudioRegisterControlGetStop(value << 8);
306 if (!wasStop && audio->ch3.stop && audio->ch3.length && !(audio->frame & 1)) {
307 --audio->ch3.length;
308 if (audio->ch3.length == 0) {
309 audio->playingCh3 = false;
310 }
311 }
312 bool wasEnable = audio->playingCh3;
313 if (GBAudioRegisterControlIsRestart(value << 8)) {
314 audio->playingCh3 = audio->ch3.enable;
315 if (!audio->ch3.length) {
316 audio->ch3.length = 256;
317 if (audio->ch3.stop && !(audio->frame & 1)) {
318 --audio->ch3.length;
319 }
320 }
321
322 if (audio->style == GB_AUDIO_DMG && wasEnable && audio->playingCh3 && audio->ch3.readable) {
323 if (audio->ch3.window < 8) {
324 audio->ch3.wavedata8[0] = audio->ch3.wavedata8[audio->ch3.window >> 1];
325 } else {
326 audio->ch3.wavedata8[0] = audio->ch3.wavedata8[((audio->ch3.window >> 1) & ~3)];
327 audio->ch3.wavedata8[1] = audio->ch3.wavedata8[((audio->ch3.window >> 1) & ~3) + 1];
328 audio->ch3.wavedata8[2] = audio->ch3.wavedata8[((audio->ch3.window >> 1) & ~3) + 2];
329 audio->ch3.wavedata8[3] = audio->ch3.wavedata8[((audio->ch3.window >> 1) & ~3) + 3];
330 }
331 }
332 audio->ch3.window = 0;
333 if (audio->style == GB_AUDIO_DMG) {
334 audio->ch3.sample = 0;
335 }
336 }
337 mTimingDeschedule(audio->timing, &audio->ch3Fade);
338 mTimingDeschedule(audio->timing, &audio->ch3Event);
339 if (audio->playingCh3) {
340 audio->ch3.readable = audio->style != GB_AUDIO_DMG;
341 // TODO: Where does this cycle delay come from?
342 mTimingSchedule(audio->timing, &audio->ch3Event, audio->timingFactor * 4 + 2 * (2048 - audio->ch3.rate));
343 }
344 *audio->nr52 &= ~0x0004;
345 *audio->nr52 |= audio->playingCh3 << 2;
346}
347
348void GBAudioWriteNR41(struct GBAudio* audio, uint8_t value) {
349 _writeDuty(&audio->ch4.envelope, value);
350 audio->ch4.length = 64 - audio->ch4.envelope.length;
351}
352
353void GBAudioWriteNR42(struct GBAudio* audio, uint8_t value) {
354 if (!_writeEnvelope(&audio->ch4.envelope, value, audio->style)) {
355 mTimingDeschedule(audio->timing, &audio->ch4Event);
356 audio->playingCh4 = false;
357 *audio->nr52 &= ~0x0008;
358 }
359}
360
361void GBAudioWriteNR43(struct GBAudio* audio, uint8_t value) {
362 audio->ch4.ratio = GBAudioRegisterNoiseFeedbackGetRatio(value);
363 audio->ch4.frequency = GBAudioRegisterNoiseFeedbackGetFrequency(value);
364 audio->ch4.power = GBAudioRegisterNoiseFeedbackGetPower(value);
365}
366
367void GBAudioWriteNR44(struct GBAudio* audio, uint8_t value) {
368 bool wasStop = audio->ch4.stop;
369 audio->ch4.stop = GBAudioRegisterNoiseControlGetStop(value);
370 if (!wasStop && audio->ch4.stop && audio->ch4.length && !(audio->frame & 1)) {
371 --audio->ch4.length;
372 if (audio->ch4.length == 0) {
373 mTimingDeschedule(audio->timing, &audio->ch4Event);
374 audio->playingCh4 = false;
375 }
376 }
377 if (GBAudioRegisterNoiseControlIsRestart(value)) {
378 audio->playingCh4 = _resetEnvelope(&audio->ch4.envelope);
379
380 if (audio->ch4.power) {
381 audio->ch4.lfsr = 0x7F;
382 } else {
383 audio->ch4.lfsr = 0x7FFF;
384 }
385 if (!audio->ch4.length) {
386 audio->ch4.length = 64;
387 if (audio->ch4.stop && !(audio->frame & 1)) {
388 --audio->ch4.length;
389 }
390 }
391 if (audio->playingCh4 && audio->ch4.envelope.dead != 2) {
392 mTimingDeschedule(audio->timing, &audio->ch4Event);
393 mTimingSchedule(audio->timing, &audio->ch4Event, 0);
394 }
395 }
396 *audio->nr52 &= ~0x0008;
397 *audio->nr52 |= audio->playingCh4 << 3;
398}
399
400void GBAudioWriteNR50(struct GBAudio* audio, uint8_t value) {
401 audio->volumeRight = GBRegisterNR50GetVolumeRight(value);
402 audio->volumeLeft = GBRegisterNR50GetVolumeLeft(value);
403}
404
405void GBAudioWriteNR51(struct GBAudio* audio, uint8_t value) {
406 audio->ch1Right = GBRegisterNR51GetCh1Right(value);
407 audio->ch2Right = GBRegisterNR51GetCh2Right(value);
408 audio->ch3Right = GBRegisterNR51GetCh3Right(value);
409 audio->ch4Right = GBRegisterNR51GetCh4Right(value);
410 audio->ch1Left = GBRegisterNR51GetCh1Left(value);
411 audio->ch2Left = GBRegisterNR51GetCh2Left(value);
412 audio->ch3Left = GBRegisterNR51GetCh3Left(value);
413 audio->ch4Left = GBRegisterNR51GetCh4Left(value);
414}
415
416void GBAudioWriteNR52(struct GBAudio* audio, uint8_t value) {
417 bool wasEnable = audio->enable;
418 audio->enable = GBAudioEnableGetEnable(value);
419 if (!audio->enable) {
420 audio->playingCh1 = 0;
421 audio->playingCh2 = 0;
422 audio->playingCh3 = 0;
423 audio->playingCh4 = 0;
424 GBAudioWriteNR10(audio, 0);
425 GBAudioWriteNR12(audio, 0);
426 GBAudioWriteNR13(audio, 0);
427 GBAudioWriteNR14(audio, 0);
428 GBAudioWriteNR22(audio, 0);
429 GBAudioWriteNR23(audio, 0);
430 GBAudioWriteNR24(audio, 0);
431 GBAudioWriteNR30(audio, 0);
432 GBAudioWriteNR32(audio, 0);
433 GBAudioWriteNR33(audio, 0);
434 GBAudioWriteNR34(audio, 0);
435 GBAudioWriteNR42(audio, 0);
436 GBAudioWriteNR43(audio, 0);
437 GBAudioWriteNR44(audio, 0);
438 GBAudioWriteNR50(audio, 0);
439 GBAudioWriteNR51(audio, 0);
440 if (audio->style != GB_AUDIO_DMG) {
441 GBAudioWriteNR11(audio, 0);
442 GBAudioWriteNR21(audio, 0);
443 GBAudioWriteNR31(audio, 0);
444 GBAudioWriteNR41(audio, 0);
445 }
446
447 if (audio->p) {
448 audio->p->memory.io[REG_NR10] = 0;
449 audio->p->memory.io[REG_NR11] = 0;
450 audio->p->memory.io[REG_NR12] = 0;
451 audio->p->memory.io[REG_NR13] = 0;
452 audio->p->memory.io[REG_NR14] = 0;
453 audio->p->memory.io[REG_NR21] = 0;
454 audio->p->memory.io[REG_NR22] = 0;
455 audio->p->memory.io[REG_NR23] = 0;
456 audio->p->memory.io[REG_NR24] = 0;
457 audio->p->memory.io[REG_NR30] = 0;
458 audio->p->memory.io[REG_NR31] = 0;
459 audio->p->memory.io[REG_NR32] = 0;
460 audio->p->memory.io[REG_NR33] = 0;
461 audio->p->memory.io[REG_NR34] = 0;
462 audio->p->memory.io[REG_NR42] = 0;
463 audio->p->memory.io[REG_NR43] = 0;
464 audio->p->memory.io[REG_NR44] = 0;
465 audio->p->memory.io[REG_NR50] = 0;
466 audio->p->memory.io[REG_NR51] = 0;
467 if (audio->style != GB_AUDIO_DMG) {
468 audio->p->memory.io[REG_NR11] = 0;
469 audio->p->memory.io[REG_NR21] = 0;
470 audio->p->memory.io[REG_NR31] = 0;
471 audio->p->memory.io[REG_NR41] = 0;
472 }
473 }
474 *audio->nr52 &= ~0x000F;
475 } else if (!wasEnable) {
476 audio->skipFrame = false;
477 audio->frame = 7;
478
479 if (audio->p) {
480 unsigned timingFactor = 0x400 >> !audio->p->doubleSpeed;
481 if (audio->p->timer.internalDiv & timingFactor) {
482 audio->skipFrame = true;
483 }
484 }
485 }
486}
487
488void _updateFrame(struct mTiming* timing, void* user, uint32_t cyclesLate) {
489 struct GBAudio* audio = user;
490 GBAudioUpdateFrame(audio, timing);
491 if (audio->style == GB_AUDIO_GBA) {
492 mTimingSchedule(timing, &audio->frameEvent, audio->timingFactor * FRAME_CYCLES - cyclesLate);
493 }
494}
495
496void GBAudioUpdateFrame(struct GBAudio* audio, struct mTiming* timing) {
497 if (!audio->enable) {
498 return;
499 }
500 if (audio->skipFrame) {
501 audio->skipFrame = false;
502 return;
503 }
504 int frame = (audio->frame + 1) & 7;
505 audio->frame = frame;
506
507 switch (frame) {
508 case 2:
509 case 6:
510 if (audio->ch1.sweep.enable) {
511 --audio->ch1.sweep.step;
512 if (audio->ch1.sweep.step == 0) {
513 audio->playingCh1 = _updateSweep(&audio->ch1, false);
514 *audio->nr52 &= ~0x0001;
515 *audio->nr52 |= audio->playingCh1;
516 }
517 }
518 // Fall through
519 case 0:
520 case 4:
521 if (audio->ch1.control.length && audio->ch1.control.stop) {
522 --audio->ch1.control.length;
523 if (audio->ch1.control.length == 0) {
524 mTimingDeschedule(timing, &audio->ch1Event);
525 audio->playingCh1 = 0;
526 *audio->nr52 &= ~0x0001;
527 }
528 }
529
530 if (audio->ch2.control.length && audio->ch2.control.stop) {
531 --audio->ch2.control.length;
532 if (audio->ch2.control.length == 0) {
533 mTimingDeschedule(timing, &audio->ch2Event);
534 audio->playingCh2 = 0;
535 *audio->nr52 &= ~0x0002;
536 }
537 }
538
539 if (audio->ch3.length && audio->ch3.stop) {
540 --audio->ch3.length;
541 if (audio->ch3.length == 0) {
542 mTimingDeschedule(timing, &audio->ch3Event);
543 audio->playingCh3 = 0;
544 *audio->nr52 &= ~0x0004;
545 }
546 }
547
548 if (audio->ch4.length && audio->ch4.stop) {
549 --audio->ch4.length;
550 if (audio->ch4.length == 0) {
551 mTimingDeschedule(timing, &audio->ch4Event);
552 audio->playingCh4 = 0;
553 *audio->nr52 &= ~0x0008;
554 }
555 }
556 break;
557 case 7:
558 if (audio->playingCh1 && !audio->ch1.envelope.dead) {
559 --audio->ch1.envelope.nextStep;
560 if (audio->ch1.envelope.nextStep == 0) {
561 _updateEnvelope(&audio->ch1.envelope);
562 if (audio->ch1.envelope.dead == 2) {
563 mTimingDeschedule(timing, &audio->ch1Event);
564 }
565 _updateSquareSample(&audio->ch1);
566 }
567 }
568
569 if (audio->playingCh2 && !audio->ch2.envelope.dead) {
570 --audio->ch2.envelope.nextStep;
571 if (audio->ch2.envelope.nextStep == 0) {
572 _updateEnvelope(&audio->ch2.envelope);
573 if (audio->ch2.envelope.dead == 2) {
574 mTimingDeschedule(timing, &audio->ch2Event);
575 }
576 _updateSquareSample(&audio->ch2);
577 }
578 }
579
580 if (audio->playingCh4 && !audio->ch4.envelope.dead) {
581 --audio->ch4.envelope.nextStep;
582 if (audio->ch4.envelope.nextStep == 0) {
583 int8_t sample = audio->ch4.sample > 0;
584 audio->ch4.samples -= audio->ch4.sample;
585 _updateEnvelope(&audio->ch4.envelope);
586 if (audio->ch4.envelope.dead == 2) {
587 mTimingDeschedule(timing, &audio->ch4Event);
588 }
589 audio->ch4.sample = sample * audio->ch4.envelope.currentVolume;
590 audio->ch4.samples += audio->ch4.sample;
591 }
592 }
593 break;
594 }
595}
596
597void GBAudioSamplePSG(struct GBAudio* audio, int16_t* left, int16_t* right) {
598 int dcOffset = audio->style == GB_AUDIO_GBA ? 0 : -0x8;
599 int sampleLeft = dcOffset;
600 int sampleRight = dcOffset;
601
602 if (!audio->forceDisableCh[0]) {
603 if (audio->ch1Left) {
604 sampleLeft += audio->ch1.sample;
605 }
606
607 if (audio->ch1Right) {
608 sampleRight += audio->ch1.sample;
609 }
610 }
611
612 if (!audio->forceDisableCh[1]) {
613 if (audio->ch2Left) {
614 sampleLeft += audio->ch2.sample;
615 }
616
617 if (audio->ch2Right) {
618 sampleRight += audio->ch2.sample;
619 }
620 }
621
622 if (!audio->forceDisableCh[2]) {
623 if (audio->ch3Left) {
624 sampleLeft += audio->ch3.sample;
625 }
626
627 if (audio->ch3Right) {
628 sampleRight += audio->ch3.sample;
629 }
630 }
631
632 if (!audio->forceDisableCh[3]) {
633 int8_t sample = _coalesceNoiseChannel(&audio->ch4);
634 if (audio->ch4Left) {
635 sampleLeft += sample;
636 }
637
638 if (audio->ch4Right) {
639 sampleRight += sample;
640 }
641 }
642
643 sampleLeft <<= 3;
644 sampleRight <<= 3;
645
646 *left = sampleLeft * (1 + audio->volumeLeft);
647 *right = sampleRight * (1 + audio->volumeRight);
648}
649
650static void _sample(struct mTiming* timing, void* user, uint32_t cyclesLate) {
651 struct GBAudio* audio = user;
652 int16_t sampleLeft = 0;
653 int16_t sampleRight = 0;
654 GBAudioSamplePSG(audio, &sampleLeft, &sampleRight);
655 sampleLeft = (sampleLeft * audio->masterVolume * 6) >> 7;
656 sampleRight = (sampleRight * audio->masterVolume * 6) >> 7;
657
658 mCoreSyncLockAudio(audio->p->sync);
659 unsigned produced;
660
661 int16_t degradedLeft = sampleLeft - (audio->capLeft >> 16);
662 int16_t degradedRight = sampleRight - (audio->capRight >> 16);
663 audio->capLeft = (sampleLeft << 16) - degradedLeft * 65184;
664 audio->capRight = (sampleRight << 16) - degradedRight * 65184;
665 sampleLeft = degradedLeft;
666 sampleRight = degradedRight;
667
668 if ((size_t) blip_samples_avail(audio->left) < audio->samples) {
669 blip_add_delta(audio->left, audio->clock, sampleLeft - audio->lastLeft);
670 blip_add_delta(audio->right, audio->clock, sampleRight - audio->lastRight);
671 audio->lastLeft = sampleLeft;
672 audio->lastRight = sampleRight;
673 audio->clock += audio->sampleInterval;
674 if (audio->clock >= CLOCKS_PER_BLIP_FRAME) {
675 blip_end_frame(audio->left, CLOCKS_PER_BLIP_FRAME);
676 blip_end_frame(audio->right, CLOCKS_PER_BLIP_FRAME);
677 audio->clock -= CLOCKS_PER_BLIP_FRAME;
678 }
679 }
680 produced = blip_samples_avail(audio->left);
681 if (audio->p->stream && audio->p->stream->postAudioFrame) {
682 audio->p->stream->postAudioFrame(audio->p->stream, sampleLeft, sampleRight);
683 }
684 bool wait = produced >= audio->samples;
685 if (!mCoreSyncProduceAudio(audio->p->sync, audio->left, audio->samples)) {
686 // Interrupted
687 audio->p->earlyExit = true;
688 }
689
690 if (wait && audio->p->stream && audio->p->stream->postAudioBuffer) {
691 audio->p->stream->postAudioBuffer(audio->p->stream, audio->left, audio->right);
692 }
693 mTimingSchedule(timing, &audio->sampleEvent, audio->sampleInterval * audio->timingFactor - cyclesLate);
694}
695
696bool _resetEnvelope(struct GBAudioEnvelope* envelope) {
697 envelope->currentVolume = envelope->initialVolume;
698 _updateEnvelopeDead(envelope);
699 if (!envelope->dead) {
700 envelope->nextStep = envelope->stepTime;
701 }
702 return envelope->initialVolume || envelope->direction;
703}
704
705void _resetSweep(struct GBAudioSweep* sweep) {
706 sweep->step = sweep->time;
707 sweep->enable = (sweep->step != 8) || sweep->shift;
708 sweep->occurred = false;
709}
710
711bool _writeSweep(struct GBAudioSweep* sweep, uint8_t value) {
712 sweep->shift = GBAudioRegisterSquareSweepGetShift(value);
713 bool oldDirection = sweep->direction;
714 sweep->direction = GBAudioRegisterSquareSweepGetDirection(value);
715 bool on = true;
716 if (sweep->occurred && oldDirection && !sweep->direction) {
717 on = false;
718 }
719 sweep->occurred = false;
720 sweep->time = GBAudioRegisterSquareSweepGetTime(value);
721 if (!sweep->time) {
722 sweep->time = 8;
723 }
724 return on;
725}
726
727void _writeDuty(struct GBAudioEnvelope* envelope, uint8_t value) {
728 envelope->length = GBAudioRegisterDutyGetLength(value);
729 envelope->duty = GBAudioRegisterDutyGetDuty(value);
730}
731
732bool _writeEnvelope(struct GBAudioEnvelope* envelope, uint8_t value, enum GBAudioStyle style) {
733 envelope->stepTime = GBAudioRegisterSweepGetStepTime(value);
734 envelope->direction = GBAudioRegisterSweepGetDirection(value);
735 envelope->initialVolume = GBAudioRegisterSweepGetInitialVolume(value);
736 if (style == GB_AUDIO_DMG && !envelope->stepTime) {
737 // TODO: Improve "zombie" mode
738 ++envelope->currentVolume;
739 envelope->currentVolume &= 0xF;
740 }
741 _updateEnvelopeDead(envelope);
742 return (envelope->initialVolume || envelope->direction) && envelope->dead != 2;
743}
744
745static void _updateSquareSample(struct GBAudioSquareChannel* ch) {
746 ch->sample = ch->control.hi * ch->envelope.currentVolume;
747}
748
749static int32_t _updateSquareChannel(struct GBAudioSquareChannel* ch) {
750 ch->control.hi = !ch->control.hi;
751 _updateSquareSample(ch);
752 int period = 4 * (2048 - ch->control.frequency);
753 switch (ch->envelope.duty) {
754 case 0:
755 return ch->control.hi ? period : period * 7;
756 case 1:
757 return ch->control.hi ? period * 2 : period * 6;
758 case 2:
759 return period * 4;
760 case 3:
761 return ch->control.hi ? period * 6 : period * 2;
762 default:
763 // This should never be hit
764 return period * 4;
765 }
766}
767
768static int8_t _coalesceNoiseChannel(struct GBAudioNoiseChannel* ch) {
769 if (!ch->nSamples) {
770 return ch->sample;
771 }
772 // TODO keep track of timing
773 int8_t sample = ch->samples / ch->nSamples;
774 ch->nSamples = 0;
775 ch->samples = 0;
776 return sample;
777}
778
779static void _updateEnvelope(struct GBAudioEnvelope* envelope) {
780 if (envelope->direction) {
781 ++envelope->currentVolume;
782 } else {
783 --envelope->currentVolume;
784 }
785 if (envelope->currentVolume >= 15) {
786 envelope->currentVolume = 15;
787 envelope->dead = 1;
788 } else if (envelope->currentVolume <= 0) {
789 envelope->currentVolume = 0;
790 envelope->dead = 2;
791 } else {
792 envelope->nextStep = envelope->stepTime;
793 }
794}
795
796static void _updateEnvelopeDead(struct GBAudioEnvelope* envelope) {
797 if (!envelope->stepTime) {
798 envelope->dead = envelope->currentVolume ? 1 : 2;
799 } else if (!envelope->direction && !envelope->currentVolume) {
800 envelope->dead = 2;
801 } else if (envelope->direction && envelope->currentVolume == 0xF) {
802 envelope->dead = 1;
803 } else {
804 envelope->dead = 0;
805 }
806}
807
808static bool _updateSweep(struct GBAudioSquareChannel* ch, bool initial) {
809 if (initial || ch->sweep.time != 8) {
810 int frequency = ch->sweep.realFrequency;
811 if (ch->sweep.direction) {
812 frequency -= frequency >> ch->sweep.shift;
813 if (!initial && frequency >= 0) {
814 ch->control.frequency = frequency;
815 ch->sweep.realFrequency = frequency;
816 }
817 } else {
818 frequency += frequency >> ch->sweep.shift;
819 if (frequency < 2048) {
820 if (!initial && ch->sweep.shift) {
821 ch->control.frequency = frequency;
822 ch->sweep.realFrequency = frequency;
823 if (!_updateSweep(ch, true)) {
824 return false;
825 }
826 }
827 } else {
828 return false;
829 }
830 }
831 ch->sweep.occurred = true;
832 }
833 ch->sweep.step = ch->sweep.time;
834 return true;
835}
836
837static void _updateChannel1(struct mTiming* timing, void* user, uint32_t cyclesLate) {
838 struct GBAudio* audio = user;
839 struct GBAudioSquareChannel* ch = &audio->ch1;
840 int cycles = _updateSquareChannel(ch);
841 mTimingSchedule(timing, &audio->ch1Event, audio->timingFactor * cycles - cyclesLate);
842}
843
844static void _updateChannel2(struct mTiming* timing, void* user, uint32_t cyclesLate) {
845 struct GBAudio* audio = user;
846 struct GBAudioSquareChannel* ch = &audio->ch2;
847 int cycles = _updateSquareChannel(ch);
848 mTimingSchedule(timing, &audio->ch2Event, audio->timingFactor * cycles - cyclesLate);
849}
850
851static void _updateChannel3(struct mTiming* timing, void* user, uint32_t cyclesLate) {
852 struct GBAudio* audio = user;
853 struct GBAudioWaveChannel* ch = &audio->ch3;
854 int i;
855 int volume;
856 switch (ch->volume) {
857 case 0:
858 volume = 4;
859 break;
860 case 1:
861 volume = 0;
862 break;
863 case 2:
864 volume = 1;
865 break;
866 default:
867 case 3:
868 volume = 2;
869 break;
870 }
871 int start;
872 int end;
873 switch (audio->style) {
874 case GB_AUDIO_DMG:
875 default:
876 ++ch->window;
877 ch->window &= 0x1F;
878 ch->sample = ch->wavedata8[ch->window >> 1];
879 if (!(ch->window & 1)) {
880 ch->sample >>= 4;
881 }
882 ch->sample &= 0xF;
883 break;
884 case GB_AUDIO_GBA:
885 if (ch->size) {
886 start = 7;
887 end = 0;
888 } else if (ch->bank) {
889 start = 7;
890 end = 4;
891 } else {
892 start = 3;
893 end = 0;
894 }
895 uint32_t bitsCarry = ch->wavedata32[end] & 0x000000F0;
896 uint32_t bits;
897 for (i = start; i >= end; --i) {
898 bits = ch->wavedata32[i] & 0x000000F0;
899 ch->wavedata32[i] = ((ch->wavedata32[i] & 0x0F0F0F0F) << 4) | ((ch->wavedata32[i] & 0xF0F0F000) >> 12);
900 ch->wavedata32[i] |= bitsCarry << 20;
901 bitsCarry = bits;
902 }
903 ch->sample = bitsCarry >> 4;
904 break;
905 }
906 if (ch->volume > 3) {
907 ch->sample += ch->sample << 1;
908 }
909 ch->sample >>= volume;
910 audio->ch3.readable = true;
911 if (audio->style == GB_AUDIO_DMG) {
912 mTimingDeschedule(audio->timing, &audio->ch3Fade);
913 mTimingSchedule(timing, &audio->ch3Fade, 2 - cyclesLate);
914 }
915 int cycles = 2 * (2048 - ch->rate);
916 mTimingSchedule(timing, &audio->ch3Event, audio->timingFactor * cycles - cyclesLate);
917}
918static void _fadeChannel3(struct mTiming* timing, void* user, uint32_t cyclesLate) {
919 UNUSED(timing);
920 UNUSED(cyclesLate);
921 struct GBAudio* audio = user;
922 audio->ch3.readable = false;
923}
924
925static void _updateChannel4(struct mTiming* timing, void* user, uint32_t cyclesLate) {
926 struct GBAudio* audio = user;
927 struct GBAudioNoiseChannel* ch = &audio->ch4;
928
929 int32_t cycles = ch->ratio ? 2 * ch->ratio : 1;
930 cycles <<= ch->frequency;
931 cycles *= 8 * audio->timingFactor;
932
933 int lsb = ch->lfsr & 1;
934 ch->sample = lsb * ch->envelope.currentVolume;
935 ++ch->nSamples;
936 ch->samples += ch->sample;
937 ch->lfsr >>= 1;
938 ch->lfsr ^= (lsb * 0x60) << (ch->power ? 0 : 8);
939
940 mTimingSchedule(timing, &audio->ch4Event, cycles - cyclesLate);
941}
942
943void GBAudioPSGSerialize(const struct GBAudio* audio, struct GBSerializedPSGState* state, uint32_t* flagsOut) {
944 uint32_t flags = 0;
945 uint32_t ch1Flags = 0;
946 uint32_t ch2Flags = 0;
947 uint32_t ch4Flags = 0;
948
949 flags = GBSerializedAudioFlagsSetFrame(flags, audio->frame);
950 flags = GBSerializedAudioFlagsSetSkipFrame(flags, audio->skipFrame);
951 STORE_32LE(audio->frameEvent.when - mTimingCurrentTime(audio->timing), 0, &state->ch1.nextFrame);
952
953 flags = GBSerializedAudioFlagsSetCh1Volume(flags, audio->ch1.envelope.currentVolume);
954 flags = GBSerializedAudioFlagsSetCh1Dead(flags, audio->ch1.envelope.dead);
955 flags = GBSerializedAudioFlagsSetCh1Hi(flags, audio->ch1.control.hi);
956 flags = GBSerializedAudioFlagsSetCh1SweepEnabled(flags, audio->ch1.sweep.enable);
957 flags = GBSerializedAudioFlagsSetCh1SweepOccurred(flags, audio->ch1.sweep.occurred);
958 ch1Flags = GBSerializedAudioEnvelopeSetLength(ch1Flags, audio->ch1.control.length);
959 ch1Flags = GBSerializedAudioEnvelopeSetNextStep(ch1Flags, audio->ch1.envelope.nextStep);
960 ch1Flags = GBSerializedAudioEnvelopeSetFrequency(ch1Flags, audio->ch1.sweep.realFrequency);
961 STORE_32LE(ch1Flags, 0, &state->ch1.envelope);
962 STORE_32LE(audio->ch1Event.when - mTimingCurrentTime(audio->timing), 0, &state->ch1.nextEvent);
963
964 flags = GBSerializedAudioFlagsSetCh2Volume(flags, audio->ch2.envelope.currentVolume);
965 flags = GBSerializedAudioFlagsSetCh2Dead(flags, audio->ch2.envelope.dead);
966 flags = GBSerializedAudioFlagsSetCh2Hi(flags, audio->ch2.control.hi);
967 ch2Flags = GBSerializedAudioEnvelopeSetLength(ch2Flags, audio->ch2.control.length);
968 ch2Flags = GBSerializedAudioEnvelopeSetNextStep(ch2Flags, audio->ch2.envelope.nextStep);
969 STORE_32LE(ch2Flags, 0, &state->ch2.envelope);
970 STORE_32LE(audio->ch2Event.when - mTimingCurrentTime(audio->timing), 0, &state->ch2.nextEvent);
971
972 flags = GBSerializedAudioFlagsSetCh3Readable(flags, audio->ch3.readable);
973 memcpy(state->ch3.wavebanks, audio->ch3.wavedata32, sizeof(state->ch3.wavebanks));
974 STORE_16LE(audio->ch3.length, 0, &state->ch3.length);
975 STORE_32LE(audio->ch3Event.when - mTimingCurrentTime(audio->timing), 0, &state->ch3.nextEvent);
976 STORE_32LE(audio->ch3Fade.when - mTimingCurrentTime(audio->timing), 0, &state->ch1.nextCh3Fade);
977
978 flags = GBSerializedAudioFlagsSetCh4Volume(flags, audio->ch4.envelope.currentVolume);
979 flags = GBSerializedAudioFlagsSetCh4Dead(flags, audio->ch4.envelope.dead);
980 STORE_32LE(audio->ch4.lfsr, 0, &state->ch4.lfsr);
981 ch4Flags = GBSerializedAudioEnvelopeSetLength(ch4Flags, audio->ch4.length);
982 ch4Flags = GBSerializedAudioEnvelopeSetNextStep(ch4Flags, audio->ch4.envelope.nextStep);
983 STORE_32LE(ch4Flags, 0, &state->ch4.envelope);
984 STORE_32LE(audio->ch4Event.when - mTimingCurrentTime(audio->timing), 0, &state->ch4.nextEvent);
985
986 STORE_32LE(flags, 0, flagsOut);
987}
988
989void GBAudioPSGDeserialize(struct GBAudio* audio, const struct GBSerializedPSGState* state, const uint32_t* flagsIn) {
990 uint32_t flags;
991 uint32_t ch1Flags = 0;
992 uint32_t ch2Flags = 0;
993 uint32_t ch4Flags = 0;
994 uint32_t when;
995
996 audio->playingCh1 = !!(*audio->nr52 & 0x0001);
997 audio->playingCh2 = !!(*audio->nr52 & 0x0002);
998 audio->playingCh3 = !!(*audio->nr52 & 0x0004);
999 audio->playingCh4 = !!(*audio->nr52 & 0x0008);
1000 audio->enable = GBAudioEnableGetEnable(*audio->nr52);
1001
1002 if (audio->style == GB_AUDIO_GBA) {
1003 LOAD_32LE(when, 0, &state->ch1.nextFrame);
1004 mTimingSchedule(audio->timing, &audio->frameEvent, when);
1005 }
1006
1007 LOAD_32LE(flags, 0, flagsIn);
1008 audio->frame = GBSerializedAudioFlagsGetFrame(flags);
1009 audio->skipFrame = GBSerializedAudioFlagsGetSkipFrame(flags);
1010
1011 LOAD_32LE(ch1Flags, 0, &state->ch1.envelope);
1012 audio->ch1.envelope.currentVolume = GBSerializedAudioFlagsGetCh1Volume(flags);
1013 audio->ch1.envelope.dead = GBSerializedAudioFlagsGetCh1Dead(flags);
1014 audio->ch1.control.hi = GBSerializedAudioFlagsGetCh1Hi(flags);
1015 audio->ch1.sweep.enable = GBSerializedAudioFlagsGetCh1SweepEnabled(flags);
1016 audio->ch1.sweep.occurred = GBSerializedAudioFlagsGetCh1SweepOccurred(flags);
1017 audio->ch1.control.length = GBSerializedAudioEnvelopeGetLength(ch1Flags);
1018 audio->ch1.envelope.nextStep = GBSerializedAudioEnvelopeGetNextStep(ch1Flags);
1019 audio->ch1.sweep.realFrequency = GBSerializedAudioEnvelopeGetFrequency(ch1Flags);
1020 LOAD_32LE(when, 0, &state->ch1.nextEvent);
1021 if (audio->ch1.envelope.dead < 2 && audio->playingCh1) {
1022 mTimingSchedule(audio->timing, &audio->ch1Event, when);
1023 }
1024
1025 LOAD_32LE(ch2Flags, 0, &state->ch2.envelope);
1026 audio->ch2.envelope.currentVolume = GBSerializedAudioFlagsGetCh2Volume(flags);
1027 audio->ch2.envelope.dead = GBSerializedAudioFlagsGetCh2Dead(flags);
1028 audio->ch2.control.hi = GBSerializedAudioFlagsGetCh2Hi(flags);
1029 audio->ch2.control.length = GBSerializedAudioEnvelopeGetLength(ch2Flags);
1030 audio->ch2.envelope.nextStep = GBSerializedAudioEnvelopeGetNextStep(ch2Flags);
1031 LOAD_32LE(when, 0, &state->ch2.nextEvent);
1032 if (audio->ch2.envelope.dead < 2 && audio->playingCh2) {
1033 mTimingSchedule(audio->timing, &audio->ch2Event, when);
1034 }
1035
1036 audio->ch3.readable = GBSerializedAudioFlagsGetCh3Readable(flags);
1037 // TODO: Big endian?
1038 memcpy(audio->ch3.wavedata32, state->ch3.wavebanks, sizeof(audio->ch3.wavedata32));
1039 LOAD_16LE(audio->ch3.length, 0, &state->ch3.length);
1040 LOAD_32LE(when, 0, &state->ch3.nextEvent);
1041 if (audio->playingCh3) {
1042 mTimingSchedule(audio->timing, &audio->ch3Event, when);
1043 }
1044 LOAD_32LE(when, 0, &state->ch1.nextCh3Fade);
1045 if (audio->ch3.readable && audio->style == GB_AUDIO_DMG) {
1046 mTimingSchedule(audio->timing, &audio->ch3Fade, when);
1047 }
1048
1049 LOAD_32LE(ch4Flags, 0, &state->ch4.envelope);
1050 audio->ch4.envelope.currentVolume = GBSerializedAudioFlagsGetCh4Volume(flags);
1051 audio->ch4.envelope.dead = GBSerializedAudioFlagsGetCh4Dead(flags);
1052 audio->ch4.length = GBSerializedAudioEnvelopeGetLength(ch4Flags);
1053 audio->ch4.envelope.nextStep = GBSerializedAudioEnvelopeGetNextStep(ch4Flags);
1054 LOAD_32LE(audio->ch4.lfsr, 0, &state->ch4.lfsr);
1055 LOAD_32LE(when, 0, &state->ch4.nextEvent);
1056 if (audio->ch4.envelope.dead < 2 && audio->playingCh4) {
1057 mTimingSchedule(audio->timing, &audio->ch4Event, when);
1058 }
1059}
1060
1061void GBAudioSerialize(const struct GBAudio* audio, struct GBSerializedState* state) {
1062 GBAudioPSGSerialize(audio, &state->audio.psg, &state->audio.flags);
1063 STORE_32LE(audio->capLeft, 0, &state->audio.capLeft);
1064 STORE_32LE(audio->capRight, 0, &state->audio.capRight);
1065 STORE_32LE(audio->sampleEvent.when - mTimingCurrentTime(audio->timing), 0, &state->audio.nextSample);
1066}
1067
1068void GBAudioDeserialize(struct GBAudio* audio, const struct GBSerializedState* state) {
1069 GBAudioPSGDeserialize(audio, &state->audio.psg, &state->audio.flags);
1070 LOAD_32LE(audio->capLeft, 0, &state->audio.capLeft);
1071 LOAD_32LE(audio->capRight, 0, &state->audio.capRight);
1072 uint32_t when;
1073 LOAD_32LE(when, 0, &state->audio.nextSample);
1074 mTimingSchedule(audio->timing, &audio->sampleEvent, when);
1075}