shithub: ft²

Download patch

ref: 89cb1fd4c15081a81c760389e6ff1f2f7cd5dd19
parent: 0909b673f37e1eb88c4948e3b95e9d6091d0a8e4
author: Olav Sørensen <olav.sorensen@live.no>
date: Fri Dec 1 12:12:55 EST 2023

float instr. envelopes + double->float on voice vols

64-bit double-precision was not really needed for these calculations.

--- a/src/ft2_audio.c
+++ b/src/ft2_audio.c
@@ -26,7 +26,7 @@
 static int32_t smpShiftValue;
 static uint32_t oldAudioFreq, tickTimeLenInt;
 static uint64_t tickTimeLenFrac;
-static double dAudioNormalizeMul, dSqrtPanningTable[256+1];
+static float fAudioNormalizeMul, fSqrtPanningTable[256+1];
 static voice_t voice[MAX_CHANNELS * 2];
 
 // globalized
@@ -115,7 +115,7 @@
 	if (!bitDepth32Flag)
 		dAmp *= 32768.0;
 
-	dAudioNormalizeMul = dAmp;
+	fAudioNormalizeMul = (float)dAmp;
 }
 
 void decreaseMasterVol(void)
@@ -196,7 +196,7 @@
 	lockMixerCallback();
 	audio.interpolationType = interpolationType;
 
