1 /* Mednafen - Multi-system Emulator
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 */
17
18 #include "pcfx.h"
19 #include "soundbox.h"
20 #include "king.h"
21 #include "../cdrom/scsicd.h"
22 #include "pce_psg/pce_psg.h"
23 #include "../clamp.h"
24 #include "../sound/OwlResampler.h"
25
26 #include <math.h>
27 #include <string.h>
28
29 static const int StepSizes[49] =
30 {
31 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50,
32 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157,
33 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449,
34 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552
35 };
36
37 static const int StepIndexDeltas[16] =
38 {
39 -1, -1, -1, -1, 2, 4, 6, 8,
40 -1, -1, -1, -1, 2, 4, 6, 8
41 };
42
43 static OwlResampler* FXres = NULL;
44 static OwlBuffer* FXsbuf[2] = { NULL, NULL };
45 RavenBuffer* FXCDDABufs[2] = { NULL, NULL }; // Used in the CDROM code
46
47 static PCE_PSG *pce_psg = NULL;
48
49 static bool SoundEnabled;
50 static uint32 adpcm_lastts;
51
52 struct SoundBox
53 {
54 uint16 ADPCMControl;
55 uint8 ADPCMVolume[2][2]; // ADPCMVolume[channel(0 or 1)][left(0) or right(1)]
56 uint8 CDDAVolume[2];
57 int32 bigdiv;
58 int32 smalldiv;
59
60 int64 ResetAntiClick[2];
61 double VolumeFiltered[2][2];
62 double vf_xv[2][2][1+1], vf_yv[2][2][1+1];
63
64 int32 ADPCMDelta[2];
65 int32 ADPCMHaveDelta[2];
66
67 int32 ADPCMPredictor[2];
68 int32 StepSizeIndex[2];
69
70 uint32 ADPCMWhichNibble[2];
71 uint16 ADPCMHalfWord[2];
72 bool ADPCMHaveHalfWord[2];
73
74 int32 ADPCM_last[2][2];
75 };
76
77 static SoundBox sbox;
78 static double ADPCMVolTable[0x40];
79
80 static bool EmulateBuggyCodec; // If true, emulate the buggy codec/algorithm used by an official PC-FX ADPCM encoder, rather than how the
81 // hardware actually works.
82 static bool ResetAntiClickEnabled; // = true;
83
84
RedoVolume(void)85 static void RedoVolume(void)
86 {
87 pce_psg->SetVolume(0.681); //0.227 * 0.50);
88 //ADPCMSynth.volume(0.50);
89 }
90
SoundBox_SetSoundRate(uint32 rate)91 bool SoundBox_SetSoundRate(uint32 rate)
92 {
93 SoundEnabled = (bool)rate;
94
95 if(FXres)
96 {
97 delete FXres;
98 FXres = NULL;
99 }
100
101 if(rate > 0)
102 {
103 FXres = new OwlResampler(PCFX_MASTER_CLOCK / 12, rate, MDFN_GetSettingF("pcfx.resamp_rate_error"), 20, MDFN_GetSettingUI("pcfx.resamp_quality"));
104
105 for(unsigned i = 0; i < 2; i++)
106 FXres->ResetBufResampState(FXsbuf[i]);
107 }
108
109 RedoVolume();
110
111 return(TRUE);
112 }
113
SoundBox_Init(bool arg_EmulateBuggyCodec,bool arg_ResetAntiClickEnabled)114 int SoundBox_Init(bool arg_EmulateBuggyCodec, bool arg_ResetAntiClickEnabled)
115 {
116 adpcm_lastts = 0;
117 SoundEnabled = false;
118
119 EmulateBuggyCodec = arg_EmulateBuggyCodec;
120 ResetAntiClickEnabled = arg_ResetAntiClickEnabled;
121
122 for(unsigned i = 0; i < 2; i++)
123 {
124 FXsbuf[i] = new OwlBuffer();
125 FXCDDABufs[i] = new RavenBuffer();
126 }
127
128 pce_psg = new PCE_PSG(FXsbuf[0]->Buf(), FXsbuf[1]->Buf(), PCE_PSG::REVISION_HUC6280A);
129
130 memset(&sbox, 0, sizeof(sbox));
131
132 // Build ADPCM volume table, 1.5dB per step, ADPCM volume settings of 0x0 through 0x1B result in silence.
133 for(int x = 0; x < 0x40; x++)
134 {
135 double flub = 1;
136 int vti = 0x3F - x;
137
138 if(x)
139 flub /= powf(2, (double)1 / 4 * x);
140
141 if(vti <= 0x1B)
142 ADPCMVolTable[vti] = 0;
143 else
144 ADPCMVolTable[vti] = flub;
145 }
146
147 return (1);
148 }
149
SoundBox_Kill(void)150 void SoundBox_Kill(void)
151 {
152 if(pce_psg)
153 {
154 delete pce_psg;
155 pce_psg = NULL;
156 }
157
158 for(unsigned i = 0; i < 2; i++)
159 {
160 if(FXsbuf[i])
161 {
162 delete FXsbuf[i];
163 FXsbuf[i] = NULL;
164 }
165 if(FXCDDABufs[i])
166 {
167 delete FXCDDABufs[i];
168 FXCDDABufs[i] = NULL;
169 }
170 }
171
172 if(FXres)
173 {
174 delete FXres;
175 FXres = NULL;
176 }
177 }
178
179 /* Macro to access currently selected PSG channel */
SoundBox_Write(uint32 A,uint16 V,const v810_timestamp_t timestamp)180 void SoundBox_Write(uint32 A, uint16 V, const v810_timestamp_t timestamp)
181 {
182 A &= 0x3F;
183
184 if(A < 0x20)
185 pce_psg->Write(timestamp / 3, A >> 1, V);
186 else
187 {
188 //printf("%04x %04x %d\n", A, V, timestamp);
189 switch(A & 0x3F)
190 {
191 case 0x20:
192 SoundBox_ADPCMUpdate(timestamp);
193 for(int ch = 0; ch < 2; ch++)
194 {
195 if(!(sbox.ADPCMControl & (0x10 << ch)) && (V & (0x10 << ch)))
196 {
197 //printf("Reset: %d\n", ch);
198
199 if(ResetAntiClickEnabled)
200 {
201 sbox.ResetAntiClick[ch] += (int64)sbox.ADPCMPredictor[ch] << 32;
202 if(sbox.ResetAntiClick[ch] > ((int64)0x3FFF << 32))
203 sbox.ResetAntiClick[ch] = (int64)0x3FFF << 32;
204 if(sbox.ResetAntiClick[ch] < ((int64)-0x4000 << 32))
205 sbox.ResetAntiClick[ch] = (int64)-0x4000 << 32;
206 }
207
208 sbox.ADPCMPredictor[ch] = 0;
209 sbox.StepSizeIndex[ch] = 0;
210 }
211 }
212 sbox.ADPCMControl = V;
213 break;
214
215 case 0x22:
216 SoundBox_ADPCMUpdate(timestamp);
217 sbox.ADPCMVolume[0][0] = V & 0x3F;
218 break;
219
220 case 0x24:
221 SoundBox_ADPCMUpdate(timestamp);
222 sbox.ADPCMVolume[0][1] = V & 0x3F;
223 break;
224
225 case 0x26:
226 SoundBox_ADPCMUpdate(timestamp);
227 sbox.ADPCMVolume[1][0] = V & 0x3F;
228 break;
229
230 case 0x28:
231 SoundBox_ADPCMUpdate(timestamp);
232 sbox.ADPCMVolume[1][1] = V & 0x3F;
233 break;
234
235 case 0x2A:
236 sbox.CDDAVolume[0] = V & 0x3F;
237 SCSICD_SetCDDAVolume(0.50f * sbox.CDDAVolume[0] / 63, 0.50f * sbox.CDDAVolume[1] / 63);
238 break;
239
240 case 0x2C:
241 sbox.CDDAVolume[1] = V & 0x3F;
242 SCSICD_SetCDDAVolume(0.50f * sbox.CDDAVolume[0] / 63, 0.50f * sbox.CDDAVolume[1] / 63);
243 break;
244 }
245 }
246 }
247
248 static uint32 KINGADPCMControl;
249
SoundBox_SetKINGADPCMControl(uint32 value)250 void SoundBox_SetKINGADPCMControl(uint32 value)
251 {
252 KINGADPCMControl = value;
253 }
254
255 /* Digital filter designed by mkfilter/mkshape/gencode A.J. Fisher
256 Command line: /www/usr/fisher/helpers/mkfilter -Bu -Lp -o 1 -a 1.5888889125e-04 0.0000000000e+00 -l */
DoVolumeFilter(int ch,int lr)257 static void DoVolumeFilter(int ch, int lr)
258 {
259 sbox.vf_xv[ch][lr][0] = sbox.vf_xv[ch][lr][1];
260 sbox.vf_xv[ch][lr][1] = (double)ADPCMVolTable[sbox.ADPCMVolume[ch][lr]] / 2.004348738e+03;
261
262 sbox.vf_yv[ch][lr][0] = sbox.vf_yv[ch][lr][1];
263 sbox.vf_yv[ch][lr][1] = (sbox.vf_xv[ch][lr][0] + sbox.vf_xv[ch][lr][1]) + ( 0.9990021696 * sbox.vf_yv[ch][lr][0]);
264 sbox.VolumeFiltered[ch][lr] = sbox.vf_yv[ch][lr][1];
265 }
266
267 static const int16 ADPCM_PhaseFilter[8][7] =
268 {
269 /* 0 */ { 40, 283, 654, 683, 331, 56, 1 }, // 2048
270 /* 1 */ { 28, 238, 618, 706, 381, 75, 2 }, // 2048
271 /* 2 */ { 19, 197, 577, 720, 432, 99, 4 }, // 2048
272 /* 3 */ { 12, 160, 532, 726, 483, 128, 7 }, // 2048
273 /* 4 */ { 7, 128, 483, 726, 532, 160, 12 }, // 2048
274 /* 5 */ { 4, 99, 432, 720, 577, 197, 19 }, // 2048
275 /* 6 */ { 2, 75, 381, 706, 618, 238, 28 }, // 2048
276 /* 7 */ { 1, 56, 331, 683, 654, 283, 40 }, // 2048
277 };
278
SoundBox_ADPCMUpdate(const v810_timestamp_t timestamp)279 v810_timestamp_t SoundBox_ADPCMUpdate(const v810_timestamp_t timestamp)
280 {
281 int32 run_time = timestamp - adpcm_lastts;
282
283 adpcm_lastts = timestamp;
284
285 sbox.bigdiv -= run_time * 2;
286
287 while(sbox.bigdiv <= 0)
288 {
289 sbox.smalldiv--;
290 while(sbox.smalldiv <= 0)
291 {
292 sbox.smalldiv += 1 << ((KINGADPCMControl >> 2) & 0x3);
293 for(int ch = 0; ch < 2; ch++)
294 {
295 // Keep playing our last halfword fetched even if KING ADPCM is disabled
296 if(sbox.ADPCMHaveHalfWord[ch] || KINGADPCMControl & (1 << ch))
297 {
298 if(!sbox.ADPCMWhichNibble[ch])
299 {
300 sbox.ADPCMHalfWord[ch] = KING_GetADPCMHalfWord(ch);
301 sbox.ADPCMHaveHalfWord[ch] = TRUE;
302 }
303
304 // If the channel's reset bit is set, don't update its ADPCM state.
305 if(sbox.ADPCMControl & (0x10 << ch))
306 {
307 sbox.ADPCMDelta[ch] = 0;
308 }
309 else
310 {
311 uint8 nibble = (sbox.ADPCMHalfWord[ch] >> (sbox.ADPCMWhichNibble[ch])) & 0xF;
312 int32 BaseStepSize = StepSizes[sbox.StepSizeIndex[ch]];
313
314 //if(!ch)
315 //printf("Nibble: %02x\n", nibble);
316
317 if(EmulateBuggyCodec)
318 {
319 if(BaseStepSize == 1552)
320 BaseStepSize = 1522;
321
322 sbox.ADPCMDelta[ch] = BaseStepSize * ((nibble & 0x7) + 1) * 2;
323 }
324 else
325 sbox.ADPCMDelta[ch] = BaseStepSize * ((nibble & 0x7) + 1);
326
327 // Linear interpolation turned on?
328 if(sbox.ADPCMControl & (0x4 << ch))
329 sbox.ADPCMDelta[ch] >>= (KINGADPCMControl >> 2) & 0x3;
330
331 if(nibble & 0x8)
332 sbox.ADPCMDelta[ch] = -sbox.ADPCMDelta[ch];
333
334 sbox.StepSizeIndex[ch] += StepIndexDeltas[nibble];
335
336 if(sbox.StepSizeIndex[ch] < 0)
337 sbox.StepSizeIndex[ch] = 0;
338
339 if(sbox.StepSizeIndex[ch] > 48)
340 sbox.StepSizeIndex[ch] = 48;
341 }
342 sbox.ADPCMHaveDelta[ch] = 1;
343
344 // Linear interpolation turned on?
345 if(sbox.ADPCMControl & (0x4 << ch))
346 sbox.ADPCMHaveDelta[ch] = 1 << ((KINGADPCMControl >> 2) & 0x3);
347
348 sbox.ADPCMWhichNibble[ch] = (sbox.ADPCMWhichNibble[ch] + 4) & 0xF;
349
350 if(!sbox.ADPCMWhichNibble[ch])
351 sbox.ADPCMHaveHalfWord[ch] = FALSE;
352 }
353 } // for(int ch...)
354 } // while(sbox.smalldiv <= 0)
355
356 const uint32 synthtime42 = (timestamp << 1) + sbox.bigdiv;
357 const uint32 synthtime14 = synthtime42 / 3;
358 const uint32 synthtime = synthtime14 >> 3;
359 const unsigned synthtime_phase = synthtime14 & 7;
360
361 //printf("Phase: %d, %d\n", synthtime42 % 24, (synthtime42 / 3) & 7);
362
363 for(int ch = 0; ch < 2; ch++)
364 {
365 //if(!ch)
366 //{
367 // printf("%d\n", synthtime - last_synthtime);
368 // last_synthtime = synthtime;
369 //}
370
371 if(sbox.ADPCMHaveDelta[ch])
372 {
373 sbox.ADPCMPredictor[ch] += sbox.ADPCMDelta[ch];
374
375 sbox.ADPCMHaveDelta[ch]--;
376
377 if(sbox.ADPCMPredictor[ch] > 0x3FFF) { sbox.ADPCMPredictor[ch] = 0x3FFF; /*printf("Overflow: %d\n", ch);*/ }
378 if(sbox.ADPCMPredictor[ch] < -0x4000) { sbox.ADPCMPredictor[ch] = -0x4000; /*printf("Underflow: %d\n", ch);*/ }
379 }
380 else
381 {
382
383 }
384
385 if(SoundEnabled)
386 {
387 int32 samp[2];
388
389 if(EmulateBuggyCodec)
390 {
391 samp[0] = (int32)(((sbox.ADPCMPredictor[ch] >> 1) + (sbox.ResetAntiClick[ch] >> 33)) * sbox.VolumeFiltered[ch][0]);
392 samp[1] = (int32)(((sbox.ADPCMPredictor[ch] >> 1) + (sbox.ResetAntiClick[ch] >> 33)) * sbox.VolumeFiltered[ch][1]);
393 }
394 else
395 {
396 samp[0] = (int32)((sbox.ADPCMPredictor[ch] + (sbox.ResetAntiClick[ch] >> 32)) * sbox.VolumeFiltered[ch][0]);
397 samp[1] = (int32)((sbox.ADPCMPredictor[ch] + (sbox.ResetAntiClick[ch] >> 32)) * sbox.VolumeFiltered[ch][1]);
398 }
399 #if 0
400 printf("%d, %f %f\n", ch, sbox.VolumeFiltered[ch][0], sbox.VolumeFiltered[ch][1]);
401
402 {
403 static int inv = 0x1FFF;
404
405 samp[0] = samp[1] = inv;
406
407 if(ch == 1)
408 inv = -inv;
409 }
410 #endif
411 for(unsigned y = 0; y < 2; y++)
412 {
413 const int32 delta = samp[y] - sbox.ADPCM_last[ch][y];
414 int32* tb = FXsbuf[y]->Buf() + (synthtime & 0xFFFF);
415 const int16* coeffs = ADPCM_PhaseFilter[synthtime_phase];
416
417 for(unsigned c = 0; c < 7; c++)
418 {
419 int32 tmp = delta * coeffs[c];
420
421 tb[c] += tmp;
422 }
423 }
424
425 sbox.ADPCM_last[ch][0] = samp[0];
426 sbox.ADPCM_last[ch][1] = samp[1];
427 }
428 }
429
430 for(int ch = 0; ch < 2; ch++)
431 {
432 sbox.ResetAntiClick[ch] -= sbox.ResetAntiClick[ch] >> 8;
433 //if(ch)
434 // MDFN_DispMessage("%d", (int)(sbox.ResetAntiClick[ch] >> 32));
435 }
436
437 for(int ch = 0; ch < 2; ch++)
438 for(int lr = 0; lr < 2; lr++)
439 {
440 DoVolumeFilter(ch, lr);
441 }
442 sbox.bigdiv += 1365 * 2 / 2;
443 }
444
445 return(timestamp + (sbox.bigdiv + 1) / 2);
446 }
447
SoundBox_Flush(const v810_timestamp_t end_timestamp,v810_timestamp_t * new_base_timestamp,int16 * SoundBuf,const int32 MaxSoundFrames)448 int32 SoundBox_Flush(const v810_timestamp_t end_timestamp, v810_timestamp_t* new_base_timestamp, int16 *SoundBuf, const int32 MaxSoundFrames)
449 {
450 const uint32 end_timestamp_div3 = end_timestamp / 3;
451 const uint32 end_timestamp_div12 = end_timestamp / 12;
452 const uint32 end_timestamp_mod12 = end_timestamp % 12;
453 const unsigned rsc = std::min<unsigned>(65536, end_timestamp_div12);
454 int32 FrameCount = 0;
455
456 *new_base_timestamp = end_timestamp_mod12;
457
458 pce_psg->Update(end_timestamp_div3);
459
460 for(unsigned y = 0; y < 2; y++)
461 {
462 if(SoundEnabled && FXres)
463 {
464 FXsbuf[y]->Integrate(rsc, 0, 0, FXCDDABufs[y]);
465 FrameCount = FXres->Resample(FXsbuf[y], rsc, SoundBuf + y, MaxSoundFrames);
466 }
467 else
468 FXsbuf[y]->ResampleSkipped(rsc);
469
470 FXCDDABufs[y]->Finish(rsc);
471 }
472
473 return(FrameCount);
474 }
475
SoundBox_ResetTS(const v810_timestamp_t ts_base)476 void SoundBox_ResetTS(const v810_timestamp_t ts_base)
477 {
478 pce_psg->ResetTS(ts_base / 3);
479 adpcm_lastts = ts_base;
480 }
481
SoundBox_Reset(const v810_timestamp_t timestamp)482 void SoundBox_Reset(const v810_timestamp_t timestamp)
483 {
484 SoundBox_ADPCMUpdate(timestamp);
485 pce_psg->Power(timestamp / 3);
486
487 sbox.ADPCMControl = 0;
488
489 memset(&sbox.vf_xv, 0, sizeof(sbox.vf_xv));
490 memset(&sbox.vf_yv, 0, sizeof(sbox.vf_yv));
491
492 for(int lr = 0; lr < 2; lr++)
493 {
494 for(int ch = 0; ch < 2; ch++)
495 {
496 sbox.ADPCMVolume[ch][lr] = 0;
497 sbox.VolumeFiltered[ch][lr] = 0;
498 }
499
500 sbox.CDDAVolume[lr] = 0;
501 }
502
503 for(int ch = 0; ch < 2; ch++)
504 {
505 sbox.ADPCMPredictor[ch] = 0;
506 sbox.StepSizeIndex[ch] = 0;
507 }
508
509 memset(sbox.ADPCMWhichNibble, 0, sizeof(sbox.ADPCMWhichNibble));
510 memset(sbox.ADPCMHalfWord, 0, sizeof(sbox.ADPCMHalfWord));
511 memset(sbox.ADPCMHaveHalfWord, 0, sizeof(sbox.ADPCMHaveHalfWord));
512
513 SCSICD_SetCDDAVolume(0.50f * sbox.CDDAVolume[0] / 63, 0.50f * sbox.CDDAVolume[1] / 63);
514
515 sbox.bigdiv = 2; // TODO: KING->SBOX ADPCM Synch //(1365 - 85 * 4) * 2; //1365 * 2 / 2;
516 sbox.smalldiv = 0;
517 }
518
SoundBox_StateAction(StateMem * sm,int load,int data_only)519 int SoundBox_StateAction(StateMem *sm, int load, int data_only)
520 {
521 int ret = 1;
522
523 ret &= pce_psg->StateAction(sm, load, data_only);
524
525 SFORMAT SoundBox_StateRegs[] =
526 {
527 SFVARN(sbox.ADPCMControl, "ADPCMControl"),
528 SFARRAYN(&sbox.ADPCMVolume[0][0], 2 * 2, "ADPCMVolume"),
529 SFARRAYN(sbox.CDDAVolume, 2, "CDDAVolume"),
530 SFVARN(sbox.bigdiv, "bigdiv"),
531 SFVARN(sbox.smalldiv, "smalldiv"),
532
533 SFARRAY64N(&sbox.ResetAntiClick[0], 2, "ResetAntiClick"),
534 SFARRAYDN(&sbox.VolumeFiltered[0][0], 2 * 2, "VolumeFiltered"),
535 SFARRAYDN(&sbox.vf_xv[0][0][0], 2 * 2 * (1 + 1), "vf_xv"),
536 SFARRAYDN(&sbox.vf_yv[0][0][0], 2 * 2 * (1 + 1), "vf_yv"),
537
538 SFARRAY32N(sbox.ADPCMDelta, 2, "ADPCMDelta"),
539 SFARRAY32N(sbox.ADPCMHaveDelta, 2, "ADPCMHaveDelta"),
540
541 SFARRAY32N(&sbox.ADPCMPredictor[0], 2, "ADPCMPredictor"),
542 SFARRAY32N(&sbox.StepSizeIndex[0], 2, "ADPCMStepSizeIndex"),
543
544 SFARRAY32N(sbox.ADPCMWhichNibble, 2, "ADPCMWNibble"),
545 SFARRAY16N(sbox.ADPCMHalfWord, 2, "ADPCMHalfWord"),
546 SFARRAYBN(sbox.ADPCMHaveHalfWord, 2, "ADPCMHHW"),
547
548 SFEND
549 };
550
551 ret &= MDFNSS_StateAction(sm, load, data_only, SoundBox_StateRegs, "SBOX", false);
552
553 if(load)
554 {
555 for(int ch = 0; ch < 2; ch++)
556 {
557 clamp(&sbox.ADPCMPredictor[ch], -0x4000, 0x3FFF);
558 clamp(&sbox.ResetAntiClick[ch], (int64)-0x4000 << 32, (int64)0x3FFF << 32);
559
560 if(!ResetAntiClickEnabled)
561 sbox.ResetAntiClick[ch] = 0;
562
563 clamp(&sbox.StepSizeIndex[ch], 0, 48);
564
565 clamp(&sbox.bigdiv, 1, 1365);
566 clamp(&sbox.smalldiv, 1, 8);
567
568 for(int lr = 0; lr < 2; lr++)
569 {
570
571 }
572 }
573 SCSICD_SetCDDAVolume(0.50f * sbox.CDDAVolume[0] / 63, 0.50f * sbox.CDDAVolume[1] / 63);
574 }
575 return(ret);
576 }
577