OSDN Git Service

[VM][General][WIP] Apply new (Upstream 2016-02-21) APIs to VMs.
[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 // for AY-3-8190/8192
11 #include "../vm.h"
12
13 #include "../../fileio.h"
14
15 // ---------------------------------------------------------------------------
16 //      \83R\83\93\83X\83g\83\89\83N\83^\81E\83f\83X\83g\83\89\83N\83^
17 //
18 PSG::PSG()
19 {
20         SetVolume(0, 0);
21         MakeNoiseTable();
22         Reset();
23         mask = 0x3f;
24         envelop_l = enveloptable_l[0]; // temporary fix
25         envelop_r = enveloptable_r[0]; // temporary fix
26 }
27
28 PSG::~PSG()
29 {
30
31 }
32
33 // ---------------------------------------------------------------------------
34 //      PSG \82ð\8f\89\8aú\89»\82·\82é(RESET) 
35 //
36 void PSG::Reset()
37 {
38         for (int i=0; i<14; i++)
39                 SetReg(i, 0);
40         SetReg(7, 0xff);
41         SetReg(14, 0xff);
42         SetReg(15, 0xff);
43 }
44
45 // ---------------------------------------------------------------------------
46 //      \83N\83\8d\83b\83N\8eü\94g\90\94\82Ì\90Ý\92è
47 //
48 void PSG::SetClock(int clock, int rate)
49 {
50         tperiodbase = int((1 << toneshift ) / 4.0 * clock / rate);
51         eperiodbase = int((1 << envshift  ) / 4.0 * clock / rate);
52         nperiodbase = int((1 << noiseshift) / 4.0 * clock / rate);
53         
54         // \8ae\83f\81[\83^\82Ì\8dX\90V
55         int tmp;
56         tmp = ((reg[0] + reg[1] * 256) & 0xfff);
57         speriod[0] = tmp ? tperiodbase / tmp : tperiodbase;
58         tmp = ((reg[2] + reg[3] * 256) & 0xfff);
59         speriod[1] = tmp ? tperiodbase / tmp : tperiodbase;
60         tmp = ((reg[4] + reg[5] * 256) & 0xfff);
61         speriod[2] = tmp ? tperiodbase / tmp : tperiodbase;
62         tmp = reg[6] & 0x1f;
63         nperiod = tmp ? nperiodbase / tmp / 2 : nperiodbase / 2;
64         tmp = ((reg[11] + reg[12] * 256) & 0xffff);
65         eperiod = tmp ? eperiodbase / tmp : eperiodbase * 2;
66 }
67
68 // ---------------------------------------------------------------------------
69 //      \83m\83C\83Y\83e\81[\83u\83\8b\82ð\8dì\90¬\82·\82é
70 //
71 void PSG::MakeNoiseTable()
72 {
73         if (!noisetable[0])
74         {
75                 int noise = 14321;
76                 for (int i=0; i<noisetablesize; i++)
77                 {
78                         int n = 0;
79                         for (int j=0; j<32; j++)
80                         {
81                                 n = n * 2 + (noise & 1);
82                                 noise = (noise >> 1) | (((noise << 14) ^ (noise << 16)) & 0x10000);
83                         }
84                         noisetable[i] = n;
85                 }
86         }
87 }
88
89 // ---------------------------------------------------------------------------
90 //      \8fo\97Í\83e\81[\83u\83\8b\82ð\8dì\90¬
91 //      \91f\92¼\82É\83e\81[\83u\83\8b\82Å\8e\9d\82Á\82½\82Ù\82¤\82ª\8fÈ\83X\83y\81[\83X\81B
92 //
93 void PSG::SetVolume(int volume_l, int volume_r)
94 {
95         double base_l = 0x4000 / 3.0 * pow(10.0, volume_l / 40.0);
96         double base_r = 0x4000 / 3.0 * pow(10.0, volume_r / 40.0);
97 #if defined(HAS_AY_3_8910) || defined(HAS_AY_3_8912)
98         // AY-3-8190/8192 (PSG): 16step
99         for (int i=31; i>=3; i-=2)
100         {
101                 EmitTableL[i] = EmitTableL[i-1] = int(base_l);
102                 EmitTableR[i] = EmitTableR[i-1] = int(base_r);
103                 base_l /= 1.189207115;
104                 base_l /= 1.189207115;
105                 base_r /= 1.189207115;
106                 base_r /= 1.189207115;
107         }
108 #else
109         // YM2203 (SSG): 32step
110         for (int i=31; i>=2; i--)
111         {
112                 EmitTableL[i] = int(base_l);
113                 EmitTableR[i] = int(base_r);
114                 base_l /= 1.189207115;
115                 base_r /= 1.189207115;
116         }
117 #endif
118         EmitTableL[1] = 0;
119         EmitTableL[0] = 0;
120         EmitTableR[1] = 0;
121         EmitTableR[0] = 0;
122         MakeEnvelopTable();
123
124         SetChannelMask(~mask);
125 }
126
127 void PSG::SetChannelMask(int c)
128
129         mask = ~c;
130         for (int i=0; i<3; i++)
131         {
132                 olevel_l[i] = mask & (1 << i) ? EmitTableL[(reg[8+i] & 15) * 2 + 1] : 0;
133                 olevel_r[i] = mask & (1 << i) ? EmitTableR[(reg[8+i] & 15) * 2 + 1] : 0;
134         }
135 }
136
137 // ---------------------------------------------------------------------------
138 //      \83G\83\93\83x\83\8d\81[\83v\94g\8c`\83e\81[\83u\83\8b
139 //
140 void PSG::MakeEnvelopTable()
141 {
142         // 0 lo  1 up 2 down 3 hi
143         static uint8 table1[16*2] =
144         {
145                 2,0, 2,0, 2,0, 2,0, 1,0, 1,0, 1,0, 1,0,
146                 2,2, 2,0, 2,1, 2,3, 1,1, 1,3, 1,2, 1,0,
147         };
148         static uint8 table2[4] = {  0,  0, 31, 31 };
149         //static uint8 table3[4] = {  0,  1, 255,  0 }; // -1 will embed bugs except some compilers.
150         static uint8 table3[4] = {  0,  1, -1,  0 }; // -1 will embed bugs except some compilers.
151
152         uint* ptr_l = enveloptable_l[0];
153         uint* ptr_r = enveloptable_r[0];
154
155         for (int i=0; i<16*2; i++)
156         {
157                 uint8 v = table2[table1[i]];
158                 
159                 for (int j=0; j<32; j++)
160                 {
161                         *ptr_l++ = EmitTableL[v];
162                         *ptr_r++ = EmitTableR[v];
163                         v += table3[table1[i]];
164                 }
165         }
166 }
167
168 // ---------------------------------------------------------------------------
169 //      PSG \82Ì\83\8c\83W\83X\83^\82É\92l\82ð\83Z\83b\83g\82·\82é
170 //      regnum          \83\8c\83W\83X\83^\82Ì\94Ô\8d\86 (0 - 15)
171 //      data            \83Z\83b\83g\82·\82é\92l
172 //
173 void PSG::SetReg(uint regnum, uint8 data)
174 {
175         if (regnum < 0x10)
176         {
177                 reg[regnum] = data;
178                 switch (regnum)
179                 {
180                         int tmp;
181
182                 case 0:         // ChA Fine Tune
183                 case 1:         // ChA Coarse Tune
184                         tmp = ((reg[0] + reg[1] * 256) & 0xfff);
185                         speriod[0] = tmp ? tperiodbase / tmp : tperiodbase;
186                         break;
187                 
188                 case 2:         // ChB Fine Tune
189                 case 3:         // ChB Coarse Tune
190                         tmp = ((reg[2] + reg[3] * 256) & 0xfff);
191                         speriod[1] = tmp ? tperiodbase / tmp : tperiodbase;
192                         break;
193                 
194                 case 4:         // ChC Fine Tune
195                 case 5:         // ChC Coarse Tune
196                         tmp = ((reg[4] + reg[5] * 256) & 0xfff);
197                         speriod[2] = tmp ? tperiodbase / tmp : tperiodbase;
198                         break;
199
200                 case 6:         // Noise generator control
201                         data &= 0x1f;
202                         nperiod = data ? nperiodbase / data : nperiodbase;
203                         break;
204
205                 case 8:
206                         olevel_l[0] = mask & 1 ? EmitTableL[(data & 15) * 2 + 1] : 0;
207                         olevel_r[0] = mask & 1 ? EmitTableR[(data & 15) * 2 + 1] : 0;
208                         break;
209
210                 case 9:
211                         olevel_l[1] = mask & 2 ? EmitTableL[(data & 15) * 2 + 1] : 0;
212                         olevel_r[1] = mask & 2 ? EmitTableR[(data & 15) * 2 + 1] : 0;
213                         break;
214                 
215                 case 10:
216                         olevel_l[2] = mask & 4 ? EmitTableL[(data & 15) * 2 + 1] : 0;
217                         olevel_r[2] = mask & 4 ? EmitTableR[(data & 15) * 2 + 1] : 0;
218                         break;
219
220                 case 11:        // Envelop period
221                 case 12:
222                         tmp = ((reg[11] + reg[12] * 256) & 0xffff);
223                         eperiod = tmp ? eperiodbase / tmp : eperiodbase * 2;
224                         break;
225
226                 case 13:        // Envelop shape
227                         ecount = 0;
228                         envelop_l = enveloptable_l[data & 15];
229                         envelop_r = enveloptable_r[data & 15];
230                         break;
231                 }
232         }
233 }
234
235 // ---------------------------------------------------------------------------
236 //
237 //
238 inline void PSG::StoreSample(Sample& dest, int32 data)
239 {
240         if (sizeof(Sample) == 2)
241                 dest = (Sample) Limit(dest + data, 0x7fff, -0x8000);
242         else
243                 dest += data;
244 }
245
246 // ---------------------------------------------------------------------------
247 //      PCM \83f\81[\83^\82ð\93f\82«\8fo\82·(2ch)
248 //      dest            PCM \83f\81[\83^\82ð\93W\8aJ\82·\82é\83|\83C\83\93\83^
249 //      nsamples        \93W\8aJ\82·\82é PCM \82Ì\83T\83\93\83v\83\8b\90\94
250 //
251 void PSG::Mix(Sample* dest, int nsamples)
252 {
253         uint8 chenable[3], nenable[3];
254         uint8 r7 = ~reg[7];
255
256         if ((r7 & 0x3f) | ((reg[8] | reg[9] | reg[10]) & 0x1f))
257         {
258                 chenable[0] = (r7 & 0x01) && (speriod[0] <= (1 << toneshift));
259                 chenable[1] = (r7 & 0x02) && (speriod[1] <= (1 << toneshift));
260                 chenable[2] = (r7 & 0x04) && (speriod[2] <= (1 << toneshift));
261                 nenable[0]  = (r7 >> 3) & 1;
262                 nenable[1]  = (r7 >> 4) & 1;
263                 nenable[2]  = (r7 >> 5) & 1;
264                 
265                 int noise, sample_l, sample_r;
266                 uint env_l;
267                 uint env_r;
268                 uint* p1_l = ((mask & 1) && (reg[ 8] & 0x10)) ? &env_l : &olevel_l[0];
269                 uint* p1_r = ((mask & 1) && (reg[ 8] & 0x10)) ? &env_r : &olevel_r[0];
270                 uint* p2_l = ((mask & 2) && (reg[ 9] & 0x10)) ? &env_l : &olevel_l[1];
271                 uint* p2_r = ((mask & 2) && (reg[ 9] & 0x10)) ? &env_r : &olevel_r[1];
272                 uint* p3_l = ((mask & 4) && (reg[10] & 0x10)) ? &env_l : &olevel_l[2];
273                 uint* p3_r = ((mask & 4) && (reg[10] & 0x10)) ? &env_r : &olevel_r[2];
274                 
275                 #define SCOUNT(ch)      (scount[ch] >> (toneshift+oversampling))
276                 
277                 if (p1_l != &env_l && p2_l != &env_l && p3_l != &env_l)
278                 {
279                         // \83G\83\93\83x\83\8d\81[\83v\96³\82µ
280                         if ((r7 & 0x38) == 0)
281                         {
282                                 // \83m\83C\83Y\96³\82µ
283                                 for (int i=0; i<nsamples; i++)
284                                 {
285                                         sample_l = 0;
286                                         sample_r = 0;
287                                         for (int j=0; j < (1 << oversampling); j++)
288                                         {
289                                                 int x, y, z;
290                                                 x = (SCOUNT(0) & chenable[0]) - 1;
291                                                 sample_l += (olevel_l[0] + x) ^ x;
292                                                 sample_r += (olevel_r[0] + x) ^ x;
293                                                 scount[0] += speriod[0];
294                                                 y = (SCOUNT(1) & chenable[1]) - 1;
295                                                 sample_l += (olevel_l[1] + y) ^ y;
296                                                 sample_r += (olevel_r[1] + y) ^ y;
297                                                 scount[1] += speriod[1];
298                                                 z = (SCOUNT(2) & chenable[2]) - 1;
299                                                 sample_l += (olevel_l[2] + z) ^ z;
300                                                 sample_r += (olevel_r[2] + z) ^ z;
301                                                 scount[2] += speriod[2];
302                                         }
303                                         sample_l /= (1 << oversampling);
304                                         sample_r /= (1 << oversampling);
305                                         StoreSample(dest[0], sample_l);
306                                         StoreSample(dest[1], sample_r);
307                                         dest += 2;
308                                 }
309                         }
310                         else
311                         {
312                                 // \83m\83C\83Y\97L\82è
313                                 for (int i=0; i<nsamples; i++)
314                                 {
315                                         sample_l = 0;
316                                         sample_r = 0;
317                                         for (int j=0; j < (1 << oversampling); j++)
318                                         {
319 #ifdef _M_IX86
320                                                 noise = noisetable[(ncount >> (noiseshift+oversampling+6)) & (noisetablesize-1)] 
321                                                         >> (ncount >> (noiseshift+oversampling+1));
322 #else
323                                                 noise = noisetable[(ncount >> (noiseshift+oversampling+6)) & (noisetablesize-1)] 
324                                                         >> (ncount >> (noiseshift+oversampling+1) & 31);
325 #endif
326                                                 ncount += nperiod;
327
328                                                 int x, y, z;
329                                                 x = ((SCOUNT(0) & chenable[0]) | (nenable[0] & noise)) - 1;             // 0 or -1
330                                                 sample_l += (olevel_l[0] + x) ^ x;
331                                                 sample_r += (olevel_r[0] + x) ^ x;
332                                                 scount[0] += speriod[0];
333                                                 y = ((SCOUNT(1) & chenable[1]) | (nenable[1] & noise)) - 1;
334                                                 sample_l += (olevel_l[1] + y) ^ y;
335                                                 sample_r += (olevel_r[1] + y) ^ y;
336                                                 scount[1] += speriod[1];
337                                                 z = ((SCOUNT(2) & chenable[2]) | (nenable[2] & noise)) - 1;
338                                                 sample_l += (olevel_l[2] + z) ^ z;
339                                                 sample_r += (olevel_r[2] + z) ^ z;
340                                                 scount[2] += speriod[2];
341                                         }
342                                         sample_l /= (1 << oversampling);
343                                         sample_r /= (1 << oversampling);
344                                         StoreSample(dest[0], sample_l);
345                                         StoreSample(dest[1], sample_r);
346                                         dest += 2;
347                                 }
348                         }
349
350                         // \83G\83\93\83x\83\8d\81[\83v\82Ì\8cv\8eZ\82ð\82³\82Ú\82Á\82½\92 \90K\82 \82í\82¹
351                         ecount = (ecount >> 8) + (eperiod >> (8-oversampling)) * nsamples;
352                         if (ecount >= (1 << (envshift+6+oversampling-8)))
353                         {
354                                 if ((reg[0x0d] & 0x0b) != 0x0a)
355                                         ecount |= (1 << (envshift+5+oversampling-8));
356                                 ecount &= (1 << (envshift+6+oversampling-8)) - 1;
357                         }
358                         ecount <<= 8;
359                 }
360                 else
361                 {
362                         // \83G\83\93\83x\83\8d\81[\83v\82 \82è
363                         for (int i=0; i<nsamples; i++)
364                         {
365                                 sample_l = 0;
366                                 sample_r = 0;
367                                 for (int j=0; j < (1 << oversampling); j++)
368                                 {
369                                         env_l = envelop_l[ecount >> (envshift+oversampling)];
370                                         env_r = envelop_r[ecount >> (envshift+oversampling)];
371                                         ecount += eperiod;
372                                         if (ecount >= (1 << (envshift+6+oversampling)))
373                                         {
374                                                 if ((reg[0x0d] & 0x0b) != 0x0a)
375                                                         ecount |= (1 << (envshift+5+oversampling));
376                                                 ecount &= (1 << (envshift+6+oversampling)) - 1;
377                                         }
378 #ifdef _M_IX86
379                                         noise = noisetable[(ncount >> (noiseshift+oversampling+6)) & (noisetablesize-1)] 
380                                                 >> (ncount >> (noiseshift+oversampling+1));
381 #else
382                                         noise = noisetable[(ncount >> (noiseshift+oversampling+6)) & (noisetablesize-1)] 
383                                                 >> (ncount >> (noiseshift+oversampling+1) & 31);
384 #endif
385                                         ncount += nperiod;
386
387                                         int x, y, z;
388                                         x = ((SCOUNT(0) & chenable[0]) | (nenable[0] & noise)) - 1;             // 0 or -1
389                                         sample_l += (*p1_l + x) ^ x;
390                                         sample_r += (*p1_r + x) ^ x;
391                                         scount[0] += speriod[0];
392                                         y = ((SCOUNT(1) & chenable[1]) | (nenable[1] & noise)) - 1;
393                                         sample_l += (*p2_l + y) ^ y;
394                                         sample_r += (*p2_r + y) ^ y;
395                                         scount[1] += speriod[1];
396                                         z = ((SCOUNT(2) & chenable[2]) | (nenable[2] & noise)) - 1;
397                                         sample_l += (*p3_l + z) ^ z;
398                                         sample_r += (*p3_r + z) ^ z;
399                                         scount[2] += speriod[2];
400                                 }
401                                 sample_l /= (1 << oversampling);
402                                 sample_r /= (1 << oversampling);
403                                 StoreSample(dest[0], sample_l);
404                                 StoreSample(dest[1], sample_r);
405                                 dest += 2;
406                         }
407                 }
408         }
409 }
410
411 // ---------------------------------------------------------------------------
412 //      \83e\81[\83u\83\8b
413 //
414 uint    PSG::noisetable[noisetablesize] = { 0, };
415 int             PSG::EmitTableL[0x20] = { -1, };
416 int             PSG::EmitTableR[0x20] = { -1, };
417 uint    PSG::enveloptable_l[16][64] = { 0, };
418 uint    PSG::enveloptable_r[16][64] = { 0, };
419
420 // ---------------------------------------------------------------------------
421 //      \83X\83e\81[\83g\83Z\81[\83u
422 //
423 #define PSG_STATE_VERSION       2
424
425 void PSG::SaveState(void *f)
426 {
427         FILEIO *state_fio = (FILEIO *)f;
428         
429         state_fio->FputUint32(PSG_STATE_VERSION);
430         
431         state_fio->Fwrite(reg, sizeof(reg), 1);
432         state_fio->FputInt32((int)(envelop_l - &enveloptable_l[0][0]));
433         state_fio->Fwrite(olevel_l, sizeof(olevel_l), 1);
434         state_fio->Fwrite(olevel_r, sizeof(olevel_r), 1);
435         state_fio->Fwrite(scount, sizeof(scount), 1);
436         state_fio->Fwrite(speriod, sizeof(speriod), 1);
437         state_fio->FputUint32(ecount);
438         state_fio->FputUint32(eperiod);
439         state_fio->FputUint32(ncount);
440         state_fio->FputUint32(nperiod);
441         state_fio->FputUint32(tperiodbase);
442         state_fio->FputUint32(eperiodbase);
443         state_fio->FputUint32(nperiodbase);
444         state_fio->FputInt32(mask);
445 }
446
447 bool PSG::LoadState(void *f)
448 {
449         FILEIO *state_fio = (FILEIO *)f;
450         
451         if(state_fio->FgetUint32() != PSG_STATE_VERSION) {
452                 return false;
453         }
454         state_fio->Fread(reg, sizeof(reg), 1);
455         int offset = state_fio->FgetInt32();
456         envelop_l = &enveloptable_l[0][0] + offset;
457         envelop_r = &enveloptable_r[0][0] + offset;
458         state_fio->Fread(olevel_l, sizeof(olevel_l), 1);
459         state_fio->Fread(olevel_r, sizeof(olevel_r), 1);
460         state_fio->Fread(scount, sizeof(scount), 1);
461         state_fio->Fread(speriod, sizeof(speriod), 1);
462         ecount = state_fio->FgetUint32();
463         eperiod = state_fio->FgetUint32();
464         ncount = state_fio->FgetUint32();
465         nperiod = state_fio->FgetUint32();
466         tperiodbase = state_fio->FgetUint32();
467         eperiodbase = state_fio->FgetUint32();
468         nperiodbase = state_fio->FgetUint32();
469         mask = state_fio->FgetInt32();
470         return true;
471 }