OSDN Git Service

[VM][DEVICE] Enable to build with new state framework.
[csp-qt/common_source_project-fm7.git] / source / src / vm / fmgen / psg.cpp
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 $
6
7 #include "headers.h"
8 #include "misc.h"
9 #include "psg.h"
10
11 #include "../../fileio.h"
12 // ---------------------------------------------------------------------------
13 //      \83R\83\93\83X\83g\83\89\83N\83^\81E\83f\83X\83g\83\89\83N\83^
14 //
15 PSG::PSG()
16 {
17         static int __num = 0;
18         chip_num = __num++;
19         // \83e\81[\83u\83\8b\8f\89\8aú\89»
20         for(int i = 0; i < noisetablesize; i++) {
21                 noisetable[i] = 0;
22         }
23         for(int i = 0; i < 32; i++) {
24                 EmitTableL[i] = EmitTableR[i] = -1;
25         }
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;
29                 }
30         }
31         SetVolume(0, 0, false);
32         MakeNoiseTable();
33         Reset();
34         mask = 0x3f;
35         envelop_l = enveloptable_l[0]; // temporary fix
36         envelop_r = enveloptable_r[0]; // temporary fix
37 }
38
39 PSG::~PSG()
40 {
41
42 }
43
44 // ---------------------------------------------------------------------------
45 //      PSG \82ð\8f\89\8aú\89»\82·\82é(RESET) 
46 //
47 void PSG::Reset()
48 {
49         for (int i=0; i<14; i++)
50                 SetReg(i, 0);
51         SetReg(7, 0xff);
52         SetReg(14, 0xff);
53         SetReg(15, 0xff);
54 }
55
56 // ---------------------------------------------------------------------------
57 //      \83N\83\8d\83b\83N\8eü\94g\90\94\82Ì\90Ý\92è
58 //
59 void PSG::SetClock(int clock, int rate)
60 {
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);
64         
65         // \8ae\83f\81[\83^\82Ì\8dX\90V
66         int tmp;
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;
73         tmp = reg[6] & 0x1f;
74         nperiod = tmp ? nperiodbase / tmp / 2 : nperiodbase / 2;
75         tmp = ((reg[11] + reg[12] * 256) & 0xffff);
76         eperiod = tmp ? eperiodbase / tmp : eperiodbase * 2;
77 }
78
79 // ---------------------------------------------------------------------------
80 //      \83m\83C\83Y\83e\81[\83u\83\8b\82ð\8dì\90¬\82·\82é
81 //
82 void PSG::MakeNoiseTable()
83 {
84         if (!noisetable[0])
85         {
86                 int noise = 14321;
87                 for (int i=0; i<noisetablesize; i++)
88                 {
89                         int n = 0;
90                         for (int j=0; j<32; j++)
91                         {
92                                 n = n * 2 + (noise & 1);
93                                 noise = (noise >> 1) | (((noise << 14) ^ ((noise & 0x0000ffff) << 16)) & 0x10000);
94                         }
95                         noisetable[i] = n;
96                 }
97         }
98 }
99
100 // ---------------------------------------------------------------------------
101 //      \8fo\97Í\83e\81[\83u\83\8b\82ð\8dì\90¬
102 //      \91f\92¼\82É\83e\81[\83u\83\8b\82Å\8e\9d\82Á\82½\82Ù\82¤\82ª\8fÈ\83X\83y\81[\83X\81B
103 //
104 void PSG::SetVolume(int volume_l, int volume_r, bool is_ay3_891x)
105 {
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);
108         
109         if(is_ay3_891x)
110         {
111                 // AY-3-8190/8192 (PSG): 16step
112                 for (int i=31; i>=3; i-=2)
113                 {
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;
120                 }
121         }
122         else
123         {
124                 // YM2203 (SSG): 32step
125                 for (int i=31; i>=2; i--)
126                 {
127                         EmitTableL[i] = int(base_l);
128                         EmitTableR[i] = int(base_r);
129                         base_l /= 1.189207115;
130                         base_r /= 1.189207115;
131                 }
132         }
133         EmitTableL[1] = 0;
134         EmitTableL[0] = 0;
135         EmitTableR[1] = 0;
136         EmitTableR[0] = 0;
137         MakeEnvelopTable();
138
139         SetChannelMask(~mask);
140 }
141
142 void PSG::SetChannelMask(int c)
143
144         mask = ~c;
145         for (int i=0; i<3; i++)
146         {
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;
149         }
150 }
151
152 // ---------------------------------------------------------------------------
153 //      \83G\83\93\83x\83\8d\81[\83v\94g\8c`\83e\81[\83u\83\8b
154 //
155 void PSG::MakeEnvelopTable()
156 {
157         // 0 lo  1 up 2 down 3 hi
158         static uint8 table1[16*2] =
159         {
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,
162         };
163         static uint8 table2[4] = {  0,  0, 31, 31 };
164         static uint8 table3[4] = {  0,  1, 255,  0 }; // 255 = -1
165
166         uint* ptr_l = enveloptable_l[0];
167         uint* ptr_r = enveloptable_r[0];
168
169         for (int i=0; i<16*2; i++)
170         {
171                 uint8 v = table2[table1[i]];
172                 
173                 for (int j=0; j<32; j++)
174                 {
175                         *ptr_l++ = EmitTableL[v];
176                         *ptr_r++ = EmitTableR[v];
177                         v += table3[table1[i]];
178                 }
179         }
180 }
181
182 // ---------------------------------------------------------------------------
183 //      PSG \82Ì\83\8c\83W\83X\83^\82É\92l\82ð\83Z\83b\83g\82·\82é
184 //      regnum          \83\8c\83W\83X\83^\82Ì\94Ô\8d\86 (0 - 15)
185 //      data            \83Z\83b\83g\82·\82é\92l
186 //
187 void PSG::SetReg(uint regnum, uint8 data)
188 {
189         if (regnum < 0x10)
190         {
191                 reg[regnum] = data;
192                 switch (regnum)
193                 {
194                         int tmp;
195
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;
200                         break;
201                 
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;
206                         break;
207                 
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;
212                         break;
213
214                 case 6:         // Noise generator control
215                         data &= 0x1f;
216                         nperiod = data ? nperiodbase / data : nperiodbase;
217                         break;
218
219                 case 8:
220                         olevel_l[0] = mask & 1 ? EmitTableL[(data & 15) * 2 + 1] : 0;
221                         olevel_r[0] = mask & 1 ? EmitTableR[(data & 15) * 2 + 1] : 0;
222                         break;
223
224                 case 9:
225                         olevel_l[1] = mask & 2 ? EmitTableL[(data & 15) * 2 + 1] : 0;
226                         olevel_r[1] = mask & 2 ? EmitTableR[(data & 15) * 2 + 1] : 0;
227                         break;
228                 
229                 case 10:
230                         olevel_l[2] = mask & 4 ? EmitTableL[(data & 15) * 2 + 1] : 0;
231                         olevel_r[2] = mask & 4 ? EmitTableR[(data & 15) * 2 + 1] : 0;
232                         break;
233
234                 case 11:        // Envelop period
235                 case 12:
236                         tmp = ((reg[11] + reg[12] * 256) & 0xffff);
237                         eperiod = tmp ? eperiodbase / tmp : eperiodbase * 2;
238                         break;
239
240                 case 13:        // Envelop shape
241                         ecount = 0;
242                         envelop_l = enveloptable_l[data & 15];
243                         envelop_r = enveloptable_r[data & 15];
244                         break;
245                 }
246         }
247 }
248
249 // ---------------------------------------------------------------------------
250 //
251 //
252 inline void PSG::StoreSample(Sample& dest, int32 data)
253 {
254         if (sizeof(Sample) == 2)
255                 dest = (Sample) Limit(dest + data, 0x7fff, -0x8000);
256         else
257                 dest += data;
258 }
259
260 // ---------------------------------------------------------------------------
261 //      PCM \83f\81[\83^\82ð\93f\82«\8fo\82·(2ch)
262 //      dest            PCM \83f\81[\83^\82ð\93W\8aJ\82·\82é\83|\83C\83\93\83^
263 //      nsamples        \93W\8aJ\82·\82é PCM \82Ì\83T\83\93\83v\83\8b\90\94
264 //
265 void PSG::Mix(Sample* dest, int nsamples)
266 {
267         uint8 chenable[3], nenable[3];
268         uint8 r7 = ~reg[7];
269
270         if ((r7 & 0x3f) | ((reg[8] | reg[9] | reg[10]) & 0x1f))
271         {
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;
278                 
279                 int noise, sample_l, sample_r;
280                 uint env_l;
281                 uint env_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];
288                 
289                 #define SCOUNT(ch)      (scount[ch] >> (toneshift+oversampling))
290                 
291                 if (p1_l != &env_l && p2_l != &env_l && p3_l != &env_l)
292                 {
293                         // \83G\83\93\83x\83\8d\81[\83v\96³\82µ
294                         if ((r7 & 0x38) == 0)
295                         {
296                                 // \83m\83C\83Y\96³\82µ
297                                 for (int i=0; i<nsamples; i++)
298                                 {
299                                         sample_l = 0;
300                                         sample_r = 0;
301                                         for (int j=0; j < (1 << oversampling); j++)
302                                         {
303                                                 int x, y, z;
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];
316                                         }
317                                         sample_l /= (1 << oversampling);
318                                         sample_r /= (1 << oversampling);
319                                         StoreSample(dest[0], sample_l);
320                                         StoreSample(dest[1], sample_r);
321                                         dest += 2;
322                                 }
323                         }
324                         else
325                         {
326                                 // \83m\83C\83Y\97L\82è
327                                 for (int i=0; i<nsamples; i++)
328                                 {
329                                         sample_l = 0;
330                                         sample_r = 0;
331                                         for (int j=0; j < (1 << oversampling); j++)
332                                         {
333 #ifdef _M_IX86
334                                                 noise = noisetable[(ncount >> (noiseshift+oversampling+6)) & (noisetablesize-1)] 
335                                                         >> (ncount >> (noiseshift+oversampling+1));
336 #else
337                                                 noise = noisetable[(ncount >> (noiseshift+oversampling+6)) & (noisetablesize-1)] 
338                                                         >> (ncount >> (noiseshift+oversampling+1) & 31);
339 #endif
340                                                 ncount += nperiod;
341
342                                                 int x, y, z;
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];
355                                         }
356                                         sample_l /= (1 << oversampling);
357                                         sample_r /= (1 << oversampling);
358                                         StoreSample(dest[0], sample_l);
359                                         StoreSample(dest[1], sample_r);
360                                         dest += 2;
361                                 }
362                         }
363
364                         // \83G\83\93\83x\83\8d\81[\83v\82Ì\8cv\8eZ\82ð\82³\82Ú\82Á\82½\92 \90K\82 \82í\82¹
365                         ecount = (ecount >> 8) + (eperiod >> (8-oversampling)) * nsamples;
366                         if (ecount >= (1 << (envshift+6+oversampling-8)))
367                         {
368                                 if ((reg[0x0d] & 0x0b) != 0x0a)
369                                         ecount |= (1 << (envshift+5+oversampling-8));
370                                 ecount &= (1 << (envshift+6+oversampling-8)) - 1;
371                         }
372                         ecount <<= 8;
373                 }
374                 else
375                 {
376                         // \83G\83\93\83x\83\8d\81[\83v\82 \82è
377                         for (int i=0; i<nsamples; i++)
378                         {
379                                 sample_l = 0;
380                                 sample_r = 0;
381                                 for (int j=0; j < (1 << oversampling); j++)
382                                 {
383                                         env_l = envelop_l[ecount >> (envshift+oversampling)];
384                                         env_r = envelop_r[ecount >> (envshift+oversampling)];
385                                         ecount += eperiod;
386                                         if (ecount >= (1 << (envshift+6+oversampling)))
387                                         {
388                                                 if ((reg[0x0d] & 0x0b) != 0x0a)
389                                                         ecount |= (1 << (envshift+5+oversampling));
390                                                 ecount &= (1 << (envshift+6+oversampling)) - 1;
391                                         }
392 #ifdef _M_IX86
393                                         noise = noisetable[(ncount >> (noiseshift+oversampling+6)) & (noisetablesize-1)] 
394                                                 >> (ncount >> (noiseshift+oversampling+1));
395 #else
396                                         noise = noisetable[(ncount >> (noiseshift+oversampling+6)) & (noisetablesize-1)] 
397                                                 >> (ncount >> (noiseshift+oversampling+1) & 31);
398 #endif
399                                         ncount += nperiod;
400
401                                         int x, y, z;
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];
414                                 }
415                                 sample_l /= (1 << oversampling);
416                                 sample_r /= (1 << oversampling);
417                                 StoreSample(dest[0], sample_l);
418                                 StoreSample(dest[1], sample_r);
419                                 dest += 2;
420                         }
421                 }
422         }
423 }
424
425 // ---------------------------------------------------------------------------
426 //      \83e\81[\83u\83\8b
427 //
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, };
433
434 // ---------------------------------------------------------------------------
435 //      \83X\83e\81[\83g\83Z\81[\83u
436 //
437 #define PSG_STATE_VERSION       2
438
439 bool PSG::ProcessState(void *f, bool loading)
440 {
441         FILEIO *state_fio = (FILEIO *)f;
442         
443         if(!state_fio->StateCheckUint32(PSG_STATE_VERSION)) {
444                 return false;
445         }
446         state_fio->StateArray(reg, sizeof(reg), 1);
447         if(loading) {
448                 int offset = state_fio->FgetInt32_LE();
449                 envelop_l = &enveloptable_l[0][0] + offset;
450         } else {
451                 state_fio->FputInt32_LE((int)(envelop_l - &enveloptable_l[0][0]));
452         }
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);
465         return true;
466 }