diff options
author | Andree Buschmann <AndreeBuschmann@t-online.de> | 2011-08-07 20:01:04 +0000 |
---|---|---|
committer | Andree Buschmann <AndreeBuschmann@t-online.de> | 2011-08-07 20:01:04 +0000 |
commit | acb0917556fc33681c1df5a530cf754193e67705 (patch) | |
tree | 052a47097009a210e4aed9c207bd6aa4828cc000 /apps/codecs/libgme/emu8950.h | |
parent | 93c6f1329a5691a8be158cefe15641bd1daf9ef8 (diff) | |
download | rockbox-acb0917556fc33681c1df5a530cf754193e67705.tar.gz rockbox-acb0917556fc33681c1df5a530cf754193e67705.zip |
Submit initial patch from FS#12176. Adds support for several new game music formats (AY, GBS, HES, KSS, SGC, VGM and VGZ) and replaces the current NSF and NSFE with a new implementation based on a port of the Game Music Emu library 'GME'. This first submit does not cover the full functionality provided by the author's original patch: Coleco-SGV is not supported, some GME-specific m3u-support has been removed and IRAM is not used yet. Further changes are very likely to follow this submit. Thanks to Mauricio Garrido.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30264 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/codecs/libgme/emu8950.h')
-rw-r--r-- | apps/codecs/libgme/emu8950.h | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/apps/codecs/libgme/emu8950.h b/apps/codecs/libgme/emu8950.h new file mode 100644 index 0000000000..88d17b956e --- /dev/null +++ b/apps/codecs/libgme/emu8950.h | |||
@@ -0,0 +1,248 @@ | |||
1 | #ifndef __Y8950_HH__ | ||
2 | #define __Y8950_HH__ | ||
3 | |||
4 | #include "blargg_common.h" | ||
5 | #include "emuadpcm.h" | ||
6 | |||
7 | #define AUDIO_MONO_BUFFER_SIZE 1024 | ||
8 | |||
9 | // Dynamic range of envelope | ||
10 | static const double EG_STEP = 0.1875; | ||
11 | #define EG_BITS 9 | ||
12 | #define EG_MUTE (1<<EG_BITS) | ||
13 | // Dynamic range of sustine level | ||
14 | static const double SL_STEP = 3.0; | ||
15 | static const int SL_BITS = 4; | ||
16 | #define SL_MUTE (1<<SL_BITS) | ||
17 | // Size of Sintable ( 1 -- 18 can be used, but 7 -- 14 recommended.) | ||
18 | #define PG_BITS 10 | ||
19 | #define PG_WIDTH (1<<PG_BITS) | ||
20 | // Phase increment counter | ||
21 | static const int DP_BITS = 19; | ||
22 | #define DP_WIDTH (1<<DP_BITS) | ||
23 | #define DP_BASE_BITS (DP_BITS - PG_BITS) | ||
24 | // Bits for envelope phase incremental counter | ||
25 | static const int EG_DP_BITS = 23; | ||
26 | #define EG_DP_WIDTH (1<<EG_DP_BITS) | ||
27 | // Dynamic range of total level | ||
28 | static const double TL_STEP = 0.75; | ||
29 | #define TL_BITS 6 | ||
30 | #define TL_MUTE (1<<TL_BITS) | ||
31 | |||
32 | static const double DB_STEP = 0.1875; | ||
33 | #define DB_BITS 9 | ||
34 | #define DB_MUTE (1<<DB_BITS) | ||
35 | // PM table is calcurated by PM_AMP * pow(2,PM_DEPTH*sin(x)/1200) | ||
36 | static const int PM_AMP_BITS = 8; | ||
37 | #define PM_AMP (1<<PM_AMP_BITS) | ||
38 | |||
39 | |||
40 | |||
41 | static const int CLK_FREQ = 3579545; | ||
42 | static const double MPI = 3.14159265358979; | ||
43 | // PM speed(Hz) and depth(cent) | ||
44 | static const double PM_SPEED = 6.4; | ||
45 | static const double PM_DEPTH = (13.75/2); | ||
46 | static const double PM_DEPTH2 = 13.75; | ||
47 | // AM speed(Hz) and depth(dB) | ||
48 | static const double AM_SPEED = 3.7; | ||
49 | static const double AM_DEPTH = 1.0; | ||
50 | static const double AM_DEPTH2 = 4.8; | ||
51 | // Bits for liner value | ||
52 | static const int DB2LIN_AMP_BITS = 11; | ||
53 | #define SLOT_AMP_BITS DB2LIN_AMP_BITS | ||
54 | |||
55 | // Bits for Pitch and Amp modulator | ||
56 | #define PM_PG_BITS 8 | ||
57 | #define PM_PG_WIDTH (1<<PM_PG_BITS) | ||
58 | static const int PM_DP_BITS = 16; | ||
59 | #define PM_DP_WIDTH (1<<PM_DP_BITS) | ||
60 | #define AM_PG_BITS 8 | ||
61 | #define AM_PG_WIDTH (1<<AM_PG_BITS) | ||
62 | static const int AM_DP_BITS = 16; | ||
63 | #define AM_DP_WIDTH (1<<AM_DP_BITS) | ||
64 | |||
65 | // Bitmask for register 0x04 | ||
66 | /** Timer1 Start. */ | ||
67 | static const int R04_ST1 = 0x01; | ||
68 | /** Timer2 Start. */ | ||
69 | static const int R04_ST2 = 0x02; | ||
70 | // not used | ||
71 | //static const int R04 = 0x04; | ||
72 | /** Mask 'Buffer Ready'. */ | ||
73 | static const int R04_MASK_BUF_RDY = 0x08; | ||
74 | /** Mask 'End of sequence'. */ | ||
75 | static const int R04_MASK_EOS = 0x10; | ||
76 | /** Mask Timer2 flag. */ | ||
77 | static const int R04_MASK_T2 = 0x20; | ||
78 | /** Mask Timer1 flag. */ | ||
79 | static const int R04_MASK_T1 = 0x40; | ||
80 | /** IRQ RESET. */ | ||
81 | static const int R04_IRQ_RESET = 0x80; | ||
82 | |||
83 | // Bitmask for status register | ||
84 | #define STATUS_EOS (R04_MASK_EOS) | ||
85 | #define STATUS_BUF_RDY (R04_MASK_BUF_RDY) | ||
86 | #define STATUS_T2 (R04_MASK_T2) | ||
87 | #define STATUS_T1 (R04_MASK_T1) | ||
88 | |||
89 | // Definition of envelope mode | ||
90 | enum { ATTACK,DECAY,SUSHOLD,SUSTINE,RELEASE,FINISH }; | ||
91 | |||
92 | struct Patch { | ||
93 | bool AM, PM, EG; | ||
94 | byte KR; // 0-1 | ||
95 | byte ML; // 0-15 | ||
96 | byte KL; // 0-3 | ||
97 | byte TL; // 0-63 | ||
98 | byte FB; // 0-7 | ||
99 | byte AR; // 0-15 | ||
100 | byte DR; // 0-15 | ||
101 | byte SL; // 0-15 | ||
102 | byte RR; // 0-15 | ||
103 | }; | ||
104 | |||
105 | void patchReset(struct Patch* p); | ||
106 | |||
107 | struct Slot { | ||
108 | // OUTPUT | ||
109 | int feedback; | ||
110 | /** Output value of slot. */ | ||
111 | int output[5]; | ||
112 | |||
113 | // for Phase Generator (PG) | ||
114 | /** Phase. */ | ||
115 | unsigned int phase; | ||
116 | /** Phase increment amount. */ | ||
117 | unsigned int dphase; | ||
118 | /** Output. */ | ||
119 | int pgout; | ||
120 | |||
121 | // for Envelope Generator (EG) | ||
122 | /** F-Number. */ | ||
123 | int fnum; | ||
124 | /** Block. */ | ||
125 | int block; | ||
126 | /** Total Level + Key scale level. */ | ||
127 | int tll; | ||
128 | /** Key scale offset (Rks). */ | ||
129 | int rks; | ||
130 | /** Current state. */ | ||
131 | int eg_mode; | ||
132 | /** Phase. */ | ||
133 | unsigned int eg_phase; | ||
134 | /** Phase increment amount. */ | ||
135 | unsigned int eg_dphase; | ||
136 | /** Output. */ | ||
137 | int egout; | ||
138 | |||
139 | bool slotStatus; | ||
140 | struct Patch patch; | ||
141 | |||
142 | // refer to Y8950-> | ||
143 | int *plfo_pm; | ||
144 | int *plfo_am; | ||
145 | }; | ||
146 | |||
147 | void slotReset(struct Slot* slot); | ||
148 | |||
149 | |||
150 | struct OPLChannel { | ||
151 | bool alg; | ||
152 | struct Slot mod, car; | ||
153 | }; | ||
154 | |||
155 | void channelReset(struct OPLChannel* ch); | ||
156 | |||
157 | |||
158 | struct Y8950 | ||
159 | { | ||
160 | int adr; | ||
161 | int output[2]; | ||
162 | // Register | ||
163 | byte reg[0x100]; | ||
164 | bool rythm_mode; | ||
165 | // Pitch Modulator | ||
166 | int pm_mode; | ||
167 | unsigned int pm_phase; | ||
168 | // Amp Modulator | ||
169 | int am_mode; | ||
170 | unsigned int am_phase; | ||
171 | |||
172 | // Noise Generator | ||
173 | int noise_seed; | ||
174 | int whitenoise; | ||
175 | int noiseA; | ||
176 | int noiseB; | ||
177 | unsigned int noiseA_phase; | ||
178 | unsigned int noiseB_phase; | ||
179 | unsigned int noiseA_dphase; | ||
180 | unsigned int noiseB_dphase; | ||
181 | |||
182 | // Channel & Slot | ||
183 | struct OPLChannel ch[9]; | ||
184 | struct Slot *slot[18]; | ||
185 | |||
186 | unsigned int pm_dphase; | ||
187 | int lfo_pm; | ||
188 | unsigned int am_dphase; | ||
189 | int lfo_am; | ||
190 | |||
191 | int maxVolume; | ||
192 | bool internalMuted; | ||
193 | |||
194 | int clockRate; | ||
195 | |||
196 | /** STATUS Register. */ | ||
197 | byte status; | ||
198 | /** bit=0 -> masked. */ | ||
199 | byte statusMask; | ||
200 | /* MsxAudioIRQHelper irq; */ | ||
201 | |||
202 | // ADPCM | ||
203 | struct Y8950Adpcm adpcm; | ||
204 | |||
205 | /** 13-bit (exponential) DAC. */ | ||
206 | /* DACSound16S dac13; */ | ||
207 | |||
208 | // DAC stuff | ||
209 | int dacSampleVolume; | ||
210 | int dacOldSampleVolume; | ||
211 | int dacSampleVolumeSum; | ||
212 | int dacCtrlVolume; | ||
213 | int dacDaVolume; | ||
214 | int dacEnabled; | ||
215 | |||
216 | // Internal buffer | ||
217 | int buffer[AUDIO_MONO_BUFFER_SIZE]; | ||
218 | }; | ||
219 | |||
220 | void OPL_init(struct Y8950* this_, byte* ramBank, int sampleRam); | ||
221 | |||
222 | void OPL_reset(struct Y8950* this_); | ||
223 | void OPL_writeReg(struct Y8950* this_, byte reg, byte data); | ||
224 | byte OPL_readReg(struct Y8950* this_, byte reg); | ||
225 | byte OPL_readStatus(struct Y8950* this_); | ||
226 | static inline void OPL_setInternalMute(struct Y8950* this_, bool muted) { this_->internalMuted = muted; } | ||
227 | static inline bool OPL_isInternalMuted(struct Y8950* this_) { return this_->internalMuted; } | ||
228 | |||
229 | void OPL_setSampleRate(struct Y8950* this_, int sampleRate, int clockRate); | ||
230 | int* OPL_updateBuffer(struct Y8950* this_, int length); | ||
231 | |||
232 | // SoundDevice | ||
233 | void OPL_setInternalVolume(struct Y8950* this_, short maxVolume); | ||
234 | |||
235 | void OPL_setStatus(struct Y8950* this_, byte flags); | ||
236 | void OPL_resetStatus(struct Y8950* this_, byte flags); | ||
237 | void OPL_changeStatusMask(struct Y8950* this_, byte newMask); | ||
238 | |||
239 | |||
240 | // Adjust envelope speed which depends on sampling rate | ||
241 | static inline unsigned int rate_adjust(double x, int rate, int clk) | ||
242 | { | ||
243 | double tmp = x * clk / 72 / rate + 0.5; // +0.5 to round | ||
244 | // assert (tmp <= 4294967295U); | ||
245 | return (unsigned int)tmp; | ||
246 | } | ||
247 | |||
248 | #endif | ||