| 126 | 1 #pragma once | 
|  | 2 | 
|  | 3 #include <stdint.h> | 
|  | 4 #include <stdbool.h> | 
|  | 5 #include "pmp_mix.h" | 
|  | 6 | 
|  | 7 #define GET_VOL \ | 
|  | 8 	const int32_t CDA_LVol = v->SLVol1; \ | 
|  | 9 	const int32_t CDA_RVol = v->SRVol1; \ | 
|  | 10 | 
|  | 11 #define GET_VOL_CENTER \ | 
|  | 12 	const int32_t CDA_LVol = v->SLVol1; \ | 
|  | 13 | 
|  | 14 #define GET_VOL_RAMP \ | 
|  | 15 	int32_t CDA_LVol = v->SLVol2; \ | 
|  | 16 	int32_t CDA_RVol = v->SRVol2; \ | 
|  | 17 | 
|  | 18 #define SET_VOL_BACK \ | 
|  | 19 	v->SLVol2 = CDA_LVol; \ | 
|  | 20 	v->SRVol2 = CDA_RVol; \ | 
|  | 21 | 
|  | 22 #define GET_MIXER_VARS \ | 
|  | 23 	int32_t *audioMix = CDA_MixBuffer + (bufferPos << 1); \ | 
|  | 24 	int32_t realPos = v->SPos; \ | 
|  | 25 	uint32_t pos = v->SPosDec; \ | 
|  | 26 	uint16_t CDA_MixBuffPos = (32768+96)-8; /* address of FT2 mix buffer minus mix sample size (used for quirky LERP) */ \ | 
|  | 27 | 
|  | 28 #define GET_RAMP_VARS \ | 
|  | 29 	int32_t CDA_LVolIP = v->SLVolIP; \ | 
|  | 30 	int32_t CDA_RVolIP = v->SRVolIP; \ | 
|  | 31 | 
|  | 32 #define SET_BASE8 \ | 
|  | 33 	const int8_t *CDA_LinearAdr = (int8_t *)v->SBase; \ | 
|  | 34 	const int8_t *CDA_LinAdrRev = (int8_t *)v->SRevBase; \ | 
|  | 35 	const int8_t *smpPtr = CDA_LinearAdr + realPos; \ | 
|  | 36 | 
|  | 37 #define SET_BASE16 \ | 
|  | 38 	const int16_t *CDA_LinearAdr = (int16_t *)v->SBase; \ | 
|  | 39 	const int16_t *CDA_LinAdrRev = (int16_t *)v->SRevBase; \ | 
|  | 40 	const int16_t *smpPtr = CDA_LinearAdr + realPos; \ | 
|  | 41 | 
|  | 42 #define INC_POS \ | 
|  | 43 	smpPtr += CDA_IPValH; \ | 
|  | 44 	smpPtr += (CDA_IPValL > (uint32_t)~pos); /* if pos would 32-bit overflow after CDA_IPValL add, add one to smpPtr (branchless) */ \ | 
|  | 45 	pos += CDA_IPValL; \ | 
|  | 46 | 
|  | 47 #define SET_BACK_MIXER_POS \ | 
|  | 48 	v->SPosDec = pos & 0xFFFF0000; \ | 
|  | 49 	v->SPos = realPos; \ | 
|  | 50 | 
|  | 51 #define VOL_RAMP \ | 
|  | 52 	CDA_LVol += CDA_LVolIP; \ | 
|  | 53 	CDA_RVol += CDA_RVolIP; \ | 
|  | 54 | 
|  | 55 // stereo mixing without interpolation | 
|  | 56 | 
|  | 57 #define MIX_8BIT \ | 
|  | 58 	sample = (*smpPtr) << (28-8); \ | 
|  | 59 	*audioMix++ += ((int64_t)sample * (int32_t)CDA_LVol) >> 32; \ | 
|  | 60 	*audioMix++ += ((int64_t)sample * (int32_t)CDA_RVol) >> 32; \ | 
|  | 61 	INC_POS \ | 
|  | 62 | 
|  | 63 #define MIX_16BIT \ | 
|  | 64 	sample = (*smpPtr) << (28-16); \ | 
|  | 65 	*audioMix++ += ((int64_t)sample * (int32_t)CDA_LVol) >> 32; \ | 
|  | 66 	*audioMix++ += ((int64_t)sample * (int32_t)CDA_RVol) >> 32; \ | 
|  | 67 	INC_POS \ | 
|  | 68 | 
|  | 69 // center mixing without interpolation | 
|  | 70 | 
|  | 71 #define MIX_8BIT_M \ | 
|  | 72 	sample = (*smpPtr) << (28-8); \ | 
|  | 73 	sample = ((int64_t)sample * (int32_t)CDA_LVol) >> 32; \ | 
|  | 74 	*audioMix++ += sample; \ | 
|  | 75 	*audioMix++ += sample; \ | 
|  | 76 	INC_POS \ | 
|  | 77 | 
|  | 78 #define MIX_16BIT_M \ | 
|  | 79 	sample = (*smpPtr) << (28-16); \ | 
|  | 80 	sample = ((int64_t)sample * (int32_t)CDA_LVol) >> 32; \ | 
|  | 81 	*audioMix++ += sample; \ | 
|  | 82 	*audioMix++ += sample; \ | 
|  | 83 	INC_POS \ | 
|  | 84 | 
|  | 85 // linear interpolation with bit-accurate results to FT2.08/FT2.09 | 
|  | 86 #define LERP(s1, s2, f) \ | 
|  | 87 { \ | 
|  | 88 	s2 -= s1; \ | 
|  | 89 	f >>= 1; \ | 
|  | 90 	s2 = ((int64_t)s2 * (int32_t)f) >> 32; \ | 
|  | 91 	f += f; \ | 
|  | 92 	s2 += s2; \ | 
|  | 93 	s2 += s1; \ | 
|  | 94 } \ | 
|  | 95 | 
|  | 96 // stereo mixing w/ linear interpolation | 
|  | 97 | 
|  | 98 #define MIX_8BIT_INTRP \ | 
|  | 99 	sample = smpPtr[0] << 8; \ | 
|  | 100 	sample2 = smpPtr[1] << 8; \ | 
|  | 101 	LERP(sample, sample2, pos) \ | 
|  | 102 	sample2 <<= (28-16); \ | 
|  | 103 	*audioMix++ += ((int64_t)sample2 * (int32_t)CDA_LVol) >> 32; \ | 
|  | 104 	*audioMix++ += ((int64_t)sample2 * (int32_t)CDA_RVol) >> 32; \ | 
|  | 105 	INC_POS \ | 
|  | 106 | 
|  | 107 #define MIX_16BIT_INTRP \ | 
|  | 108 	sample = smpPtr[0]; \ | 
|  | 109 	sample2 = smpPtr[1]; \ | 
|  | 110 	LERP(sample, sample2, pos) \ | 
|  | 111 	sample2 <<= (28-16); \ | 
|  | 112 	*audioMix++ += ((int64_t)sample2 * (int32_t)CDA_LVol) >> 32; \ | 
|  | 113 	*audioMix++ += ((int64_t)sample2 * (int32_t)CDA_RVol) >> 32; \ | 
|  | 114 	INC_POS \ | 
|  | 115 | 
|  | 116 // center mixing w/ linear interpolation | 
|  | 117 | 
|  | 118 #define MIX_8BIT_INTRP_M \ | 
|  | 119 	sample = smpPtr[0] << 8; \ | 
|  | 120 	sample2 = smpPtr[1] << 8; \ | 
|  | 121 	LERP(sample, sample2, pos) \ | 
|  | 122 	sample2 <<= (28-16); \ | 
|  | 123 	sample = ((int64_t)sample2 * (int32_t)CDA_LVol) >> 32; \ | 
|  | 124 	*audioMix++ += sample; \ | 
|  | 125 	*audioMix++ += sample; \ | 
|  | 126 	INC_POS \ | 
|  | 127 | 
|  | 128 #define MIX_16BIT_INTRP_M \ | 
|  | 129 	sample = smpPtr[0]; \ | 
|  | 130 	sample2 = smpPtr[1]; \ | 
|  | 131 	LERP(sample, sample2, pos) \ | 
|  | 132 	sample2 <<= (28-16); \ | 
|  | 133 	sample = ((int64_t)sample2 * (int32_t)CDA_LVol) >> 32; \ | 
|  | 134 	*audioMix++ += sample; \ | 
|  | 135 	*audioMix++ += sample; \ | 
|  | 136 	INC_POS \ | 
|  | 137 | 
|  | 138 // ------------------------ | 
|  | 139 | 
|  | 140 #define LIMIT_MIX_NUM \ | 
|  | 141 	int32_t samplesToMix; \ | 
|  | 142 	int32_t SFrq = v->SFrq; \ | 
|  | 143 	int32_t i = (v->SLen-1) - realPos; \ | 
|  | 144 	if (i > UINT16_MAX) i = UINT16_MAX; /* 8bb: added this to prevent 64-bit div (still bit-accurate mixing results) */ \ | 
|  | 145 	if (SFrq != 0) \ | 
|  | 146 	{ \ | 
|  | 147 		const uint32_t tmp32 = (i << 16) | ((0xFFFF0000 - pos) >> 16); \ | 
|  | 148 		samplesToMix = (tmp32 / (uint32_t)SFrq) + 1; \ | 
|  | 149 	} \ | 
|  | 150 	else \ | 
|  | 151 	{ \ | 
|  | 152 		samplesToMix = 65535; \ | 
|  | 153 	} \ | 
|  | 154 	\ | 
|  | 155 	if (samplesToMix > CDA_BytesLeft) \ | 
|  | 156 		samplesToMix = CDA_BytesLeft; \ | 
|  | 157 | 
|  | 158 #define LIMIT_MIX_NUM_RAMP \ | 
|  | 159 	if (v->SVolIPLen == 0) \ | 
|  | 160 	{ \ | 
|  | 161 		CDA_LVolIP = 0; \ | 
|  | 162 		CDA_RVolIP = 0; \ | 
|  | 163 	} \ | 
|  | 164 	else \ | 
|  | 165 	{ \ | 
|  | 166 		if (samplesToMix > v->SVolIPLen) \ | 
|  | 167 			samplesToMix = v->SVolIPLen; \ | 
|  | 168 		\ | 
|  | 169 		v->SVolIPLen -= samplesToMix; \ | 
|  | 170 	} \ | 
|  | 171 | 
|  | 172 #define HANDLE_POS_START \ | 
|  | 173 	const bool backwards = (v->SType & (SType_Rev+SType_RevDir)) == SType_Rev+SType_RevDir; \ | 
|  | 174 	if (backwards) \ | 
|  | 175 	{ \ | 
|  | 176 		SFrq = 0 - SFrq; \ | 
|  | 177 		realPos = ~realPos; \ | 
|  | 178 		smpPtr = CDA_LinAdrRev + realPos; \ | 
|  | 179 		pos ^= 0xFFFF0000; \ | 
|  | 180 	} \ | 
|  | 181 	else \ | 
|  | 182 	{ \ | 
|  | 183 		smpPtr = CDA_LinearAdr + realPos; \ | 
|  | 184 	} \ | 
|  | 185 	\ | 
|  | 186 	pos += CDA_MixBuffPos; \ | 
|  | 187 	const int32_t CDA_IPValH = (int32_t)SFrq >> 16; \ | 
|  | 188 	const uint32_t CDA_IPValL = ((uint32_t)(SFrq & 0xFFFF) << 16) + 8; /* 8 = mixer buffer increase (for LERP to be bit-accurate to FT2) */ \ | 
|  | 189 | 
|  | 190 #define HANDLE_POS_END \ | 
|  | 191 	if (backwards) \ | 
|  | 192 	{ \ | 
|  | 193 		pos ^= 0xFFFF0000; \ | 
|  | 194 		realPos = ~(int32_t)(smpPtr - CDA_LinAdrRev); \ | 
|  | 195 	} \ | 
|  | 196 	else \ | 
|  | 197 	{ \ | 
|  | 198 		realPos = (int32_t)(smpPtr - CDA_LinearAdr); \ | 
|  | 199 	} \ | 
|  | 200 	CDA_MixBuffPos = pos & 0xFFFF; \ | 
|  | 201 	pos &= 0xFFFF0000; \ | 
|  | 202 	\ | 
|  | 203 	if (realPos >= v->SLen) \ | 
|  | 204 	{ \ | 
|  | 205 		uint8_t SType = v->SType; \ | 
|  | 206 		if (SType & (SType_Fwd+SType_Rev)) \ | 
|  | 207 		{ \ | 
|  | 208 			do \ | 
|  | 209 			{ \ | 
|  | 210 				realPos -= v->SRepL; \ | 
|  | 211 				SType ^= SType_RevDir; \ | 
|  | 212 			} \ | 
|  | 213 			while (realPos >= v->SLen); \ | 
|  | 214 			v->SType = SType; \ | 
|  | 215 		} \ | 
|  | 216 		else \ | 
|  | 217 		{ \ | 
|  | 218 			v->SType = SType_Off; \ | 
|  | 219 			return; \ | 
|  | 220 		} \ | 
|  | 221 	} \ | 
|  | 222 | 
|  | 223 typedef void (*mixRoutine)(void *, int32_t, int32_t); | 
|  | 224 | 
|  | 225 extern mixRoutine mixRoutineTable[16]; | 
|  | 226 | 
|  | 227 void PMPMix32Proc(CIType *v, int32_t numSamples, int32_t bufferPos); |