| 
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);
 |