-	// set sinc polyphase LUT pointers
+	// set sinc LUT pointers
 	if (config.interpolation == INTERPOLATION_SINC8)
 	{
 		fKaiserSinc = fKaiserSinc_8;
@@ -217,7 +217,7 @@
 {
 	// same formula as FT2's panning table (with 0.0 .. 1.0 scale)
 	for (int32_t i = 0; i <= 256; i++)
-		dSqrtPanningTable[i] = sqrt(i / 256.0);
+		fSqrtPanningTable[i] = (float)sqrt(i / 256.0);
 }
 
 static void voiceUpdateVolumes(int32_t i, uint8_t status)
@@ -224,8 +224,8 @@
 {
 	voice_t *v = &voice[i];
 
-	v->fTargetVolumeL = (float)(v->dVolume * dSqrtPanningTable[256-v->panning]);
-	v->fTargetVolumeR = (float)(v->dVolume * dSqrtPanningTable[    v->panning]);
+	v->fTargetVolumeL = v->fVolume * fSqrtPanningTable[256-v->panning];
+	v->fTargetVolumeR = v->fVolume * fSqrtPanningTable[    v->panning];
 
 	if (!audio.volumeRampingFlag)
 	{
@@ -250,7 +250,7 @@
 
 			voice_t *f = &voice[MAX_CHANNELS+i];
 
-			*f = *v; // store current voice in respective fadeout ramp voice
+			*f = *v; // copy current voice to new fadeout-ramp voice
 
 			const float fVolumeLDiff = 0.0f - f->fCurrVolumeL;
 			const float fVolumeRDiff = 0.0f - f->fCurrVolumeR;
@@ -365,10 +365,10 @@
 
 		if (status & IS_Vol)
 		{
-			v->dVolume = ch->dFinalVol;
+			v->fVolume = ch->fFinalVol;
 
 			// set scope volume
-			const int32_t scopeVolume = (int32_t)((SCOPE_HEIGHT * ch->dFinalVol) + 0.5); // rounded
+			const int32_t scopeVolume = (int32_t)((SCOPE_HEIGHT * ch->fFinalVol) + 0.5f); // rounded
 			v->scopeVolume = (uint8_t)scopeVolume;
 		}
 
@@ -387,9 +387,9 @@
 
 				if (ch->finalPeriod == 0) // in FT2, period 0 -> delta 0
 				{
-					v->scopeDelta = 0;
 					v->oldDelta = 0;
 					v->fSincLUT = fKaiserSinc;
+					v->scopeDelta = 0;
 				}
 				else
 				{
@@ -396,7 +396,7 @@
 					const double dHz = dPeriod2Hz(ch->finalPeriod);
 					const uintCPUWord_t delta = v->oldDelta = (intCPUWord_t)((dHz * audio.dHz2MixDeltaMul) + 0.5); // Hz -> fixed-point delta (rounded)
 
-					// decide which polyphase sinc LUT to use according to resampling ratio
+					// decide which sinc LUT to use according to the resampling ratio
 					if (delta <= (uintCPUWord_t)(1.1875 * MIXER_FRAC_SCALE))
 						v->fSincLUT = fKaiserSinc;
 					else if (delta <= (uintCPUWord_t)(1.5 * MIXER_FRAC_SCALE))
@@ -418,19 +418,22 @@
 	}
 }
 
-static void sendSamples16BitStereo(uint8_t *stream, uint32_t sampleBlockLength)
+static void sendSamples16BitStereo(void *stream, uint32_t sampleBlockLength)
 {
-	int16_t *streamPointer16 = (int16_t *)stream;
+	int16_t *streamPtr16 = (int16_t *)stream;
 	for (uint32_t i = 0; i < sampleBlockLength; i++)
 	{
-		int32_t L = (int32_t)((double)audio.fMixBufferL[i] * dAudioNormalizeMul);
-		CLAMP16(L);
-		*streamPointer16++ = (int16_t)L;
+		// TODO: This could use dithering (a proper implementation, that is...)
 
-		int32_t R = (int32_t)((double)audio.fMixBufferR[i] * dAudioNormalizeMul);
+		int32_t L = (int32_t)(audio.fMixBufferL[i] * fAudioNormalizeMul);
+		int32_t R = (int32_t)(audio.fMixBufferR[i] * fAudioNormalizeMul);
+
+		CLAMP16(L);
 		CLAMP16(R);
-		*streamPointer16++ = (int16_t)R;
 
+		*streamPtr16++ = (int16_t)L;
+		*streamPtr16++ = (int16_t)R;
+
 		// clear what we read from the mixing buffer
 		audio.fMixBufferL[i] = 0.0f;
 		audio.fMixBufferR[i] = 0.0f;
@@ -437,18 +440,16 @@
 	}
 }
 
-static void sendSamples32BitFloatStereo(uint8_t *stream, uint32_t sampleBlockLength)
+static void sendSamples32BitFloatStereo(void *stream, uint32_t sampleBlockLength)
 {
-	float *fStreamPointer32 = (float *)stream;
+	float *fStreamPtr32 = (float *)stream;
 	for (uint32_t i = 0; i < sampleBlockLength; i++)
 	{
-		double dL = (double)audio.fMixBufferL[i] * dAudioNormalizeMul;
-		dL = CLAMP(dL, -1.0, 1.0);
-		*fStreamPointer32++ = (float)dL;
+		const float fL = audio.fMixBufferL[i] * fAudioNormalizeMul;
+		const float fR = audio.fMixBufferR[i] * fAudioNormalizeMul;
 
-		double dR = (double)audio.fMixBufferR[i] * dAudioNormalizeMul;
-		dR = CLAMP(dR, -1.0, 1.0);
-		*fStreamPointer32++ = (float)dR;
+		*fStreamPtr32++ = CLAMP(fL, -1.0f, 1.0f);
+		*fStreamPtr32++ = CLAMP(fR, -1.0f, 1.0f);
 
 		// clear what we read from the mixing buffer
 		audio.fMixBufferL[i] = 0.0f;
@@ -495,7 +496,7 @@
 }
 
 // used for song-to-WAV renderer
-void mixReplayerTickToBuffer(uint32_t samplesToMix, uint8_t *stream, uint8_t bitDepth)
+void mixReplayerTickToBuffer(uint32_t samplesToMix, void *stream, uint8_t bitDepth)
 {
 	doChannelMixing(0, samplesToMix);
 
--- a/src/ft2_audio.h
+++ b/src/ft2_audio.h
@@ -78,8 +78,7 @@
 	const int16_t *leftEdgeTaps16;
 
 	const float *fSincLUT;
-	double dVolume;
-	float fCurrVolumeL, fCurrVolumeR, fVolumeLDelta, fVolumeRDelta, fTargetVolumeL, fTargetVolumeR;
+	float fVolume, fCurrVolumeL, fCurrVolumeR, fVolumeLDelta, fVolumeRDelta, fTargetVolumeL, fTargetVolumeR;
 } voice_t;
 
 #ifdef _MSC_VER
@@ -155,7 +154,7 @@
 void unlockMixerCallback(void);
 void resetRampVolumes(void);
 void updateVoices(void);
-void mixReplayerTickToBuffer(uint32_t samplesToMix, uint8_t *stream, uint8_t bitDepth);
+void mixReplayerTickToBuffer(uint32_t samplesToMix, void *stream, uint8_t bitDepth);
 
 // in ft2_audio.c
 extern audio_t audio;
--- a/src/ft2_header.h
+++ b/src/ft2_header.h
@@ -12,7 +12,7 @@
 #endif
 #include "ft2_replayer.h"
 
-#define PROG_VER_STR "1.73"
+#define PROG_VER_STR "1.74"
 
 // do NOT change these! It will only mess things up...
 
--- a/src/ft2_replayer.c
+++ b/src/ft2_replayer.c
@@ -758,12 +758,12 @@
 {
 	bool envUpdate;
 	int8_t point;
-	int16_t tick;
+	int32_t tick;
 
 	instr_t *ins = ch->instrPtr;
 	assert(ins != NULL);
 
-	// (envelope precision has been updated from x.8fp to x.16fp)
+	// envelope precision has been upgraded from .8fp to single-precision float
 
 	// *** VOLUME ENVELOPE ***
 	if (ins->volEnvFlags & ENV_ENABLED)
@@ -784,23 +784,25 @@
 					point--;
 
 					tick -= ins->volEnvPoints[point][0];
-					if (tick == 0)
+					if (tick == 0) // FT2 doesn't test for <= 0 here
 					{
 						envUpdate = false;
 						break;
 					}
 
-					if (ins->volEnvPoints[point+1][0] <= ins->volEnvPoints[point][0])
+					const int32_t xDiff = ins->volEnvPoints[point+1][0] - ins->volEnvPoints[point+0][0];
+					if (xDiff <= 0)
 					{
 						envUpdate = true;
 						break;
 					}
 
-					int32_t delta = (int8_t)((ins->volEnvPoints[point+1][1] - ins->volEnvPoints[point][1]) & 0xFF) << 16;
-					delta /= (ins->volEnvPoints[point+1][0]-ins->volEnvPoints[point][0]);
+					const int32_t y0 = ins->volEnvPoints[point+0][1] & 0xFF;
+					const int32_t y1 = ins->volEnvPoints[point+1][1] & 0xFF;
+					const int32_t yDiff = y1 - y0;
 
-					ch->volEnvDelta = delta;
-					ch->volEnvValue = (ch->volEnvDelta * (tick-1)) + ((int8_t)(ins->volEnvPoints[point][1] & 0xFF) << 16);
+					ch->fVolEnvDelta = (float)yDiff / (float)xDiff;
+					ch->fVolEnvValue = (float)y0 + (ch->fVolEnvDelta * (tick-1));
 
 					point++;
 
@@ -817,8 +819,8 @@
 
 		if (envUpdate)
 		{
-			ch->volEnvDelta = 0;
-			ch->volEnvValue = (int8_t)(ins->volEnvPoints[point][1] & 0xFF) << 16;
+			ch->fVolEnvDelta = 0.0f;
+			ch->fVolEnvValue = (float)(int32_t)(ins->volEnvPoints[point][1] & 0xFF);
 		}
 
 		if (point >= ins->volEnvLength)
@@ -832,7 +834,7 @@
 	}
 
 	// *** PANNING ENVELOPE ***
-	if (ins->volEnvFlags & ENV_SUSTAIN) // FT2 PLAYER BUG: Should've been ins->panEnvFlags
+	if (ins->volEnvFlags & ENV_SUSTAIN) // FT2 REPLAYER BUG: Should've been ins->panEnvFlags
 	{
 		ch->panEnvTick = param-1;
 
@@ -850,23 +852,25 @@
 					point--;
 
 					tick -= ins->panEnvPoints[point][0];
-					if (tick == 0)
+					if (tick == 0) // FT2 doesn't test for <= 0 here
 					{
 						envUpdate = false;
 						break;
 					}
 
-					if (ins->panEnvPoints[point+1][0] <= ins->panEnvPoints[point][0])
+					const int32_t xDiff = ins->panEnvPoints[point+1][0] - ins->panEnvPoints[point+0][0];
+					if (xDiff <= 0)
 					{
 						envUpdate = true;
 						break;
 					}
 
-					int32_t delta = (int8_t)((ins->panEnvPoints[point+1][1] - ins->panEnvPoints[point][1]) & 0xFF) << 16;
-					delta /= (ins->panEnvPoints[point+1][0]-ins->panEnvPoints[point][0]);
+					const int32_t y0 = ins->panEnvPoints[point+0][1] & 0xFF;
+					const int32_t y1 = ins->panEnvPoints[point+1][1] & 0xFF;
+					const int32_t yDiff = y1 - y0;
 
-					ch->panEnvDelta = delta;
-					ch->panEnvValue = (ch->panEnvDelta * (tick-1)) + ((int8_t)(ins->panEnvPoints[point][1] & 0xFF) << 16);
+					ch->fPanEnvDelta = (float)yDiff / (float)xDiff;
+					ch->fPanEnvValue = (float)y0 + (ch->fPanEnvDelta * (tick-1));
 
 					point++;
 
@@ -883,8 +887,8 @@
 
 		if (envUpdate)
 		{
-			ch->panEnvDelta = 0;
-			ch->panEnvValue = (int8_t)(ins->panEnvPoints[point][1] & 0xFF) << 16;
+			ch->fPanEnvDelta = 0.0f;
+			ch->fPanEnvValue = (float)(int32_t)(ins->panEnvPoints[point][1] & 0xFF);
 		}
 
 		if (point >= ins->panEnvLength)
@@ -1375,8 +1379,7 @@
 {
 	bool envInterpolateFlag, envDidInterpolate;
 	uint8_t envPos;
-	int32_t envVal;
-	double dVol;
+	float fEnvVal, fVol;
 
 	instr_t *ins = ch->instrPtr;
 	assert(ins != NULL);
@@ -1399,10 +1402,10 @@
 
 	if (!ch->mute)
 	{
-		// (envelope precision has been updated from x.8fp to x.16fp)
+		// envelope precision has been upgraded from .8fp to single-precision float
 
 		// *** VOLUME ENVELOPE ***
-		envVal = 0;
+		fEnvVal = 0.0f;
 		if (ins->volEnvFlags & ENV_ENABLED)
 		{
 			envDidInterpolate = false;
@@ -1410,7 +1413,7 @@
 
 			if (++ch->volEnvTick == ins->volEnvPoints[envPos][0])
 			{
-				ch->volEnvValue = (int8_t)(ins->volEnvPoints[envPos][1] & 0xFF) << 16;
+				ch->fVolEnvValue = (float)(int32_t)(ins->volEnvPoints[envPos][1] & 0xFF);
 
 				envPos++;
 				if (ins->volEnvFlags & ENV_LOOP)
@@ -1423,7 +1426,7 @@
 						{
 							envPos = ins->volEnvLoopStart;
 							ch->volEnvTick = ins->volEnvPoints[envPos][0];
-							ch->volEnvValue = (int8_t)(ins->volEnvPoints[envPos][1] & 0xFF) << 16;
+							ch->fVolEnvValue = (float)(int32_t)(ins->volEnvPoints[envPos][1] & 0xFF);
 						}
 					}
 
@@ -1438,7 +1441,7 @@
 						if (envPos-1 == ins->volEnvSustain)
 						{
 							envPos--;
-							ch->volEnvDelta = 0;
+							ch->fVolEnvDelta = 0.0f;
 							envInterpolateFlag = false;
 						}
 					}
@@ -1447,44 +1450,49 @@
 					{
 						ch->volEnvPos = envPos;
 
-						ch->volEnvDelta = 0;
-						if (ins->volEnvPoints[envPos][0] > ins->volEnvPoints[envPos-1][0])
+						const int32_t x0 = ins->volEnvPoints[envPos-1][0];
+						const int32_t x1 = ins->volEnvPoints[envPos-0][0];
+
+						const int32_t xDiff = x1 - x0;
+						if (xDiff > 0)
 						{
-							int32_t delta = (int8_t)((ins->volEnvPoints[envPos][1] - ins->volEnvPoints[envPos-1][1]) & 0xFF) << 16;
-							delta /= (ins->volEnvPoints[envPos][0]-ins->volEnvPoints[envPos-1][0]);
-							ch->volEnvDelta = delta;
+							const int32_t y0 = ins->volEnvPoints[envPos-1][1] & 0xFF;
+							const int32_t y1 = ins->volEnvPoints[envPos-0][1] & 0xFF;
 
-							envVal = ch->volEnvValue;
+							const int32_t yDiff = y1 - y0;
+							ch->fVolEnvDelta = (float)yDiff / (float)xDiff;
+
+							fEnvVal = ch->fVolEnvValue;
 							envDidInterpolate = true;
 						}
+						else
+						{
+							ch->fVolEnvDelta = 0.0f;
+						}
 					}
 				}
 				else
 				{
-					ch->volEnvDelta = 0;
+					ch->fVolEnvDelta = 0.0f;
 				}
 			}
 
 			if (!envDidInterpolate)
 			{
-				ch->volEnvValue += ch->volEnvDelta;
+				ch->fVolEnvValue += ch->fVolEnvDelta;
 
-				envVal = ch->volEnvValue;
-				if (envVal > 64<<16)
+				fEnvVal = ch->fVolEnvValue;
+				if (fEnvVal < 0.0f || fEnvVal > 64.0f)
 				{
-					if (envVal > 128<<16)
-						envVal = 64<<16;
-					else
-						envVal = 0;
-
-					ch->volEnvDelta = 0;
+					fEnvVal = CLAMP(fEnvVal, 0.0f, 64.0f);
+					ch->fVolEnvDelta = 0.0f;
 				}
 			}
 
 			const int32_t vol = song.globalVolume * ch->outVol * ch->fadeoutVol;
 
-			dVol = vol * (1.0 / (64.0 * 64.0 * 32768.0));
-			dVol *= envVal * (1.0 / (64.0 * (1 << 16))); // volume envelope value
+			fVol = vol * (1.0f / (64.0f * 64.0f * 32768.0f));
+			fVol *= fEnvVal * (1.0f / 64.0f); // volume envelope value
 
 			ch->status |= IS_Vol; // update mixer vol every tick when vol envelope is enabled
 		}
@@ -1492,22 +1500,20 @@
 		{
 			const int32_t vol = song.globalVolume * ch->outVol * ch->fadeoutVol;
 
-			dVol = vol * (1.0 / (64.0 * 64.0 * 32768.0));
+			fVol = vol * (1.0f / (64.0f * 64.0f * 32768.0f));
 		}
 
-		/* FT2 doesn't clamp here, but it's actually important if you
-		** move envelope points with the mouse while playing the instrument.
-		*/
-		ch->dFinalVol = CLAMP(dVol, 0.0, 1.0);
+		// FT2 doesn't clamp the volume, but let's do it anyway
+		ch->fFinalVol = CLAMP(fVol, 0.0f, 1.0f);
 	}
 	else
 	{
-		ch->dFinalVol = 0.0;
+		ch->fFinalVol = 0.0f;
 	}
 
 	// *** PANNING ENVELOPE ***
 
-	envVal = 0;
+	fEnvVal = 0.0f;
 	if (ins->panEnvFlags & ENV_ENABLED)
 	{
 		envDidInterpolate = false;
@@ -1515,7 +1521,7 @@
 
 		if (++ch->panEnvTick == ins->panEnvPoints[envPos][0])
 		{
-			ch->panEnvValue = (int8_t)(ins->panEnvPoints[envPos][1] & 0xFF) << 16;
+			ch->fPanEnvValue = (float)(int32_t)(ins->panEnvPoints[envPos][1] & 0xFF);
 
 			envPos++;
 			if (ins->panEnvFlags & ENV_LOOP)
@@ -1529,7 +1535,7 @@
 						envPos = ins->panEnvLoopStart;
 
 						ch->panEnvTick = ins->panEnvPoints[envPos][0];
-						ch->panEnvValue = (int8_t)(ins->panEnvPoints[envPos][1] & 0xFF) << 16;
+						ch->fPanEnvValue = (float)(int32_t)(ins->panEnvPoints[envPos][1] & 0xFF);
 					}
 				}
 
@@ -1544,7 +1550,7 @@
 					if (envPos-1 == ins->panEnvSustain)
 					{
 						envPos--;
-						ch->panEnvDelta = 0;
+						ch->fPanEnvDelta = 0.0f;
 						envInterpolateFlag = false;
 					}
 				}
@@ -1553,46 +1559,53 @@
 				{
 					ch->panEnvPos = envPos;
 
-					ch->panEnvDelta = 0;
-					if (ins->panEnvPoints[envPos][0] > ins->panEnvPoints[envPos-1][0])
+					const int32_t x0 = ins->panEnvPoints[envPos-1][0];
+					const int32_t x1 = ins->panEnvPoints[envPos-0][0];
+
+					const int32_t xDiff = x1 - x0;
+					if (xDiff > 0)
 					{
-						int32_t delta = (int8_t)((ins->panEnvPoints[envPos][1] - ins->panEnvPoints[envPos-1][1]) & 0xFF) << 16;
-						delta /= (ins->panEnvPoints[envPos][0]-ins->panEnvPoints[envPos-1][0]);
-						ch->panEnvDelta = delta;
+						const int32_t y0 = ins->panEnvPoints[envPos-1][1] & 0xFF;
+						const int32_t y1 = ins->panEnvPoints[envPos-0][1] & 0xFF;
 
-						envVal = ch->panEnvValue;
+						const int32_t yDiff = y1 - y0;
+						ch->fPanEnvDelta = (float)yDiff / (float)xDiff;
+
+						fEnvVal = ch->fPanEnvValue;
 						envDidInterpolate = true;
 					}
+					else
+					{
+						ch->fPanEnvDelta = 0.0f;
+					}
 				}
 			}
 			else
 			{
-				ch->panEnvDelta = 0;
+				ch->fPanEnvDelta = 0.0f;
 			}
 		}
 
 		if (!envDidInterpolate)
 		{
-			ch->panEnvValue += ch->panEnvDelta;
+			ch->fPanEnvValue += ch->fPanEnvDelta;
 
-			envVal = ch->panEnvValue;
-			if (envVal > 64<<16)
+			fEnvVal = ch->fPanEnvValue;
+			if (fEnvVal < 0.0f || fEnvVal > 64.0f)
 			{
-				if (envVal > 128<<16)
-					envVal = 64<<16;
-				else
-					envVal = 0;
-
-				ch->panEnvDelta = 0;
+				fEnvVal = CLAMP(fEnvVal, 0.0f, 64.0f);
+				ch->fPanEnvDelta = 0.0f;
 			}
 		}
 
