Submit initial patch from FS#12176. Adds support for several new game music formats...
[kugel-rb.git] / apps / codecs / libgme / ym2612_emu.h
blob19f0903d61c02d11a54c6542c291fdb4203cab32
1 // YM2612 FM sound chip emulator
3 // Game_Music_Emu 0.6-pre
4 #ifndef YM2612_EMU_H
5 #define YM2612_EMU_H
7 #include "blargg_common.h"
9 enum { ym2612_out_chan_count = 2 }; // stereo
10 enum { ym2612_channel_count = 6 };
11 enum { ym2612_disabled_time = -1 };
13 struct slot_t
15 const int *DT; // parametre detune
16 int MUL; // parametre "multiple de frequence"
17 int TL; // Total Level = volume lorsque l'enveloppe est au plus haut
18 int TLL; // Total Level ajusted
19 int SLL; // Sustin Level (ajusted) = volume où l'enveloppe termine sa premiere phase de regression
20 int KSR_S; // Key Scale Rate Shift = facteur de prise en compte du KSL dans la variations de l'enveloppe
21 int KSR; // Key Scale Rate = cette valeur est calculee par rapport à la frequence actuelle, elle va influer
22 // sur les differents parametres de l'enveloppe comme l'attaque, le decay ... comme dans la realite !
23 int SEG; // Type enveloppe SSG
24 int env_xor;
25 int env_max;
27 const int *AR; // Attack Rate (table pointeur) = Taux d'attaque (AR [KSR])
28 const int *DR; // Decay Rate (table pointeur) = Taux pour la regression (DR [KSR])
29 const int *SR; // Sustin Rate (table pointeur) = Taux pour le maintien (SR [KSR])
30 const int *RR; // Release Rate (table pointeur) = Taux pour le rel'chement (RR [KSR])
31 int Fcnt; // Frequency Count = compteur-frequence pour determiner l'amplitude actuelle (SIN [Finc >> 16])
32 int Finc; // frequency step = pas d'incrementation du compteur-frequence
33 // plus le pas est grand, plus la frequence est aïgu (ou haute)
34 int Ecurp; // Envelope current phase = cette variable permet de savoir dans quelle phase
35 // de l'enveloppe on se trouve, par exemple phase d'attaque ou phase de maintenue ...
36 // en fonction de la valeur de cette variable, on va appeler une fonction permettant
37 // de mettre à jour l'enveloppe courante.
38 int Ecnt; // Envelope counter = le compteur-enveloppe permet de savoir où l'on se trouve dans l'enveloppe
39 int Einc; // Envelope step courant
40 int Ecmp; // Envelope counter limite pour la prochaine phase
41 int EincA; // Envelope step for Attack = pas d'incrementation du compteur durant la phase d'attaque
42 // cette valeur est egal à AR [KSR]
43 int EincD; // Envelope step for Decay = pas d'incrementation du compteur durant la phase de regression
44 // cette valeur est egal à DR [KSR]
45 int EincS; // Envelope step for Sustain = pas d'incrementation du compteur durant la phase de maintenue
46 // cette valeur est egal à SR [KSR]
47 int EincR; // Envelope step for Release = pas d'incrementation du compteur durant la phase de rel'chement
48 // cette valeur est egal à RR [KSR]
49 int *OUTp; // pointeur of SLOT output = pointeur permettant de connecter la sortie de ce slot à l'entree
50 // d'un autre ou carrement à la sortie de la voie
51 int INd; // input data of the slot = donnees en entree du slot
52 int ChgEnM; // Change envelop mask.
53 int AMS; // AMS depth level of this SLOT = degre de modulation de l'amplitude par le LFO
54 int AMSon; // AMS enable flag = drapeau d'activation de l'AMS
57 struct channel_
59 int S0_OUT [4]; // anciennes sorties slot 0 (pour le feed back)
60 int LEFT; // LEFT enable flag
61 int RIGHT; // RIGHT enable flag
62 int ALGO; // Algorythm = determine les connections entre les operateurs
63 int FB; // shift count of self feed back = degre de "Feed-Back" du SLOT 1 (il est son unique entree)
64 int FMS; // Frequency Modulation Sensitivity of channel = degre de modulation de la frequence sur la voie par le LFO
65 int AMS; // Amplitude Modulation Sensitivity of channel = degre de modulation de l'amplitude sur la voie par le LFO
66 int FNUM [4]; // hauteur frequence de la voie (+ 3 pour le mode special)
67 int FOCT [4]; // octave de la voie (+ 3 pour le mode special)
68 int KC [4]; // Key Code = valeur fonction de la frequence (voir KSR pour les slots, KSR = KC >> KSR_S)
69 struct slot_t SLOT [4]; // four slot.operators = les 4 slots de la voie
70 int FFlag; // Frequency step recalculation flag
73 struct state_t
75 int TimerBase; // TimerBase calculation
76 int Status; // YM2612 Status (timer overflow)
77 int TimerA; // timerA limit = valeur jusqu'à laquelle le timer A doit compter
78 int TimerAL;
79 int TimerAcnt; // timerA counter = valeur courante du Timer A
80 int TimerB; // timerB limit = valeur jusqu'à laquelle le timer B doit compter
81 int TimerBL;
82 int TimerBcnt; // timerB counter = valeur courante du Timer B
83 int Mode; // Mode actuel des voie 3 et 6 (normal / special)
84 int DAC; // DAC enabled flag
85 struct channel_ CHANNEL [ym2612_channel_count]; // Les 6 voies du YM2612
86 int REG [2] [0x100]; // Sauvegardes des valeurs de tout les registres, c'est facultatif
87 // cela nous rend le debuggage plus facile
90 #undef PI
91 #define PI 3.14159265358979323846
93 #define ATTACK 0
94 #define DECAY 1
95 #define SUBSTAIN 2
96 #define RELEASE 3
98 // SIN_LBITS <= 16
99 // LFO_HBITS <= 16
100 // (SIN_LBITS + SIN_HBITS) <= 26
101 // (ENV_LBITS + ENV_HBITS) <= 28
102 // (LFO_LBITS + LFO_HBITS) <= 28
104 #define SIN_HBITS 12 // Sinus phase counter int part
105 #define SIN_LBITS (26 - SIN_HBITS) // Sinus phase counter float part (best setting)
107 #if (SIN_LBITS > 16)
108 #define SIN_LBITS 16 // Can't be greater than 16 bits
109 #endif
111 #define ENV_HBITS 12 // Env phase counter int part
112 #define ENV_LBITS (28 - ENV_HBITS) // Env phase counter float part (best setting)
114 #define LFO_HBITS 10 // LFO phase counter int part
115 #define LFO_LBITS (28 - LFO_HBITS) // LFO phase counter float part (best setting)
117 #define SIN_LENGHT (1 << SIN_HBITS)
118 #define ENV_LENGHT (1 << ENV_HBITS)
119 #define LFO_LENGHT (1 << LFO_HBITS)
121 #define TL_LENGHT (ENV_LENGHT * 3) // Env + TL scaling + LFO
123 #define SIN_MASK (SIN_LENGHT - 1)
124 #define ENV_MASK (ENV_LENGHT - 1)
125 #define LFO_MASK (LFO_LENGHT - 1)
127 #define ENV_STEP (96.0 / ENV_LENGHT) // ENV_MAX = 96 dB
129 #define ENV_ATTACK ((ENV_LENGHT * 0) << ENV_LBITS)
130 #define ENV_DECAY ((ENV_LENGHT * 1) << ENV_LBITS)
131 #define ENV_END ((ENV_LENGHT * 2) << ENV_LBITS)
133 #define MAX_OUT_BITS (SIN_HBITS + SIN_LBITS + 2) // Modulation = -4 <--> +4
134 #define MAX_OUT ((1 << MAX_OUT_BITS) - 1)
136 #define PG_CUT_OFF ((int) (78.0 / ENV_STEP))
137 //#define ENV_CUT_OFF ((int) (68.0 / ENV_STEP))
139 #define AR_RATE 399128
140 #define DR_RATE 5514396
142 //#define AR_RATE 426136
143 //#define DR_RATE (AR_RATE * 12)
145 #define LFO_FMS_LBITS 9 // FIXED (LFO_FMS_BASE gives somethink as 1)
146 #define LFO_FMS_BASE ((int) (0.05946309436 * 0.0338 * (double) (1 << LFO_FMS_LBITS)))
148 #define S0 0 // Stupid typo of the YM2612
149 #define S1 2
150 #define S2 1
151 #define S3 3
153 struct tables_t
155 short SIN_TAB [SIN_LENGHT]; // SINUS TABLE (offset into TL TABLE)
156 int LFOcnt; // LFO counter = compteur-frequence pour le LFO
157 int LFOinc; // LFO step counter = pas d'incrementation du compteur-frequence du LFO
158 // plus le pas est grand, plus la frequence est grande
159 unsigned int AR_TAB [128]; // Attack rate table
160 unsigned int DR_TAB [96]; // Decay rate table
161 unsigned int DT_TAB [8] [32]; // Detune table
162 unsigned int SL_TAB [16]; // Substain level table
163 unsigned int NULL_RATE [32]; // Table for NULL rate
164 int LFO_INC_TAB [8]; // LFO step table
166 short ENV_TAB [2 * ENV_LENGHT + 8]; // ENV CURVE TABLE (attack & decay)
168 short LFO_ENV_TAB [LFO_LENGHT]; // LFO AMS TABLE (adjusted for 11.8 dB)
169 short LFO_FREQ_TAB [LFO_LENGHT]; // LFO FMS TABLE
170 int TL_TAB [TL_LENGHT * 2]; // TOTAL LEVEL TABLE (positif and minus)
171 unsigned int DECAY_TO_ATTACK [ENV_LENGHT]; // Conversion from decay to attack phase
172 unsigned int FINC_TAB [2048]; // Frequency step table
175 struct Ym2612_Impl
177 struct state_t YM2612;
178 int mute_mask;
179 struct tables_t g;
182 void impl_reset( struct Ym2612_Impl* impl );
184 struct Ym2612_Emu {
185 struct Ym2612_Impl impl;
187 // Impl
188 int last_time;
189 int sample_rate;
190 int clock_rate;
191 short* out;
194 static inline void Ym2612_init( struct Ym2612_Emu* this_ )
196 this_->last_time = ym2612_disabled_time; this_->out = 0;
197 this_->impl.mute_mask = 0;
200 // Sets sample rate and chip clock rate, in Hz. Returns non-zero
201 // if error. If clock_rate=0, uses sample_rate*144
202 const char* Ym2612_set_rate( struct Ym2612_Emu* this_, double sample_rate, double clock_rate );
204 // Resets to power-up state
205 void Ym2612_reset( struct Ym2612_Emu* this_ );
207 // Mutes voice n if bit n (1 << n) of mask is set
208 void Ym2612_mute_voices( struct Ym2612_Emu* this_, int mask );
210 // Writes addr to register 0 then data to register 1
211 void Ym2612_write0( struct Ym2612_Emu* this_, int addr, int data ) ICODE_ATTR;
213 // Writes addr to register 2 then data to register 3
214 void Ym2612_write1( struct Ym2612_Emu* this_, int addr, int data ) ICODE_ATTR;
216 // Runs and adds pair_count*2 samples into current output buffer contents
217 void Ym2612_run( struct Ym2612_Emu* this_, int pair_count, short* out ) ICODE_ATTR;
219 static inline void Ym2612_enable( struct Ym2612_Emu* this_, bool b ) { this_->last_time = b ? 0 : ym2612_disabled_time; }
220 static inline bool Ym2612_enabled( struct Ym2612_Emu* this_ ) { return this_->last_time != ym2612_disabled_time; }
221 static inline void Ym2612_begin_frame( struct Ym2612_Emu* this_, short* buf ) { this_->out = buf; this_->last_time = 0; }
223 static inline int Ym2612_run_until( struct Ym2612_Emu* this_, int time )
225 int count = time - this_->last_time;
226 if ( count > 0 )
228 if ( this_->last_time < 0 )
229 return false;
230 this_->last_time = time;
231 short* p = this_->out;
232 this_->out += count * ym2612_out_chan_count;
233 Ym2612_run( this_, count, p );
235 return true;
237 #endif