1 // for finding memory leaks in debug mode with Visual Studio
2 #if defined _DEBUG && defined _MSC_VER
3 #include <crtdbg.h>
4 #endif
5 
6 #include <stdio.h>
7 #include <stdint.h>
8 #include "ft2_header.h"
9 #include "ft2_config.h"
10 #include "scopes/ft2_scopes.h"
11 #include "ft2_video.h"
12 #include "ft2_gui.h"
13 #include "ft2_midi.h"
14 #include "ft2_wav_renderer.h"
15 #include "ft2_tables.h"
16 #include "ft2_structs.h"
17 // --------------------------------
18 #include "mixer/ft2_mix.h"
19 #include "mixer/ft2_center_mix.h"
20 #include "mixer/ft2_silence_mix.h"
21 // --------------------------------
22 
23 // hide POSIX warnings
24 #ifdef _MSC_VER
25 #pragma warning(disable: 4996)
26 #endif
27 
28 #define INITIAL_DITHER_SEED 0x12345000
29 
30 static int8_t pmpCountDiv, pmpChannels = 2;
31 static uint16_t smpBuffSize;
32 static uint32_t oldAudioFreq, tickTimeLen, tickTimeLenFrac, randSeed = INITIAL_DITHER_SEED;
33 static float fAudioNormalizeMul, fPanningTab[256+1];
34 static double dAudioNormalizeMul, dPrngStateL, dPrngStateR;
35 static voice_t voice[MAX_CHANNELS * 2];
36 static void (*sendAudSamplesFunc)(uint8_t *, uint32_t, uint8_t); // "send mixed samples" routines
37 
38 // globalized
39 audio_t audio;
40 pattSyncData_t *pattSyncEntry;
41 chSyncData_t *chSyncEntry;
42 chSync_t chSync;
43 pattSync_t pattSync;
44 volatile bool pattQueueClearing, chQueueClearing;
45 
resetCachedMixerVars(void)46 void resetCachedMixerVars(void)
47 {
48 	channel_t *ch = channel;
49 	for (int32_t i = 0; i < MAX_CHANNELS; i++, ch++)
50 		ch->oldFinalPeriod = -1;
51 
52 	voice_t *v = voice;
53 	for (int32_t i = 0; i < MAX_CHANNELS*2; i++, v++)
54 		v->oldDelta = 0;
55 }
56 
stopVoice(int32_t i)57 void stopVoice(int32_t i)
58 {
59 	voice_t *v;
60 
61 	v = &voice[i];
62 	memset(v, 0, sizeof (voice_t));
63 	v->panning = 128;
64 
65 	// clear "fade out" voice too
66 
67 	v = &voice[MAX_CHANNELS + i];
68 	memset(v, 0, sizeof (voice_t));
69 	v->panning = 128;
70 }
71 
setNewAudioSettings(void)72 bool setNewAudioSettings(void) // only call this from the main input/video thread
73 {
74 	pauseAudio();
75 
76 	if (!setupAudio(CONFIG_HIDE_ERRORS))
77 	{
78 		// set back old known working settings
79 
80 		config.audioFreq = audio.lastWorkingAudioFreq;
81 		config.specialFlags &= ~(BITDEPTH_16 + BITDEPTH_32 + BUFFSIZE_512 + BUFFSIZE_1024 + BUFFSIZE_2048);
82 		config.specialFlags |= audio.lastWorkingAudioBits;
83 
84 		if (audio.lastWorkingAudioDeviceName != NULL)
85 		{
86 			if (audio.currOutputDevice != NULL)
87 			{
88 				free(audio.currOutputDevice);
89 				audio.currOutputDevice = NULL;
90 			}
91 
92 			audio.currOutputDevice = strdup(audio.lastWorkingAudioDeviceName);
93 		}
94 
95 		// also update config audio radio buttons if we're on that screen at the moment
96 		if (ui.configScreenShown && editor.currConfigScreen == CONFIG_SCREEN_IO_DEVICES)
97 			setConfigIORadioButtonStates();
98 
99 		// if it didn't work to use the old settings again, then something is seriously wrong...
100 		if (!setupAudio(CONFIG_HIDE_ERRORS))
101 			okBox(0, "System message", "Couldn't find a working audio mode... You'll get no sound / replayer timer!");
102 
103 		resumeAudio();
104 		return false;
105 	}
106 
107 	resumeAudio();
108 
109 	setWavRenderFrequency(audio.freq);
110 	setWavRenderBitDepth((config.specialFlags & BITDEPTH_32) ? 32 : 16);
111 	return true;
112 }
113 
114 // amp = 1..32, masterVol = 0..256
setAudioAmp(int16_t amp,int16_t masterVol,bool bitDepth32Flag)115 void setAudioAmp(int16_t amp, int16_t masterVol, bool bitDepth32Flag)
116 {
117 	amp = CLAMP(amp, 1, 32);
118 	masterVol = CLAMP(masterVol, 0, 256);
119 
120 	double dAmp = (amp * masterVol) / (32.0 * 256.0);
121 	if (!bitDepth32Flag)
122 		dAmp *= 32768.0;
123 
124 	dAudioNormalizeMul = dAmp;
125 	fAudioNormalizeMul = (float)dAmp;
126 }
127 
decreaseMasterVol(void)128 void decreaseMasterVol(void)
129 {
130 	if (config.masterVol >= 16)
131 		config.masterVol -= 16;
132 	else
133 		config.masterVol = 0;
134 
135 	setAudioAmp(config.boostLevel, config.masterVol, !!(config.specialFlags & BITDEPTH_32));
136 
137 	// if Config -> I/O Devices is open, update master volume scrollbar
138 	if (ui.configScreenShown && editor.currConfigScreen == CONFIG_SCREEN_IO_DEVICES)
139 		drawScrollBar(SB_MASTERVOL_SCROLL);
140 }
141 
increaseMasterVol(void)142 void increaseMasterVol(void)
143 {
144 	if (config.masterVol < (256-16))
145 		config.masterVol += 16;
146 	else
147 		config.masterVol = 256;
148 
149 	setAudioAmp(config.boostLevel, config.masterVol, !!(config.specialFlags & BITDEPTH_32));
150 
151 	// if Config -> I/O Devices is open, update master volume scrollbar
152 	if (ui.configScreenShown && editor.currConfigScreen == CONFIG_SCREEN_IO_DEVICES)
153 		drawScrollBar(SB_MASTERVOL_SCROLL);
154 }
155 
setNewAudioFreq(uint32_t freq)156 void setNewAudioFreq(uint32_t freq) // for song-to-WAV rendering
157 {
158 	if (freq == 0)
159 		return;
160 
161 	oldAudioFreq = audio.freq;
162 	audio.freq = freq;
163 
164 	const bool mustRecalcTables = audio.freq != oldAudioFreq;
165 	if (mustRecalcTables)
166 		calcReplayerVars(audio.freq);
167 }
168 
setBackOldAudioFreq(void)169 void setBackOldAudioFreq(void) // for song-to-WAV rendering
170 {
171 	const bool mustRecalcTables = audio.freq != oldAudioFreq;
172 
173 	audio.freq = oldAudioFreq;
174 
175 	if (mustRecalcTables)
176 		calcReplayerVars(audio.freq);
177 }
178 
setMixerBPM(int32_t bpm)179 void setMixerBPM(int32_t bpm)
180 {
181 	if (bpm < MIN_BPM || bpm > MAX_BPM)
182 		return;
183 
184 	int32_t i = bpm - MIN_BPM;
185 
186 	audio.samplesPerTick64 = audio.samplesPerTick64Tab[i]; // fixed-point
187 	audio.samplesPerTick = (audio.samplesPerTick64 + (1LL << 31)) >> 32; // rounded
188 
189 	// for audio/video sync timestamp
190 	tickTimeLen = audio.tickTimeTab[i];
191 	tickTimeLenFrac = audio.tickTimeFracTab[i];
192 
193 	// for calculating volume ramp length for tick-length ramps
194 	audio.fRampTickMul = audio.fRampTickMulTab[i];
195 }
196 
audioSetVolRamp(bool volRamp)197 void audioSetVolRamp(bool volRamp)
198 {
199 	lockMixerCallback();
200 	audio.volumeRampingFlag = volRamp;
201 	unlockMixerCallback();
202 }
203 
audioSetInterpolationType(uint8_t interpolationType)204 void audioSetInterpolationType(uint8_t interpolationType)
205 {
206 	lockMixerCallback();
207 	audio.interpolationType = interpolationType;
208 	unlockMixerCallback();
209 }
210 
calcPanningTable(void)211 void calcPanningTable(void)
212 {
213 	// same formula as FT2's panning table (with 0.0f..1.0f range)
214 	for (int32_t i = 0; i <= 256; i++)
215 		fPanningTab[i] = sqrtf(i / 256.0f);
216 }
217 
voiceUpdateVolumes(int32_t i,uint8_t status)218 static void voiceUpdateVolumes(int32_t i, uint8_t status)
219 {
220 	voice_t *v = &voice[i];
221 
222 	const float fVolumeL = v->fVolume * fPanningTab[256-v->panning];
223 	const float fVolumeR = v->fVolume * fPanningTab[    v->panning];
224 
225 	if (!audio.volumeRampingFlag)
226 	{
227 		// volume ramping is disabled
228 		v->fVolumeL = fVolumeL;
229 		v->fVolumeR = fVolumeR;
230 		v->volumeRampLength = 0;
231 		return;
232 	}
233 
234 	v->fVolumeLTarget = fVolumeL;
235 	v->fVolumeRTarget = fVolumeR;
236 
237 	if (status & IS_Trigger)
238 	{
239 		// sample is about to start, ramp out/in at the same time
240 
241 		// setup "fade out" voice (only if current voice volume > 0)
242 		if (v->fVolumeL > 0.0f || v->fVolumeR > 0.0f)
243 		{
244 			voice_t *f = &voice[MAX_CHANNELS+i];
245 
246 			*f = *v; // copy voice
247 
248 			f->volumeRampLength = audio.quickVolRampSamples;
249 
250 			const float fVolumeLTarget = -f->fVolumeL;
251 			const float fVolumeRTarget = -f->fVolumeR;
252 
253 			f->fVolumeLDelta = fVolumeLTarget * audio.fRampQuickVolMul;
254 			f->fVolumeRDelta = fVolumeRTarget * audio.fRampQuickVolMul;
255 
256 			f->isFadeOutVoice = true;
257 		}
258 
259 		// make current voice fade in from zero when it starts
260 		v->fVolumeL = 0.0f;
261 		v->fVolumeR = 0.0f;
262 	}
263 
264 	// ramp volume changes
265 
266 	/* FT2 has two internal volume ramping lengths:
267 	** IS_QuickVol: 5ms
268 	** Normal: The duration of a tick (samplesPerTick)
269 	*/
270 
271 	// if destination volume and current volume is the same (and we have no sample trigger), don't do ramp
272 	if (fVolumeL == v->fVolumeL && fVolumeR == v->fVolumeR && !(status & IS_Trigger))
273 	{
274 		// there is no volume change
275 		v->volumeRampLength = 0;
276 	}
277 	else
278 	{
279 		const float fVolumeLTarget = fVolumeL - v->fVolumeL;
280 		const float fVolumeRTarget = fVolumeR - v->fVolumeR;
281 
282 		if (status & IS_QuickVol)
283 		{
284 			v->fVolumeLDelta = fVolumeLTarget * audio.fRampQuickVolMul;
285 			v->fVolumeRDelta = fVolumeRTarget * audio.fRampQuickVolMul;
286 			v->volumeRampLength = audio.quickVolRampSamples;
287 
288 		}
289 		else
290 		{
291 			v->fVolumeLDelta = fVolumeLTarget * audio.fRampTickMul;
292 			v->fVolumeRDelta = fVolumeRTarget * audio.fRampTickMul;
293 			v->volumeRampLength = audio.samplesPerTick;
294 		}
295 	}
296 }
297 
voiceTrigger(int32_t ch,sample_t * s,int32_t position)298 static void voiceTrigger(int32_t ch, sample_t *s, int32_t position)
299 {
300 	voice_t *v = &voice[ch];
301 
302 	int32_t length = s->length;
303 	int32_t loopStart = s->loopStart;
304 	int32_t loopLength = s->loopLength;
305 	int32_t loopEnd = s->loopStart + s->loopLength;
306 	uint8_t loopType = GET_LOOPTYPE(s->flags);
307 	bool sample16Bit = !!(s->flags & SAMPLE_16BIT);
308 
309 	if (s->dataPtr == NULL || length < 1)
310 	{
311 		v->active = false; // shut down voice (illegal parameters)
312 		return;
313 	}
314 
315 	if (loopLength < 1) // disable loop if loopLength is below 1
316 		loopType = 0;
317 
318 	if (sample16Bit)
319 	{
320 		v->base16 = (const int16_t *)s->dataPtr;
321 		v->revBase16 = &v->base16[loopStart + loopEnd]; // for pingpong loops
322 		v->leftEdgeTaps16 = s->leftEdgeTapSamples16 + SINC_LEFT_TAPS;
323 	}
324 	else
325 	{
326 		v->base8 = s->dataPtr;
327 		v->revBase8 = &v->base8[loopStart + loopEnd]; // for pingpong loops
328 		v->leftEdgeTaps8 = s->leftEdgeTapSamples8 + SINC_LEFT_TAPS;
329 	}
330 
331 	v->hasLooped = false; // for sinc interpolation special case
332 	v->samplingBackwards = false;
333 	v->loopType = loopType;
334 	v->sampleEnd = (loopType == LOOP_OFF) ? length : loopEnd;
335 	v->loopStart = loopStart;
336 	v->loopLength = loopLength;
337 	v->position = position;
338 	v->positionFrac = 0;
339 
340 	// if position overflows, shut down voice (f.ex. through 9xx command)
341 	if (v->position >= v->sampleEnd)
342 	{
343 		v->active = false;
344 		return;
345 	}
346 
347 	v->mixFuncOffset = (sample16Bit * 9) + (audio.interpolationType * 3) + loopType;
348 	v->active = true;
349 }
350 
resetRampVolumes(void)351 void resetRampVolumes(void)
352 {
353 	voice_t *v = voice;
354 	for (int32_t i = 0; i < song.numChannels; i++, v++)
355 	{
356 		v->fVolumeL = v->fVolumeLTarget;
357 		v->fVolumeR = v->fVolumeRTarget;
358 		v->volumeRampLength = 0;
359 	}
360 }
361 
updateVoices(void)362 void updateVoices(void)
363 {
364 	channel_t *ch = channel;
365 	voice_t *v = voice;
366 
367 	for (int32_t i = 0; i < song.numChannels; i++, ch++, v++)
368 	{
369 		const uint8_t status = ch->tmpStatus = ch->status; // (tmpStatus is used for audio/video sync queue)
370 		if (status == 0)
371 			continue;
372 
373 		ch->status = 0;
374 
375 		if (status & IS_Vol)
376 		{
377 			v->fVolume = ch->fFinalVol;
378 
379 			const int32_t scopeVolume = (int32_t)((SCOPE_HEIGHT * ch->fFinalVol) + 0.5f); // rounded
380 			v->scopeVolume = (uint8_t)scopeVolume;
381 		}
382 
383 		if (status & IS_Pan)
384 			v->panning = ch->finalPan;
385 
386 		if (status & (IS_Vol + IS_Pan))
387 			voiceUpdateVolumes(i, status);
388 
389 		if (status & IS_Period)
390 		{
391 			// use cached values when possible
392 			if (ch->finalPeriod != ch->oldFinalPeriod)
393 			{
394 				ch->oldFinalPeriod = ch->finalPeriod;
395 
396 				if (ch->finalPeriod == 0) // in FT2, period 0 -> delta 0
397 				{
398 					v->scopeDelta = 0;
399 					v->oldDelta = 0;
400 					v->fSincLUT = fKaiserSinc;
401 				}
402 				else
403 				{
404 					const double dHz = dPeriod2Hz(ch->finalPeriod);
405 					const uintCPUWord_t delta = v->oldDelta = (intCPUWord_t)((dHz * audio.dHz2MixDeltaMul) + 0.5); // Hz -> fixed-point delta (rounded)
406 
407 					// decide which polyphase sinc LUT to use according to resampling ratio
408 					if (delta <= (uintCPUWord_t)(1.1875 * MIXER_FRAC_SCALE))
409 						v->fSincLUT = fKaiserSinc;
410 					else if (delta <= (uintCPUWord_t)(1.5 * MIXER_FRAC_SCALE))
411 						v->fSincLUT = fDownSample1;
412 					else
413 						v->fSincLUT = fDownSample2;
414 
415 					// set scope delta
416 					const double dHz2ScopeDeltaMul = SCOPE_FRAC_SCALE / (double)SCOPE_HZ;
417 					v->scopeDelta = (intCPUWord_t)((dHz * dHz2ScopeDeltaMul) + 0.5); // Hz -> fixed-point delta (rounded)
418 				}
419 			}
420 
421 			v->delta = v->oldDelta;
422 		}
423 
424 		if (status & IS_Trigger)
425 			voiceTrigger(i, ch->smpPtr, ch->smpStartPos);
426 	}
427 }
428 
resetAudioDither(void)429 void resetAudioDither(void)
430 {
431 	randSeed = INITIAL_DITHER_SEED;
432 	dPrngStateL = 0.0;
433 	dPrngStateR = 0.0;
434 }
435 
random32(void)436 static inline int32_t random32(void)
437 {
438 	// LCG 32-bit random
439 	randSeed *= 134775813;
440 	randSeed++;
441 
442 	return (int32_t)randSeed;
443 }
444 
sendSamples16BitDitherStereo(uint8_t * stream,uint32_t sampleBlockLength,uint8_t numAudioChannels)445 static void sendSamples16BitDitherStereo(uint8_t *stream, uint32_t sampleBlockLength, uint8_t numAudioChannels)
446 {
447 	int32_t out32;
448 	double dOut, dPrng;
449 
450 	int16_t *streamPointer16 = (int16_t *)stream;
451 	for (uint32_t i = 0; i < sampleBlockLength; i++)
452 	{
453 		// left channel - 1-bit triangular dithering
454 		dPrng = random32() * (0.5 / INT32_MAX); // -0.5 .. 0.5
455 		dOut = (double)audio.fMixBufferL[i] * dAudioNormalizeMul;
456 		dOut = (dOut + dPrng) - dPrngStateL;
457 		dPrngStateL = dPrng;
458 		out32 = (int32_t)dOut;
459 		CLAMP16(out32);
460 		*streamPointer16++ = (int16_t)out32;
461 
462 		// right channel - 1-bit triangular dithering
463 		dPrng = random32() * (0.5 / INT32_MAX); // -0.5 .. 0.5
464 		dOut = (double)audio.fMixBufferR[i] * dAudioNormalizeMul;
465 		dOut = (dOut + dPrng) - dPrngStateR;
466 		dPrngStateR = dPrng;
467 		out32 = (int32_t)dOut;
468 		CLAMP16(out32);
469 		*streamPointer16++ = (int16_t)out32;
470 
471 		// clear what we read from the mixing buffer
472 		audio.fMixBufferL[i] = 0.0f;
473 		audio.fMixBufferR[i] = 0.0f;
474 	}
475 
476 	(void)numAudioChannels;
477 }
478 
sendSamples16BitDitherMultiChan(uint8_t * stream,uint32_t sampleBlockLength,uint8_t numAudioChannels)479 static void sendSamples16BitDitherMultiChan(uint8_t *stream, uint32_t sampleBlockLength, uint8_t numAudioChannels)
480 {
481 	int32_t out32;
482 	double dOut, dPrng;
483 
484 	int16_t *streamPointer16 = (int16_t *)stream;
485 	for (uint32_t i = 0; i < sampleBlockLength; i++)
486 	{
487 		// left channel - 1-bit triangular dithering
488 		dPrng = random32() * (0.5 / INT32_MAX); // -0.5 .. 0.5
489 		dOut = (double)audio.fMixBufferL[i] * dAudioNormalizeMul;
490 		dOut = (dOut + dPrng) - dPrngStateL;
491 		dPrngStateL = dPrng;
492 		out32 = (int32_t)dOut;
493 		CLAMP16(out32);
494 		*streamPointer16++ = (int16_t)out32;
495 
496 		// right channel - 1-bit triangular dithering
497 		dPrng = random32() * (0.5 / INT32_MAX); // -0.5 .. 0.5
498 		dOut = (double)audio.fMixBufferR[i] * dAudioNormalizeMul;
499 		dOut = (dOut + dPrng) - dPrngStateR;
500 		dPrngStateR = dPrng;
501 		out32 = (int32_t)dOut;
502 		CLAMP16(out32);
503 		*streamPointer16++ = (int16_t)out32;
504 
505 		// clear what we read from the mixing buffer
506 		audio.fMixBufferL[i] = 0.0f;
507 		audio.fMixBufferR[i] = 0.0f;
508 
509 		// send zeroes to the rest of the channels
510 		for (uint32_t j = 2; j < numAudioChannels; j++)
511 			*streamPointer16++ = 0;
512 	}
513 }
514 
sendSamples32BitStereo(uint8_t * stream,uint32_t sampleBlockLength,uint8_t numAudioChannels)515 static void sendSamples32BitStereo(uint8_t *stream, uint32_t sampleBlockLength, uint8_t numAudioChannels)
516 {
517 	float fOut, *fStreamPointer32 = (float *)stream;
518 	for (uint32_t i = 0; i < sampleBlockLength; i++)
519 	{
520 		// left channel
521 		fOut = audio.fMixBufferL[i] * fAudioNormalizeMul;
522 		fOut = CLAMP(fOut, -1.0f, 1.0f);
523 		*fStreamPointer32++ = fOut;
524 
525 		// right channel
526 		fOut = audio.fMixBufferR[i] * fAudioNormalizeMul;
527 		fOut = CLAMP(fOut, -1.0f, 1.0f);
528 		*fStreamPointer32++ = fOut;
529 
530 		// clear what we read from the mixing buffer
531 		audio.fMixBufferL[i] = 0.0f;
532 		audio.fMixBufferR[i] = 0.0f;
533 	}
534 
535 	(void)numAudioChannels;
536 }
537 
sendSamples32BitMultiChan(uint8_t * stream,uint32_t sampleBlockLength,uint8_t numAudioChannels)538 static void sendSamples32BitMultiChan(uint8_t *stream, uint32_t sampleBlockLength, uint8_t numAudioChannels)
539 {
540 	float fOut, *fStreamPointer32 = (float *)stream;
541 	for (uint32_t i = 0; i < sampleBlockLength; i++)
542 	{
543 		// left channel
544 		fOut = audio.fMixBufferL[i] * fAudioNormalizeMul;
545 		fOut = CLAMP(fOut, -1.0f, 1.0f);
546 		*fStreamPointer32++ = fOut;
547 
548 		// right channel
549 		fOut = audio.fMixBufferR[i] * fAudioNormalizeMul;
550 		fOut = CLAMP(fOut, -1.0f, 1.0f);
551 		*fStreamPointer32++ = fOut;
552 
553 		// clear what we read from the mixing buffer
554 		audio.fMixBufferL[i] = 0.0f;
555 		audio.fMixBufferR[i] = 0.0f;
556 
557 		// send zeroes to the rest of the channels
558 		for (uint32_t j = 2; j < numAudioChannels; j++)
559 			*fStreamPointer32++ = 0.0f;
560 	}
561 }
562 
doChannelMixing(int32_t bufferPosition,int32_t samplesToMix)563 static void doChannelMixing(int32_t bufferPosition, int32_t samplesToMix)
564 {
565 	voice_t *v = voice; // normal voices
566 	voice_t *r = &voice[MAX_CHANNELS]; // volume ramp fadeout-voices
567 
568 	for (int32_t i = 0; i < song.numChannels; i++, v++, r++)
569 	{
570 		if (v->active)
571 		{
572 			bool centerMixFlag;
573 
574 			const bool volRampFlag = (v->volumeRampLength > 0);
575 			if (volRampFlag)
576 			{
577 				centerMixFlag = (v->fVolumeLTarget == v->fVolumeRTarget) && (v->fVolumeLDelta == v->fVolumeRDelta);
578 			}
579 			else // no volume ramping active
580 			{
581 				if (v->fVolumeL == 0.0f && v->fVolumeR == 0.0f)
582 				{
583 					silenceMixRoutine(v, samplesToMix);
584 					continue;
585 				}
586 
587 				centerMixFlag = (v->fVolumeL == v->fVolumeR);
588 			}
589 
590 			mixFuncTab[((int32_t)centerMixFlag * 36) + ((int32_t)volRampFlag * 18) + v->mixFuncOffset](v, bufferPosition, samplesToMix);
591 		}
592 
593 		if (r->active) // volume ramp fadeout-voice
594 		{
595 			const bool centerMixFlag = (r->fVolumeLTarget == r->fVolumeRTarget) && (r->fVolumeLDelta == r->fVolumeRDelta);
596 			mixFuncTab[((int32_t)centerMixFlag * 36) + 18 + r->mixFuncOffset](r, bufferPosition, samplesToMix);
597 		}
598 	}
599 }
600 
601 // used for song-to-WAV renderer
mixReplayerTickToBuffer(uint32_t samplesToMix,uint8_t * stream,uint8_t bitDepth)602 void mixReplayerTickToBuffer(uint32_t samplesToMix, uint8_t *stream, uint8_t bitDepth)
603 {
604 	assert(samplesToMix <= MAX_WAV_RENDER_SAMPLES_PER_TICK);
605 	doChannelMixing(0, samplesToMix);
606 
607 	// normalize mix buffer and send to audio stream
608 	if (bitDepth == 16)
609 		sendSamples16BitDitherStereo(stream, samplesToMix, 2);
610 	else
611 		sendSamples32BitStereo(stream, samplesToMix, 2);
612 }
613 
pattQueueReadSize(void)614 int32_t pattQueueReadSize(void)
615 {
616 	while (pattQueueClearing);
617 
618 	if (pattSync.writePos > pattSync.readPos)
619 		return pattSync.writePos - pattSync.readPos;
620 	else if (pattSync.writePos < pattSync.readPos)
621 		return pattSync.writePos - pattSync.readPos + SYNC_QUEUE_LEN + 1;
622 	else
623 		return 0;
624 }
625 
pattQueueWriteSize(void)626 int32_t pattQueueWriteSize(void)
627 {
628 	int32_t size;
629 
630 	if (pattSync.writePos > pattSync.readPos)
631 	{
632 		size = pattSync.readPos - pattSync.writePos + SYNC_QUEUE_LEN;
633 	}
634 	else if (pattSync.writePos < pattSync.readPos)
635 	{
636 		pattQueueClearing = true;
637 
638 		/* Buffer is full, reset the read/write pos. This is actually really nasty since
639 		** read/write are two different threads, but because of timestamp validation it
640 		** shouldn't be that dangerous.
641 		** It will also create a small visual stutter while the buffer is getting filled,
642 		** though that is barely noticable on normal buffer sizes, and it takes a minute
643 		** or two at max BPM between each time (when queue size is default, 4095)
644 		*/
645 		pattSync.data[0].timestamp = 0;
646 		pattSync.readPos = 0;
647 		pattSync.writePos = 0;
648 
649 		size = SYNC_QUEUE_LEN;
650 
651 		pattQueueClearing = false;
652 	}
653 	else
654 	{
655 		size = SYNC_QUEUE_LEN;
656 	}
657 
658 	return size;
659 }
660 
pattQueuePush(pattSyncData_t t)661 bool pattQueuePush(pattSyncData_t t)
662 {
663 	if (!pattQueueWriteSize())
664 		return false;
665 
666 	assert(pattSync.writePos <= SYNC_QUEUE_LEN);
667 	pattSync.data[pattSync.writePos] = t;
668 	pattSync.writePos = (pattSync.writePos + 1) & SYNC_QUEUE_LEN;
669 
670 	return true;
671 }
672 
pattQueuePop(void)673 bool pattQueuePop(void)
674 {
675 	if (!pattQueueReadSize())
676 		return false;
677 
678 	pattSync.readPos = (pattSync.readPos + 1) & SYNC_QUEUE_LEN;
679 	assert(pattSync.readPos <= SYNC_QUEUE_LEN);
680 
681 	return true;
682 }
683 
pattQueuePeek(void)684 pattSyncData_t *pattQueuePeek(void)
685 {
686 	if (!pattQueueReadSize())
687 		return NULL;
688 
689 	assert(pattSync.readPos <= SYNC_QUEUE_LEN);
690 	return &pattSync.data[pattSync.readPos];
691 }
692 
getPattQueueTimestamp(void)693 uint64_t getPattQueueTimestamp(void)
694 {
695 	if (!pattQueueReadSize())
696 		return 0;
697 
698 	assert(pattSync.readPos <= SYNC_QUEUE_LEN);
699 	return pattSync.data[pattSync.readPos].timestamp;
700 }
701 
chQueueReadSize(void)702 int32_t chQueueReadSize(void)
703 {
704 	while (chQueueClearing);
705 
706 	if (chSync.writePos > chSync.readPos)
707 		return chSync.writePos - chSync.readPos;
708 	else if (chSync.writePos < chSync.readPos)
709 		return chSync.writePos - chSync.readPos + SYNC_QUEUE_LEN + 1;
710 	else
711 		return 0;
712 }
713 
chQueueWriteSize(void)714 int32_t chQueueWriteSize(void)
715 {
716 	int32_t size;
717 
718 	if (chSync.writePos > chSync.readPos)
719 	{
720 		size = chSync.readPos - chSync.writePos + SYNC_QUEUE_LEN;
721 	}
722 	else if (chSync.writePos < chSync.readPos)
723 	{
724 		chQueueClearing = true;
725 
726 		/* Buffer is full, reset the read/write pos. This is actually really nasty since
727 		** read/write are two different threads, but because of timestamp validation it
728 		** shouldn't be that dangerous.
729 		** It will also create a small visual stutter while the buffer is getting filled,
730 		** though that is barely noticable on normal buffer sizes, and it takes several
731 		** minutes between each time (when queue size is default, 16384)
732 		*/
733 		chSync.data[0].timestamp = 0;
734 		chSync.readPos = 0;
735 		chSync.writePos = 0;
736 
737 		size = SYNC_QUEUE_LEN;
738 
739 		chQueueClearing = false;
740 	}
741 	else
742 	{
743 		size = SYNC_QUEUE_LEN;
744 	}
745 
746 	return size;
747 }
748 
chQueuePush(chSyncData_t t)749 bool chQueuePush(chSyncData_t t)
750 {
751 	if (!chQueueWriteSize())
752 		return false;
753 
754 	assert(chSync.writePos <= SYNC_QUEUE_LEN);
755 	chSync.data[chSync.writePos] = t;
756 	chSync.writePos = (chSync.writePos + 1) & SYNC_QUEUE_LEN;
757 
758 	return true;
759 }
760 
chQueuePop(void)761 bool chQueuePop(void)
762 {
763 	if (!chQueueReadSize())
764 		return false;
765 
766 	chSync.readPos = (chSync.readPos + 1) & SYNC_QUEUE_LEN;
767 	assert(chSync.readPos <= SYNC_QUEUE_LEN);
768 
769 	return true;
770 }
771 
chQueuePeek(void)772 chSyncData_t *chQueuePeek(void)
773 {
774 	if (!chQueueReadSize())
775 		return NULL;
776 
777 	assert(chSync.readPos <= SYNC_QUEUE_LEN);
778 	return &chSync.data[chSync.readPos];
779 }
780 
getChQueueTimestamp(void)781 uint64_t getChQueueTimestamp(void)
782 {
783 	if (!chQueueReadSize())
784 		return 0;
785 
786 	assert(chSync.readPos <= SYNC_QUEUE_LEN);
787 	return chSync.data[chSync.readPos].timestamp;
788 }
789 
lockAudio(void)790 void lockAudio(void)
791 {
792 	if (audio.dev != 0)
793 		SDL_LockAudioDevice(audio.dev);
794 
795 	audio.locked = true;
796 }
797 
unlockAudio(void)798 void unlockAudio(void)
799 {
800 	if (audio.dev != 0)
801 		SDL_UnlockAudioDevice(audio.dev);
802 
803 	audio.locked = false;
804 }
805 
resetSyncQueues(void)806 void resetSyncQueues(void)
807 {
808 	pattSync.data[0].timestamp = 0;
809 	pattSync.readPos = 0;
810 	pattSync.writePos = 0;
811 
812 	chSync.data[0].timestamp = 0;
813 	chSync.writePos = 0;
814 	chSync.readPos = 0;
815 }
816 
lockMixerCallback(void)817 void lockMixerCallback(void) // lock audio + clear voices/scopes (for short operations)
818 {
819 	if (!audio.locked)
820 		lockAudio();
821 
822 	audio.resetSyncTickTimeFlag = true;
823 
824 	stopVoices(); // VERY important! prevents potential crashes by purging pointers
825 
826 	// scopes, mixer and replayer are guaranteed to not be active at this point
827 
828 	resetSyncQueues();
829 }
830 
unlockMixerCallback(void)831 void unlockMixerCallback(void)
832 {
833 	stopVoices(); // VERY important! prevents potential crashes by purging pointers
834 
835 	if (audio.locked)
836 		unlockAudio();
837 }
838 
pauseAudio(void)839 void pauseAudio(void) // lock audio + clear voices/scopes + render silence (for long operations)
840 {
841 	if (audioPaused)
842 	{
843 		stopVoices(); // VERY important! prevents potential crashes by purging pointers
844 		return;
845 	}
846 
847 	if (audio.dev > 0)
848 		SDL_PauseAudioDevice(audio.dev, true);
849 
850 	audio.resetSyncTickTimeFlag = true;
851 
852 	stopVoices(); // VERY important! prevents potential crashes by purging pointers
853 
854 	// scopes, mixer and replayer are guaranteed to not be active at this point
855 
856 	resetSyncQueues();
857 	audioPaused = true;
858 }
859 
resumeAudio(void)860 void resumeAudio(void) // unlock audio
861 {
862 	if (!audioPaused)
863 		return;
864 
865 	if (audio.dev > 0)
866 		SDL_PauseAudioDevice(audio.dev, false);
867 
868 	audioPaused = false;
869 }
870 
fillVisualsSyncBuffer(void)871 static void fillVisualsSyncBuffer(void)
872 {
873 	pattSyncData_t pattSyncData;
874 	chSyncData_t chSyncData;
875 
876 	if (audio.resetSyncTickTimeFlag)
877 	{
878 		audio.resetSyncTickTimeFlag = false;
879 
880 		audio.tickTime64 = SDL_GetPerformanceCounter() + audio.audLatencyPerfValInt;
881 		audio.tickTime64Frac = audio.audLatencyPerfValFrac;
882 	}
883 
884 	if (songPlaying)
885 	{
886 		// push pattern variables to sync queue
887 		pattSyncData.tick = song.curReplayerTick;
888 		pattSyncData.row = song.curReplayerRow;
889 		pattSyncData.pattNum = song.curReplayerPattNum;
890 		pattSyncData.songPos = song.curReplayerSongPos;
891 		pattSyncData.BPM = song.BPM;
892 		pattSyncData.speed = (uint8_t)song.speed;
893 		pattSyncData.globalVolume = (uint8_t)song.globalVolume;
894 		pattSyncData.timestamp = audio.tickTime64;
895 		pattQueuePush(pattSyncData);
896 	}
897 
898 	// push channel variables to sync queue
899 
900 	syncedChannel_t *c = chSyncData.channels;
901 	channel_t *s = channel;
902 	voice_t *v = voice;
903 
904 	for (int32_t i = 0; i < song.numChannels; i++, c++, s++, v++)
905 	{
906 		c->scopeVolume = v->scopeVolume;
907 		c->scopeDelta = v->scopeDelta;
908 		c->instrNum = s->instrNum;
909 		c->smpNum = s->smpNum;
910 		c->status = s->tmpStatus;
911 		c->smpStartPos = s->smpStartPos;
912 
913 		c->pianoNoteNum = 255; // no piano key
914 		if (songPlaying && (c->status & IS_Period) && s->envSustainActive)
915 		{
916 			const int32_t note = getPianoKey(s->finalPeriod, s->finetune, s->relativeNote);
917 			if (note >= 0 && note <= 95)
918 				c->pianoNoteNum = (uint8_t)note;
919 		}
920 	}
921 
922 	chSyncData.timestamp = audio.tickTime64;
923 	chQueuePush(chSyncData);
924 
925 	audio.tickTime64 += tickTimeLen;
926 	audio.tickTime64Frac += tickTimeLenFrac;
927 	if (audio.tickTime64Frac > UINT32_MAX)
928 	{
929 		audio.tickTime64Frac &= UINT32_MAX;
930 		audio.tickTime64++;
931 	}
932 }
933 
audioCallback(void * userdata,Uint8 * stream,int len)934 static void SDLCALL audioCallback(void *userdata, Uint8 *stream, int len)
935 {
936 	if (editor.wavIsRendering)
937 		return;
938 
939 	len /= pmpCountDiv; // bytes -> samples
940 	if (len <= 0)
941 		return;
942 
943 	assert(len <= MAX_WAV_RENDER_SAMPLES_PER_TICK);
944 
945 	int32_t bufferPosition = 0;
946 
947 	int32_t samplesLeft = len;
948 	while (samplesLeft > 0)
949 	{
950 		if (audio.tickSampleCounter64 <= 0) // new replayer tick
951 		{
952 			replayerBusy = true;
953 
954 			if (audio.volumeRampingFlag)
955 				resetRampVolumes();
956 
957 			tickReplayer();
958 			updateVoices();
959 			fillVisualsSyncBuffer();
960 
961 			audio.tickSampleCounter64 += audio.samplesPerTick64;
962 
963 			replayerBusy = false;
964 		}
965 
966 		const int32_t remainingTick = (audio.tickSampleCounter64 + UINT32_MAX) >> 32; // ceil (rounded upwards)
967 
968 		int32_t samplesToMix = samplesLeft;
969 		if (samplesToMix > remainingTick)
970 			samplesToMix = remainingTick;
971 
972 		doChannelMixing(bufferPosition, samplesToMix);
973 
974 		bufferPosition += samplesToMix;
975 		samplesLeft -= samplesToMix;
976 		audio.tickSampleCounter64 -= (int64_t)samplesToMix << 32;
977 	}
978 
979 	// normalize mix buffer and send to audio stream
980 	sendAudSamplesFunc(stream, len, pmpChannels);
981 
982 	(void)userdata;
983 }
984 
setupAudioBuffers(void)985 static bool setupAudioBuffers(void)
986 {
987 	const uint32_t sampleSize = sizeof (float);
988 
989 	audio.fMixBufferLUnaligned = (float *)MALLOC_PAD(MAX_WAV_RENDER_SAMPLES_PER_TICK * sampleSize, 256);
990 	audio.fMixBufferRUnaligned = (float *)MALLOC_PAD(MAX_WAV_RENDER_SAMPLES_PER_TICK * sampleSize, 256);
991 
992 	if (audio.fMixBufferLUnaligned == NULL || audio.fMixBufferRUnaligned == NULL)
993 		return false;
994 
995 	// make aligned main pointers
996 	audio.fMixBufferL = (float *)ALIGN_PTR(audio.fMixBufferLUnaligned, 256);
997 	audio.fMixBufferR = (float *)ALIGN_PTR(audio.fMixBufferRUnaligned, 256);
998 
999 	// clear buffers
1000 	memset(audio.fMixBufferL, 0, MAX_WAV_RENDER_SAMPLES_PER_TICK * sampleSize);
1001 	memset(audio.fMixBufferR, 0, MAX_WAV_RENDER_SAMPLES_PER_TICK * sampleSize);
1002 
1003 	return true;
1004 }
1005 
freeAudioBuffers(void)1006 static void freeAudioBuffers(void)
1007 {
1008 	if (audio.fMixBufferLUnaligned != NULL)
1009 	{
1010 		free(audio.fMixBufferLUnaligned);
1011 		audio.fMixBufferLUnaligned = NULL;
1012 	}
1013 
1014 	if (audio.fMixBufferRUnaligned != NULL)
1015 	{
1016 		free(audio.fMixBufferRUnaligned);
1017 		audio.fMixBufferRUnaligned = NULL;
1018 	}
1019 
1020 	audio.fMixBufferL = NULL;
1021 	audio.fMixBufferR = NULL;
1022 }
1023 
updateSendAudSamplesRoutine(bool lockMixer)1024 void updateSendAudSamplesRoutine(bool lockMixer)
1025 {
1026 	if (lockMixer)
1027 		lockMixerCallback();
1028 
1029 	if (config.specialFlags & BITDEPTH_16)
1030 	{
1031 		if (pmpChannels > 2)
1032 			sendAudSamplesFunc = sendSamples16BitDitherMultiChan;
1033 		else
1034 			sendAudSamplesFunc = sendSamples16BitDitherStereo;
1035 	}
1036 	else
1037 	{
1038 		if (pmpChannels > 2)
1039 			sendAudSamplesFunc = sendSamples32BitMultiChan;
1040 		else
1041 			sendAudSamplesFunc = sendSamples32BitStereo;
1042 	}
1043 
1044 	if (lockMixer)
1045 		unlockMixerCallback();
1046 }
1047 
calcAudioLatencyVars(int32_t audioBufferSize,int32_t audioFreq)1048 static void calcAudioLatencyVars(int32_t audioBufferSize, int32_t audioFreq)
1049 {
1050 	double dInt;
1051 
1052 	if (audioFreq == 0)
1053 		return;
1054 
1055 	const double dAudioLatencySecs = audioBufferSize / (double)audioFreq;
1056 
1057 	double dFrac = modf(dAudioLatencySecs * editor.dPerfFreq, &dInt);
1058 
1059 	// integer part
1060 	audio.audLatencyPerfValInt = (int32_t)dInt;
1061 
1062 	// fractional part (scaled to 0..2^32-1)
1063 	dFrac *= UINT32_MAX+1.0;
1064 	audio.audLatencyPerfValFrac = (uint32_t)dFrac;
1065 
1066 	audio.dAudioLatencyMs = dAudioLatencySecs * 1000.0;
1067 }
1068 
setLastWorkingAudioDevName(void)1069 static void setLastWorkingAudioDevName(void)
1070 {
1071 	if (audio.lastWorkingAudioDeviceName != NULL)
1072 	{
1073 		free(audio.lastWorkingAudioDeviceName);
1074 		audio.lastWorkingAudioDeviceName = NULL;
1075 	}
1076 
1077 	if (audio.currOutputDevice != NULL)
1078 		audio.lastWorkingAudioDeviceName = strdup(audio.currOutputDevice);
1079 }
1080 
setupAudio(bool showErrorMsg)1081 bool setupAudio(bool showErrorMsg)
1082 {
1083 	SDL_AudioSpec want, have;
1084 
1085 	closeAudio();
1086 
1087 	if (config.audioFreq < MIN_AUDIO_FREQ || config.audioFreq > MAX_AUDIO_FREQ)
1088 		config.audioFreq = DEFAULT_AUDIO_FREQ;
1089 
1090 	// get audio buffer size from config special flags
1091 
1092 	uint16_t configAudioBufSize = 1024;
1093 	if (config.specialFlags & BUFFSIZE_512)
1094 		configAudioBufSize = 512;
1095 	else if (config.specialFlags & BUFFSIZE_2048)
1096 		configAudioBufSize = 2048;
1097 
1098 	audio.wantFreq = config.audioFreq;
1099 	audio.wantSamples = configAudioBufSize;
1100 	audio.wantChannels = 2;
1101 
1102 	// set up audio device
1103 	memset(&want, 0, sizeof (want));
1104 
1105 	// these three may change after opening a device, but our mixer is dealing with it
1106 	want.freq = config.audioFreq;
1107 	want.format = (config.specialFlags & BITDEPTH_32) ? AUDIO_F32 : AUDIO_S16;
1108 	want.channels = 2;
1109 	// -------------------------------------------------------------------------------
1110 	want.callback = audioCallback;
1111 	want.samples  = configAudioBufSize;
1112 
1113 	audio.dev = SDL_OpenAudioDevice(audio.currOutputDevice, 0, &want, &have, SDL_AUDIO_ALLOW_ANY_CHANGE); // prevent SDL2 from resampling
1114 	if (audio.dev == 0)
1115 	{
1116 		if (showErrorMsg)
1117 			showErrorMsgBox("Couldn't open audio device:\n\"%s\"\n\nDo you have any audio device enabled and plugged in?", SDL_GetError());
1118 
1119 		return false;
1120 	}
1121 
1122 	// test if the received audio format is compatible
1123 	if (have.format != AUDIO_S16 && have.format != AUDIO_F32)
1124 	{
1125 		if (showErrorMsg)
1126 			showErrorMsgBox("Couldn't open audio device:\nThe program doesn't support an SDL_AudioFormat of '%d' (not 16-bit or 32-bit float).",
1127 				(uint32_t)have.format);
1128 
1129 		closeAudio();
1130 		return false;
1131 	}
1132 
1133 	// test if the received audio rate is compatible
1134 
1135 #if CPU_64BIT
1136 	if (have.freq != 44100 && have.freq != 48000 && have.freq != 96000 && have.freq != 192000)
1137 #else
1138 	if (have.freq != 44100 && have.freq != 48000)
1139 #endif
1140 	{
1141 		if (showErrorMsg)
1142 			showErrorMsgBox("Couldn't open audio device:\nThis program doesn't support an audio output rate of %dHz. Sorry!", have.freq);
1143 
1144 		closeAudio();
1145 		return false;
1146 	}
1147 
1148 	if (!setupAudioBuffers())
1149 	{
1150 		if (showErrorMsg)
1151 			showErrorMsgBox("Not enough memory!");
1152 
1153 		closeAudio();
1154 		return false;
1155 	}
1156 
1157 	// set new bit depth flag
1158 
1159 	int8_t newBitDepth = 16;
1160 	config.specialFlags &= ~BITDEPTH_32;
1161 	config.specialFlags |=  BITDEPTH_16;
1162 
1163 	if (have.format == AUDIO_F32)
1164 	{
1165 		newBitDepth = 24;
1166 		config.specialFlags &= ~BITDEPTH_16;
1167 		config.specialFlags |=  BITDEPTH_32;
1168 	}
1169 
1170 	audio.haveFreq = have.freq;
1171 	audio.haveSamples = have.samples;
1172 	audio.haveChannels = have.channels;
1173 
1174 	// set a few variables
1175 
1176 	config.audioFreq = have.freq;
1177 	audio.freq = have.freq;
1178 	smpBuffSize = have.samples;
1179 
1180 	calcAudioLatencyVars(have.samples, have.freq);
1181 
1182 	pmpChannels = have.channels;
1183 	pmpCountDiv = pmpChannels * ((newBitDepth == 16) ? sizeof (int16_t) : sizeof (float));
1184 
1185 	// make a copy of the new known working audio settings
1186 
1187 	audio.lastWorkingAudioFreq = config.audioFreq;
1188 	audio.lastWorkingAudioBits = config.specialFlags & (BITDEPTH_16 + BITDEPTH_32 + BUFFSIZE_512 + BUFFSIZE_1024 + BUFFSIZE_2048);
1189 	setLastWorkingAudioDevName();
1190 
1191 	// update config audio radio buttons if we're on that screen at the moment
1192 	if (ui.configScreenShown && editor.currConfigScreen == CONFIG_SCREEN_IO_DEVICES)
1193 		showConfigScreen();
1194 
1195 	updateWavRendererSettings();
1196 	setAudioAmp(config.boostLevel, config.masterVol, !!(config.specialFlags & BITDEPTH_32));
1197 
1198 	// don't call stopVoices() in this routine
1199 	for (int32_t i = 0; i < MAX_CHANNELS; i++)
1200 		stopVoice(i);
1201 
1202 	stopAllScopes();
1203 
1204 	audio.tickSampleCounter64 = 0; // zero tick sample counter so that it will instantly initiate a tick
1205 
1206 	calcReplayerVars(audio.freq);
1207 
1208 	if (song.BPM == 0)
1209 		song.BPM = 125;
1210 
1211 	setMixerBPM(song.BPM); // this is important
1212 
1213 	updateSendAudSamplesRoutine(false);
1214 	audio.resetSyncTickTimeFlag = true;
1215 
1216 	setWavRenderFrequency(audio.freq);
1217 	setWavRenderBitDepth((config.specialFlags & BITDEPTH_32) ? 32 : 16);
1218 
1219 	return true;
1220 }
1221 
closeAudio(void)1222 void closeAudio(void)
1223 {
1224 	if (audio.dev > 0)
1225 	{
1226 		SDL_PauseAudioDevice(audio.dev, true);
1227 		SDL_CloseAudioDevice(audio.dev);
1228 		audio.dev = 0;
1229 	}
1230 
1231 	freeAudioBuffers();
1232 }
1233