-		envVal -= 32<<16; // center panning envelope value
+		fEnvVal -= 32.0f; // center panning envelope value (0..64 -> -32..32)
 
-		const int32_t pan = 128 - ABS(ch->outPan-128);
-		const int32_t panAdd = (pan * envVal) >> (16+5);
-		ch->finalPan = (uint8_t)(ch->outPan + panAdd);
+		const int32_t pan = 128 - ABS(ch->outPan - 128);
+		const float fPanAdd = (pan * fEnvVal) * (1.0f / 32.0f);
+		const int32_t newPan = (int32_t)(ch->outPan + fPanAdd); // truncate here, do not round
 
+		ch->finalPan = (uint8_t)CLAMP(newPan, 0, 255);
+
 		ch->status |= IS_Pan; // update pan every tick because pan envelope is enabled
 	}
 	else
@@ -3096,7 +3109,7 @@
 		ch->realVol = 0;
 		ch->outVol = 0;
 		ch->oldVol = 0;
-		ch->dFinalVol = 0.0;
+		ch->fFinalVol = 0.0f;
 		ch->oldPan = 128;
 		ch->outPan = 128;
 		ch->finalPan = 128;
--- a/src/ft2_replayer.h
+++ b/src/ft2_replayer.h
@@ -256,10 +256,9 @@
 	uint16_t volEnvTick, panEnvTick, autoVibAmp, autoVibSweep;
 	uint16_t midiVibDepth;
 	int32_t fadeoutVol, fadeoutSpeed;
