1 // ---------------------------------------------------------------------------
2 // PSG Sound Implementation
3 // Copyright (C) cisc 1997, 1999.
4 // ---------------------------------------------------------------------------
5 // $Id: psg.cpp,v 1.10 2002/05/15 21:38:01 cisc Exp $
11 #include "../../fileio.h"
12 // ---------------------------------------------------------------------------
20 for(int i = 0; i < noisetablesize; i++) {
23 for(int i = 0; i < 32; i++) {
24 EmitTableL[i] = EmitTableR[i] = -1;
26 for(int i = 0; i < 16; i++) {
27 for(int j = 0; j < 64; j++) {
28 enveloptable_l[i][j] = enveloptable_r[i][j] = 0;
31 SetVolume(0, 0, false);
35 envelop_l = enveloptable_l[0]; // temporary fix
36 envelop_r = enveloptable_r[0]; // temporary fix
44 // ---------------------------------------------------------------------------
49 for (int i=0; i<14; i++)
56 // ---------------------------------------------------------------------------
59 void PSG::SetClock(int clock, int rate)
61 tperiodbase = int((1 << toneshift ) / 4.0 * clock / rate);
62 eperiodbase = int((1 << envshift ) / 4.0 * clock / rate);
63 nperiodbase = int((1 << noiseshift) / 4.0 * clock / rate);
67 tmp = ((reg[0] + reg[1] * 256) & 0xfff);
68 speriod[0] = tmp ? tperiodbase / tmp : tperiodbase;
69 tmp = ((reg[2] + reg[3] * 256) & 0xfff);
70 speriod[1] = tmp ? tperiodbase / tmp : tperiodbase;
71 tmp = ((reg[4] + reg[5] * 256) & 0xfff);
72 speriod[2] = tmp ? tperiodbase / tmp : tperiodbase;
74 nperiod = tmp ? nperiodbase / tmp / 2 : nperiodbase / 2;
75 tmp = ((reg[11] + reg[12] * 256) & 0xffff);
76 eperiod = tmp ? eperiodbase / tmp : eperiodbase * 2;
79 // ---------------------------------------------------------------------------
82 void PSG::MakeNoiseTable()
87 for (int i=0; i<noisetablesize; i++)
90 for (int j=0; j<32; j++)
92 n = n * 2 + (noise & 1);
93 noise = (noise >> 1) | (((noise << 14) ^ ((noise & 0x0000ffff) << 16)) & 0x10000);
100 // ---------------------------------------------------------------------------
102 // 素直にテーブルで持ったほうが省スペース。
104 void PSG::SetVolume(int volume_l, int volume_r, bool is_ay3_891x)
106 double base_l = 0x4000 / 3.0 * pow(10.0, volume_l / 40.0);
107 double base_r = 0x4000 / 3.0 * pow(10.0, volume_r / 40.0);
111 // AY-3-8190/8192 (PSG): 16step
112 for (int i=31; i>=3; i-=2)
114 EmitTableL[i] = EmitTableL[i-1] = int(base_l);
115 EmitTableR[i] = EmitTableR[i-1] = int(base_r);
116 base_l /= 1.189207115;
117 base_l /= 1.189207115;
118 base_r /= 1.189207115;
119 base_r /= 1.189207115;
124 // YM2203 (SSG): 32step
125 for (int i=31; i>=2; i--)
127 EmitTableL[i] = int(base_l);
128 EmitTableR[i] = int(base_r);
129 base_l /= 1.189207115;
130 base_r /= 1.189207115;
139 SetChannelMask(~mask);
142 void PSG::SetChannelMask(int c)
145 for (int i=0; i<3; i++)
147 olevel_l[i] = mask & (1 << i) ? EmitTableL[(reg[8+i] & 15) * 2 + 1] : 0;
148 olevel_r[i] = mask & (1 << i) ? EmitTableR[(reg[8+i] & 15) * 2 + 1] : 0;
152 // ---------------------------------------------------------------------------
155 void PSG::MakeEnvelopTable()
157 // 0 lo 1 up 2 down 3 hi
158 static uint8 table1[16*2] =
160 2,0, 2,0, 2,0, 2,0, 1,0, 1,0, 1,0, 1,0,
161 2,2, 2,0, 2,1, 2,3, 1,1, 1,3, 1,2, 1,0,
163 static uint8 table2[4] = { 0, 0, 31, 31 };
164 static uint8 table3[4] = { 0, 1, 255, 0 }; // 255 = -1
166 uint* ptr_l = enveloptable_l[0];
167 uint* ptr_r = enveloptable_r[0];
169 for (int i=0; i<16*2; i++)
171 uint8 v = table2[table1[i]];
173 for (int j=0; j<32; j++)
175 *ptr_l++ = EmitTableL[v];
176 *ptr_r++ = EmitTableR[v];
177 v += table3[table1[i]];
182 // ---------------------------------------------------------------------------
184 // regnum レジスタの番号 (0 - 15)
187 void PSG::SetReg(uint regnum, uint8 data)
196 case 0: // ChA Fine Tune
197 case 1: // ChA Coarse Tune
198 tmp = ((reg[0] + reg[1] * 256) & 0xfff);
199 speriod[0] = tmp ? tperiodbase / tmp : tperiodbase;
202 case 2: // ChB Fine Tune
203 case 3: // ChB Coarse Tune
204 tmp = ((reg[2] + reg[3] * 256) & 0xfff);
205 speriod[1] = tmp ? tperiodbase / tmp : tperiodbase;
208 case 4: // ChC Fine Tune
209 case 5: // ChC Coarse Tune
210 tmp = ((reg[4] + reg[5] * 256) & 0xfff);
211 speriod[2] = tmp ? tperiodbase / tmp : tperiodbase;
214 case 6: // Noise generator control
216 nperiod = data ? nperiodbase / data : nperiodbase;
220 olevel_l[0] = mask & 1 ? EmitTableL[(data & 15) * 2 + 1] : 0;
221 olevel_r[0] = mask & 1 ? EmitTableR[(data & 15) * 2 + 1] : 0;
225 olevel_l[1] = mask & 2 ? EmitTableL[(data & 15) * 2 + 1] : 0;
226 olevel_r[1] = mask & 2 ? EmitTableR[(data & 15) * 2 + 1] : 0;
230 olevel_l[2] = mask & 4 ? EmitTableL[(data & 15) * 2 + 1] : 0;
231 olevel_r[2] = mask & 4 ? EmitTableR[(data & 15) * 2 + 1] : 0;
234 case 11: // Envelop period
236 tmp = ((reg[11] + reg[12] * 256) & 0xffff);
237 eperiod = tmp ? eperiodbase / tmp : eperiodbase * 2;
240 case 13: // Envelop shape
242 envelop_l = enveloptable_l[data & 15];
243 envelop_r = enveloptable_r[data & 15];
249 // ---------------------------------------------------------------------------
252 inline void PSG::StoreSample(Sample& dest, int32 data)
254 __UNLIKELY_IF(sizeof(Sample) == 2)
255 dest = (Sample) Limit(dest + data, 0x7fff, -0x8000);
260 // ---------------------------------------------------------------------------
262 // dest PCM データを展開するポインタ
263 // nsamples 展開する PCM のサンプル数
265 void PSG::Mix(Sample* dest, int nsamples)
267 uint8 chenable[3], nenable[3];
270 if ((r7 & 0x3f) | ((reg[8] | reg[9] | reg[10]) & 0x1f))
272 chenable[0] = (r7 & 0x01) && (speriod[0] <= (1 << toneshift));
273 chenable[1] = (r7 & 0x02) && (speriod[1] <= (1 << toneshift));
274 chenable[2] = (r7 & 0x04) && (speriod[2] <= (1 << toneshift));
275 nenable[0] = (r7 >> 3) & 1;
276 nenable[1] = (r7 >> 4) & 1;
277 nenable[2] = (r7 >> 5) & 1;
279 int noise, sample_l, sample_r;
282 uint* p1_l = ((mask & 1) && (reg[ 8] & 0x10)) ? &env_l : &olevel_l[0];
283 uint* p1_r = ((mask & 1) && (reg[ 8] & 0x10)) ? &env_r : &olevel_r[0];
284 uint* p2_l = ((mask & 2) && (reg[ 9] & 0x10)) ? &env_l : &olevel_l[1];
285 uint* p2_r = ((mask & 2) && (reg[ 9] & 0x10)) ? &env_r : &olevel_r[1];
286 uint* p3_l = ((mask & 4) && (reg[10] & 0x10)) ? &env_l : &olevel_l[2];
287 uint* p3_r = ((mask & 4) && (reg[10] & 0x10)) ? &env_r : &olevel_r[2];
289 #define SCOUNT(ch) (scount[ch] >> (toneshift+oversampling))
291 if (p1_l != &env_l && p2_l != &env_l && p3_l != &env_l)
294 if ((r7 & 0x38) == 0)
297 for (int i=0; i<nsamples; i++)
301 for (int j=0; j < (1 << oversampling); j++)
304 x = (SCOUNT(0) & chenable[0]) - 1;
305 sample_l += (olevel_l[0] + x) ^ x;
306 sample_r += (olevel_r[0] + x) ^ x;
307 scount[0] += speriod[0];
308 y = (SCOUNT(1) & chenable[1]) - 1;
309 sample_l += (olevel_l[1] + y) ^ y;
310 sample_r += (olevel_r[1] + y) ^ y;
311 scount[1] += speriod[1];
312 z = (SCOUNT(2) & chenable[2]) - 1;
313 sample_l += (olevel_l[2] + z) ^ z;
314 sample_r += (olevel_r[2] + z) ^ z;
315 scount[2] += speriod[2];
317 sample_l /= (1 << oversampling);
318 sample_r /= (1 << oversampling);
319 StoreSample(dest[0], sample_l);
320 StoreSample(dest[1], sample_r);
327 for (int i=0; i<nsamples; i++)
331 for (int j=0; j < (1 << oversampling); j++)
334 noise = noisetable[(ncount >> (noiseshift+oversampling+6)) & (noisetablesize-1)]
335 >> (ncount >> (noiseshift+oversampling+1));
337 noise = noisetable[(ncount >> (noiseshift+oversampling+6)) & (noisetablesize-1)]
338 >> (ncount >> (noiseshift+oversampling+1) & 31);
343 x = ((SCOUNT(0) & chenable[0]) | (nenable[0] & noise)) - 1; // 0 or -1
344 sample_l += (olevel_l[0] + x) ^ x;
345 sample_r += (olevel_r[0] + x) ^ x;
346 scount[0] += speriod[0];
347 y = ((SCOUNT(1) & chenable[1]) | (nenable[1] & noise)) - 1;
348 sample_l += (olevel_l[1] + y) ^ y;
349 sample_r += (olevel_r[1] + y) ^ y;
350 scount[1] += speriod[1];
351 z = ((SCOUNT(2) & chenable[2]) | (nenable[2] & noise)) - 1;
352 sample_l += (olevel_l[2] + z) ^ z;
353 sample_r += (olevel_r[2] + z) ^ z;
354 scount[2] += speriod[2];
356 sample_l /= (1 << oversampling);
357 sample_r /= (1 << oversampling);
358 StoreSample(dest[0], sample_l);
359 StoreSample(dest[1], sample_r);
364 // エンベロープの計算をさぼった帳尻あわせ
365 ecount = (ecount >> 8) + (eperiod >> (8-oversampling)) * nsamples;
366 if (ecount >= (1 << (envshift+6+oversampling-8)))
368 if ((reg[0x0d] & 0x0b) != 0x0a)
369 ecount |= (1 << (envshift+5+oversampling-8));
370 ecount &= (1 << (envshift+6+oversampling-8)) - 1;
377 for (int i=0; i<nsamples; i++)
381 for (int j=0; j < (1 << oversampling); j++)
383 env_l = envelop_l[ecount >> (envshift+oversampling)];
384 env_r = envelop_r[ecount >> (envshift+oversampling)];
386 if (ecount >= (1 << (envshift+6+oversampling)))
388 if ((reg[0x0d] & 0x0b) != 0x0a)
389 ecount |= (1 << (envshift+5+oversampling));
390 ecount &= (1 << (envshift+6+oversampling)) - 1;
393 noise = noisetable[(ncount >> (noiseshift+oversampling+6)) & (noisetablesize-1)]
394 >> (ncount >> (noiseshift+oversampling+1));
396 noise = noisetable[(ncount >> (noiseshift+oversampling+6)) & (noisetablesize-1)]
397 >> (ncount >> (noiseshift+oversampling+1) & 31);
402 x = ((SCOUNT(0) & chenable[0]) | (nenable[0] & noise)) - 1; // 0 or -1
403 sample_l += (*p1_l + x) ^ x;
404 sample_r += (*p1_r + x) ^ x;
405 scount[0] += speriod[0];
406 y = ((SCOUNT(1) & chenable[1]) | (nenable[1] & noise)) - 1;
407 sample_l += (*p2_l + y) ^ y;
408 sample_r += (*p2_r + y) ^ y;
409 scount[1] += speriod[1];
410 z = ((SCOUNT(2) & chenable[2]) | (nenable[2] & noise)) - 1;
411 sample_l += (*p3_l + z) ^ z;
412 sample_r += (*p3_r + z) ^ z;
413 scount[2] += speriod[2];
415 sample_l /= (1 << oversampling);
416 sample_r /= (1 << oversampling);
417 StoreSample(dest[0], sample_l);
418 StoreSample(dest[1], sample_r);
425 // ---------------------------------------------------------------------------
428 //uint PSG::noisetable[noisetablesize] = { 0, };
429 //int PSG::EmitTableL[0x20] = { -1, };
430 //int PSG::EmitTableR[0x20] = { -1, };
431 //uint PSG::enveloptable_l[16][64] = { 0, };
432 //uint PSG::enveloptable_r[16][64] = { 0, };
434 // ---------------------------------------------------------------------------
437 #define PSG_STATE_VERSION 2
439 bool PSG::ProcessState(void *f, bool loading)
441 FILEIO *state_fio = (FILEIO *)f;
443 if(!state_fio->StateCheckUint32(PSG_STATE_VERSION)) {
446 state_fio->StateArray(reg, sizeof(reg), 1);
448 int offset = state_fio->FgetInt32_LE();
449 envelop_l = &enveloptable_l[0][0] + offset;
451 state_fio->FputInt32_LE((int)(envelop_l - &enveloptable_l[0][0]));
453 state_fio->StateArray(olevel_l, sizeof(olevel_l), 1);
454 state_fio->StateArray(olevel_r, sizeof(olevel_r), 1);
455 state_fio->StateArray(scount, sizeof(scount), 1);
456 state_fio->StateArray(speriod, sizeof(speriod), 1);
457 state_fio->StateValue(ecount);
458 state_fio->StateValue(eperiod);
459 state_fio->StateValue(ncount);
460 state_fio->StateValue(nperiod);
461 state_fio->StateValue(tperiodbase);
462 state_fio->StateValue(eperiodbase);
463 state_fio->StateValue(nperiodbase);
464 state_fio->StateValue(mask);