Mercurial > pmdwin
comparison fmgen/opna.c @ 0:c55ea9478c80
Hello Gensokyo!
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Tue, 21 May 2013 10:29:21 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:c55ea9478c80 |
---|---|
1 // FIXME: move ugly-ass legalese somewhere where it won't be seen | |
2 // by anyone other than lawyers. (/dev/null would be ideal but sadly | |
3 // we live in an imperfect world). | |
4 /* Copyright (c) 2012/2013, Peter Barfuss | |
5 All rights reserved. | |
6 | |
7 Redistribution and use in source and binary forms, with or without | |
8 modification, are permitted provided that the following conditions are met: | |
9 | |
10 1. Redistributions of source code must retain the above copyright notice, this | |
11 list of conditions and the following disclaimer. | |
12 2. Redistributions in binary form must reproduce the above copyright notice, | |
13 this list of conditions and the following disclaimer in the documentation | |
14 and/or other materials provided with the distribution. | |
15 | |
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | |
20 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
21 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
22 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
23 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |
26 | |
27 #include <stdint.h> | |
28 #include <math.h> | |
29 #include <unistd.h> | |
30 #include "op.h" | |
31 #include "psg.h" | |
32 #include "opna.h" | |
33 static const uint8_t notetab[128] = | |
34 { | |
35 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, | |
36 4, 4, 4, 4, 4, 4, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7, | |
37 8, 8, 8, 8, 8, 8, 8, 9, 10, 11, 11, 11, 11, 11, 11, 11, | |
38 12, 12, 12, 12, 12, 12, 12, 13, 14, 15, 15, 15, 15, 15, 15, 15, | |
39 16, 16, 16, 16, 16, 16, 16, 17, 18, 19, 19, 19, 19, 19, 19, 19, | |
40 20, 20, 20, 20, 20, 20, 20, 21, 22, 23, 23, 23, 23, 23, 23, 23, | |
41 24, 24, 24, 24, 24, 24, 24, 25, 26, 27, 27, 27, 27, 27, 27, 27, | |
42 28, 28, 28, 28, 28, 28, 28, 29, 30, 31, 31, 31, 31, 31, 31, 31, | |
43 }; | |
44 | |
45 static const int8_t dttab[256] = | |
46 { | |
47 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
48 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
49 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, | |
50 4, 6, 6, 6, 8, 8, 8, 10, 10, 12, 12, 14, 16, 16, 16, 16, | |
51 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 8, 8, 8, 10, | |
52 10, 12, 12, 14, 16, 16, 18, 20, 22, 24, 26, 28, 32, 32, 32, 32, | |
53 4, 4, 4, 4, 4, 6, 6, 6, 8, 8, 8, 10, 10, 12, 12, 14, | |
54 16, 16, 18, 20, 22, 24, 26, 28, 32, 34, 38, 40, 44, 44, 44, 44, | |
55 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
56 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
57 0, 0, 0, 0, -2, -2, -2, -2, -2, -2, -2, -2, -4, -4, -4, -4, | |
58 -4, -6, -6, -6, -8, -8, -8,-10,-10,-12,-12,-14,-16,-16,-16,-16, | |
59 -2, -2, -2, -2, -4, -4, -4, -4, -4, -6, -6, -6, -8, -8, -8,-10, | |
60 -10,-12,-12,-14,-16,-16,-18,-20,-22,-24,-26,-28,-32,-32,-32,-32, | |
61 -4, -4, -4, -4, -4, -6, -6, -6, -8, -8, -8,-10,-10,-12,-12,-14, | |
62 -16,-16,-18,-20,-22,-24,-26,-28,-32,-34,-38,-40,-44,-44,-44,-44, | |
63 }; | |
64 | |
65 static uint8_t gaintab[64] = { | |
66 0xff, 0xea, 0xd7, 0xc5, 0xb5, 0xa6, 0x98, 0x8b, 0x80, 0x75, 0x6c, 0x63, 0x5a, 0x53, 0x4c, 0x46, | |
67 0x40, 0x3b, 0x36, 0x31, 0x2d, 0x2a, 0x26, 0x23, 0x20, 0x1d, 0x1b, 0x19, 0x17, 0x15, 0x13, 0x12, | |
68 0x10, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a, 0x0a, 0x09, 0x08, 0x07, 0x07, 0x06, 0x06, 0x05, 0x05, 0x04, | |
69 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, | |
70 }; | |
71 | |
72 // sinf(M_PI*(2*i+1)/1024.0f), i=0,...,511. | |
73 // Should make this twice as large (so a duplicate of the top 512, but with the other half of the | |
74 // interval [0,2*M_PI], therefore the negative of the first half), and then get rid of the | |
75 // silly hack in Sinetable(). However, I'm not actually sure which will use less gates on an FPGA, | |
76 // and there's really no speed difference on any machine newer than a 6502, probably. | |
77 static uint16_t sinetable[512] = { | |
78 0x1, 0x2, 0x4, 0x5, 0x7, 0x9, 0xa, 0xc, 0xd, 0xf, 0x10, 0x12, 0x14, 0x15, 0x17, 0x18, | |
79 0x1a, 0x1b, 0x1d, 0x1f, 0x20, 0x22, 0x23, 0x25, 0x26, 0x28, 0x29, 0x2b, 0x2d, 0x2e, 0x30, 0x31, | |
80 0x33, 0x34, 0x36, 0x37, 0x39, 0x3a, 0x3c, 0x3d, 0x3f, 0x40, 0x42, 0x44, 0x45, 0x47, 0x48, 0x4a, | |
81 0x4b, 0x4d, 0x4e, 0x50, 0x51, 0x53, 0x54, 0x56, 0x57, 0x58, 0x5a, 0x5b, 0x5d, 0x5e, 0x60, 0x61, | |
82 0x63, 0x64, 0x66, 0x67, 0x68, 0x6a, 0x6b, 0x6d, 0x6e, 0x70, 0x71, 0x72, 0x74, 0x75, 0x77, 0x78, | |
83 0x79, 0x7b, 0x7c, 0x7d, 0x7f, 0x80, 0x82, 0x83, 0x84, 0x86, 0x87, 0x88, 0x8a, 0x8b, 0x8c, 0x8e, | |
84 0x8f, 0x90, 0x91, 0x93, 0x94, 0x95, 0x97, 0x98, 0x99, 0x9a, 0x9c, 0x9d, 0x9e, 0x9f, 0xa1, 0xa2, | |
85 0xa3, 0xa4, 0xa5, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, | |
86 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, | |
87 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd4, | |
88 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xde, 0xdf, 0xe0, 0xe1, 0xe1, | |
89 0xe2, 0xe3, 0xe4, 0xe4, 0xe5, 0xe6, 0xe6, 0xe7, 0xe8, 0xe8, 0xe9, 0xea, 0xea, 0xeb, 0xec, 0xec, | |
90 0xed, 0xed, 0xee, 0xef, 0xef, 0xf0, 0xf0, 0xf1, 0xf1, 0xf2, 0xf2, 0xf3, 0xf3, 0xf4, 0xf4, 0xf5, | |
91 0xf5, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, | |
92 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, | |
93 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, | |
94 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
95 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfd, 0xfd, 0xfd, 0xfd, 0xfc, 0xfc, 0xfc, 0xfc, 0xfb, | |
96 0xfb, 0xfb, 0xfa, 0xfa, 0xfa, 0xf9, 0xf9, 0xf9, 0xf8, 0xf8, 0xf7, 0xf7, 0xf7, 0xf6, 0xf6, 0xf5, | |
97 0xf5, 0xf4, 0xf4, 0xf3, 0xf3, 0xf2, 0xf2, 0xf1, 0xf1, 0xf0, 0xf0, 0xef, 0xef, 0xee, 0xed, 0xed, | |
98 0xec, 0xec, 0xeb, 0xea, 0xea, 0xe9, 0xe8, 0xe8, 0xe7, 0xe6, 0xe6, 0xe5, 0xe4, 0xe4, 0xe3, 0xe2, | |
99 0xe1, 0xe1, 0xe0, 0xdf, 0xde, 0xde, 0xdd, 0xdc, 0xdb, 0xda, 0xda, 0xd9, 0xd8, 0xd7, 0xd6, 0xd5, | |
100 0xd4, 0xd4, 0xd3, 0xd2, 0xd1, 0xd0, 0xcf, 0xce, 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc8, 0xc7, 0xc6, | |
101 0xc5, 0xc4, 0xc3, 0xc2, 0xc1, 0xc0, 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8, 0xb7, 0xb6, | |
102 0xb4, 0xb3, 0xb2, 0xb1, 0xb0, 0xaf, 0xae, 0xad, 0xab, 0xaa, 0xa9, 0xa8, 0xa7, 0xa5, 0xa4, 0xa3, | |
103 0xa2, 0xa1, 0x9f, 0x9e, 0x9d, 0x9c, 0x9a, 0x99, 0x98, 0x97, 0x95, 0x94, 0x93, 0x91, 0x90, 0x8f, | |
104 0x8e, 0x8c, 0x8b, 0x8a, 0x88, 0x87, 0x86, 0x84, 0x83, 0x82, 0x80, 0x7f, 0x7d, 0x7c, 0x7b, 0x79, | |
105 0x78, 0x77, 0x75, 0x74, 0x72, 0x71, 0x70, 0x6e, 0x6d, 0x6b, 0x6a, 0x68, 0x67, 0x66, 0x64, 0x63, | |
106 0x61, 0x60, 0x5e, 0x5d, 0x5b, 0x5a, 0x58, 0x57, 0x56, 0x54, 0x53, 0x51, 0x50, 0x4e, 0x4d, 0x4b, | |
107 0x4a, 0x48, 0x47, 0x45, 0x44, 0x42, 0x40, 0x3f, 0x3d, 0x3c, 0x3a, 0x39, 0x37, 0x36, 0x34, 0x33, | |
108 0x31, 0x30, 0x2e, 0x2d, 0x2b, 0x29, 0x28, 0x26, 0x25, 0x23, 0x22, 0x20, 0x1f, 0x1d, 0x1b, 0x1a, | |
109 0x18, 0x17, 0x15, 0x14, 0x12, 0x10, 0xf, 0xd, 0xc, 0xa, 0x9, 0x7, 0x6, 0x4, 0x2, 0x1, | |
110 }; | |
111 | |
112 static uint8_t tablemade = false; | |
113 static uint8_t cltab[512]; | |
114 static uint32_t tltab[FM_TLENTS]; | |
115 static uint32_t lfotab[8]; | |
116 static const uint8_t fbtab[8] = { 31, 7, 6, 5, 4, 3, 2, 1 }; | |
117 | |
118 /* Amplitude/Phase modulation tables. */ | |
119 static const float pms[8] = { 0, 1/720., 2/720., 3/720., 4/720., 6/720., 12/720., 24/720. }; // OPNA | |
120 static const uint8_t amt[4] = { 29, 4, 2, 1 }; // OPNA | |
121 static int pmtable[8][FM_LFOENTS]; | |
122 uint8_t aml, pml; | |
123 int pmv; | |
124 | |
125 // --------------------------------------------------------------------------- | |
126 static inline void LFO(OPNA *opna) | |
127 { | |
128 uint8_t c = (opna->lfocount >> FM_LFOCBITS) & 0xff; | |
129 opna->lfocount += opna->lfodcount; | |
130 if (c < 0x40) pml = c * 2 + 0x80; | |
131 else if (c < 0xc0) pml = 0x7f - (c - 0x40) * 2 + 0x80; | |
132 else pml = (c - 0xc0) * 2; | |
133 if (c < 0x80) aml = (c << 1); | |
134 else aml = ~(c << 1); | |
135 } | |
136 | |
137 // --------------------------------------------------------------------------- | |
138 // Magic. No, really. | |
139 // In reality this just initialises some tables used by everything else, | |
140 // that are dependent on both the chip clock and the "DAC" samplerate. | |
141 // The hilarious thing though is that this is really the only place where | |
142 // the chip clock value gets actually *used*, and even then it's indirectly | |
143 // via the ratio parameter. | |
144 // | |
145 static uint32_t currentratio = ~0; | |
146 static float rr; | |
147 static uint32_t ratetable[64]; | |
148 static void MakeTimeTable(uint32_t ratio) | |
149 { | |
150 int h, l; | |
151 | |
152 if (ratio != currentratio) | |
153 { | |
154 currentratio = ratio; | |
155 // PG Part | |
156 rr = (float)ratio / (1 << (2 + FM_RATIOBITS - FM_PGBITS)); | |
157 | |
158 // EG | |
159 for (h=1; h<16; h++) | |
160 { | |
161 for (l=0; l<4; l++) | |
162 { | |
163 int m = h == 15 ? 8 : l+4; | |
164 ratetable[h*4+l] = | |
165 ((ratio << (FM_EGBITS - 3 - FM_RATIOBITS)) << Min(h, 11)) * m; | |
166 } | |
167 } | |
168 ratetable[0] = ratetable[1] = ratetable[2] = ratetable[3] = 0; | |
169 ratetable[5] = ratetable[4], ratetable[7] = ratetable[6]; | |
170 } | |
171 } | |
172 | |
173 static void SetEGRate(FMOperator *op, uint r) | |
174 { | |
175 op->egstepd = ratetable[r]; | |
176 op->egtransa = Limit(15 - (r>>2), 4, 1); | |
177 op->egtransd = 16 >> op->egtransa; | |
178 } | |
179 | |
180 // Standard operator init routine. Zeros out some more stuff | |
181 // than OperatorReset() does, then calls OperatorReset(). | |
182 // | |
183 void OperatorInit(FMOperator *op) | |
184 { | |
185 // EG Part | |
186 op->ar = op->dr = op->sr = op->rr = op->ksr = 0; | |
187 op->ams = 0; | |
188 op->mute = false; | |
189 op->keyon = false; | |
190 | |
191 // PG Part | |
192 op->multiple = 0; | |
193 op->detune = 0; | |
194 | |
195 // LFO | |
196 op->ms = 0; | |
197 | |
198 OperatorReset(op); | |
199 } | |
200 | |
201 // Standard operator reset routine. Init EG/PG to defaults, | |
202 // clear any stored samples, then force a reinit of EG/PG | |
203 // in OperatorPrepare() below by setting paramchanged to 1. | |
204 // | |
205 void OperatorReset(FMOperator *op) | |
206 { | |
207 // EG part | |
208 op->tl = op->tll = 127; | |
209 op->eglevel = 0xff; | |
210 op->eglvnext = 0x100; | |
211 SetEGRate(op, 0); | |
212 op->phase = off; | |
213 op->egstep = 0; | |
214 | |
215 // PG part | |
216 op->pgcount = 0; | |
217 | |
218 // OP part | |
219 op->out = op->out2 = 0; | |
220 op->paramchanged = true; | |
221 } | |
222 | |
223 // Init EG, PG. | |
224 // PG init is trivial, simply set pgdcount (phase counter increment) | |
225 // based on multiple, detune and bn. | |
226 // See Pages 24-26 of the OPNA manual for details. | |
227 // EG init is your standard ADSR state machine. Should (hopefully!) | |
228 // be self-explanatory, especially if you've ever seen a software implementation | |
229 // of ADSR before (seriously, they're all the damn same). | |
230 // | |
231 void OperatorPrepare(FMOperator *op) | |
232 { | |
233 if (op->paramchanged) | |
234 { | |
235 uint8_t l = ((op->multiple) ? 2*op->multiple : 1); | |
236 op->paramchanged = false; | |
237 // PG Part | |
238 op->pgdcount = (op->dp + dttab[op->detune + op->bn]) * (uint32_t)(l * rr); | |
239 op->pgdcountl = op->pgdcount >> 11; | |
240 | |
241 // EG Part | |
242 op->ksr = op->bn >> (3-op->ks); | |
243 | |
244 switch (op->phase) | |
245 { | |
246 case attack: | |
247 SetEGRate(op, op->ar ? Min(63, op->ar+op->ksr) : 0); | |
248 break; | |
249 case decay: | |
250 SetEGRate(op, op->dr ? Min(63, op->dr+op->ksr) : 0); | |
251 op->eglvnext = op->sl * 8; | |
252 break; | |
253 case sustain: | |
254 SetEGRate(op, op->sr ? Min(63, op->sr+op->ksr) : 0); | |
255 break; | |
256 case release: | |
257 SetEGRate(op, Min(63, op->rr+op->ksr)); | |
258 break; | |
259 case next: // temporal | |
260 break; | |
261 case off: // temporal | |
262 break; | |
263 } | |
264 // LFO | |
265 op->ams = (op->amon ? (op->ms >> 4) & 3 : 0); | |
266 } | |
267 } | |
268 | |
269 // FIXME: Rename. "Phase" here refers to ADSR DFA state, | |
270 // not PG/sine table phase. Also, yeah, this does the | |
271 // ADSR DFA state transitions. | |
272 // | |
273 static void ShiftPhase(FMOperator *op, EGPhase nextphase) | |
274 { | |
275 switch (nextphase) | |
276 { | |
277 case attack: // Attack Phase | |
278 op->tl = op->tll; | |
279 if ((op->ar+op->ksr) < 62) { | |
280 SetEGRate(op, op->ar ? Min(63, op->ar+op->ksr) : 0); | |
281 op->phase = attack; | |
282 break; | |
283 } | |
284 case decay: // Decay Phase | |
285 if (op->sl) { | |
286 op->eglevel = 0; | |
287 op->eglvnext = op->sl*8; | |
288 SetEGRate(op, op->dr ? Min(63, op->dr+op->ksr) : 0); | |
289 op->phase = decay; | |
290 break; | |
291 } | |
292 case sustain: // Sustain Phase | |
293 op->eglevel = op->sl*8; | |
294 op->eglvnext = 0x100; | |
295 SetEGRate(op, op->sr ? Min(63, op->sr+op->ksr) : 0); | |
296 op->phase = sustain; | |
297 break; | |
298 | |
299 case release: // Release Phase | |
300 if (op->phase == attack || (op->eglevel < 0x100/* && phase != off*/)) { | |
301 op->eglvnext = 0x100; | |
302 SetEGRate(op, Min(63, op->rr+op->ksr)); | |
303 op->phase = release; | |
304 break; | |
305 } | |
306 case off: // off | |
307 default: | |
308 op->eglevel = 0xff; | |
309 op->eglvnext = 0x100; | |
310 SetEGRate(op, 0); | |
311 op->phase = off; | |
312 break; | |
313 } | |
314 } | |
315 | |
316 // Block/F-Num | |
317 static inline void SetFNum(FMOperator *op, uint f) | |
318 { | |
319 op->dp = (f & 2047) << ((f >> 11) & 7); | |
320 op->bn = notetab[(f >> 7) & 127]; | |
321 op->paramchanged = true; | |
322 } | |
323 | |
324 // Clock the EG for one operator. | |
325 // Essentially just a call to ShiftPhase, | |
326 // but decrements the output EG level if starting | |
327 // from the attack phase, otherwise incrementing it. | |
328 // Should probably integrate the special case for attack | |
329 // from ShiftPhase() directly into here at some point. | |
330 void EGCalc(FMOperator *op) | |
331 { | |
332 op->egstep += 3L << (11 + FM_EGBITS); | |
333 if (op->phase == attack) | |
334 { | |
335 op->eglevel -= 1 + (op->eglevel >> op->egtransa); | |
336 if (op->eglevel <= 0) | |
337 ShiftPhase(op, decay); | |
338 } | |
339 else | |
340 { | |
341 op->eglevel += op->egtransd; | |
342 if (op->eglevel >= op->eglvnext) | |
343 ShiftPhase(op, (EGPhase)(op->phase+1)); | |
344 } | |
345 } | |
346 | |
347 // KeyOn, hopefully obvious. | |
348 static void KeyOn(FMOperator *op) | |
349 { | |
350 if (!op->keyon) { | |
351 op->keyon = true; | |
352 if (op->phase == off || op->phase == release) { | |
353 ShiftPhase(op, attack); | |
354 op->out = op->out2 = 0; | |
355 op->pgcount = 0; | |
356 } | |
357 } | |
358 } | |
359 | |
360 // KeyOff, hopefully obvious. | |
361 static void KeyOff(FMOperator *op) | |
362 { | |
363 if (op->keyon) { | |
364 op->keyon = false; | |
365 ShiftPhase(op, release); | |
366 } | |
367 } | |
368 | |
369 // PG uses 9 bits, with the table itsself using another 10 bits. | |
370 // The top bits are the actually relevant ones, given that the PG increment will basically set | |
371 // the lowest few bits to nonsense. | |
372 // The hack there that checks for bit 10 in the right place and if yes, does some strange xor magic | |
373 // makes the value of Sine() negative if we're in the top half of the [0,2*M_PI] interval. | |
374 // It is, of course, one/two's complement specific, but I have yet to hear of an integer arithmetic implementation | |
375 // on any modern machine that isn't at least one of those two. (In fact, I think they're all two's complement, even). | |
376 #define Sine(s) sinetable[((s) >> (20+FM_PGBITS-FM_OPSINBITS))&(FM_OPSINENTS/2-1)]^(-(((s) & 0x10000000) >> 27)) | |
377 //#define LogToLin(x) cltab[x] | |
378 | |
379 static inline uint32_t LogToLin(uint32_t x) { | |
380 if(x >= 1024) { | |
381 return 0; | |
382 } | |
383 return cltab[x]; | |
384 } | |
385 | |
386 // PG clock routine. | |
387 // Does this really need to be in its own function anymore? | |
388 // It's literally just a trivial increment of a counter now, nothing more. | |
389 // Its output, btw, is 2^(20+PGBITS) / cycle, with PGBITS=9 in this implementation. | |
390 static inline uint32_t PGCalc(FMOperator *op) | |
391 { | |
392 uint32_t ret = op->pgcount; | |
393 op->pgcount += op->pgdcount; | |
394 return ret; | |
395 } | |
396 | |
397 // Same as above, but with PM if enabled. | |
398 // Same comments as above apply. | |
399 static inline uint32_t PGCalcL(FMOperator *op) | |
400 { | |
401 uint32_t ret = op->pgcount; | |
402 op->pgcount += op->pgdcount + ((op->pgdcountl * pmv) >> 5); | |
403 return ret; | |
404 } | |
405 | |
406 // Clock one FM operator. Does a lookup in the sine table | |
407 // for the waveform to output, possibly frequency-modulating | |
408 // that with the contents of in, then clocks the Phase Generator | |
409 // for that operator, stores the output sample and returns. | |
410 // Should probably integrate PGCalc() into this function, | |
411 // at some point at least. | |
412 static inline int32_t Calc(FMOperator *op, int32_t in) | |
413 { | |
414 int32_t tmp = Sine(op->pgcount + (in << 7)); | |
415 PGCalc(op); | |
416 op->out = op->egout*tmp; | |
417 return op->out; | |
418 } | |
419 | |
420 // Version of the above that gets used when the chip-internal LFO | |
421 // is enabled. Basically identical to the above, except with more Vibrato. | |
422 static inline int32_t CalcL(FMOperator *op, int32_t in) | |
423 { | |
424 int32_t tmp = Sine(op->pgcount + (in << 7)); | |
425 PGCalcL(op); | |
426 op->out = op->egout*tmp; | |
427 return op->out; | |
428 } | |
429 | |
430 // Clock operator 0. OP0 is special as it does not take an input from | |
431 // another operator, rather it can frequency-modulate itsself via the | |
432 // fb parameter (which specifies feedback amount). This is incredibly | |
433 // useful, and makes it possible to define a lot more instruments | |
434 // for the OPNA than you'd be able to otherwise. | |
435 #define FM_PRECISEFEEDBACK 1 | |
436 static inline void CalcFB(FMOperator *op, uint fb) | |
437 { | |
438 int32_t tmp; | |
439 int32_t in = op->out + op->out2; | |
440 op->out2 = op->out; | |
441 if (FM_PRECISEFEEDBACK && fb == 31) | |
442 tmp = Sine(op->pgcount); | |
443 else | |
444 tmp = Sine(op->pgcount + ((in << 6) >> fb)); | |
445 | |
446 PGCalc(op); | |
447 op->out = op->egout*tmp; | |
448 } | |
449 | |
450 // Version of the above, but with 100% as much LFO as the above. | |
451 // See comment above CalcL() for details/explanation. | |
452 static inline void CalcFBL(FMOperator *op, uint fb) | |
453 { | |
454 int32_t tmp; | |
455 int32_t in = op->out + op->out2; | |
456 op->out2 = op->out; | |
457 | |
458 if (FM_PRECISEFEEDBACK && fb == 31) | |
459 tmp = Sine(op->pgcount); | |
460 else | |
461 tmp = Sine(op->pgcount + ((in << 6) >> fb)); | |
462 | |
463 PGCalcL(op); | |
464 op->out = op->egout*tmp; | |
465 } | |
466 | |
467 // --------------------------------------------------------------------------- | |
468 // 4-op Channel | |
469 // Sets the "algorithm", i.e. the connections between individual operators | |
470 // in a channel. See Page 22 of the manual for pretty drawings of all of the | |
471 // different algorithms supported by the OPNA. | |
472 // | |
473 static void SetAlgorithm(Channel4 *ch4, uint algo) | |
474 { | |
475 static const uint8_t table1[8][6] = | |
476 { | |
477 { 0, 1, 1, 2, 2, 3 }, { 1, 0, 0, 1, 1, 2 }, | |
478 { 1, 1, 1, 0, 0, 2 }, { 0, 1, 2, 1, 1, 2 }, | |
479 { 0, 1, 2, 2, 2, 1 }, { 0, 1, 0, 1, 0, 1 }, | |
480 { 0, 1, 2, 1, 2, 1 }, { 1, 0, 1, 0, 1, 0 }, | |
481 }; | |
482 | |
483 ch4->idx[0] = table1[algo][0]; // in[0]; | |
484 ch4->idx[1] = table1[algo][2]; // in[1]; | |
485 ch4->idx[2] = table1[algo][4]; // in[2]; | |
486 ch4->idx[3] = table1[algo][1]; // out[0]; | |
487 ch4->idx[4] = table1[algo][3]; // out[1]; | |
488 ch4->idx[5] = table1[algo][5]; // out[2]; | |
489 ch4->op[0].out2 = ch4->op[0].out = 0; | |
490 } | |
491 | |
492 static inline void Ch4Init(Channel4 *ch4) | |
493 { | |
494 int i; | |
495 for(i=0; i<4; i++) { | |
496 OperatorInit(&ch4->op[i]); | |
497 } | |
498 SetAlgorithm(ch4, 0); | |
499 ch4->pms = pmtable[0]; | |
500 } | |
501 | |
502 // Reinit all operators on a given channel if paramchanged=true | |
503 // for that channel, set the PM table for that channel, then determine | |
504 // if there is any output from this channel, based on: | |
505 // - mute state of each operator | |
506 // - keyon state of each operator | |
507 // - AM (Tremolo) enable for each operator. | |
508 // Bit 0 of the return value is set if there is any output, | |
509 // Bit 1 is set if tremolo is enabled for any of the operators on this | |
510 // channel. | |
511 static inline int Ch4Prepare(Channel4 *ch4) | |
512 { | |
513 OperatorPrepare(&ch4->op[0]); | |
514 OperatorPrepare(&ch4->op[1]); | |
515 OperatorPrepare(&ch4->op[2]); | |
516 OperatorPrepare(&ch4->op[3]); | |
517 | |
518 ch4->pms = pmtable[ch4->op[0].ms & 7]; | |
519 if(ch4->op[0].mute && ch4->op[1].mute && ch4->op[2].mute && ch4->op[3].mute) return 0; | |
520 int key = (IsOn(&ch4->op[0]) | IsOn(&ch4->op[1]) | IsOn(&ch4->op[2]) | IsOn(&ch4->op[3])) ? 1 : 0; | |
521 int lfo = ch4->op[0].ms & (ch4->op[0].amon | ch4->op[1].amon | ch4->op[2].amon | ch4->op[3].amon ? 0x37 : 7) ? 2 : 0; | |
522 return key | lfo; | |
523 } | |
524 | |
525 // Clock one channel. Clocks all the Envelope Generators in parallel | |
526 // (well, okay, in sequence, but a hardware implementation *should* | |
527 // clock them in parallel as they are completely independent tasks, | |
528 // all that is important is that you don't execute Calc{L,FB,FBL} | |
529 // until all of the EGs are done clocking - but that should be, again, | |
530 // straightforward to implement in hardware). | |
531 // | |
532 int32_t Ch4Calc(Channel4 *ch4) | |
533 { | |
534 int i; | |
535 ch4->buf[1] = ch4->buf[2] = ch4->buf[3] = 0; | |
536 for(i=0; i<4; i++) { | |
537 if ((ch4->op[i].egstep -= ch4->op[i].egstepd) < 0) | |
538 EGCalc(&ch4->op[i]); | |
539 ch4->op[i].egout = LogToLin(ch4->op[i].eglevel)*gaintab[ch4->op[i].tl]; | |
540 } | |
541 | |
542 ch4->buf[0] = ch4->op[0].out; CalcFB(&ch4->op[0], ch4->fb); | |
543 ch4->buf[ch4->idx[3]] += Calc(&ch4->op[1], ch4->buf[ch4->idx[0]]); | |
544 ch4->buf[ch4->idx[4]] += Calc(&ch4->op[2], ch4->buf[ch4->idx[1]]); | |
545 int o = ch4->op[3].out; | |
546 Calc(&ch4->op[3], ch4->buf[ch4->idx[2]]); | |
547 return ((ch4->buf[ch4->idx[5]] + o) >> 8); | |
548 } | |
549 | |
550 // Same as above, but with LFO. Should see if I can merge the two somehow and just set | |
551 // a flag whenever I want to mix in Vibrato/Tremolo effects. Also, this code is basically | |
552 // completely untested, due to the surprising difficulty of finding test samples that | |
553 // actually use the chip-internal LFO. (And if you've somehow found one of those, | |
554 // now try *also* finding a good-quality recording of it being played back on the chip | |
555 // itsself. I should go ask the folks at soundshock.se or something, come to think of it). | |
556 // | |
557 int32_t Ch4CalcL(Channel4 *ch4) | |
558 { | |
559 int i; | |
560 pmv = ch4->pms[pml]; | |
561 ch4->buf[1] = ch4->buf[2] = ch4->buf[3] = 0; | |
562 for(i=0; i<4; i++) { | |
563 if ((ch4->op[i].egstep -= ch4->op[i].egstepd) < 0) | |
564 EGCalc(&ch4->op[i]); | |
565 ch4->op[i].egout = (LogToLin(ch4->op[i].eglevel + (aml >> amt[ch4->op[i].ams]))*gaintab[ch4->op[i].tl]); | |
566 } | |
567 | |
568 ch4->buf[0] = ch4->op[0].out; CalcFBL(&ch4->op[0], ch4->fb); | |
569 ch4->buf[ch4->idx[3]] += CalcL(&ch4->op[1], ch4->buf[ch4->idx[0]]); | |
570 ch4->buf[ch4->idx[4]] += CalcL(&ch4->op[2], ch4->buf[ch4->idx[1]]); | |
571 int o = ch4->op[3].out; | |
572 CalcL(&ch4->op[3], ch4->buf[ch4->idx[2]]); | |
573 return ((ch4->buf[ch4->idx[5]] + o) >> 8); | |
574 } | |
575 | |
576 // This essentially initializes a couple constant tables | |
577 // and chip-specific parameters based on what the chip clock and "DAC" samplerate | |
578 // were set to in OPNAInit(). psgrate is always equal to the user-requested samplerate, | |
579 // whereas rate is only equal to that in the interpolation=false case, otherwise | |
580 // it's set to whatever value is needed to downsample 55466Hz to the user-requested | |
581 // samplerate, which will (almost?) always be either 44100Hz or 48000Hz. | |
582 // TODO: better-quality resampling may be of use here, possibly. | |
583 // | |
584 static void SetPrescaler(OPNA *opna, uint32_t p) | |
585 { | |
586 static const char table[3][2] = { { 6, 4 }, { 3, 2 }, { 2, 1 } }; | |
587 static const uint8_t table2[8] = { 109, 78, 72, 68, 63, 45, 9, 6 }; | |
588 // 512 | |
589 if (opna->prescale != p) | |
590 { | |
591 opna->prescale = p; | |
592 uint32_t i, fmclock = opna->clock / table[p][0] / 12; | |
593 | |
594 if (opna->interpolation) { | |
595 opna->rate = fmclock * 2; | |
596 do { | |
597 opna->rate >>= 1; | |
598 opna->mpratio = opna->psgrate * 16384 / opna->rate; | |
599 } while (opna->mpratio <= 8192); | |
600 } else { | |
601 opna->rate = opna->psgrate; | |
602 } | |
603 uint32_t ratio = ((fmclock << FM_RATIOBITS) + opna->rate/2) / opna->rate; | |
604 opna->timer_step = (int32_t)(1000000.0f * 65536.0f/fmclock); | |
605 MakeTimeTable(ratio); | |
606 PSGSetClock(&opna->psg, opna->clock / table[p][1], opna->psgrate); | |
607 | |
608 for (i=0; i<8; i++) { | |
609 lfotab[i] = (ratio << (1+FM_LFOCBITS-FM_RATIOBITS)) / table2[i]; | |
610 } | |
611 } | |
612 } | |
613 | |
614 static inline void RebuildTimeTable(OPNA *opna) | |
615 { | |
616 int p = opna->prescale; | |
617 opna->prescale = -1; | |
618 SetPrescaler(opna, p); | |
619 } | |
620 | |
621 // Set volume. Just a dB->internal linear scale conversion here, nothing more. | |
622 // | |
623 void SetVolumeFM(OPNA *opna, int db) | |
624 { | |
625 db = Min(db, 20); | |
626 if (db > -192) | |
627 opna->fmvolume = lrintf(16384.0f * expf((float)M_LN10*(db / 40.0f))); | |
628 else | |
629 opna->fmvolume = 0; | |
630 } | |
631 | |
632 // Chip-internal TimerA() handler. All it does is implement CSM, i.e. | |
633 // channel 3 will get keyed on and off whenever the TimerA() interrupt fires. | |
634 // To the best of my knowledge, CSM was intended to be used to implement | |
635 // primitive formant synthesis (which Yamaha later repackaged in a much more | |
636 // elaborate and featured implementation in their FS1R), and used by | |
637 // approximately nobody. It's also been removed from the YMF288/OPN3. | |
638 // | |
639 static void TimerA(OPNA *opna) | |
640 { | |
641 int i; | |
642 if (opna->regtc & 0x80) | |
643 { | |
644 for(i=0; i<4; i++) | |
645 KeyOn(&opna->csmch->op[i]); | |
646 for(i=0; i<4; i++) | |
647 KeyOff(&opna->csmch->op[i]); | |
648 } | |
649 } | |
650 | |
651 // --------------------------------------------------------------------------- | |
652 // Clock timers. TimerA has a resolution of 9 microseconds (assuming standard | |
653 // chip clockspeed of 8MHz, which all of this code of course does), and | |
654 // on the Speak Board for the PC-9801 is used only for the purpose of sound effects. | |
655 // TimerB, on the other hand, has a resolution of 144 microseconds, and is basically | |
656 // used as the main chip clock. Also, binding "sound-effects" to TimerB (needed as | |
657 // ZUN uses the sound-effects feature to implement PSG percussion) results in tiny | |
658 // changes to the output file, precisely none of them audible, making TimerA | |
659 // all but useless in this case. Note that TimerA is also used internally in the chip | |
660 // to implement CSM-mode (see comment above). | |
661 // | |
662 uint8_t OPNATimerCount(OPNA *opna, int32_t us) | |
663 { | |
664 uint8_t event = 0; | |
665 | |
666 if (opna->timera_count) { | |
667 opna->timera_count -= us << 16; | |
668 if (opna->timera_count <= 0) { | |
669 event = 1; | |
670 TimerA(opna); | |
671 | |
672 while (opna->timera_count <= 0) | |
673 opna->timera_count += opna->timera; | |
674 | |
675 if (opna->regtc & 4) { | |
676 if (!(opna->status & 1)) { | |
677 opna->status |= 1; | |
678 } | |
679 } | |
680 } | |
681 } | |
682 if (opna->timerb_count) { | |
683 opna->timerb_count -= us << 12; | |
684 if (opna->timerb_count <= 0) { | |
685 event = 1; | |
686 while (opna->timerb_count <= 0) | |
687 opna->timerb_count += opna->timerb; | |
688 | |
689 if (opna->regtc & 8) { | |
690 if (!(opna->status & 2)) { | |
691 opna->status |= 2; | |
692 } | |
693 } | |
694 } | |
695 } | |
696 return event; | |
697 } | |
698 | |
699 // Rhythm source samples. pcm_s8 (*not* u8!), and found in rhythmdata.h, | |
700 // which is included in rhythmdata.c in order to keep the size of the | |
701 // object file that you get from compiling this file at a reasonable size, | |
702 // for debugging/testing/sanity purposes. | |
703 // | |
704 extern const unsigned char* rhythmdata[6]; | |
705 static const unsigned int rhythmdatalen[6] = { | |
706 9013, 10674, 66610, 7259, 18562, 3042 | |
707 }; | |
708 | |
709 // --------------------------------------------------------------------------- | |
710 // Main chip init routine. | |
711 // c is the chip clock, which should never be set to anything other than 8MHz. | |
712 // r is the chip samplerate, set to 44100 typically. | |
713 // ipflag - if true, ignore the value of r, clock the "DAC" at the OPNA-internal | |
714 // samplerate of 55466Hz, then downsample to whatever the actual value of r is. | |
715 // | |
716 uint8_t OPNAInit(OPNA *opna, uint c, uint r, uint8_t ipflag) | |
717 { | |
718 int i; | |
719 opna->devmask = 0x7; | |
720 opna->prescale = 0; | |
721 opna->rate = 44100; | |
722 opna->mixl = 0; | |
723 opna->mixdelta = 16383; | |
724 opna->interpolation = false; | |
725 | |
726 MakeTable(); | |
727 for (i=0; i<6; i++) { | |
728 Ch4Init(&opna->ch[i]); | |
729 opna->rhythm[i].sample = 0; | |
730 opna->rhythm[i].pos = 0; | |
731 opna->rhythm[i].size = 0; | |
732 opna->rhythm[i].volume = 0; | |
733 } | |
734 opna->rhythmtvol = 0; | |
735 opna->csmch = &opna->ch[2]; | |
736 for (i=0; i<6; i++) | |
737 opna->rhythm[i].pos = ~0; | |
738 | |
739 for (i=0; i<6; i++) | |
740 { | |
741 uint8_t *file_buf = (uint8_t*)0; | |
742 uint32_t fsize; | |
743 file_buf = (uint8_t*)rhythmdata[i]; | |
744 fsize = rhythmdatalen[i]; | |
745 file_buf += 44; | |
746 fsize -= 44; | |
747 fsize /= 2; | |
748 opna->rhythm[i].sample = (int8_t*)file_buf; | |
749 opna->rhythm[i].rate = 44100; | |
750 opna->rhythm[i].step = opna->rhythm[i].rate * 1024 / opna->rate; | |
751 opna->rhythm[i].pos = opna->rhythm[i].size = fsize * 1024; | |
752 } | |
753 | |
754 c /= 2; | |
755 opna->clock = c; | |
756 if (!OPNASetRate(opna, r, ipflag)) | |
757 return false; | |
758 RebuildTimeTable(opna); | |
759 OPNAReset(opna); | |
760 PSGInit(&opna->psg); | |
761 | |
762 SetVolumeFM(opna, 0); | |
763 SetVolumePSG(&opna->psg, 0); | |
764 OPNASetChannelMask(opna, ~0); | |
765 for (i=0; i<6; i++) | |
766 SetVolumeRhythm(opna, 0, 0); | |
767 return true; | |
768 } | |
769 | |
770 // --------------------------------------------------------------------------- | |
771 // Reset chip. Your standard routine, basically zeros everything in sight. | |
772 // | |
773 void OPNAReset(OPNA *opna) | |
774 { | |
775 int i, j; | |
776 | |
777 opna->status = 0; | |
778 SetPrescaler(opna, 0); | |
779 opna->timera_count = 0; | |
780 opna->timerb_count = 0; | |
781 PSGReset(&opna->psg); | |
782 opna->reg29 = 0x1f; | |
783 opna->rhythmkey = 0; | |
784 for (i=0x20; i<0x28; i++) OPNASetReg(opna, i, 0); | |
785 for (i=0x30; i<0xc0; i++) OPNASetReg(opna, i, 0); | |
786 for (i=0x130; i<0x1c0; i++) OPNASetReg(opna, i, 0); | |
787 for (i=0x100; i<0x110; i++) OPNASetReg(opna, i, 0); | |
788 for (i=0x10; i<0x20; i++) OPNASetReg(opna, i, 0); | |
789 for (i=0; i<6; i++) | |
790 { | |
791 opna->pan[i] = 3; | |
792 for(j=0; j<4; j++) | |
793 OperatorReset(&opna->ch[i].op[j]); | |
794 } | |
795 | |
796 opna->statusnext = 0; | |
797 opna->lfocount = 0; | |
798 opna->status = 0; | |
799 } | |
800 | |
801 // --------------------------------------------------------------------------- | |
802 // Change OPNA "DAC" samplerate. | |
803 // r and ipflag are as in OPNAInit(), above. | |
804 // | |
805 uint8_t OPNASetRate(OPNA *opna, uint r, uint8_t ipflag) | |
806 { | |
807 int i, j; | |
808 opna->interpolation = ipflag; | |
809 opna->psgrate = r; | |
810 RebuildTimeTable(opna); | |
811 opna->lfodcount = opna->reg22 & 0x08 ? lfotab[opna->reg22 & 7] : 0; | |
812 | |
813 for (i=0; i<6; i++) { | |
814 for (j=0; j<4; j++) | |
815 opna->ch[i].op[j].paramchanged = true; | |
816 } | |
817 for (i=0; i<6; i++) { | |
818 opna->rhythm[i].step = opna->rhythm[i].rate * 1024 / r; | |
819 } | |
820 return true; | |
821 } | |
822 | |
823 // --------------------------------------------------------------------------- | |
824 // Set OPNA channel mask. The 6 LSBs of mask are 0 to disable that FM channel, | |
825 // and 1 to enable it. The next 3 LSBs are passed to PSGSetChannelMask() to, | |
826 // well, set the PSG channel mask (which behaves the same way: 0 disables | |
827 // a given channel and 1 enables it). | |
828 // | |
829 void OPNASetChannelMask(OPNA *opna, uint mask) | |
830 { | |
831 int i, j; | |
832 for (i=0; i<6; i++) { | |
833 for (j=0; j<4; j++) { | |
834 opna->ch[i].op[j].mute = (!(mask & (1 << i))); | |
835 opna->ch[i].op[j].paramchanged = true; | |
836 } | |
837 } | |
838 PSGSetChannelMask(&opna->psg, (mask >> 6)); | |
839 } | |
840 | |
841 // --------------------------------------------------------------------------- | |
842 // Main OPNA register-set routine. Really long and boring switch-case. | |
843 // Basically taken directly from the manual - the only parts of the spec | |
844 // that were even the least bit tricky to implement were the f-number tables, | |
845 // everything else is basically obvious. | |
846 // | |
847 void OPNASetReg(OPNA *opna, uint addr, uint data) | |
848 { | |
849 uint j, _dp = 0; | |
850 int c = addr & 3; | |
851 switch (addr) | |
852 { | |
853 uint modified; | |
854 uint tmp; | |
855 | |
856 // Timer ----------------------------------------------------------------- | |
857 case 0x24: case 0x25: | |
858 opna->regta[addr & 1] = (uint8_t)data; | |
859 tmp = (opna->regta[0] << 2) + (opna->regta[1] & 3); | |
860 opna->timera = (1024-tmp) * opna->timer_step; | |
861 break; | |
862 | |
863 case 0x26: | |
864 opna->timerb = (256-data) * opna->timer_step; | |
865 break; | |
866 | |
867 case 0x27: | |
868 tmp = opna->regtc ^ data; | |
869 opna->regtc = (uint8_t)data; | |
870 if (data & 0x10) | |
871 opna->status &= ~1; | |
872 if (data & 0x20) | |
873 opna->status &= ~2; | |
874 if (tmp & 0x01) | |
875 opna->timera_count = (data & 1) ? opna->timera : 0; | |
876 if (tmp & 0x02) | |
877 opna->timerb_count = (data & 2) ? opna->timerb : 0; | |
878 break; | |
879 | |
880 // Misc ------------------------------------------------------------------ | |
881 case 0x28: // Key On/Off | |
882 if ((data & 3) < 3) | |
883 { | |
884 uint32_t key = (data >> 4); | |
885 c = (data & 3) + (data & 4 ? 3 : 0); | |
886 if (key & 0x1) KeyOn(&opna->ch[c].op[0]); else KeyOff(&opna->ch[c].op[0]); | |
887 if (key & 0x2) KeyOn(&opna->ch[c].op[1]); else KeyOff(&opna->ch[c].op[1]); | |
888 if (key & 0x4) KeyOn(&opna->ch[c].op[2]); else KeyOff(&opna->ch[c].op[2]); | |
889 if (key & 0x8) KeyOn(&opna->ch[c].op[3]); else KeyOff(&opna->ch[c].op[3]); | |
890 } | |
891 break; | |
892 | |
893 // Status Mask ----------------------------------------------------------- | |
894 case 0x29: | |
895 opna->reg29 = data; | |
896 break; | |
897 | |
898 // Prescaler ------------------------------------------------------------- | |
899 case 0x2d: case 0x2e: case 0x2f: | |
900 SetPrescaler(opna, (addr-0x2d)); | |
901 break; | |
902 | |
903 // F-Number -------------------------------------------------------------- | |
904 case 0x1a0: case 0x1a1: case 0x1a2: | |
905 c += 3; | |
906 case 0xa0: case 0xa1: case 0xa2: | |
907 opna->fnum[c] = data + opna->fnum2[c] * 0x100; | |
908 _dp = (opna->fnum[c] & 2047) << ((opna->fnum[c] >> 11) & 7); | |
909 for(j=0; j<4; j++) { | |
910 opna->ch[c].op[j].dp = _dp; | |
911 opna->ch[c].op[j].bn = notetab[(opna->fnum[c] >> 7) & 127]; | |
912 opna->ch[c].op[j].paramchanged = true; | |
913 } | |
914 break; | |
915 | |
916 case 0x1a4: case 0x1a5: case 0x1a6: | |
917 c += 3; | |
918 case 0xa4 : case 0xa5: case 0xa6: | |
919 opna->fnum2[c] = (uint8_t)data; | |
920 break; | |
921 | |
922 case 0xa8: case 0xa9: case 0xaa: | |
923 opna->fnum3[c] = data + opna->fnum2[c+6] * 0x100; | |
924 break; | |
925 | |
926 case 0xac : case 0xad: case 0xae: | |
927 opna->fnum2[c+6] = (uint8_t)data; | |
928 break; | |
929 | |
930 // Algorithm ------------------------------------------------------------- | |
931 case 0x1b0: case 0x1b1: case 0x1b2: | |
932 c += 3; | |
933 case 0xb0: case 0xb1: case 0xb2: | |
934 opna->ch[c].fb = fbtab[((data >> 3) & 7)]; | |
935 SetAlgorithm(&opna->ch[c], data & 7); | |
936 break; | |
937 | |
938 case 0x1b4: case 0x1b5: case 0x1b6: | |
939 c += 3; | |
940 case 0xb4: case 0xb5: case 0xb6: | |
941 opna->pan[c] = (data >> 6) & 3; | |
942 for(j=0; j<4; j++) { | |
943 opna->ch[c].op[j].ms = data; | |
944 opna->ch[c].op[j].paramchanged = true; | |
945 } | |
946 break; | |
947 | |
948 // Rhythm ---------------------------------------------------------------- | |
949 case 0x10: // DM/KEYON | |
950 if (!(data & 0x80)) // KEY ON | |
951 { | |
952 opna->rhythmkey |= data & 0x3f; | |
953 if (data & 0x01) opna->rhythm[0].pos = 0; | |
954 if (data & 0x02) opna->rhythm[1].pos = 0; | |
955 if (data & 0x04) opna->rhythm[2].pos = 0; | |
956 if (data & 0x08) opna->rhythm[3].pos = 0; | |
957 if (data & 0x10) opna->rhythm[4].pos = 0; | |
958 if (data & 0x20) opna->rhythm[5].pos = 0; | |
959 } | |
960 else | |
961 { // DUMP | |
962 opna->rhythmkey &= ~data; | |
963 } | |
964 break; | |
965 | |
966 case 0x11: | |
967 opna->rhythmtl = ~data & 63; | |
968 break; | |
969 | |
970 case 0x18: // Bass Drum | |
971 case 0x19: // Snare Drum | |
972 case 0x1a: // Top Cymbal | |
973 case 0x1b: // Hihat | |
974 case 0x1c: // Tom-tom | |
975 case 0x1d: // Rim shot | |
976 opna->rhythm[addr & 7].pan = (data >> 6) & 3; | |
977 opna->rhythm[addr & 7].level = ~data & 31; | |
978 break; | |
979 | |
980 // LFO ------------------------------------------------------------------- | |
981 case 0x22: | |
982 modified = opna->reg22 ^ data; | |
983 opna->reg22 = data; | |
984 if (modified & 0x8) | |
985 opna->lfocount = 0; | |
986 opna->lfodcount = opna->reg22 & 8 ? lfotab[opna->reg22 & 7] : 0; | |
987 break; | |
988 | |
989 // PSG ------------------------------------------------------------------- | |
990 case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: | |
991 case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: | |
992 PSGSetReg(&opna->psg, addr, data); | |
993 break; | |
994 | |
995 // ADSR ------------------------------------------------------------------ | |
996 default: | |
997 if (c < 3) | |
998 { | |
999 if (addr & 0x100) | |
1000 c += 3; | |
1001 { | |
1002 uint8_t slottable[4] = { 0, 2, 1, 3 }; | |
1003 uint32_t slot = slottable[(addr >> 2) & 3]; | |
1004 FMOperator* op = &opna->ch[c].op[slot]; | |
1005 | |
1006 switch ((addr >> 4) & 15) | |
1007 { | |
1008 case 3: // 30-3E DT/MULTI | |
1009 op->detune = (((data >> 4) & 0x07) * 0x20); | |
1010 op->multiple = (data & 0x0f); | |
1011 op->paramchanged = 1; | |
1012 break; | |
1013 | |
1014 case 4: // 40-4E TL | |
1015 if(!((opna->regtc & 0x80) && (opna->csmch == &opna->ch[c]))) { | |
1016 op->tl = (data & 0x7f); | |
1017 op->paramchanged = 1; | |
1018 } | |
1019 op->tll = (data & 0x7f); | |
1020 break; | |
1021 | |
1022 case 5: // 50-5E KS/AR | |
1023 op->ks = ((data >> 6) & 3); | |
1024 op->ar = ((data & 0x1f) * 2); | |
1025 op->paramchanged = 1; | |
1026 break; | |
1027 | |
1028 case 6: // 60-6E DR/AMON | |
1029 op->dr = ((data & 0x1f) * 2); | |
1030 op->amon = ((data & 0x80) != 0); | |
1031 op->paramchanged = 1; | |
1032 break; | |
1033 | |
1034 case 7: // 70-7E SR | |
1035 op->sr = ((data & 0x1f) * 2); | |
1036 op->paramchanged = 1; | |
1037 break; | |
1038 | |
1039 case 8: // 80-8E SL/RR | |
1040 op->sl = (((data >> 4) & 15) * 4); | |
1041 op->rr = ((data & 0x0f) * 4 + 2); | |
1042 op->paramchanged = 1; | |
1043 break; | |
1044 | |
1045 case 9: // 90-9E SSG-EC | |
1046 op->ssgtype = (data & 0x0f); | |
1047 break; | |
1048 } | |
1049 } | |
1050 } | |
1051 break; | |
1052 } | |
1053 } | |
1054 | |
1055 // --------------------------------------------------------------------------- | |
1056 // Read OPNA register. Pointless. Only SSG registers can be read, and of those | |
1057 // the only one anyone seems to be interested in reading is register 7, | |
1058 // which as I explain in detail in psg.c, is completely superfluous. | |
1059 // | |
1060 uint OPNAGetReg(OPNA *opna, uint addr) | |
1061 { | |
1062 if (addr < 0x10) | |
1063 return PSGGetReg(&opna->psg, addr); | |
1064 if (addr == 0xff) | |
1065 return 1; | |
1066 return 0; | |
1067 } | |
1068 | |
1069 // --------------------------------------------------------------------------- | |
1070 | |
1071 static inline void MixSubSL(Channel4 ch[6], int activech, int32_t *dest) | |
1072 { | |
1073 if (activech & 0x001) (*dest = Ch4CalcL(&ch[0])); | |
1074 if (activech & 0x004) (*dest += Ch4CalcL(&ch[1])); | |
1075 if (activech & 0x010) (*dest += Ch4CalcL(&ch[2])); | |
1076 if (activech & 0x040) (*dest += Ch4CalcL(&ch[3])); | |
1077 if (activech & 0x100) (*dest += Ch4CalcL(&ch[4])); | |
1078 if (activech & 0x400) (*dest += Ch4CalcL(&ch[5])); | |
1079 } | |
1080 | |
1081 static inline void MixSubS(Channel4 ch[6], int activech, int32_t *dest) | |
1082 { | |
1083 if (activech & 0x001) (*dest = Ch4Calc(&ch[0])); | |
1084 if (activech & 0x004) (*dest += Ch4Calc(&ch[1])); | |
1085 if (activech & 0x010) (*dest += Ch4Calc(&ch[2])); | |
1086 if (activech & 0x040) (*dest += Ch4Calc(&ch[3])); | |
1087 if (activech & 0x100) (*dest += Ch4Calc(&ch[4])); | |
1088 if (activech & 0x400) (*dest += Ch4Calc(&ch[5])); | |
1089 } | |
1090 | |
1091 // --------------------------------------------------------------------------- | |
1092 // Mix FM channels and output. Mix6 runs at user-specified samplerate, | |
1093 // Mix6I runs at the chip samplerate of 55466Hz and then downsamples | |
1094 // to the user-specified samplerate. It is an open problem as to determining | |
1095 // if one of these sounds better than the other. | |
1096 // | |
1097 #define IStoSample(s) ((Limit((s) >> 2, 0xffff, -0xffff) * opna->fmvolume) >> 14) | |
1098 //#define IStoSample(s) ((((s) >> 3) * fmvolume) >> 14) | |
1099 | |
1100 static void Mix6(OPNA *opna, Sample* buffer, uint32_t nsamples, int activech) | |
1101 { | |
1102 Sample* limit = buffer + nsamples; | |
1103 Sample* dest; | |
1104 // Mix | |
1105 int32_t ibuf; | |
1106 | |
1107 for (dest = buffer; dest < limit; dest+=1) | |
1108 { | |
1109 ibuf = 0; | |
1110 if (activech & 0xaaa) | |
1111 LFO(opna), MixSubSL(opna->ch, activech, &ibuf); | |
1112 else | |
1113 MixSubS(opna->ch, activech, &ibuf); | |
1114 dest[0] += IStoSample(ibuf); | |
1115 } | |
1116 } | |
1117 | |
1118 // --------------------------------------------------------------------------- | |
1119 // See comment above Mix6(), above. | |
1120 // | |
1121 static void Mix6I(OPNA *opna, Sample* buffer, uint32_t nsamples, int activech) | |
1122 { | |
1123 // Mix | |
1124 int32_t ibuf; | |
1125 | |
1126 int32_t delta = opna->mixdelta; | |
1127 Sample* limit = buffer + nsamples; | |
1128 Sample *dest; | |
1129 if (opna->mpratio < 16384) | |
1130 { | |
1131 for (dest = buffer; dest < limit; dest+=1) | |
1132 { | |
1133 int32_t l, d; | |
1134 while (delta > 0) | |
1135 { | |
1136 ibuf = 0; | |
1137 if (activech & 0xaaa) | |
1138 LFO(opna), MixSubSL(opna->ch, activech, &ibuf); | |
1139 else | |
1140 MixSubS(opna->ch, activech, &ibuf); | |
1141 | |
1142 l = IStoSample(ibuf); | |
1143 d = Min(opna->mpratio, delta); | |
1144 opna->mixl += l * d; | |
1145 delta -= opna->mpratio; | |
1146 } | |
1147 dest[0] += (opna->mixl >> 14); | |
1148 opna->mixl = l * (16384-d); | |
1149 delta += 16384; | |
1150 } | |
1151 } else { | |
1152 int impr = 16384 * 16384 / opna->mpratio; | |
1153 for (dest = buffer; dest < limit; dest+=1) | |
1154 { | |
1155 if (delta < 0) | |
1156 { | |
1157 delta += 16384; | |
1158 opna->mixl = opna->mixl1; | |
1159 | |
1160 ibuf = 0; | |
1161 if (activech & 0xaaa) | |
1162 LFO(opna), MixSubSL(opna->ch, activech, &ibuf); | |
1163 else | |
1164 MixSubS(opna->ch, activech, &ibuf); | |
1165 | |
1166 opna->mixl1 = IStoSample(ibuf); | |
1167 } | |
1168 int32_t l = (delta * opna->mixl + (16384 - delta) * opna->mixl1) / 16384; | |
1169 dest[0] += l; | |
1170 delta -= impr; | |
1171 } | |
1172 } | |
1173 opna->mixdelta = delta; | |
1174 } | |
1175 | |
1176 // --------------------------------------------------------------------------- | |
1177 // Main FM output routine. Clocks all of the operators on the chip, then mixes | |
1178 // together the output using one of Mix6() or Mix6I() above, and then outputs | |
1179 // the result to OPNAMix, which is what the calling routine will actually use. | |
1180 // buffer should be a pointer to a buffer of type Sample (int32_t in this | |
1181 // implementation, though another used float and in principle int16_t *should* | |
1182 // be sufficient), and be of size at least equal to nsamples. | |
1183 // | |
1184 static void FMMix(OPNA *opna, Sample* buffer, uint32_t nsamples) | |
1185 { | |
1186 uint j; | |
1187 if (opna->fmvolume > 0) | |
1188 { | |
1189 // Set F-Number | |
1190 if (!(opna->regtc & 0xc0)) { | |
1191 uint _dp = (opna->fnum[opna->csmch-opna->ch] & 2047) << ((opna->fnum[opna->csmch-opna->ch] >> 11) & 7); | |
1192 for(j=0; j<4; j++) { | |
1193 opna->csmch->op[j].dp = _dp; | |
1194 opna->csmch->op[j].bn = notetab[(opna->fnum[opna->csmch-opna->ch] >> 7) & 127]; | |
1195 opna->csmch->op[j].paramchanged = true; | |
1196 } | |
1197 } else { | |
1198 SetFNum(&opna->csmch->op[0], opna->fnum3[1]); SetFNum(&opna->csmch->op[1], opna->fnum3[2]); | |
1199 SetFNum(&opna->csmch->op[2], opna->fnum3[0]); SetFNum(&opna->csmch->op[3], opna->fnum[2]); | |
1200 } | |
1201 | |
1202 int act = (((Ch4Prepare(&opna->ch[2]) << 2) | Ch4Prepare(&opna->ch[1])) << 2) | Ch4Prepare(&opna->ch[0]); | |
1203 if (opna->reg29 & 0x80) | |
1204 act |= (Ch4Prepare(&opna->ch[3]) | ((Ch4Prepare(&opna->ch[4]) | (Ch4Prepare(&opna->ch[5]) << 2)) << 2)) << 6; | |
1205 if (!(opna->reg22 & 0x08)) | |
1206 act &= 0x555; | |
1207 | |
1208 if (act & 0x555) | |
1209 { | |
1210 if (opna->interpolation) | |
1211 Mix6I(opna, buffer, nsamples, act); | |
1212 else | |
1213 Mix6(opna, buffer, nsamples, act); | |
1214 } else { | |
1215 opna->mixl = 0, opna->mixdelta = 16383; | |
1216 } | |
1217 } | |
1218 } | |
1219 | |
1220 // --------------------------------------------------------------------------- | |
1221 // Mix Rhythm generator output. Boring, just takes the PCM samples, | |
1222 // multiplies them by the volume set for that rhythm sample, and then outputs | |
1223 // the appropriate length of sample for that given samplerate to buffer. | |
1224 // The same restrictions on buffer as in FMMix() above apply. | |
1225 // | |
1226 static void RhythmMix(OPNA *opna, Sample* buffer, uint32_t count) | |
1227 { | |
1228 int i; | |
1229 Sample *dest; | |
1230 if (opna->rhythmtvol < 128 && opna->rhythm[0].sample && (opna->rhythmkey & 0x3f)) | |
1231 { | |
1232 Sample* limit = buffer + count; | |
1233 for (i=0; i<6; i++) | |
1234 { | |
1235 Rhythm *r = &opna->rhythm[i]; | |
1236 if ((opna->rhythmkey & (1 << i)) && r->level >= 0) | |
1237 { | |
1238 int db = Limit(opna->rhythmtl+r->level+r->volume, 95, -31); | |
1239 int vol = tltab[FM_TLPOS + db]; | |
1240 | |
1241 for (dest = buffer; dest<limit && r->pos < r->size; dest+=1) | |
1242 { | |
1243 int sample = ((r->sample[r->pos / 1024] << 8) * vol) >> 12; | |
1244 r->pos += r->step; | |
1245 dest[0] += sample; | |
1246 } | |
1247 } | |
1248 } | |
1249 } | |
1250 } | |
1251 | |
1252 // --------------------------------------------------------------------------- | |
1253 // Main OPNA output routine. See FMMix(), RhythmMix() above and PSGMix() | |
1254 // in psg.c for details. | |
1255 // | |
1256 void OPNAMix(OPNA *opna, Sample* buffer, uint32_t nsamples) | |
1257 { | |
1258 if(opna->devmask & 1) FMMix(opna, buffer, nsamples); | |
1259 if(opna->devmask & 2) PSGMix(&opna->psg, buffer, nsamples); | |
1260 if(opna->devmask & 4) RhythmMix(opna, buffer, nsamples); | |
1261 } | |
1262 | |
1263 // --------------------------------------------------------------------------- | |
1264 // Table setup/generation routines. | |
1265 // FIXME: unify cltab/tltab and then hardcode the result, it's tiny enough | |
1266 // that we don't really need to bother with runtime init for it. | |
1267 // | |
1268 void MakeTable(void) { | |
1269 int i, j; | |
1270 if (tablemade) | |
1271 return; | |
1272 | |
1273 tablemade = true; | |
1274 for (i=-FM_TLPOS; i<FM_TLENTS-FM_TLPOS; i++) | |
1275 { | |
1276 tltab[FM_TLPOS + i] = (uint32_t)(4096.0f * expf((float)M_LN2*(i * -16.0f / FM_TLENTS)))-1; | |
1277 // LOG2("tltab[%4d] = 0x%.4x\n", i, tltab[FM_TLPOS+i]); | |
1278 } | |
1279 for (i=0; i<512; i++) | |
1280 { | |
1281 int c = (int)(((1 << 8) - 1) * expf((float)M_LN2*(-i / 64.0f))); | |
1282 #if 1 | |
1283 // ÀºÅÙÍÞÀ© | |
1284 // c += 1 << 3; | |
1285 // c &= ~1 << 3; | |
1286 for (j=16; j>11; j--) | |
1287 { | |
1288 if ((1 << j) & c) | |
1289 { | |
1290 c &= ((1 << 11) - 1) << (j - 10); | |
1291 break; | |
1292 } | |
1293 } | |
1294 #endif | |
1295 cltab[i] = c; | |
1296 // LOG2("cltab[%4d*2] = %6d\n", i, cltab[i*2]); | |
1297 } | |
1298 // 3 6, 12 30 60 240 420 / 720 | |
1299 // 1.000963 | |
1300 // lfofref[level * max * wave]; | |
1301 // pre = lfofref[level][pms * wave >> 8]; | |
1302 for (i=0; i<8; i++) | |
1303 { | |
1304 float pmb = pms[i]; | |
1305 for (j=0; j<FM_LFOENTS; j++) | |
1306 { | |
1307 pmtable[i][j] = | |
1308 (int)(0x10000 * (expf((float)M_LN2*(pmb * (2*j - FM_LFOENTS+1) / (FM_LFOENTS-1)) - 1))); | |
1309 // LOG4("pmtable[%d][%.2x] = %5d ", i, j, pmtable[i][j]); | |
1310 // LOG1(" %7.2f\n", log(1. + pmtable[i][j] / 65536.) / log(2) * 1200); | |
1311 } | |
1312 } | |
1313 } | |
1314 |