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