comparison src/Input/console/Ym2612_Emu.cxx @ 0:13389e613d67 trunk

[svn] - initial import of audacious-plugins tree (lots to do)
author nenolod
date Mon, 18 Sep 2006 01:11:49 -0700
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:13389e613d67
1
2 // Game_Music_Emu 0.3.0. http://www.slack.net/~ant/
3
4 // Based on Gens 2.10 ym2612.c
5
6 #include "Ym2612_Emu.h"
7
8 #include <assert.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <limits.h>
12 #include <stdio.h>
13 #include <math.h>
14
15 /* Copyright (C) 2002 Stéphane Dallongeville (gens AT consolemul.com) */
16 /* Copyright (C) 2004-2006 Shay Green. This module is free software; you
17 can redistribute it and/or modify it under the terms of the GNU Lesser
18 General Public License as published by the Free Software Foundation; either
19 version 2.1 of the License, or (at your option) any later version. This
20 module is distributed in the hope that it will be useful, but WITHOUT ANY
21 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
22 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
23 more details. You should have received a copy of the GNU Lesser General
24 Public License along with this module; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
26
27 // This is mostly the original source in its C style and all.
28 //
29 // Somewhat optimized and simplified. Uses a template to generate the many
30 // variants of Update_Chan. Rewrote header file. In need of full rewrite by
31 // someone more familiar with FM sound and the YM2612. Has some inaccuracies
32 // compared to the Sega Genesis sound, particularly being mixed at such a
33 // high sample accuracy (the Genesis sounds like it has only 8 bit samples).
34 // - Shay
35
36 const int output_bits = 14;
37
38 struct slot_t
39 {
40 const int *DT; // parametre detune
41 int MUL; // parametre "multiple de frequence"
42 int TL; // Total Level = volume lorsque l'enveloppe est au plus haut
43 int TLL; // Total Level ajusted
44 int SLL; // Sustin Level (ajusted) = volume où l'enveloppe termine sa premiere phase de regression
45 int KSR_S; // Key Scale Rate Shift = facteur de prise en compte du KSL dans la variations de l'enveloppe
46 int KSR; // Key Scale Rate = cette valeur est calculee par rapport à la frequence actuelle, elle va influer
47 // sur les differents parametres de l'enveloppe comme l'attaque, le decay ... comme dans la realite !
48 int SEG; // Type enveloppe SSG
49 int env_xor;
50 int env_max;
51
52 const int *AR; // Attack Rate (table pointeur) = Taux d'attaque (AR[KSR])
53 const int *DR; // Decay Rate (table pointeur) = Taux pour la regression (DR[KSR])
54 const int *SR; // Sustin Rate (table pointeur) = Taux pour le maintien (SR[KSR])
55 const int *RR; // Release Rate (table pointeur) = Taux pour le rel'chement (RR[KSR])
56 int Fcnt; // Frequency Count = compteur-frequence pour determiner l'amplitude actuelle (SIN[Finc >> 16])
57 int Finc; // frequency step = pas d'incrementation du compteur-frequence
58 // plus le pas est grand, plus la frequence est aïgu (ou haute)
59 int Ecurp; // Envelope current phase = cette variable permet de savoir dans quelle phase
60 // de l'enveloppe on se trouve, par exemple phase d'attaque ou phase de maintenue ...
61 // en fonction de la valeur de cette variable, on va appeler une fonction permettant
62 // de mettre à jour l'enveloppe courante.
63 int Ecnt; // Envelope counter = le compteur-enveloppe permet de savoir où l'on se trouve dans l'enveloppe
64 int Einc; // Envelope step courant
65 int Ecmp; // Envelope counter limite pour la prochaine phase
66 int EincA; // Envelope step for Attack = pas d'incrementation du compteur durant la phase d'attaque
67 // cette valeur est egal à AR[KSR]
68 int EincD; // Envelope step for Decay = pas d'incrementation du compteur durant la phase de regression
69 // cette valeur est egal à DR[KSR]
70 int EincS; // Envelope step for Sustain = pas d'incrementation du compteur durant la phase de maintenue
71 // cette valeur est egal à SR[KSR]
72 int EincR; // Envelope step for Release = pas d'incrementation du compteur durant la phase de rel'chement
73 // cette valeur est egal à RR[KSR]
74 int *OUTp; // pointeur of SLOT output = pointeur permettant de connecter la sortie de ce slot à l'entree
75 // d'un autre ou carrement à la sortie de la voie
76 int INd; // input data of the slot = donnees en entree du slot
77 int ChgEnM; // Change envelop mask.
78 int AMS; // AMS depth level of this SLOT = degre de modulation de l'amplitude par le LFO
79 int AMSon; // AMS enable flag = drapeau d'activation de l'AMS
80 };
81
82 struct channel_t
83 {
84 int S0_OUT[4]; // anciennes sorties slot 0 (pour le feed back)
85 int LEFT; // LEFT enable flag
86 int RIGHT; // RIGHT enable flag
87 int ALGO; // Algorythm = determine les connections entre les operateurs
88 int FB; // shift count of self feed back = degre de "Feed-Back" du SLOT 1 (il est son unique entree)
89 int FMS; // Frequency Modulation Sensitivity of channel = degre de modulation de la frequence sur la voie par le LFO
90 int AMS; // Amplitude Modulation Sensitivity of channel = degre de modulation de l'amplitude sur la voie par le LFO
91 int FNUM[4]; // hauteur frequence de la voie (+ 3 pour le mode special)
92 int FOCT[4]; // octave de la voie (+ 3 pour le mode special)
93 int KC[4]; // Key Code = valeur fonction de la frequence (voir KSR pour les slots, KSR = KC >> KSR_S)
94 slot_t SLOT[4]; // four slot.operators = les 4 slots de la voie
95 int FFlag; // Frequency step recalculation flag
96 };
97
98 struct state_t
99 {
100 int TimerBase; // TimerBase calculation
101 int Status; // YM2612 Status (timer overflow)
102 int TimerA; // timerA limit = valeur jusqu'à laquelle le timer A doit compter
103 int TimerAL;
104 int TimerAcnt; // timerA counter = valeur courante du Timer A
105 int TimerB; // timerB limit = valeur jusqu'à laquelle le timer B doit compter
106 int TimerBL;
107 int TimerBcnt; // timerB counter = valeur courante du Timer B
108 int Mode; // Mode actuel des voie 3 et 6 (normal / special)
109 int DAC; // DAC enabled flag
110 channel_t CHANNEL[Ym2612_Emu::channel_count]; // Les 6 voies du YM2612
111 int REG[2][0x100]; // Sauvegardes des valeurs de tout les registres, c'est facultatif
112 // cela nous rend le debuggage plus facile
113 };
114
115 #ifndef PI
116 #define PI 3.14159265358979323846
117 #endif
118
119 #define ATTACK 0
120 #define DECAY 1
121 #define SUBSTAIN 2
122 #define RELEASE 3
123
124 // SIN_LBITS <= 16
125 // LFO_HBITS <= 16
126 // (SIN_LBITS + SIN_HBITS) <= 26
127 // (ENV_LBITS + ENV_HBITS) <= 28
128 // (LFO_LBITS + LFO_HBITS) <= 28
129
130 #define SIN_HBITS 12 // Sinus phase counter int part
131 #define SIN_LBITS (26 - SIN_HBITS) // Sinus phase counter float part (best setting)
132
133 #if (SIN_LBITS > 16)
134 #define SIN_LBITS 16 // Can't be greater than 16 bits
135 #endif
136
137 #define ENV_HBITS 12 // Env phase counter int part
138 #define ENV_LBITS (28 - ENV_HBITS) // Env phase counter float part (best setting)
139
140 #define LFO_HBITS 10 // LFO phase counter int part
141 #define LFO_LBITS (28 - LFO_HBITS) // LFO phase counter float part (best setting)
142
143 #define SIN_LENGHT (1 << SIN_HBITS)
144 #define ENV_LENGHT (1 << ENV_HBITS)
145 #define LFO_LENGHT (1 << LFO_HBITS)
146
147 #define TL_LENGHT (ENV_LENGHT * 3) // Env + TL scaling + LFO
148
149 #define SIN_MASK (SIN_LENGHT - 1)
150 #define ENV_MASK (ENV_LENGHT - 1)
151 #define LFO_MASK (LFO_LENGHT - 1)
152
153 #define ENV_STEP (96.0 / ENV_LENGHT) // ENV_MAX = 96 dB
154
155 #define ENV_ATTACK ((ENV_LENGHT * 0) << ENV_LBITS)
156 #define ENV_DECAY ((ENV_LENGHT * 1) << ENV_LBITS)
157 #define ENV_END ((ENV_LENGHT * 2) << ENV_LBITS)
158
159 #define MAX_OUT_BITS (SIN_HBITS + SIN_LBITS + 2) // Modulation = -4 <--> +4
160 #define MAX_OUT ((1 << MAX_OUT_BITS) - 1)
161
162 #define PG_CUT_OFF ((int) (78.0 / ENV_STEP))
163 #define ENV_CUT_OFF ((int) (68.0 / ENV_STEP))
164
165 #define AR_RATE 399128
166 #define DR_RATE 5514396
167
168 //#define AR_RATE 426136
169 //#define DR_RATE (AR_RATE * 12)
170
171 #define LFO_FMS_LBITS 9 // FIXED (LFO_FMS_BASE gives somethink as 1)
172 #define LFO_FMS_BASE ((int) (0.05946309436 * 0.0338 * (double) (1 << LFO_FMS_LBITS)))
173
174 #define S0 0 // Stupid typo of the YM2612
175 #define S1 2
176 #define S2 1
177 #define S3 3
178
179 inline void set_seg( slot_t& s, int seg )
180 {
181 s.env_xor = 0;
182 s.env_max = INT_MAX;
183 s.SEG = seg;
184 if ( seg & 4 )
185 {
186 s.env_xor = ENV_MASK;
187 s.env_max = ENV_MASK;
188 }
189 }
190
191 struct tables_t
192 {
193 short SIN_TAB [SIN_LENGHT]; // SINUS TABLE (offset into TL TABLE)
194 int LFOcnt; // LFO counter = compteur-frequence pour le LFO
195 int LFOinc; // LFO step counter = pas d'incrementation du compteur-frequence du LFO
196 // plus le pas est grand, plus la frequence est grande
197 unsigned int AR_TAB [128]; // Attack rate table
198 unsigned int DR_TAB [96]; // Decay rate table
199 unsigned int DT_TAB [8] [32]; // Detune table
200 unsigned int SL_TAB [16]; // Substain level table
201 unsigned int NULL_RATE [32]; // Table for NULL rate
202 int LFO_INC_TAB [8]; // LFO step table
203
204 short ENV_TAB [2 * ENV_LENGHT + 8]; // ENV CURVE TABLE (attack & decay)
205
206 short LFO_ENV_TAB [LFO_LENGHT]; // LFO AMS TABLE (adjusted for 11.8 dB)
207 short LFO_FREQ_TAB [LFO_LENGHT]; // LFO FMS TABLE
208 int TL_TAB [TL_LENGHT * 2]; // TOTAL LEVEL TABLE (positif and minus)
209 unsigned int DECAY_TO_ATTACK [ENV_LENGHT]; // Conversion from decay to attack phase
210 unsigned int FINC_TAB [2048]; // Frequency step table
211 };
212
213 static const unsigned char DT_DEF_TAB [4 * 32] =
214 {
215 // FD = 0
216 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
217 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
218
219 // FD = 1
220 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
221 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 8, 8, 8,
222
223 // FD = 2
224 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5,
225 5, 6, 6, 7, 8, 8, 9, 10, 11, 12, 13, 14, 16, 16, 16, 16,
226
227 // FD = 3
228 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7,
229 8 , 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 20, 22, 22, 22, 22
230 };
231
232 static const unsigned char FKEY_TAB [16] =
233 {
234 0, 0, 0, 0,
235 0, 0, 0, 1,
236 2, 3, 3, 3,
237 3, 3, 3, 3
238 };
239
240 static const unsigned char LFO_AMS_TAB [4] =
241 {
242 31, 4, 1, 0
243 };
244
245 static const unsigned char LFO_FMS_TAB [8] =
246 {
247 LFO_FMS_BASE * 0, LFO_FMS_BASE * 1,
248 LFO_FMS_BASE * 2, LFO_FMS_BASE * 3,
249 LFO_FMS_BASE * 4, LFO_FMS_BASE * 6,
250 LFO_FMS_BASE * 12, LFO_FMS_BASE * 24
251 };
252
253 inline void YM2612_Special_Update() { }
254
255 struct Ym2612_Impl
256 {
257 enum { channel_count = Ym2612_Emu::channel_count };
258
259 state_t YM2612;
260 int mute_mask;
261 tables_t g;
262
263 void KEY_ON( channel_t&, int );
264 void KEY_OFF( channel_t&, int );
265 int SLOT_SET( int, int );
266 int CHANNEL_SET( int, int );
267 int YM_SET( int, int );
268
269 void set_rate( double sample_rate, double clock_factor );
270 void reset();
271 void write0( int addr, int data );
272 void write1( int addr, int data );
273 void run_timer( int );
274 void run( int pair_count, Ym2612_Emu::sample_t* );
275 };
276
277 void Ym2612_Impl::KEY_ON( channel_t& ch, int nsl)
278 {
279 slot_t *SL = &(ch.SLOT [nsl]); // on recupere le bon pointeur de slot
280
281 if (SL->Ecurp == RELEASE) // la touche est-elle rel'chee ?
282 {
283 SL->Fcnt = 0;
284
285 // Fix Ecco 2 splash sound
286
287 SL->Ecnt = (g.DECAY_TO_ATTACK [g.ENV_TAB [SL->Ecnt >> ENV_LBITS]] + ENV_ATTACK) & SL->ChgEnM;
288 SL->ChgEnM = ~0;
289
290 // SL->Ecnt = g.DECAY_TO_ATTACK [g.ENV_TAB [SL->Ecnt >> ENV_LBITS]] + ENV_ATTACK;
291 // SL->Ecnt = 0;
292
293 SL->Einc = SL->EincA;
294 SL->Ecmp = ENV_DECAY;
295 SL->Ecurp = ATTACK;
296 }
297 }
298
299
300 void Ym2612_Impl::KEY_OFF(channel_t& ch, int nsl)
301 {
302 slot_t *SL = &(ch.SLOT [nsl]); // on recupere le bon pointeur de slot
303
304 if (SL->Ecurp != RELEASE) // la touche est-elle appuyee ?
305 {
306 if (SL->Ecnt < ENV_DECAY) // attack phase ?
307 {
308 SL->Ecnt = (g.ENV_TAB [SL->Ecnt >> ENV_LBITS] << ENV_LBITS) + ENV_DECAY;
309 }
310
311 SL->Einc = SL->EincR;
312 SL->Ecmp = ENV_END;
313 SL->Ecurp = RELEASE;
314 }
315 }
316
317
318 int Ym2612_Impl::SLOT_SET( int Adr, int data )
319 {
320 int nch = Adr & 3;
321 if ( nch == 3 )
322 return 1;
323
324 channel_t& ch = YM2612.CHANNEL [nch + (Adr & 0x100 ? 3 : 0)];
325 slot_t& sl = ch.SLOT [(Adr >> 2) & 3];
326
327 switch ( Adr & 0xF0 )
328 {
329 case 0x30:
330 if ( (sl.MUL = (data & 0x0F)) != 0 ) sl.MUL <<= 1;
331 else sl.MUL = 1;
332
333 sl.DT = (int*) g.DT_TAB [(data >> 4) & 7];
334
335 ch.SLOT [0].Finc = -1;
336
337 break;
338
339 case 0x40:
340 sl.TL = data & 0x7F;
341
342 // SOR2 do a lot of TL adjustement and this fix R.Shinobi jump sound...
343 YM2612_Special_Update();
344
345 #if ((ENV_HBITS - 7) < 0)
346 sl.TLL = sl.TL >> (7 - ENV_HBITS);
347 #else
348 sl.TLL = sl.TL << (ENV_HBITS - 7);
349 #endif
350
351 break;
352
353 case 0x50:
354 sl.KSR_S = 3 - (data >> 6);
355
356 ch.SLOT [0].Finc = -1;
357
358 if (data &= 0x1F) sl.AR = (int*) &g.AR_TAB [data << 1];
359 else sl.AR = (int*) &g.NULL_RATE [0];
360
361 sl.EincA = sl.AR [sl.KSR];
362 if (sl.Ecurp == ATTACK) sl.Einc = sl.EincA;
363 break;
364
365 case 0x60:
366 if ( (sl.AMSon = (data & 0x80)) != 0 ) sl.AMS = ch.AMS;
367 else sl.AMS = 31;
368
369 if (data &= 0x1F) sl.DR = (int*) &g.DR_TAB [data << 1];
370 else sl.DR = (int*) &g.NULL_RATE [0];
371
372 sl.EincD = sl.DR [sl.KSR];
373 if (sl.Ecurp == DECAY) sl.Einc = sl.EincD;
374 break;
375
376 case 0x70:
377 if (data &= 0x1F) sl.SR = (int*) &g.DR_TAB [data << 1];
378 else sl.SR = (int*) &g.NULL_RATE [0];
379
380 sl.EincS = sl.SR [sl.KSR];
381 if ((sl.Ecurp == SUBSTAIN) && (sl.Ecnt < ENV_END)) sl.Einc = sl.EincS;
382 break;
383
384 case 0x80:
385 sl.SLL = g.SL_TAB [data >> 4];
386
387 sl.RR = (int*) &g.DR_TAB [((data & 0xF) << 2) + 2];
388
389 sl.EincR = sl.RR [sl.KSR];
390 if ((sl.Ecurp == RELEASE) && (sl.Ecnt < ENV_END)) sl.Einc = sl.EincR;
391 break;
392
393 case 0x90:
394 // SSG-EG envelope shapes :
395 /*
396 E At Al H
397
398 1 0 0 0 \\\\
399 1 0 0 1 \___
400 1 0 1 0 \/\/
401 1 0 1 1 \
402 1 1 0 0 ////
403 1 1 0 1 /
404 1 1 1 0 /\/\
405 1 1 1 1 /___
406
407 E = SSG-EG enable
408 At = Start negate
409 Al = Altern
410 H = Hold */
411
412 set_seg( sl, (data & 8) ? (data & 0x0F) : 0 );
413 break;
414 }
415
416 return 0;
417 }
418
419
420 int Ym2612_Impl::CHANNEL_SET( int Adr, int data )
421 {
422 int num = Adr & 3;
423 if ( num == 3 )
424 return 1;
425
426 channel_t& ch = YM2612.CHANNEL [num + (Adr & 0x100 ? 3 : 0)];
427
428 switch ( Adr & 0xFC )
429 {
430 case 0xA0:
431 YM2612_Special_Update();
432
433 ch.FNUM [0] = (ch.FNUM [0] & 0x700) + data;
434 ch.KC [0] = (ch.FOCT [0] << 2) | FKEY_TAB [ch.FNUM [0] >> 7];
435
436 ch.SLOT [0].Finc = -1;
437 break;
438
439 case 0xA4:
440 YM2612_Special_Update();
441
442 ch.FNUM [0] = (ch.FNUM [0] & 0x0FF) + ((data & 0x07) << 8);
443 ch.FOCT [0] = (data & 0x38) >> 3;
444 ch.KC [0] = (ch.FOCT [0] << 2) | FKEY_TAB [ch.FNUM [0] >> 7];
445
446 ch.SLOT [0].Finc = -1;
447 break;
448
449 case 0xA8:
450 if ( Adr < 0x100 )
451 {
452 num++;
453
454 YM2612_Special_Update();
455
456 YM2612.CHANNEL [2].FNUM [num] = (YM2612.CHANNEL [2].FNUM [num] & 0x700) + data;
457 YM2612.CHANNEL [2].KC [num] = (YM2612.CHANNEL [2].FOCT [num] << 2) |
458 FKEY_TAB [YM2612.CHANNEL [2].FNUM [num] >> 7];
459
460 YM2612.CHANNEL [2].SLOT [0].Finc = -1;
461 }
462 break;
463
464 case 0xAC:
465 if ( Adr < 0x100 )
466 {
467 num++;
468
469 YM2612_Special_Update();
470
471 YM2612.CHANNEL [2].FNUM [num] = (YM2612.CHANNEL [2].FNUM [num] & 0x0FF) + ((data & 0x07) << 8);
472 YM2612.CHANNEL [2].FOCT [num] = (data & 0x38) >> 3;
473 YM2612.CHANNEL [2].KC [num] = (YM2612.CHANNEL [2].FOCT [num] << 2) |
474 FKEY_TAB [YM2612.CHANNEL [2].FNUM [num] >> 7];
475
476 YM2612.CHANNEL [2].SLOT [0].Finc = -1;
477 }
478 break;
479
480 case 0xB0:
481 if ( ch.ALGO != (data & 7) )
482 {
483 // Fix VectorMan 2 heli sound (level 1)
484 YM2612_Special_Update();
485
486 ch.ALGO = data & 7;
487
488 ch.SLOT [0].ChgEnM = 0;
489 ch.SLOT [1].ChgEnM = 0;
490 ch.SLOT [2].ChgEnM = 0;
491 ch.SLOT [3].ChgEnM = 0;
492 }
493
494 ch.FB = 9 - ((data >> 3) & 7); // Real thing ?
495
496 // if (ch.FB = ((data >> 3) & 7)) ch.FB = 9 - ch.FB; // Thunder force 4 (music stage 8), Gynoug, Aladdin bug sound...
497 // else ch.FB = 31;
498 break;
499
500 case 0xB4: {
501 YM2612_Special_Update();
502
503 ch.LEFT = 0 - ((data >> 7) & 1);
504 ch.RIGHT = 0 - ((data >> 6) & 1);
505
506 ch.AMS = LFO_AMS_TAB [(data >> 4) & 3];
507 ch.FMS = LFO_FMS_TAB [data & 7];
508
509 for ( int i = 0; i < 4; i++ )
510 {
511 slot_t& sl = ch.SLOT [i];
512 sl.AMS = (sl.AMSon ? ch.AMS : 31);
513 }
514 break;
515 }
516 }
517
518 return 0;
519 }
520
521
522 int Ym2612_Impl::YM_SET(int Adr, int data)
523 {
524 switch ( Adr )
525 {
526 case 0x22:
527 if (data & 8) // LFO enable
528 {
529 // Cool Spot music 1, LFO modified severals time which
530 // distord the sound, have to check that on a real genesis...
531
532 g.LFOinc = g.LFO_INC_TAB [data & 7];
533 }
534 else
535 {
536 g.LFOinc = g.LFOcnt = 0;
537 }
538 break;
539
540 case 0x24:
541 YM2612.TimerA = (YM2612.TimerA & 0x003) | (((int) data) << 2);
542
543 if (YM2612.TimerAL != (1024 - YM2612.TimerA) << 12)
544 {
545 YM2612.TimerAcnt = YM2612.TimerAL = (1024 - YM2612.TimerA) << 12;
546 }
547 break;
548
549 case 0x25:
550 YM2612.TimerA = (YM2612.TimerA & 0x3fc) | (data & 3);
551
552 if (YM2612.TimerAL != (1024 - YM2612.TimerA) << 12)
553 {
554 YM2612.TimerAcnt = YM2612.TimerAL = (1024 - YM2612.TimerA) << 12;
555 }
556 break;
557
558 case 0x26:
559 YM2612.TimerB = data;
560
561 if (YM2612.TimerBL != (256 - YM2612.TimerB) << (4 + 12))
562 {
563 YM2612.TimerBcnt = YM2612.TimerBL = (256 - YM2612.TimerB) << (4 + 12);
564 }
565 break;
566
567 case 0x27:
568 // Parametre divers
569 // b7 = CSM MODE
570 // b6 = 3 slot mode
571 // b5 = reset b
572 // b4 = reset a
573 // b3 = timer enable b
574 // b2 = timer enable a
575 // b1 = load b
576 // b0 = load a
577
578 if ((data ^ YM2612.Mode) & 0x40)
579 {
580 // We changed the channel 2 mode, so recalculate phase step
581 // This fix the punch sound in Street of Rage 2
582
583 YM2612_Special_Update();
584
585 YM2612.CHANNEL [2].SLOT [0].Finc = -1; // recalculate phase step
586 }
587
588 // if ((data & 2) && (YM2612.Status & 2)) YM2612.TimerBcnt = YM2612.TimerBL;
589 // if ((data & 1) && (YM2612.Status & 1)) YM2612.TimerAcnt = YM2612.TimerAL;
590
591 // YM2612.Status &= (~data >> 4); // Reset du Status au cas ou c'est demande
592 YM2612.Status &= (~data >> 4) & (data >> 2); // Reset Status
593
594 YM2612.Mode = data;
595 break;
596
597 case 0x28: {
598 int nch = data & 3;
599 if ( nch == 3 )
600 return 1;
601 if ( data & 4 )
602 nch += 3;
603 channel_t& ch = YM2612.CHANNEL [nch];
604
605 YM2612_Special_Update();
606
607 if (data & 0x10) KEY_ON(ch, S0); // On appuie sur la touche pour le slot 1
608 else KEY_OFF(ch, S0); // On rel'che la touche pour le slot 1
609 if (data & 0x20) KEY_ON(ch, S1); // On appuie sur la touche pour le slot 3
610 else KEY_OFF(ch, S1); // On rel'che la touche pour le slot 3
611 if (data & 0x40) KEY_ON(ch, S2); // On appuie sur la touche pour le slot 2
612 else KEY_OFF(ch, S2); // On rel'che la touche pour le slot 2
613 if (data & 0x80) KEY_ON(ch, S3); // On appuie sur la touche pour le slot 4
614 else KEY_OFF(ch, S3); // On rel'che la touche pour le slot 4
615 break;
616 }
617
618 case 0x2B:
619 if (YM2612.DAC ^ (data & 0x80)) YM2612_Special_Update();
620
621 YM2612.DAC = data & 0x80; // activation/desactivation du DAC
622 break;
623 }
624
625 return 0;
626 }
627
628 void Ym2612_Impl::set_rate( double sample_rate, double clock_rate )
629 {
630 assert( sample_rate );
631 assert( clock_rate > sample_rate );
632
633 int i;
634
635 // 144 = 12 * (prescale * 2) = 12 * 6 * 2
636 // prescale set to 6 by default
637
638 double Frequence = clock_rate / sample_rate / 144.0;
639 //dprintf( "Frequence: %.40f\n", Frequence );
640 if ( fabs( Frequence - 1.0 ) < 0.0000001 )
641 Frequence = 1.0;
642 YM2612.TimerBase = int (Frequence * 4096.0);
643
644 // Tableau TL :
645 // [0 - 4095] = +output [4095 - ...] = +output overflow (fill with 0)
646 // [12288 - 16383] = -output [16384 - ...] = -output overflow (fill with 0)
647
648 for(i = 0; i < TL_LENGHT; i++)
649 {
650 if (i >= PG_CUT_OFF) // YM2612 cut off sound after 78 dB (14 bits output ?)
651 {
652 g.TL_TAB [TL_LENGHT + i] = g.TL_TAB [i] = 0;
653 }
654 else
655 {
656 double x = MAX_OUT; // Max output
657 x /= pow( 10.0, (ENV_STEP * i) / 20.0 ); // Decibel -> Voltage
658
659 g.TL_TAB [i] = (int) x;
660 g.TL_TAB [TL_LENGHT + i] = -g.TL_TAB [i];
661 }
662 }
663
664 // Tableau SIN :
665 // g.SIN_TAB [x] [y] = sin(x) * y;
666 // x = phase and y = volume
667
668 g.SIN_TAB [0] = g.SIN_TAB [SIN_LENGHT / 2] = PG_CUT_OFF;
669
670 for(i = 1; i <= SIN_LENGHT / 4; i++)
671 {
672 double x = sin(2.0 * PI * (double) (i) / (double) (SIN_LENGHT)); // Sinus
673 x = 20 * log10(1 / x); // convert to dB
674
675 int j = (int) (x / ENV_STEP); // Get TL range
676
677 if (j > PG_CUT_OFF) j = (int) PG_CUT_OFF;
678
679 g.SIN_TAB [i] = g.SIN_TAB [(SIN_LENGHT / 2) - i] = j;
680 g.SIN_TAB [(SIN_LENGHT / 2) + i] = g.SIN_TAB [SIN_LENGHT - i] = TL_LENGHT + j;
681 }
682
683 // Tableau LFO (LFO wav) :
684
685 for(i = 0; i < LFO_LENGHT; i++)
686 {
687 double x = sin(2.0 * PI * (double) (i) / (double) (LFO_LENGHT)); // Sinus
688 x += 1.0;
689 x /= 2.0; // positive only
690 x *= 11.8 / ENV_STEP; // ajusted to MAX enveloppe modulation
691
692 g.LFO_ENV_TAB [i] = (int) x;
693
694 x = sin(2.0 * PI * (double) (i) / (double) (LFO_LENGHT)); // Sinus
695 x *= (double) ((1 << (LFO_HBITS - 1)) - 1);
696
697 g.LFO_FREQ_TAB [i] = (int) x;
698
699 }
700
701 // Tableau Enveloppe :
702 // g.ENV_TAB [0] -> g.ENV_TAB [ENV_LENGHT - 1] = attack curve
703 // g.ENV_TAB [ENV_LENGHT] -> g.ENV_TAB [2 * ENV_LENGHT - 1] = decay curve
704
705 for(i = 0; i < ENV_LENGHT; i++)
706 {
707 // Attack curve (x^8 - music level 2 Vectorman 2)
708 double x = pow(((double) ((ENV_LENGHT - 1) - i) / (double) (ENV_LENGHT)), 8);
709 x *= ENV_LENGHT;
710
711 g.ENV_TAB [i] = (int) x;
712
713 // Decay curve (just linear)
714 x = pow(((double) (i) / (double) (ENV_LENGHT)), 1);
715 x *= ENV_LENGHT;
716
717 g.ENV_TAB [ENV_LENGHT + i] = (int) x;
718 }
719 for ( i = 0; i < 8; i++ )
720 g.ENV_TAB [i + ENV_LENGHT * 2] = 0;
721
722 g.ENV_TAB [ENV_END >> ENV_LBITS] = ENV_LENGHT - 1; // for the stopped state
723
724 // Tableau pour la conversion Attack -> Decay and Decay -> Attack
725
726 int j = ENV_LENGHT - 1;
727 for ( i = 0; i < ENV_LENGHT; i++ )
728 {
729 while ( j && g.ENV_TAB [j] < i )
730 j--;
731
732 g.DECAY_TO_ATTACK [i] = j << ENV_LBITS;
733 }
734
735 // Tableau pour le Substain Level
736
737 for(i = 0; i < 15; i++)
738 {
739 double x = i * 3; // 3 and not 6 (Mickey Mania first music for test)
740 x /= ENV_STEP;
741
742 int j = (int) x;
743 j <<= ENV_LBITS;
744
745 g.SL_TAB [i] = j + ENV_DECAY;
746 }
747
748 g.SL_TAB [15] = ((ENV_LENGHT - 1) << ENV_LBITS) + ENV_DECAY; // special case : volume off
749
750 // Tableau Frequency Step
751
752 for(i = 0; i < 2048; i++)
753 {
754 double x = (double) (i) * Frequence;
755
756 #if ((SIN_LBITS + SIN_HBITS - (21 - 7)) < 0)
757 x /= (double) (1 << ((21 - 7) - SIN_LBITS - SIN_HBITS));
758 #else
759 x *= (double) (1 << (SIN_LBITS + SIN_HBITS - (21 - 7)));
760 #endif
761
762 x /= 2.0; // because MUL = value * 2
763
764 g.FINC_TAB [i] = (unsigned int) x;
765 }
766
767 // Tableaux Attack & Decay Rate
768
769 for(i = 0; i < 4; i++)
770 {
771 g.AR_TAB [i] = 0;
772 g.DR_TAB [i] = 0;
773 }
774
775 for(i = 0; i < 60; i++)
776 {
777 double x = Frequence;
778
779 x *= 1.0 + ((i & 3) * 0.25); // bits 0-1 : x1.00, x1.25, x1.50, x1.75
780 x *= (double) (1 << ((i >> 2))); // bits 2-5 : shift bits (x2^0 - x2^15)
781 x *= (double) (ENV_LENGHT << ENV_LBITS); // on ajuste pour le tableau g.ENV_TAB
782
783 g.AR_TAB [i + 4] = (unsigned int) (x / AR_RATE);
784 g.DR_TAB [i + 4] = (unsigned int) (x / DR_RATE);
785 }
786
787 for(i = 64; i < 96; i++)
788 {
789 g.AR_TAB [i] = g.AR_TAB [63];
790 g.DR_TAB [i] = g.DR_TAB [63];
791
792 g.NULL_RATE [i - 64] = 0;
793 }
794
795 for ( i = 96; i < 128; i++ )
796 g.AR_TAB [i] = 0;
797
798 // Tableau Detune
799
800 for(i = 0; i < 4; i++)
801 {
802 for (int j = 0; j < 32; j++)
803 {
804 #if ((SIN_LBITS + SIN_HBITS - 21) < 0)
805 double x = (double) DT_DEF_TAB [(i << 5) + j] * Frequence / (double) (1 << (21 - SIN_LBITS - SIN_HBITS));
806 #else
807 double x = (double) DT_DEF_TAB [(i << 5) + j] * Frequence * (double) (1 << (SIN_LBITS + SIN_HBITS - 21));
808 #endif
809
810 g.DT_TAB [i + 0] [j] = (int) x;
811 g.DT_TAB [i + 4] [j] = (int) -x;
812 }
813 }
814
815 // Tableau LFO
816 g.LFO_INC_TAB [0] = (unsigned int) (3.98 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
817 g.LFO_INC_TAB [1] = (unsigned int) (5.56 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
818 g.LFO_INC_TAB [2] = (unsigned int) (6.02 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
819 g.LFO_INC_TAB [3] = (unsigned int) (6.37 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
820 g.LFO_INC_TAB [4] = (unsigned int) (6.88 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
821 g.LFO_INC_TAB [5] = (unsigned int) (9.63 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
822 g.LFO_INC_TAB [6] = (unsigned int) (48.1 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
823 g.LFO_INC_TAB [7] = (unsigned int) (72.2 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
824
825 reset();
826 }
827
828 const char* Ym2612_Emu::set_rate( double sample_rate, double clock_rate )
829 {
830 if ( !impl )
831 {
832 impl = (Ym2612_Impl*) malloc( sizeof *impl );
833 if ( !impl )
834 return "Out of memory";
835 impl->mute_mask = 0;
836 }
837 memset( &impl->YM2612, 0, sizeof impl->YM2612 );
838
839 impl->set_rate( sample_rate, clock_rate );
840
841 return 0;
842 }
843
844 Ym2612_Emu::~Ym2612_Emu()
845 {
846 free( impl );
847 }
848
849 inline void Ym2612_Impl::write0( int opn_addr, int data )
850 {
851 assert( (unsigned) data <= 0xFF );
852
853 if ( opn_addr < 0x30 )
854 {
855 YM2612.REG [0] [opn_addr] = data;
856 YM_SET( opn_addr, data );
857 }
858 else if ( YM2612.REG [0] [opn_addr] != data )
859 {
860 YM2612.REG [0] [opn_addr] = data;
861
862 if ( opn_addr < 0xA0 )
863 SLOT_SET( opn_addr, data );
864 else
865 CHANNEL_SET( opn_addr, data );
866 }
867 }
868
869 inline void Ym2612_Impl::write1( int opn_addr, int data )
870 {
871 assert( (unsigned) data <= 0xFF );
872
873 if ( opn_addr >= 0x30 && YM2612.REG [1] [opn_addr] != data )
874 {
875 YM2612.REG [1] [opn_addr] = data;
876
877 if ( opn_addr < 0xA0 )
878 SLOT_SET( opn_addr + 0x100, data );
879 else
880 CHANNEL_SET( opn_addr + 0x100, data );
881 }
882 }
883
884 void Ym2612_Emu::reset()
885 {
886 impl->reset();
887 }
888
889 void Ym2612_Impl::reset()
890 {
891 g.LFOcnt = 0;
892 YM2612.TimerA = 0;
893 YM2612.TimerAL = 0;
894 YM2612.TimerAcnt = 0;
895 YM2612.TimerB = 0;
896 YM2612.TimerBL = 0;
897 YM2612.TimerBcnt = 0;
898 YM2612.DAC = 0;
899
900 YM2612.Status = 0;
901
902 int i;
903 for ( i = 0; i < channel_count; i++ )
904 {
905 channel_t& ch = YM2612.CHANNEL [i];
906
907 ch.LEFT = ~0;
908 ch.RIGHT = ~0;
909 ch.ALGO = 0;
910 ch.FB = 31;
911 ch.FMS = 0;
912 ch.AMS = 0;
913
914 for ( int j = 0 ;j < 4 ; j++ )
915 {
916 ch.S0_OUT [j] = 0;
917 ch.FNUM [j] = 0;
918 ch.FOCT [j] = 0;
919 ch.KC [j] = 0;
920
921 ch.SLOT [j].Fcnt = 0;
922 ch.SLOT [j].Finc = 0;
923 ch.SLOT [j].Ecnt = ENV_END; // Put it at the end of Decay phase...
924 ch.SLOT [j].Einc = 0;
925 ch.SLOT [j].Ecmp = 0;
926 ch.SLOT [j].Ecurp = RELEASE;
927
928 ch.SLOT [j].ChgEnM = 0;
929 }
930 }
931
932 for ( i = 0; i < 0x100; i++ )
933 {
934 YM2612.REG [0] [i] = -1;
935 YM2612.REG [1] [i] = -1;
936 }
937
938 for ( i = 0xB6; i >= 0xB4; i-- )
939 {
940 write0( i, 0xC0 );
941 write1( i, 0xC0 );
942 }
943
944 for ( i = 0xB2; i >= 0x22; i-- )
945 {
946 write0( i, 0 );
947 write1( i, 0 );
948 }
949
950 write0( 0x2A, 0x80 );
951 }
952
953 void Ym2612_Emu::write0( int addr, int data )
954 {
955 impl->write0( addr, data );
956 }
957
958 void Ym2612_Emu::write1( int addr, int data )
959 {
960 impl->write1( addr, data );
961 }
962
963 void Ym2612_Emu::mute_voices( int mask ) { impl->mute_mask = mask; }
964
965 static void update_envelope_( slot_t* sl )
966 {
967 switch ( sl->Ecurp )
968 {
969 case 0:
970 // Env_Attack_Next
971
972 // Verified with Gynoug even in HQ (explode SFX)
973 sl->Ecnt = ENV_DECAY;
974
975 sl->Einc = sl->EincD;
976 sl->Ecmp = sl->SLL;
977 sl->Ecurp = DECAY;
978 break;
979
980 case 1:
981 // Env_Decay_Next
982
983 // Verified with Gynoug even in HQ (explode SFX)
984 sl->Ecnt = sl->SLL;
985
986 sl->Einc = sl->EincS;
987 sl->Ecmp = ENV_END;
988 sl->Ecurp = SUBSTAIN;
989 break;
990
991 case 2:
992 // Env_Substain_Next(slot_t *SL)
993 if (sl->SEG & 8) // SSG envelope type
994 {
995 int release = sl->SEG & 1;
996
997 if ( !release )
998 {
999 // re KEY ON
1000
1001 // sl->Fcnt = 0;
1002 // sl->ChgEnM = ~0;
1003
1004 sl->Ecnt = 0;
1005 sl->Einc = sl->EincA;
1006 sl->Ecmp = ENV_DECAY;
1007 sl->Ecurp = ATTACK;
1008 }
1009
1010 set_seg( *sl, (sl->SEG << 1) & 4 );
1011
1012 if ( !release )
1013 break;
1014 }
1015 // fall through
1016
1017 case 3:
1018 // Env_Release_Next
1019 sl->Ecnt = ENV_END;
1020 sl->Einc = 0;
1021 sl->Ecmp = ENV_END + 1;
1022 break;
1023
1024 // default: no op
1025 }
1026 }
1027
1028 inline void update_envelope( slot_t& sl )
1029 {
1030 int ecmp = sl.Ecmp;
1031 if ( (sl.Ecnt += sl.Einc) >= ecmp )
1032 update_envelope_( &sl );
1033 }
1034
1035 template<int algo>
1036 struct ym2612_update_chan {
1037 static void func( tables_t&, channel_t&, Ym2612_Emu::sample_t*, int );
1038 };
1039
1040 typedef void (*ym2612_update_chan_t)( tables_t&, channel_t&, Ym2612_Emu::sample_t*, int );
1041
1042 template<int algo>
1043 void ym2612_update_chan<algo>::func( tables_t& g, channel_t& ch,
1044 Ym2612_Emu::sample_t* buf, int length )
1045 {
1046 int not_end = ch.SLOT [S3].Ecnt - ENV_END;
1047
1048 // algo is a compile-time constant, so all conditions based on it are resolved
1049 // during compilation
1050
1051 // special cases
1052 if ( algo == 7 )
1053 not_end |= ch.SLOT [S0].Ecnt - ENV_END;
1054
1055 if ( algo >= 5 )
1056 not_end |= ch.SLOT [S2].Ecnt - ENV_END;
1057
1058 if ( algo >= 4 )
1059 not_end |= ch.SLOT [S1].Ecnt - ENV_END;
1060
1061 int CH_S0_OUT_1 = ch.S0_OUT [1];
1062
1063 int in0 = ch.SLOT [S0].Fcnt;
1064 int in1 = ch.SLOT [S1].Fcnt;
1065 int in2 = ch.SLOT [S2].Fcnt;
1066 int in3 = ch.SLOT [S3].Fcnt;
1067
1068 int YM2612_LFOinc = g.LFOinc;
1069 int YM2612_LFOcnt = g.LFOcnt + YM2612_LFOinc;
1070
1071 if ( !not_end )
1072 return;
1073
1074 do
1075 {
1076 // envelope
1077 int const env_LFO = g.LFO_ENV_TAB [YM2612_LFOcnt >> LFO_LBITS & LFO_MASK];
1078
1079 short const* const ENV_TAB = g.ENV_TAB;
1080
1081 #define CALC_EN( x ) \
1082 int temp##x = ENV_TAB [ch.SLOT [S##x].Ecnt >> ENV_LBITS] + ch.SLOT [S##x].TLL; \
1083 int en##x = ((temp##x ^ ch.SLOT [S##x].env_xor) + (env_LFO >> ch.SLOT [S##x].AMS)) & \
1084 ((temp##x - ch.SLOT [S##x].env_max) >> 31);
1085
1086 CALC_EN( 0 )
1087 CALC_EN( 1 )
1088 CALC_EN( 2 )
1089 CALC_EN( 3 )
1090
1091 int const* const TL_TAB = g.TL_TAB;
1092
1093 #define SINT( i, o ) (TL_TAB [g.SIN_TAB [(i)] + (o)])
1094
1095 // feedback
1096 int CH_S0_OUT_0 = ch.S0_OUT [0];
1097 {
1098 int temp = in0 + ((CH_S0_OUT_0 + CH_S0_OUT_1) >> ch.FB);
1099 CH_S0_OUT_1 = CH_S0_OUT_0;
1100 CH_S0_OUT_0 = SINT( (temp >> SIN_LBITS) & SIN_MASK, en0 );
1101 }
1102
1103 int CH_OUTd;
1104 if ( algo == 0 )
1105 {
1106 int temp = in1 + CH_S0_OUT_1;
1107 temp = in2 + SINT( (temp >> SIN_LBITS) & SIN_MASK, en1 );
1108 temp = in3 + SINT( (temp >> SIN_LBITS) & SIN_MASK, en2 );
1109 CH_OUTd = SINT( (temp >> SIN_LBITS) & SIN_MASK, en3 );
1110 }
1111 else if ( algo == 1 )
1112 {
1113 int temp = in2 + CH_S0_OUT_1 + SINT( (in1 >> SIN_LBITS) & SIN_MASK, en1 );
1114 temp = in3 + SINT( (temp >> SIN_LBITS) & SIN_MASK, en2 );
1115 CH_OUTd = SINT( (temp >> SIN_LBITS) & SIN_MASK, en3 );
1116 }
1117 else if ( algo == 2 )
1118 {
1119 int temp = in2 + SINT( (in1 >> SIN_LBITS) & SIN_MASK, en1 );
1120 temp = in3 + CH_S0_OUT_1 + SINT( (temp >> SIN_LBITS) & SIN_MASK, en2 );
1121 CH_OUTd = SINT( (temp >> SIN_LBITS) & SIN_MASK, en3 );
1122 }
1123 else if ( algo == 3 )
1124 {
1125 int temp = in1 + CH_S0_OUT_1;
1126 temp = in3 + SINT( (temp >> SIN_LBITS) & SIN_MASK, en1 ) +
1127 SINT( (in2 >> SIN_LBITS) & SIN_MASK, en2 );
1128 CH_OUTd = SINT( (temp >> SIN_LBITS) & SIN_MASK, en3 );
1129 }
1130 else if ( algo == 4 )
1131 {
1132 int temp = in3 + SINT( (in2 >> SIN_LBITS) & SIN_MASK, en2 );
1133 CH_OUTd = SINT( (temp >> SIN_LBITS) & SIN_MASK, en3 ) +
1134 SINT( ((in1 + CH_S0_OUT_1) >> SIN_LBITS) & SIN_MASK, en1 );
1135 //DO_LIMIT
1136 }
1137 else if ( algo == 5 )
1138 {
1139 int temp = CH_S0_OUT_1;
1140 CH_OUTd = SINT( ((in3 + temp) >> SIN_LBITS) & SIN_MASK, en3 ) +
1141 SINT( ((in1 + temp) >> SIN_LBITS) & SIN_MASK, en1 ) +
1142 SINT( ((in2 + temp) >> SIN_LBITS) & SIN_MASK, en2 );
1143 //DO_LIMIT
1144 }
1145 else if ( algo == 6 )
1146 {
1147 CH_OUTd = SINT( (in3 >> SIN_LBITS) & SIN_MASK, en3 ) +
1148 SINT( ((in1 + CH_S0_OUT_1) >> SIN_LBITS) & SIN_MASK, en1 ) +
1149 SINT( (in2 >> SIN_LBITS) & SIN_MASK, en2 );
1150 //DO_LIMIT
1151 }
1152 else if ( algo == 7 )
1153 {
1154 CH_OUTd = SINT( (in3 >> SIN_LBITS) & SIN_MASK, en3 ) +
1155 SINT( (in1 >> SIN_LBITS) & SIN_MASK, en1 ) +
1156 SINT( (in2 >> SIN_LBITS) & SIN_MASK, en2 ) + CH_S0_OUT_1;
1157 //DO_LIMIT
1158 }
1159
1160 CH_OUTd >>= MAX_OUT_BITS - output_bits + 2;
1161
1162 // update phase
1163 unsigned freq_LFO = ((g.LFO_FREQ_TAB [YM2612_LFOcnt >> LFO_LBITS & LFO_MASK] *
1164 ch.FMS) >> (LFO_HBITS - 1 + 1)) + (1L << (LFO_FMS_LBITS - 1));
1165 YM2612_LFOcnt += YM2612_LFOinc;
1166 in0 += (ch.SLOT [S0].Finc * freq_LFO) >> (LFO_FMS_LBITS - 1);
1167 in1 += (ch.SLOT [S1].Finc * freq_LFO) >> (LFO_FMS_LBITS - 1);
1168 in2 += (ch.SLOT [S2].Finc * freq_LFO) >> (LFO_FMS_LBITS - 1);
1169 in3 += (ch.SLOT [S3].Finc * freq_LFO) >> (LFO_FMS_LBITS - 1);
1170
1171 int t0 = buf [0] + (CH_OUTd & ch.LEFT);
1172 int t1 = buf [1] + (CH_OUTd & ch.RIGHT);
1173
1174 update_envelope( ch.SLOT [0] );
1175 update_envelope( ch.SLOT [1] );
1176 update_envelope( ch.SLOT [2] );
1177 update_envelope( ch.SLOT [3] );
1178
1179 ch.S0_OUT [0] = CH_S0_OUT_0;
1180 buf [0] = t0;
1181 buf [1] = t1;
1182 buf += 2;
1183 }
1184 while ( --length );
1185
1186 ch.S0_OUT [1] = CH_S0_OUT_1;
1187
1188 ch.SLOT [S0].Fcnt = in0;
1189 ch.SLOT [S1].Fcnt = in1;
1190 ch.SLOT [S2].Fcnt = in2;
1191 ch.SLOT [S3].Fcnt = in3;
1192 }
1193
1194 static const ym2612_update_chan_t UPDATE_CHAN [8] = {
1195 &ym2612_update_chan<0>::func,
1196 &ym2612_update_chan<1>::func,
1197 &ym2612_update_chan<2>::func,
1198 &ym2612_update_chan<3>::func,
1199 &ym2612_update_chan<4>::func,
1200 &ym2612_update_chan<5>::func,
1201 &ym2612_update_chan<6>::func,
1202 &ym2612_update_chan<7>::func
1203 };
1204
1205 void Ym2612_Impl::run_timer( int length )
1206 {
1207 int const step = 6;
1208 int remain = length;
1209 do
1210 {
1211 int n = step;
1212 if ( n > remain )
1213 n = remain;
1214 remain -= n;
1215
1216 long i = n * YM2612.TimerBase;
1217 if (YM2612.Mode & 1) // Timer A ON ?
1218 {
1219 // if ((YM2612.TimerAcnt -= 14073) <= 0) // 13879=NTSC (old: 14475=NTSC 14586=PAL)
1220 if ((YM2612.TimerAcnt -= i) <= 0)
1221 {
1222 // timer a overflow
1223
1224 YM2612.Status |= (YM2612.Mode & 0x04) >> 2;
1225 YM2612.TimerAcnt += YM2612.TimerAL;
1226
1227 if (YM2612.Mode & 0x80)
1228 {
1229 KEY_ON( YM2612.CHANNEL [2], 0 );
1230 KEY_ON( YM2612.CHANNEL [2], 1 );
1231 KEY_ON( YM2612.CHANNEL [2], 2 );
1232 KEY_ON( YM2612.CHANNEL [2], 3 );
1233 }
1234 }
1235 }
1236
1237 if (YM2612.Mode & 2) // Timer B ON ?
1238 {
1239 // if ((YM2612.TimerBcnt -= 14073) <= 0) // 13879=NTSC (old: 14475=NTSC 14586=PAL)
1240 if ((YM2612.TimerBcnt -= i) <= 0)
1241 {
1242 // timer b overflow
1243 YM2612.Status |= (YM2612.Mode & 0x08) >> 2;
1244 YM2612.TimerBcnt += YM2612.TimerBL;
1245 }
1246 }
1247 }
1248 while ( remain > 0 );
1249 }
1250
1251 void Ym2612_Impl::run( int pair_count, Ym2612_Emu::sample_t* out )
1252 {
1253 if ( pair_count <= 0 )
1254 return;
1255
1256 if ( YM2612.Mode & 3 )
1257 run_timer( pair_count );
1258
1259 // Mise à jour des pas des compteurs-frequences s'ils ont ete modifies
1260
1261 for ( int chi = 0; chi < channel_count; chi++ )
1262 {
1263 channel_t& ch = YM2612.CHANNEL [chi];
1264 if ( ch.SLOT [0].Finc != -1 )
1265 continue;
1266
1267 int i2 = 0;
1268 if ( chi == 2 && (YM2612.Mode & 0x40) )
1269 i2 = 2;
1270
1271 for ( int i = 0; i < 4; i++ )
1272 {
1273 // static int seq [4] = { 2, 1, 3, 0 };
1274 // if ( i2 ) i2 = seq [i];
1275
1276 slot_t& sl = ch.SLOT [i];
1277 int finc = g.FINC_TAB [ch.FNUM [i2]] >> (7 - ch.FOCT [i2]);
1278 int ksr = ch.KC [i2] >> sl.KSR_S; // keycode attenuation
1279 sl.Finc = (finc + sl.DT [ch.KC [i2]]) * sl.MUL;
1280 if (sl.KSR != ksr) // si le KSR a change alors
1281 { // les differents taux pour l'enveloppe sont mis à jour
1282 sl.KSR = ksr;
1283
1284 sl.EincA = sl.AR [ksr];
1285 sl.EincD = sl.DR [ksr];
1286 sl.EincS = sl.SR [ksr];
1287 sl.EincR = sl.RR [ksr];
1288
1289 if (sl.Ecurp == ATTACK)
1290 {
1291 sl.Einc = sl.EincA;
1292 }
1293 else if (sl.Ecurp == DECAY)
1294 {
1295 sl.Einc = sl.EincD;
1296 }
1297 else if (sl.Ecnt < ENV_END)
1298 {
1299 if (sl.Ecurp == SUBSTAIN)
1300 sl.Einc = sl.EincS;
1301 else if (sl.Ecurp == RELEASE)
1302 sl.Einc = sl.EincR;
1303 }
1304 }
1305
1306 if ( i2 )
1307 i2 = (i2 ^ 2) ^ (i2 >> 1);
1308 }
1309 }
1310
1311 for ( int i = 0; i < channel_count; i++ )
1312 {
1313 if ( !(mute_mask & (1 << i)) && (i != 5 || !YM2612.DAC) )
1314 UPDATE_CHAN [YM2612.CHANNEL [i].ALGO]( g, YM2612.CHANNEL [i], out, pair_count );
1315 }
1316
1317 g.LFOcnt += g.LFOinc * pair_count;
1318 }
1319
1320 void Ym2612_Emu::run( int pair_count, sample_t* out ) { impl->run( pair_count, out ); }
1321