-	int32_t volEnvDelta, panEnvDelta, volEnvValue, panEnvValue;
 	int32_t oldFinalPeriod, smpStartPos;
 
-	double dFinalVol; // 0.0 .. 1.0
+	float fFinalVol, fVolEnvDelta, fPanEnvDelta, fVolEnvValue, fPanEnvValue;
 
 	sample_t *smpPtr;
 	instr_t *instrPtr;
--- a/src/mixer/ft2_mix_macros.h
+++ b/src/mixer/ft2_mix_macros.h
@@ -383,8 +383,8 @@
 #define LIMIT_MIX_NUM_RAMP \
 	if (v->volumeRampLength == 0) \
 	{ \
-		fVolumeLDelta = 0.0; \
-		fVolumeRDelta = 0.0; \
+		fVolumeLDelta = 0.0f; \
+		fVolumeRDelta = 0.0f; \
 		\
 		if (v->isFadeOutVoice) \
 		{ \
@@ -403,7 +403,7 @@
 #define LIMIT_MIX_NUM_MONO_RAMP \
 	if (v->volumeRampLength == 0) \
 	{ \
-		fVolumeLDelta = 0.0; \
+		fVolumeLDelta = 0.0f; \
 		if (v->isFadeOutVoice) \
 		{ \
 			v->active = false; /* volume ramp fadeout-voice is done, shut it down */ \
--- a/src/scopes/ft2_scopes.c
+++ b/src/scopes/ft2_scopes.c
@@ -78,7 +78,7 @@
 		ch->realVol = 0;
 		ch->outVol = 0;
 		ch->oldVol = 0;
-		ch->dFinalVol = 0.0;
+		ch->fFinalVol = 0.0f;
 		ch->outPan = 128;
 		ch->oldPan = 128;
 		ch->finalPan = 128;