1 #include "burnint.h"
2 #include "dac.h"
3 
4 #define DAC_NUM		(8)	// Maximum DAC chips
5 
6 struct dac_info
7 {
8 	INT16	Output;
9 	INT16	Output2;
10 	INT32   Stereo;
11 	double 	nVolume;
12 	INT32 	nCurrentPosition;
13 	INT32	Initialized;
14 	INT32	OutputDir;
15 	INT32	(*pSyncCallback)();
16 };
17 
18 static struct dac_info dac_table[DAC_NUM];
19 
20 static INT16 UnsignedVolTable[256];
21 static INT16 SignedVolTable[256];
22 
23 static INT16 *lBuffer = NULL;
24 static INT16 *rBuffer = NULL;
25 
26 static INT32 NumChips;
27 
28 static INT32 bAddSignal;
29 
30 static INT32 (*pCPUTotalCycles)() = NULL;
31 static UINT32 nDACCPUMHZ = 0;
32 
33 // single-order dc blocking filter
34 static INT32 dac_dcblock   = 0; // enable
35 static INT16 dac_lastin_r  = 0;
36 static INT16 dac_lastout_r = 0;
37 static INT16 dac_lastin_l  = 0;
38 static INT16 dac_lastout_l = 0;
39 
DACDCBlock(INT32 enable)40 void DACDCBlock(INT32 enable)
41 {
42     dac_dcblock = enable;
43 }
44 
dc_blockR(INT16 sam)45 static INT16 dc_blockR(INT16 sam)
46 {
47     if (!dac_dcblock) return sam;
48     INT16 outr = sam - dac_lastin_r + 0.998 * dac_lastout_r;
49     dac_lastin_r = sam;
50     dac_lastout_r = outr;
51 
52     return outr;
53 }
54 
dc_blockL(INT16 sam)55 static INT16 dc_blockL(INT16 sam)
56 {
57     if (!dac_dcblock) return sam;
58     INT16 outl = sam - dac_lastin_l + 0.998 * dac_lastout_l;
59     dac_lastin_l = sam;
60     dac_lastout_l = outl;
61 
62     return outl;
63 }
64 
DACSyncInternal()65 static INT32 DACSyncInternal()
66 {
67 	return (INT32)(float)(nBurnSoundLen * (pCPUTotalCycles() / (nDACCPUMHZ / (nBurnFPS / 100.0000))));
68 }
69 
UpdateStream(INT32 chip,INT32 length)70 static void UpdateStream(INT32 chip, INT32 length)
71 {
72 	struct dac_info *ptr;
73 
74 	if (lBuffer == NULL) {	// delay buffer allocation for cases when fps is not 60
75 		lBuffer = (INT16*)BurnMalloc(nBurnSoundLen * sizeof(INT16));
76 		memset (lBuffer, 0, nBurnSoundLen * sizeof(INT16));
77 	}
78 	if (rBuffer == NULL) {	// delay buffer allocation for cases when fps is not 60
79 		rBuffer = (INT16*)BurnMalloc(nBurnSoundLen * sizeof(INT16));
80 		memset (rBuffer, 0, nBurnSoundLen * sizeof(INT16));
81 	}
82 
83 	ptr = &dac_table[chip];
84 	if (ptr->Initialized == 0) return;
85 
86 	if (length > nBurnSoundLen) length = nBurnSoundLen;
87 	length -= ptr->nCurrentPosition;
88 	if (length <= 0) return;
89 
90 	INT16 *lbuf = lBuffer + ptr->nCurrentPosition;
91 	INT16 *rbuf = rBuffer + ptr->nCurrentPosition;
92 
93 	INT16 lOut = ((ptr->OutputDir & BURN_SND_ROUTE_LEFT ) == BURN_SND_ROUTE_LEFT ) ? ptr->Output : 0;
94 	INT16 rOut = ((ptr->OutputDir & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) ? ((ptr->Stereo) ? ptr->Output2 : ptr->Output) : 0;
95 
96 	ptr->nCurrentPosition += length;
97 
98 	if (rOut && lOut) {
99 		while (length--) {
100 			*lbuf = BURN_SND_CLIP((INT32)(*lbuf + lOut));
101 			*rbuf = BURN_SND_CLIP((INT32)(*rbuf + rOut));
102 			lbuf++,rbuf++;
103 		}
104 	} else if (lOut) {
105 		while (length--) {
106 			*lbuf = BURN_SND_CLIP((INT32)(*lbuf + lOut));
107 			lbuf++;
108 		}
109 	} else if (rOut) {
110 		while (length--) {
111 			*rbuf = BURN_SND_CLIP((INT32)(*rbuf + rOut));
112 			rbuf++;
113 		}
114 	}
115 }
116 
DACUpdate(INT16 * Buffer,INT32 Length)117 void DACUpdate(INT16* Buffer, INT32 Length)
118 {
119 #if defined FBA_DEBUG
120 	if (!DebugSnd_DACInitted) bprintf(PRINT_ERROR, _T("DACUpdate called without init\n"));
121 #endif
122 
123 	struct dac_info *ptr;
124 
125 	for (INT32 i = 0; i < NumChips; i++) {
126 		UpdateStream(i, nBurnSoundLen);
127 	}
128 
129 	INT16 *lbuf = lBuffer;
130 	INT16 *rbuf = rBuffer;
131 
132 	if (bAddSignal) {
133 		while (Length--) {
134 			Buffer[0] = BURN_SND_CLIP((INT32)(dc_blockL(lbuf[0]) + Buffer[0]));
135 			Buffer[1] = BURN_SND_CLIP((INT32)(dc_blockR(rbuf[0]) + Buffer[1]));
136 			Buffer += 2;
137 			lbuf[0] = 0; // clear buffer
138 			rbuf[0] = 0; // clear buffer
139 			lbuf++;
140 			rbuf++;
141 		}
142 	} else {
143 		while (Length--) {
144 			Buffer[0] = dc_blockL(lbuf[0]);
145 			Buffer[1] = dc_blockR(rbuf[0]);
146 			Buffer += 2;
147 			lbuf[0] = 0; // clear buffer
148 			rbuf[0] = 0; // clear buffer
149 			lbuf++;
150 			rbuf++;
151 		}
152 	}
153 
154 	for (INT32 i = 0; i < NumChips; i++) {
155 		ptr = &dac_table[i];
156 		ptr->nCurrentPosition = 0;
157 	}
158 }
159 
DACWrite(INT32 Chip,UINT8 Data)160 void DACWrite(INT32 Chip, UINT8 Data)
161 {
162 #if defined FBA_DEBUG
163 	if (!DebugSnd_DACInitted) bprintf(PRINT_ERROR, _T("DACWrite called without init\n"));
164 	if (Chip > NumChips) bprintf(PRINT_ERROR, _T("DACWrite called with invalid chip number %x\n"), Chip);
165 #endif
166 
167 	struct dac_info *ptr;
168 
169 	ptr = &dac_table[Chip];
170 
171 	UpdateStream(Chip, ptr->pSyncCallback());
172 
173 	ptr->Output = (INT32)(UnsignedVolTable[Data] * ptr->nVolume);
174 }
175 
DACWrite16(INT32 Chip,INT16 Data)176 void DACWrite16(INT32 Chip, INT16 Data)
177 {
178 #if defined FBA_DEBUG
179 	if (!DebugSnd_DACInitted) bprintf(PRINT_ERROR, _T("DACWrite16 called without init\n"));
180 	if (Chip > NumChips) bprintf(PRINT_ERROR, _T("DACWrite16 called with invalid chip number %x\n"), Chip);
181 #endif
182 
183 	struct dac_info *ptr;
184 
185 	ptr = &dac_table[Chip];
186 
187 	Data = (INT32)(Data * ptr->nVolume);
188 
189 	if (Data != ptr->Output) {
190 		UpdateStream(Chip, ptr->pSyncCallback());
191 		ptr->Output = Data;
192 	}
193 }
194 
DACWrite16Stereo(INT32 Chip,INT16 Data,INT16 Data2)195 void DACWrite16Stereo(INT32 Chip, INT16 Data, INT16 Data2)
196 {
197 #if defined FBA_DEBUG
198 	if (!DebugSnd_DACInitted) bprintf(PRINT_ERROR, _T("DACWrite16Stereo called without init\n"));
199 	if (Chip > NumChips) bprintf(PRINT_ERROR, _T("DACWrite16Stereo called with invalid chip number %x\n"), Chip);
200 #endif
201 
202 	struct dac_info *ptr;
203 
204 	ptr = &dac_table[Chip];
205 
206 	Data = (INT32)(Data * ptr->nVolume);
207 	Data2 = (INT32)(Data2 * ptr->nVolume);
208 
209 	if (Data != ptr->Output || Data2 != ptr->Output2) {
210 		UpdateStream(Chip, ptr->pSyncCallback());
211 		ptr->Output = Data;
212 		ptr->Output2 = Data2;
213 	}
214 }
215 
DACWrite16Signed(INT32 Chip,UINT16 Data)216 void DACWrite16Signed(INT32 Chip, UINT16 Data)
217 {
218 #if defined FBA_DEBUG
219 	if (!DebugSnd_DACInitted) bprintf(PRINT_ERROR, _T("DACWrite16 called without init\n"));
220 	if (Chip > NumChips) bprintf(PRINT_ERROR, _T("DACWrite16 called with invalid chip number %x\n"), Chip);
221 #endif
222 
223 	struct dac_info *ptr;
224 
225 	ptr = &dac_table[Chip];
226 
227     INT16 Signed = Data - 0x8000;
228 
229 	Data = (INT32)(Signed * ptr->nVolume);
230 
231 	if (Data != ptr->Output) {
232 		UpdateStream(Chip, ptr->pSyncCallback());
233 		ptr->Output = Data;
234 	}
235 }
236 
DACSignedWrite(INT32 Chip,UINT8 Data)237 void DACSignedWrite(INT32 Chip, UINT8 Data)
238 {
239 #if defined FBA_DEBUG
240 	if (!DebugSnd_DACInitted) bprintf(PRINT_ERROR, _T("DACSignedWrite called without init\n"));
241 	if (Chip > NumChips) bprintf(PRINT_ERROR, _T("DACSignedWrite called with invalid chip number %x\n"), Chip);
242 #endif
243 	struct dac_info *ptr;
244 
245 	ptr = &dac_table[Chip];
246 
247 	UpdateStream(Chip, ptr->pSyncCallback());
248 
249 	ptr->Output = (INT32)(SignedVolTable[Data] * ptr->nVolume);
250 }
251 
DACBuildVolTables()252 static void DACBuildVolTables()
253 {
254 	for (INT32 i = 0;i < 256;i++) {
255 		UnsignedVolTable[i] = i * 0x101 / 2;
256 		SignedVolTable[i] = i * 0x101 - 0x8000;
257 	}
258 }
259 
DACStereoMode(INT32 Chip)260 void DACStereoMode(INT32 Chip)
261 {
262 #if defined FBA_DEBUG
263 	if (!DebugSnd_DACInitted) bprintf(PRINT_ERROR, _T("DACStereoMode called without init\n"));
264 	if (Chip > NumChips) bprintf(PRINT_ERROR, _T("DACStereoMode called with invalid chip number %x\n"), Chip);
265 #endif
266 
267 	struct dac_info *ptr;
268 	ptr = &dac_table[Chip];
269 
270 	ptr->Stereo = 1;
271 }
272 
DACInit(INT32 Num,UINT32 Clock,INT32 bAdd,INT32 (* pCPUCyclesCB)(),INT32 nCpuMHZ)273 void DACInit(INT32 Num, UINT32 Clock, INT32 bAdd, INT32 (*pCPUCyclesCB)(), INT32 nCpuMHZ)
274 {
275 	if (pCPUCyclesCB == NULL) {
276 		bprintf(PRINT_ERROR, _T("DACInit pCPUCyclesCB is NULL.\n"));
277 	}
278 	if (nCpuMHZ == 0) {
279 		bprintf(PRINT_ERROR, _T("DACInit nCPUMHZ is 0.\n"));
280 	}
281 
282 	pCPUTotalCycles = pCPUCyclesCB;
283 	nDACCPUMHZ = nCpuMHZ;
284 
285 	DACInit(Num, Clock, bAdd, DACSyncInternal);
286 }
287 
288 
DACInit(INT32 Num,UINT32,INT32 bAdd,INT32 (* pSyncCB)())289 void DACInit(INT32 Num, UINT32 /*Clock*/, INT32 bAdd, INT32 (*pSyncCB)())
290 {
291 #if defined FBA_DEBUG
292 	if (Num >= DAC_NUM) bprintf (PRINT_ERROR, _T("DACInit called for too many chips (%d)! Change DAC_NUM (%d)!\n"), Num, DAC_NUM);
293 	if (pSyncCB == NULL) bprintf (PRINT_ERROR, _T("DACInit called with NULL callback!\n"));
294 #endif
295 
296 	struct dac_info *ptr;
297 
298 	DebugSnd_DACInitted = 1;
299 
300 	NumChips = Num + 1;
301 
302 	ptr = &dac_table[Num];
303 
304 	memset (ptr, 0, sizeof(dac_info));
305 
306 	ptr->Initialized = 1;
307 	ptr->nVolume = 1.00;
308 	ptr->OutputDir = BURN_SND_ROUTE_BOTH;
309 	ptr->Stereo = 0;
310 	ptr->pSyncCallback = pSyncCB;
311 
312 	DACBuildVolTables(); // necessary to build for every chip?
313 
314 	bAddSignal = bAdd;
315 }
316 
DACSetRoute(INT32 Chip,double nVolume,INT32 nRouteDir)317 void DACSetRoute(INT32 Chip, double nVolume, INT32 nRouteDir)
318 {
319 #if defined FBA_DEBUG
320 	if (!DebugSnd_DACInitted) bprintf(PRINT_ERROR, _T("DACSetRoute called without init\n"));
321 	if (Chip > NumChips) bprintf(PRINT_ERROR, _T("DACSetRoute called with invalid chip %i\n"), Chip);
322 #endif
323 
324 	struct dac_info *ptr;
325 
326 	ptr = &dac_table[Chip];
327 	ptr->nVolume = nVolume;
328 	ptr->OutputDir = nRouteDir;
329 }
330 
DACReset()331 void DACReset()
332 {
333 #if defined FBA_DEBUG
334 	if (!DebugSnd_DACInitted) bprintf(PRINT_ERROR, _T("DACReset called without init\n"));
335 #endif
336 
337 	struct dac_info *ptr;
338 
339 	for (INT32 i = 0; i < NumChips; i++) {
340 		ptr = &dac_table[i];
341 
342 		ptr->nCurrentPosition = 0;
343 		ptr->Output = 0;
344 		ptr->Output2 = 0;
345     }
346 
347     dac_lastin_r = dac_lastout_r = 0;
348 	dac_lastin_l = dac_lastout_l = 0;
349 }
350 
DACExit()351 void DACExit()
352 {
353 #if defined FBA_DEBUG
354 	if (!DebugSnd_DACInitted) bprintf(PRINT_ERROR, _T("DACExit called without init\n"));
355 #endif
356 
357 	if (!DebugSnd_DACInitted) return;
358 
359 	struct dac_info *ptr;
360 
361 	for (INT32 i = 0; i < DAC_NUM; i++) {
362 		ptr = &dac_table[i];
363 
364 		ptr->Initialized = 0;
365 		ptr->pSyncCallback = NULL;
366 	}
367 
368 	pCPUTotalCycles = NULL;
369 	nDACCPUMHZ = 0;
370 
371 	NumChips = 0;
372 
373     dac_dcblock = 0;
374 
375 	DebugSnd_DACInitted = 0;
376 
377 	BurnFree (lBuffer);
378 	BurnFree (rBuffer);
379 	lBuffer = NULL;
380 	rBuffer = NULL;
381 }
382 
DACScan(INT32 nAction,INT32 * pnMin)383 void DACScan(INT32 nAction, INT32 *pnMin)
384 {
385 #if defined FBA_DEBUG
386 	if (!DebugSnd_DACInitted) bprintf(PRINT_ERROR, _T("DACScan called without init\n"));
387 #endif
388 
389 	if (pnMin != NULL) {
390 		*pnMin = 0x029719;
391 	}
392 
393 	struct dac_info *ptr;
394 
395 	if (nAction & ACB_DRIVER_DATA) {
396 		for (INT32 i = 0; i < NumChips; i++) {
397 			ptr = &dac_table[i];
398 
399 			SCAN_VAR(ptr->Output);
400 			SCAN_VAR(ptr->Output2);
401 		}
402 	}
403 }
404