1 #include "burnint.h"
2 #include "burn_ym2610.h"
3 
4 void (*BurnYM2610Update)(INT16* pSoundBuf, INT32 nSegmentEnd);
5 
6 static INT32 (*BurnYM2610StreamCallback)(INT32 nSoundRate);
7 
8 static INT32 nBurnYM2610SoundRate;
9 
10 static INT16* pBuffer;
11 static INT16* pYM2610Buffer[6];
12 
13 static INT32* pAYBuffer;
14 
15 static INT32 nYM2610Position;
16 static INT32 nAY8910Position;
17 
18 static UINT32 nSampleSize;
19 static INT32 nFractionalPosition;
20 
21 static INT32 bYM2610AddSignal;
22 
23 static double YM2610Volumes[3];
24 static INT32 YM2610RouteDirs[3];
25 
26 static double YM2610LeftVolumes[3];
27 static double YM2610RightVolumes[3];
28 
29 INT32 bYM2610UseSeperateVolumes; // support custom Taito panning hardware
30 
31 // ----------------------------------------------------------------------------
32 // Dummy functions
33 
YM2610UpdateDummy(INT16 *,INT32)34 static void YM2610UpdateDummy(INT16*, INT32)
35 {
36 	return;
37 }
38 
YM2610StreamCallbackDummy(INT32)39 static INT32 YM2610StreamCallbackDummy(INT32)
40 {
41 	return 0;
42 }
43 
44 // ----------------------------------------------------------------------------
45 // Execute YM2610 for part of a frame
46 
AY8910Render(INT32 nSegmentLength)47 static void AY8910Render(INT32 nSegmentLength)
48 {
49 #if defined FBA_DEBUG
50 	if (!DebugSnd_YM2610Initted) bprintf(PRINT_ERROR, _T("BurnYM2610 AY8910Render called without init\n"));
51 #endif
52 
53 	if (nAY8910Position >= nSegmentLength) {
54 		return;
55 	}
56 
57 	nSegmentLength -= nAY8910Position;
58 
59 	pYM2610Buffer[2] = pBuffer + 2 * 4096 + 4 + nAY8910Position;
60 	pYM2610Buffer[3] = pBuffer + 3 * 4096 + 4 + nAY8910Position;
61 	pYM2610Buffer[4] = pBuffer + 4 * 4096 + 4 + nAY8910Position;
62 
63 	AY8910Update(0, &pYM2610Buffer[2], nSegmentLength);
64 
65 	nAY8910Position += nSegmentLength;
66 }
67 
YM2610Render(INT32 nSegmentLength)68 static void YM2610Render(INT32 nSegmentLength)
69 {
70 #if defined FBA_DEBUG
71 	if (!DebugSnd_YM2610Initted) bprintf(PRINT_ERROR, _T("YM2610Render called without init\n"));
72 #endif
73 
74 	if (nYM2610Position >= nSegmentLength) {
75 		return;
76 	}
77 
78 	nSegmentLength -= nYM2610Position;
79 
80 	pYM2610Buffer[0] = pBuffer + 0 * 4096 + 4 + nYM2610Position;
81 	pYM2610Buffer[1] = pBuffer + 1 * 4096 + 4 + nYM2610Position;
82 
83 	YM2610UpdateOne(0, &pYM2610Buffer[0], nSegmentLength);
84 
85 	nYM2610Position += nSegmentLength;
86 }
87 
88 // ----------------------------------------------------------------------------
89 // Update the sound buffer
90 
YM2610UpdateResample(INT16 * pSoundBuf,INT32 nSegmentEnd)91 static void YM2610UpdateResample(INT16* pSoundBuf, INT32 nSegmentEnd)
92 {
93 #if defined FBA_DEBUG
94 	if (!DebugSnd_YM2610Initted) bprintf(PRINT_ERROR, _T("YM2610UpdateResample called without init\n"));
95 #endif
96 
97 	INT32 nSegmentLength = nSegmentEnd;
98 	INT32 nSamplesNeeded = nSegmentEnd * nBurnYM2610SoundRate / nBurnSoundRate + 1;
99 
100 	if (nSamplesNeeded < nAY8910Position) {
101 		nSamplesNeeded = nAY8910Position;
102 	}
103 	if (nSamplesNeeded < nYM2610Position) {
104 		nSamplesNeeded = nYM2610Position;
105 	}
106 
107 	if (nSegmentLength > nBurnSoundLen) {
108 		nSegmentLength = nBurnSoundLen;
109 	}
110 	nSegmentLength <<= 1;
111 
112 	YM2610Render(nSamplesNeeded);
113 	AY8910Render(nSamplesNeeded);
114 
115 	pYM2610Buffer[0] = pBuffer + 0 * 4096 + 4;
116 	pYM2610Buffer[1] = pBuffer + 1 * 4096 + 4;
117 	pYM2610Buffer[2] = pBuffer + 2 * 4096 + 4;
118 	pYM2610Buffer[3] = pBuffer + 3 * 4096 + 4;
119 	pYM2610Buffer[4] = pBuffer + 4 * 4096 + 4;
120 	pYM2610Buffer[5] = pBuffer + 5 * 4096 + 4;
121 
122 	for (INT32 i = (nFractionalPosition >> 16) - 4; i < nSamplesNeeded; i++) {
123 		pYM2610Buffer[5][i] = BURN_SND_CLIP(pYM2610Buffer[2][i] + pYM2610Buffer[3][i] + pYM2610Buffer[4][i]);
124 	}
125 
126 	for (INT32 i = (nFractionalPosition & 0xFFFF0000) >> 15; i < nSegmentLength; i += 2, nFractionalPosition += nSampleSize) {
127 		INT32 nLeftSample[4] = {0, 0, 0, 0};
128 		INT32 nRightSample[4] = {0, 0, 0, 0};
129 		INT32 nTotalLeftSample, nTotalRightSample;
130 
131 		if (bYM2610UseSeperateVolumes) {
132 			nLeftSample[0] += (INT32)(pYM2610Buffer[5][(nFractionalPosition >> 16) - 3] * YM2610LeftVolumes[BURN_SND_YM2610_AY8910_ROUTE]);
133 			nLeftSample[1] += (INT32)(pYM2610Buffer[5][(nFractionalPosition >> 16) - 2] * YM2610LeftVolumes[BURN_SND_YM2610_AY8910_ROUTE]);
134 			nLeftSample[2] += (INT32)(pYM2610Buffer[5][(nFractionalPosition >> 16) - 1] * YM2610LeftVolumes[BURN_SND_YM2610_AY8910_ROUTE]);
135 			nLeftSample[3] += (INT32)(pYM2610Buffer[5][(nFractionalPosition >> 16) - 0] * YM2610LeftVolumes[BURN_SND_YM2610_AY8910_ROUTE]);
136 
137 			nLeftSample[0] += (INT32)(pYM2610Buffer[0][(nFractionalPosition >> 16) - 3] * YM2610LeftVolumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
138 			nLeftSample[1] += (INT32)(pYM2610Buffer[0][(nFractionalPosition >> 16) - 2] * YM2610LeftVolumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
139 			nLeftSample[2] += (INT32)(pYM2610Buffer[0][(nFractionalPosition >> 16) - 1] * YM2610LeftVolumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
140 			nLeftSample[3] += (INT32)(pYM2610Buffer[0][(nFractionalPosition >> 16) - 0] * YM2610LeftVolumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
141 
142 			nLeftSample[0] += (INT32)(pYM2610Buffer[1][(nFractionalPosition >> 16) - 3] * YM2610LeftVolumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
143 			nLeftSample[1] += (INT32)(pYM2610Buffer[1][(nFractionalPosition >> 16) - 2] * YM2610LeftVolumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
144 			nLeftSample[2] += (INT32)(pYM2610Buffer[1][(nFractionalPosition >> 16) - 1] * YM2610LeftVolumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
145 			nLeftSample[3] += (INT32)(pYM2610Buffer[1][(nFractionalPosition >> 16) - 0] * YM2610LeftVolumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
146 
147 			nRightSample[0] += (INT32)(pYM2610Buffer[5][(nFractionalPosition >> 16) - 3] * YM2610RightVolumes[BURN_SND_YM2610_AY8910_ROUTE]);
148 			nRightSample[1] += (INT32)(pYM2610Buffer[5][(nFractionalPosition >> 16) - 2] * YM2610RightVolumes[BURN_SND_YM2610_AY8910_ROUTE]);
149 			nRightSample[2] += (INT32)(pYM2610Buffer[5][(nFractionalPosition >> 16) - 1] * YM2610RightVolumes[BURN_SND_YM2610_AY8910_ROUTE]);
150 			nRightSample[3] += (INT32)(pYM2610Buffer[5][(nFractionalPosition >> 16) - 0] * YM2610RightVolumes[BURN_SND_YM2610_AY8910_ROUTE]);
151 
152 			nRightSample[0] += (INT32)(pYM2610Buffer[0][(nFractionalPosition >> 16) - 3] * YM2610RightVolumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
153 			nRightSample[1] += (INT32)(pYM2610Buffer[0][(nFractionalPosition >> 16) - 2] * YM2610RightVolumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
154 			nRightSample[2] += (INT32)(pYM2610Buffer[0][(nFractionalPosition >> 16) - 1] * YM2610RightVolumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
155 			nRightSample[3] += (INT32)(pYM2610Buffer[0][(nFractionalPosition >> 16) - 0] * YM2610RightVolumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
156 
157 			nRightSample[0] += (INT32)(pYM2610Buffer[1][(nFractionalPosition >> 16) - 3] * YM2610RightVolumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
158 			nRightSample[1] += (INT32)(pYM2610Buffer[1][(nFractionalPosition >> 16) - 2] * YM2610RightVolumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
159 			nRightSample[2] += (INT32)(pYM2610Buffer[1][(nFractionalPosition >> 16) - 1] * YM2610RightVolumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
160 			nRightSample[3] += (INT32)(pYM2610Buffer[1][(nFractionalPosition >> 16) - 0] * YM2610RightVolumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
161 		} else {
162 			if ((YM2610RouteDirs[BURN_SND_YM2610_AY8910_ROUTE] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
163 				nLeftSample[0] += (INT32)(pYM2610Buffer[5][(nFractionalPosition >> 16) - 3] * YM2610Volumes[BURN_SND_YM2610_AY8910_ROUTE]);
164 				nLeftSample[1] += (INT32)(pYM2610Buffer[5][(nFractionalPosition >> 16) - 2] * YM2610Volumes[BURN_SND_YM2610_AY8910_ROUTE]);
165 				nLeftSample[2] += (INT32)(pYM2610Buffer[5][(nFractionalPosition >> 16) - 1] * YM2610Volumes[BURN_SND_YM2610_AY8910_ROUTE]);
166 				nLeftSample[3] += (INT32)(pYM2610Buffer[5][(nFractionalPosition >> 16) - 0] * YM2610Volumes[BURN_SND_YM2610_AY8910_ROUTE]);
167 			}
168 			if ((YM2610RouteDirs[BURN_SND_YM2610_AY8910_ROUTE] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
169 				nRightSample[0] += (INT32)(pYM2610Buffer[5][(nFractionalPosition >> 16) - 3] * YM2610Volumes[BURN_SND_YM2610_AY8910_ROUTE]);
170 				nRightSample[1] += (INT32)(pYM2610Buffer[5][(nFractionalPosition >> 16) - 2] * YM2610Volumes[BURN_SND_YM2610_AY8910_ROUTE]);
171 				nRightSample[2] += (INT32)(pYM2610Buffer[5][(nFractionalPosition >> 16) - 1] * YM2610Volumes[BURN_SND_YM2610_AY8910_ROUTE]);
172 				nRightSample[3] += (INT32)(pYM2610Buffer[5][(nFractionalPosition >> 16) - 0] * YM2610Volumes[BURN_SND_YM2610_AY8910_ROUTE]);
173 			}
174 
175 			if ((YM2610RouteDirs[BURN_SND_YM2610_YM2610_ROUTE_1] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
176 				nLeftSample[0] += (INT32)(pYM2610Buffer[0][(nFractionalPosition >> 16) - 3] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
177 				nLeftSample[1] += (INT32)(pYM2610Buffer[0][(nFractionalPosition >> 16) - 2] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
178 				nLeftSample[2] += (INT32)(pYM2610Buffer[0][(nFractionalPosition >> 16) - 1] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
179 				nLeftSample[3] += (INT32)(pYM2610Buffer[0][(nFractionalPosition >> 16) - 0] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
180 			}
181 			if ((YM2610RouteDirs[BURN_SND_YM2610_YM2610_ROUTE_1] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
182 				nRightSample[0] += (INT32)(pYM2610Buffer[0][(nFractionalPosition >> 16) - 3] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
183 				nRightSample[1] += (INT32)(pYM2610Buffer[0][(nFractionalPosition >> 16) - 2] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
184 				nRightSample[2] += (INT32)(pYM2610Buffer[0][(nFractionalPosition >> 16) - 1] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
185 				nRightSample[3] += (INT32)(pYM2610Buffer[0][(nFractionalPosition >> 16) - 0] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
186 			}
187 
188 			if ((YM2610RouteDirs[BURN_SND_YM2610_YM2610_ROUTE_2] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
189 				nLeftSample[0] += (INT32)(pYM2610Buffer[1][(nFractionalPosition >> 16) - 3] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
190 				nLeftSample[1] += (INT32)(pYM2610Buffer[1][(nFractionalPosition >> 16) - 2] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
191 				nLeftSample[2] += (INT32)(pYM2610Buffer[1][(nFractionalPosition >> 16) - 1] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
192 				nLeftSample[3] += (INT32)(pYM2610Buffer[1][(nFractionalPosition >> 16) - 0] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
193 			}
194 			if ((YM2610RouteDirs[BURN_SND_YM2610_YM2610_ROUTE_2] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
195 				nRightSample[0] += (INT32)(pYM2610Buffer[1][(nFractionalPosition >> 16) - 3] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
196 				nRightSample[1] += (INT32)(pYM2610Buffer[1][(nFractionalPosition >> 16) - 2] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
197 				nRightSample[2] += (INT32)(pYM2610Buffer[1][(nFractionalPosition >> 16) - 1] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
198 				nRightSample[3] += (INT32)(pYM2610Buffer[1][(nFractionalPosition >> 16) - 0] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
199 			}
200 		}
201 
202 		nTotalLeftSample = INTERPOLATE4PS_16BIT((nFractionalPosition >> 4) & 0x0fff, nLeftSample[0], nLeftSample[1], nLeftSample[2], nLeftSample[3]);
203 		nTotalRightSample = INTERPOLATE4PS_16BIT((nFractionalPosition >> 4) & 0x0fff, nRightSample[0], nRightSample[1], nRightSample[2], nRightSample[3]);
204 
205 		nTotalLeftSample = BURN_SND_CLIP(nTotalLeftSample);
206 		nTotalRightSample = BURN_SND_CLIP(nTotalRightSample);
207 
208 		if (bYM2610AddSignal) {
209 //			pSoundBuf[i + 0] += nTotalLeftSample;
210 //			pSoundBuf[i + 1] += nTotalRightSample;
211 			pSoundBuf[i + 0] = BURN_SND_CLIP(pSoundBuf[i + 0] + nTotalLeftSample);
212 			pSoundBuf[i + 1] = BURN_SND_CLIP(pSoundBuf[i + 1] + nTotalRightSample);
213 		} else {
214 			pSoundBuf[i + 0] = nTotalLeftSample;
215 			pSoundBuf[i + 1] = nTotalRightSample;
216 		}
217 	}
218 
219 	if (nSegmentEnd >= nBurnSoundLen) {
220 		INT32 nExtraSamples = nSamplesNeeded - (nFractionalPosition >> 16);
221 
222 		for (INT32 i = -4; i < nExtraSamples; i++) {
223 			pYM2610Buffer[0][i] = pYM2610Buffer[0][(nFractionalPosition >> 16) + i];
224 			pYM2610Buffer[1][i] = pYM2610Buffer[1][(nFractionalPosition >> 16) + i];
225 			pYM2610Buffer[2][i] = pYM2610Buffer[2][(nFractionalPosition >> 16) + i];
226 			pYM2610Buffer[3][i] = pYM2610Buffer[3][(nFractionalPosition >> 16) + i];
227 			pYM2610Buffer[4][i] = pYM2610Buffer[4][(nFractionalPosition >> 16) + i];
228 		}
229 
230 		nFractionalPosition &= 0xFFFF;
231 
232 		nYM2610Position = nExtraSamples;
233 		nAY8910Position = nExtraSamples;
234 
235 		dTime += 100.0 / nBurnFPS;
236 	}
237 }
238 
YM2610UpdateNormal(INT16 * pSoundBuf,INT32 nSegmentEnd)239 static void YM2610UpdateNormal(INT16* pSoundBuf, INT32 nSegmentEnd)
240 {
241 #if defined FBA_DEBUG
242 	if (!DebugSnd_YM2610Initted) bprintf(PRINT_ERROR, _T("YM2610UpdateNormal called without init\n"));
243 #endif
244 
245 	INT32 nSegmentLength = nSegmentEnd;
246 
247 	if (nSegmentEnd < nAY8910Position) {
248 		nSegmentEnd = nAY8910Position;
249 	}
250 	if (nSegmentEnd < nYM2610Position) {
251 		nSegmentEnd = nYM2610Position;
252 	}
253 
254 	if (nSegmentLength > nBurnSoundLen) {
255 		nSegmentLength = nBurnSoundLen;
256 	}
257 
258 	YM2610Render(nSegmentEnd);
259 	AY8910Render(nSegmentEnd);
260 
261 	pYM2610Buffer[0] = pBuffer + 4 + 0 * 4096;
262 	pYM2610Buffer[1] = pBuffer + 4 + 1 * 4096;
263 	pYM2610Buffer[2] = pBuffer + 4 + 2 * 4096;
264 	pYM2610Buffer[3] = pBuffer + 4 + 3 * 4096;
265 	pYM2610Buffer[4] = pBuffer + 4 + 4 * 4096;
266 
267 	for (INT32 n = nFractionalPosition; n < nSegmentLength; n++) {
268 		INT32 nAYSample, nLeftSample = 0, nRightSample = 0;
269 
270 		nAYSample  = pYM2610Buffer[2][n];
271 		nAYSample += pYM2610Buffer[3][n];
272 		nAYSample += pYM2610Buffer[4][n];
273 
274 		if (bYM2610UseSeperateVolumes) {
275 			nLeftSample += (INT32)(nAYSample * YM2610LeftVolumes[BURN_SND_YM2610_AY8910_ROUTE]);
276 			nLeftSample += (INT32)(pYM2610Buffer[0][n] * YM2610LeftVolumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
277 			nLeftSample += (INT32)(pYM2610Buffer[1][n] * YM2610LeftVolumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
278 
279 			nRightSample += (INT32)(nAYSample * YM2610RightVolumes[BURN_SND_YM2610_AY8910_ROUTE]);
280 			nRightSample += (INT32)(pYM2610Buffer[0][n] * YM2610RightVolumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
281 			nRightSample += (INT32)(pYM2610Buffer[1][n] * YM2610RightVolumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
282 		} else {
283 			if ((YM2610RouteDirs[BURN_SND_YM2610_AY8910_ROUTE] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
284 				nLeftSample += (INT32)(nAYSample * YM2610Volumes[BURN_SND_YM2610_AY8910_ROUTE]);
285 			}
286 			if ((YM2610RouteDirs[BURN_SND_YM2610_AY8910_ROUTE] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
287 				nRightSample += (INT32)(nAYSample * YM2610Volumes[BURN_SND_YM2610_AY8910_ROUTE]);
288 			}
289 
290 			if ((YM2610RouteDirs[BURN_SND_YM2610_YM2610_ROUTE_1] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
291 				nLeftSample += (INT32)(pYM2610Buffer[0][n] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
292 			}
293 			if ((YM2610RouteDirs[BURN_SND_YM2610_YM2610_ROUTE_1] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
294 				nRightSample += (INT32)(pYM2610Buffer[0][n] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
295 			}
296 
297 			if ((YM2610RouteDirs[BURN_SND_YM2610_YM2610_ROUTE_2] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
298 				nLeftSample += (INT32)(pYM2610Buffer[1][n] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
299 			}
300 			if ((YM2610RouteDirs[BURN_SND_YM2610_YM2610_ROUTE_2] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
301 				nRightSample += (INT32)(pYM2610Buffer[1][n] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
302 			}
303 		}
304 
305 		nLeftSample = BURN_SND_CLIP(nLeftSample);
306 		nRightSample = BURN_SND_CLIP(nRightSample);
307 
308 		if (bYM2610AddSignal) {
309 			//pSoundBuf[(n << 1) + 0] += nLeftSample;
310 			//pSoundBuf[(n << 1) + 1] += nRightSample;
311 			pSoundBuf[(n << 1) + 0] = BURN_SND_CLIP(pSoundBuf[(n << 1) + 0] + nLeftSample);
312 			pSoundBuf[(n << 1) + 1] = BURN_SND_CLIP(pSoundBuf[(n << 1) + 1] + nRightSample);
313 		} else {
314 			pSoundBuf[(n << 1) + 0] = nLeftSample;
315 			pSoundBuf[(n << 1) + 1] = nRightSample;
316 		}
317 	}
318 
319 	nFractionalPosition = nSegmentLength;
320 
321 	if (nSegmentEnd >= nBurnSoundLen) {
322 		INT32 nExtraSamples = nSegmentEnd - nBurnSoundLen;
323 
324 		for (INT32 i = 0; i < nExtraSamples; i++) {
325 			pYM2610Buffer[0][i] = pYM2610Buffer[0][nBurnSoundLen + i];
326 			pYM2610Buffer[1][i] = pYM2610Buffer[1][nBurnSoundLen + i];
327 			pYM2610Buffer[2][i] = pYM2610Buffer[2][nBurnSoundLen + i];
328 			pYM2610Buffer[3][i] = pYM2610Buffer[3][nBurnSoundLen + i];
329 			pYM2610Buffer[4][i] = pYM2610Buffer[4][nBurnSoundLen + i];
330 		}
331 
332 		nFractionalPosition = 0;
333 
334 		nYM2610Position = nExtraSamples;
335 		nAY8910Position = nExtraSamples;
336 
337 		dTime += 100.0 / nBurnFPS;
338 	}
339 }
340 
341 // ----------------------------------------------------------------------------
342 // Callbacks for YM2610 core
343 
BurnYM2610UpdateRequest()344 void BurnYM2610UpdateRequest()
345 {
346 #if defined FBA_DEBUG
347 	if (!DebugSnd_YM2610Initted) bprintf(PRINT_ERROR, _T("YM2610UpdateRequest called without init\n"));
348 #endif
349 
350 	YM2610Render(BurnYM2610StreamCallback(nBurnYM2610SoundRate));
351 }
352 
BurnAY8910UpdateRequest()353 static void BurnAY8910UpdateRequest()
354 {
355 #if defined FBA_DEBUG
356 	if (!DebugSnd_YM2610Initted) bprintf(PRINT_ERROR, _T("BurnYM2610 BurnAY8910UpdateRequest called without init\n"));
357 #endif
358 
359 	AY8910Render(BurnYM2610StreamCallback(nBurnYM2610SoundRate));
360 }
361 
362 // ----------------------------------------------------------------------------
363 // Initialisation, etc.
364 
BurnYM2610Reset()365 void BurnYM2610Reset()
366 {
367 #if defined FBA_DEBUG
368 	if (!DebugSnd_YM2610Initted) bprintf(PRINT_ERROR, _T("BurnYM2610Reset called without init\n"));
369 #endif
370 
371 	BurnTimerReset();
372 
373 	YM2610ResetChip(0);
374 }
375 
BurnYM2610Exit()376 void BurnYM2610Exit()
377 {
378 #if defined FBA_DEBUG
379 	if (!DebugSnd_YM2610Initted) bprintf(PRINT_ERROR, _T("BurnYM2610Exit called without init\n"));
380 #endif
381 
382 	if (!DebugSnd_YM2610Initted) return;
383 
384 	YM2610Shutdown();
385 	AY8910Exit(0);
386 
387 	BurnTimerExit();
388 
389 	BurnFree(pBuffer);
390 	BurnFree(pAYBuffer);
391 
392 	bYM2610AddSignal = 0;
393 	bYM2610UseSeperateVolumes = 0;
394 
395 	DebugSnd_YM2610Initted = 0;
396 }
397 
BurnYM2610MapADPCMROM(UINT8 * YM2610ADPCMAROM,INT32 nYM2610ADPCMASize,UINT8 * YM2610ADPCMBROM,INT32 nYM2610ADPCMBSize)398 void BurnYM2610MapADPCMROM(UINT8* YM2610ADPCMAROM, INT32 nYM2610ADPCMASize, UINT8* YM2610ADPCMBROM, INT32 nYM2610ADPCMBSize)
399 {
400 #if defined FBA_DEBUG
401 	if (!DebugSnd_YM2610Initted) bprintf(PRINT_ERROR, _T("BurnYM2610MapADPCMROM called without init\n"));
402 #endif
403 
404 	YM2610SetRom(0, YM2610ADPCMAROM, nYM2610ADPCMASize, YM2610ADPCMBROM, nYM2610ADPCMBSize);
405 }
406 
BurnYM2610Init(INT32 nClockFrequency,UINT8 * YM2610ADPCMAROM,INT32 * nYM2610ADPCMASize,UINT8 * YM2610ADPCMBROM,INT32 * nYM2610ADPCMBSize,FM_IRQHANDLER IRQCallback,INT32 bAddSignal)407 INT32 BurnYM2610Init(INT32 nClockFrequency, UINT8* YM2610ADPCMAROM, INT32* nYM2610ADPCMASize, UINT8* YM2610ADPCMBROM, INT32* nYM2610ADPCMBSize, FM_IRQHANDLER IRQCallback, INT32 bAddSignal)
408 {
409 	return BurnYM2610Init(nClockFrequency, YM2610ADPCMAROM, nYM2610ADPCMASize, YM2610ADPCMBROM, nYM2610ADPCMBSize, IRQCallback, BurnSynchroniseStream, BurnGetTime, bAddSignal);
410 }
411 
BurnYM2610Init(INT32 nClockFrequency,UINT8 * YM2610ADPCMAROM,INT32 * nYM2610ADPCMASize,UINT8 * YM2610ADPCMBROM,INT32 * nYM2610ADPCMBSize,FM_IRQHANDLER IRQCallback,INT32 (* StreamCallback)(INT32),double (* GetTimeCallback)(),INT32 bAddSignal)412 INT32 BurnYM2610Init(INT32 nClockFrequency, UINT8* YM2610ADPCMAROM, INT32* nYM2610ADPCMASize, UINT8* YM2610ADPCMBROM, INT32* nYM2610ADPCMBSize, FM_IRQHANDLER IRQCallback, INT32 (*StreamCallback)(INT32), double (*GetTimeCallback)(), INT32 bAddSignal)
413 {
414 	DebugSnd_YM2610Initted = 1;
415 
416 	BurnTimerInit(&YM2610TimerOver, GetTimeCallback);
417 
418 	if (nBurnSoundRate <= 0) {
419 		BurnYM2610StreamCallback = YM2610StreamCallbackDummy;
420 
421 		BurnYM2610Update = YM2610UpdateDummy;
422 
423 		AY8910InitYM(0, nClockFrequency, 11025, NULL, NULL, NULL, NULL, BurnAY8910UpdateRequest);
424 		YM2610Init(1, nClockFrequency, 11025, (void**)(&YM2610ADPCMAROM), nYM2610ADPCMASize, (void**)(&YM2610ADPCMBROM), nYM2610ADPCMBSize, &BurnOPNTimerCallback, IRQCallback);
425 		return 0;
426 	}
427 
428 	BurnYM2610StreamCallback = StreamCallback;
429 
430 	if (nFMInterpolation == 3) {
431 		// Set YM2610 core samplerate to match the hardware
432 		nBurnYM2610SoundRate = nClockFrequency / 144;
433 		// Bring YM2610 core samplerate within usable range
434 		while (nBurnYM2610SoundRate > nBurnSoundRate * 3) {
435 			nBurnYM2610SoundRate >>= 1;
436 		}
437 
438 		BurnYM2610Update = YM2610UpdateResample;
439 
440 		nSampleSize = (UINT32)nBurnYM2610SoundRate * (1 << 16) / nBurnSoundRate;
441 	} else {
442 		nBurnYM2610SoundRate = nBurnSoundRate;
443 
444 		BurnYM2610Update = YM2610UpdateNormal;
445 	}
446 
447 	AY8910InitYM(0, nClockFrequency, nBurnYM2610SoundRate, NULL, NULL, NULL, NULL, BurnAY8910UpdateRequest);
448 	YM2610Init(1, nClockFrequency, nBurnYM2610SoundRate, (void**)(&YM2610ADPCMAROM), nYM2610ADPCMASize, (void**)(&YM2610ADPCMBROM), nYM2610ADPCMBSize, &BurnOPNTimerCallback, IRQCallback);
449 
450 	pBuffer = (INT16*)BurnMalloc(4096 * 6 * sizeof(INT16));
451 	memset(pBuffer, 0, 4096 * 6 * sizeof(INT16));
452 
453 	pAYBuffer = (INT32*)BurnMalloc(4096 * sizeof(INT32));
454 	memset(pAYBuffer, 0, 4096 * sizeof(INT32));
455 
456 	nYM2610Position = 0;
457 	nAY8910Position = 0;
458 
459 	nFractionalPosition = 0;
460 	bYM2610AddSignal = bAddSignal;
461 
462 	// default routes
463 	YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_1] = 1.00;
464 	YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_2] = 1.00;
465 	YM2610Volumes[BURN_SND_YM2610_AY8910_ROUTE] = 1.00;
466 	YM2610RouteDirs[BURN_SND_YM2610_YM2610_ROUTE_1] = BURN_SND_ROUTE_LEFT;
467 	YM2610RouteDirs[BURN_SND_YM2610_YM2610_ROUTE_2] = BURN_SND_ROUTE_RIGHT;
468 	YM2610RouteDirs[BURN_SND_YM2610_AY8910_ROUTE] = BURN_SND_ROUTE_BOTH;
469 
470 	bYM2610UseSeperateVolumes = 0;
471 	YM2610LeftVolumes[BURN_SND_YM2610_YM2610_ROUTE_1] = 1.00;
472 	YM2610LeftVolumes[BURN_SND_YM2610_YM2610_ROUTE_2] = 1.00;
473 	YM2610LeftVolumes[BURN_SND_YM2610_AY8910_ROUTE] = 1.00;
474 	YM2610RightVolumes[BURN_SND_YM2610_YM2610_ROUTE_1] = 1.00;
475 	YM2610RightVolumes[BURN_SND_YM2610_YM2610_ROUTE_2] = 1.00;
476 	YM2610RightVolumes[BURN_SND_YM2610_AY8910_ROUTE] = 1.00;
477 
478 	return 0;
479 }
480 
BurnYM2610SetRoute(INT32 nIndex,double nVolume,INT32 nRouteDir)481 void BurnYM2610SetRoute(INT32 nIndex, double nVolume, INT32 nRouteDir)
482 {
483 #if defined FBA_DEBUG
484 	if (!DebugSnd_YM2610Initted) bprintf(PRINT_ERROR, _T("BurnYM2610SetRoute called without init\n"));
485 	if (nIndex < 0 || nIndex > 2) bprintf(PRINT_ERROR, _T("BurnYM2610SetRoute called with invalid index %i\n"), nIndex);
486 #endif
487 
488 	YM2610Volumes[nIndex] = nVolume;
489 	YM2610RouteDirs[nIndex] = nRouteDir;
490 }
491 
BurnYM2610SetLeftVolume(INT32 nIndex,double nLeftVolume)492 void BurnYM2610SetLeftVolume(INT32 nIndex, double nLeftVolume)
493 {
494 #if defined FBA_DEBUG
495 	if (!DebugSnd_YM2610Initted) bprintf(PRINT_ERROR, _T("BurnYM2610SetLeftVolume called without init\n"));
496 	if (nIndex < 0 || nIndex > 2) bprintf(PRINT_ERROR, _T("BurnYM2610SetLeftVolume called with invalid index %i\n"), nIndex);
497 #endif
498 
499 	YM2610LeftVolumes[nIndex] = nLeftVolume;
500 }
501 
BurnYM2610SetRightVolume(INT32 nIndex,double nRightVolume)502 void BurnYM2610SetRightVolume(INT32 nIndex, double nRightVolume)
503 {
504 #if defined FBA_DEBUG
505 	if (!DebugSnd_YM2610Initted) bprintf(PRINT_ERROR, _T("BurnYM2610SetRightVolume called without init\n"));
506 	if (nIndex < 0 || nIndex > 2) bprintf(PRINT_ERROR, _T("BurnYM2610SetRightVolume called with invalid index %i\n"), nIndex);
507 #endif
508 
509 	YM2610RightVolumes[nIndex] = nRightVolume;
510 }
511 
BurnYM2610Scan(INT32 nAction,INT32 * pnMin)512 void BurnYM2610Scan(INT32 nAction, INT32* pnMin)
513 {
514 #if defined FBA_DEBUG
515 	if (!DebugSnd_YM2610Initted) bprintf(PRINT_ERROR, _T("BurnYM2610Scan called without init\n"));
516 #endif
517 
518 	BurnTimerScan(nAction, pnMin);
519 	AY8910Scan(nAction, pnMin);
520 
521 	if (nAction & ACB_DRIVER_DATA) {
522 		SCAN_VAR(nYM2610Position);
523 		SCAN_VAR(nAY8910Position);
524 	}
525 }
526