…Show last 1390 lines
61
62#define PI2 ((float)(2.0f * PI))
63
64//Silence value?
65#define Silence 0x1FF
66
67//Sign bit, disable mask and extension to 16-bit value! 3-bits exponent and 8-bits mantissa(which becomes 10-bits during lookup of Exponential data)
68//Sign bit itself!
69#define SIGNBIT 0x8000
70//Sign mask for preventing overflow
71#define SIGNMASK 0x7FFF
72
73//Convert cents to samples to increase (instead of 1 sample/sample). Floating point number (between 0.0+ usually?) Use this as a counter for the current samples (1.1+1.1..., so keep the rest value (1,1,1,...,0,1,1,1,...))
74//The same applies to absolute and relative timecents (with absolute referring to 1 second intervals (framerate samples) and relative to the absolute value)
75#define cents2samplesfactor(cents) pow(2, ((cents) / 1200))
76//Convert to samples (not entire numbers, so keep them counted)!
77
78//extern void set_port_write_redirector (uint16_t startport, uint16_t endport, void *callback);
79//extern void set_port_read_redirector (uint16_t startport, uint16_t endport, void *callback);
80
81uint16_t baseport = 0x388; //Adlib address(w)/status(r) port, +1=Data port (write only)
82
83//Sample based information!
84DOUBLE usesamplerate = 0.0; //The sample rate to use for output!
85DOUBLE adlib_soundtick = 0.0; //The length of a sample in ns!
86//The length of a sample step:
87#ifdef IS_LONGDOUBLE
88#define adlib_sampleLength (1.0L / (14318180.0L / 288.0L))
89#else
90#define adlib_sampleLength (1.0 / (14318180.0 / 288.0))
91#endif
92
93//Counter info
94float counter80 = 0.0f, counter320 = 0.0f; //Counter ticks!
95byte timer80=0, timer320=0; //Timer variables for current timer ticks!
96
97//Registers itself
98byte adlibregmem[0xFF], adlibaddr = 0;
99
100word OPL2_ExpTable[0x100], OPL2_LogSinTable[0x100]; //The OPL2 Exponentional and Log-Sin tables!
101DOUBLE OPL2_ExponentialLookup[0x10000]; //Full exponential lookup table!
102float OPL2_ExponentialLookup2[0x10000]; //The full exponential lookup table, converted to -1 to +1 range!
103float OPL2_TremoloVibratoLookup[0x10000]; //The full tremolo/vibrato lookup table!
104word OPL2_TremoloVibratoLookupPhase[0x10000]; //The full tremolo/vibrato lookup table!
105
106byte adliboperators[2][0x10] = { //Groupings of 22 registers! (20,40,60,80,E0)
107 { 0x00, 0x01, 0x02, 0x08, 0x09, 0x0A, 0x10, 0x11, 0x12,255,255,255,255,255,255 },
108 { 0x03, 0x04, 0x05, 0x0B, 0x0C, 0x0D, 0x13, 0x14, 0x15,255,255,255,255,255,255 }
109};
110
111byte adliboperatorsreverse[0x20] = { 0, 1, 2, 0, 1, 2, 255, 255, 3, 4, 5, 3, 4, 5, 255, 255, 6, 7, 8, 6, 7, 8,255,255,255,255,255,255,255,255,255,255}; //Channel lookup of adlib operators!
112byte adliboperatorsreversekeyon[0x20] = { 1, 1, 1, 2, 2, 2, 255, 255, 1, 1, 1, 2, 2, 2, 255, 255, 1, 1, 1, 2, 2, 2,0,0,0,0,0,0,0,0,0,0}; //Modulator/carrier lookup of adlib operators in the keyon bits!
113
114static const float feedbacklookup[8] = { 0, (float)(37.5), (float)(75), (float)(150), (float)(300), (float)600, (float)(1200), (float)(1200*2.0) }; //The feedback to use from opl3emu! Seems to be half a sinus wave per number!
115float feedbacklookup2[8]; //Actual feedback lookup value!
116
117byte wavemask = 0; //Wave select mask!
118
119byte NTS; //NTS bit!
120byte CSMMode; //CSM mode enabled?
121
122SOUNDDOUBLEBUFFER adlib_soundbuffer; //Our sound buffer for rendering!
123
124#ifdef WAV_ADLIB
125WAVEFILE *adlibout = NULL;
126#endif
127
128typedef struct
129{
130 word m_fnum, m_block; //Our settings!
131 uint8_t keyon;
132 uint8_t synthmode; //What synthesizer mode (1=Additive synthesis, 0=Frequency modulation)
133 float feedback; //The feedback strength of the modulator signal.
134} ADLIBCHANNEL; //A channel!
135
136typedef struct {
137 //Effects
138 word outputlevel; //(RAW) output level!
139 word volenv; //(RAW) volume level!
140 byte m_ar, m_dr, m_sl, m_rr; //Four rates and levels!
141 uint_32 m_counter; //Counter for the volume envelope!
142 word m_env;
143 word m_ksl, m_kslAdd, m_ksr; //Various key setttings regarding pitch&envelope!
144 byte ReleaseImmediately; //Release even when the note is still turned on?
145 word m_kslAdd2; //Translated value of m_ksl!
146
147 //Volume envelope
148 uint8_t volenvstatus; //Envelope status and raw volume envelope value(0-64)
149 word gain; //The gain gotten from the volume envelopes!
150 word rawgain; //The gain without main volume control!
151
152 byte vibrato, tremolo; //Vibrato/tremolo setting for this channel. 1=Enabled, 0=Disabled.
153
154 //Signal generation
155 byte wavesel;
156 float ModulatorFrequencyMultiple; //What harmonic to sound?
157 float lastsignal[2]; //The last signal produced!
158 uint_32 phase; //Current phase calculated!
159 word increment; //Increment each sample!
160 ADLIBCHANNEL *channel;
161} ADLIBOP; //An adlib operator to process!
162
163ADLIBOP adlibop[0x20];
164
165ADLIBCHANNEL adlibch[0x10];
166
167word outputtable[0x40]; //Build using software formulas!
168
169uint8_t adlibpercussion = 0, adlibstatus = 0;
170
171uint_32 OPL2_RNGREG = 0;
172uint_32 OPL2_RNG = 0; //The current random generated sample!
173
174uint16_t adlibport = 0x388;
175
176
177//Tremolo/vibrato support
178
179typedef struct
180{
181 float time; //Current time(loops every second)!
182 float current; //Current value in absolute data!
183 word phase; //Raw phase!
184 float depth; //The depth to apply!
185 float active; //Active value, depending on tremolo/vibrato what this is: tremolo: volume to apply. vibrato: speedup to apply.
186} TREMOLOVIBRATOSIGNAL; //Tremolo&vibrato signals!
187
188TREMOLOVIBRATOSIGNAL tremolovibrato[2]; //Tremolo&vibrato!
189
190//RNG
191
192OPTINLINE void OPL2_stepRNG() //Runs at the sampling rate!
193{
194 OPL2_RNG = ( (OPL2_RNGREG) ^ (OPL2_RNGREG>>14) ^ (OPL2_RNGREG>>15) ^ (OPL2_RNGREG>>22) ) & 1; //Get the current RNG!
195 OPL2_RNGREG = (OPL2_RNG<<22) | (OPL2_RNGREG>>1);
196}
197
198OPTINLINE float calcModulatorFrequencyMultiple(byte data)
199{
200 switch (data)
201 {
202 case 0: return 0.5f;
203 case 11: return 10.0f;
204 case 13: return 12.0f;
205 case 14: return 15.0f;
206 default: return (float)data; //The same number!
207 }
208}
209
210//Attenuation setting!
211void EnvelopeGenerator_setAttennuation(ADLIBOP *operator); //Prototype!
212void EnvelopeGenerator_setAttennuationCustom(ADLIBOP *op)
213{
214 op->m_kslAdd2 = (op->m_kslAdd<<3); //Multiply with 8!
215}
216
217
218void writeadlibKeyON(byte channel, byte forcekeyon)
219{
220 byte isflipkeyon = 0; //Are we processing a low or high flipped key-on for High-hat/Cymbal? 1=Start modulator, 2=Start carrier!
221 byte ispercussionflipping = 0;
222 byte keyon;
223 byte oldkeyon;
224 keyon = ((adlibregmem[0xB0 + (channel&0xF)] >> 5) & 1)?3:0; //New key on for melodic channels? Affect both operators! This disturbs percussion mode!
225 if (adlibpercussion && (channel&0x80)) //Percussion enabled and percussion channel changed?
226 {
227 keyon = adlibregmem[0xBD]; //Total key status for percussion channels?
228 switch (channel&0xF) //What channel?
229 {
230 //Adjusted according to http://www.4front-tech.com/dmguide/dmfm.html
231 case 6: //Bass drum? Uses the channel normally!
232 keyon = (keyon&0x10)?3:0; //Bass drum on? Key on/off on both operators!
233 channel = 6; //Use channel 6!
234 break;
235 case 7: //Snare drum(Modulator)/Hi-hat(Carrier)? fmopl.c: High-hat uses modulator, Snare drum uses Carrier signals.
236 keyon = ((keyon>>3)&1)|((keyon<<1)&2); //Shift the information to modulator and carrier positions!
237 channel = 7; //Use channel 7!
238 ispercussionflipping = 1; //Enable flip key-on for modulator(High-hat)!
239 break;
240 case 8: //Tom-tom(Carrier)/Cymbal(Modulator)? fmopl.c:Tom-tom uses Modulator, Cymbal uses Carrier signals.
241 keyon = ((keyon>>2)&1)|(keyon&2); //Shift the information to modulator and carrier positions!
242 channel = 8; //Use channel 8!
243 ispercussionflipping = 2; //Enable flip key-on for carrier(Cymbal)!
244 break;
245 default: //Unknown channel?
246 //New key on for melodic channels? Don't change anything!
247 break;
248 }
249 }
250
251 oldkeyon = adlibch[channel].keyon; //Current&old key on!
252
253 nextkeyon:
254 adlibch[channel].m_block = (adlibregmem[0xB0 + channel] >> 2) & 7;
255 adlibch[channel].m_fnum = (adlibregmem[0xA0 + channel] | ((adlibregmem[0xB0 + channel] & 3) << 8)); //Frequency number!
256 if (adliboperators[0][channel] != 0xFF)
257 {
258 adlibop[adliboperators[0][channel]].increment = ((((uint_32)(adlibch[channel].m_fnum*(1.0/169.0)*(14318180.0 / 288.0))) >> (7 - adlibch[channel].m_block)) * adlibop[adliboperators[0][channel]].ModulatorFrequencyMultiple); //Calculate the effective frequency!
259 }
260 if (adliboperators[1][channel] != 0xFF)
261 {
262 adlibop[adliboperators[1][channel]].increment = ((((uint_32)(adlibch[channel].m_fnum*(1.0/169.0) * (14318180.0 / 288.0))) >> (7 - adlibch[channel].m_block)) * adlibop[adliboperators[1][channel]].ModulatorFrequencyMultiple); //Calculate the effective frequency!
263 }
264
265 if ((adliboperators[0][channel]!=0xFF) && ((((keyon&1) && ((oldkeyon^keyon)&1)) || (forcekeyon&1)) || (isflipkeyon==1))) //Key ON on operator #1 or flip starting the modulator?
266 {
267 if (adlibop[adliboperators[0][channel]&0x1F].volenvstatus==0) //Not retriggering the volume envelope?
268 {
269 adlibop[adliboperators[0][channel]&0x1F].volenv = Silence; //No raw level: Start silence!
270 adlibop[adliboperators[0][channel]&0x1F].m_env = Silence; //No raw level: Start level!
271 }
272 adlibop[adliboperators[0][channel]&0x1F].volenvstatus = 1; //Start attacking!
273 adlibop[adliboperators[0][channel]&0x1F].gain = ((adlibop[adliboperators[0][channel]].volenv)<<3); //Apply the start gain!
274 adlibop[adliboperators[0][channel]&0x1F].m_counter = 0; //No raw level: Start counter!
275 adlibop[adliboperators[0][channel]&0x1F].phase = 0; //Initialise operator signal!
276 adlibop[adliboperators[0][channel]&0x1F].lastsignal[0] = adlibop[adliboperators[1][channel]&0x1F].lastsignal[1] = 0.0f; //Reset the last signals!
277 EnvelopeGenerator_setAttennuation(&adlibop[adliboperators[0][channel]&0x1F]);
278 EnvelopeGenerator_setAttennuationCustom(&adlibop[adliboperators[0][channel]&0x1F]);
279 if (ispercussionflipping==1) //Are we flipping on this key-on?
280 {
281 ispercussionflipping = 3; //Start the other percussion flip after we're done!
282 }
283 }
284
285 //Below block is a fix for stuck notes!
286 if ((adliboperators[0][channel] != 0xFF) && (((keyon & 1) == 0) && ((oldkeyon^keyon) & 1) && ((forcekeyon & 1) == 0))) //Key OFF on operator #1?
287 {
288 if (adlibop[adliboperators[0][channel] & 0x1F].volenvstatus == 0) //Not retriggering the volume envelope?
289 {
290 adlibop[adliboperators[0][channel] & 0x1F].volenv = Silence; //No raw level: Start silence!
291 adlibop[adliboperators[0][channel] & 0x1F].m_env = Silence; //No raw level: Start level!
292 }
293 adlibop[adliboperators[0][channel] & 0x1F].volenvstatus = 4; //Start attacking!
294 adlibop[adliboperators[0][channel] & 0x1F].gain = ((adlibop[adliboperators[0][channel]].volenv) << 3); //Apply the start gain!
295 EnvelopeGenerator_setAttennuation(&adlibop[adliboperators[0][channel] & 0x1F]);
296 EnvelopeGenerator_setAttennuationCustom(&adlibop[adliboperators[0][channel] & 0x1F]);
297 }
298
299 if ((adliboperators[1][channel]!=0xFF) && ((((keyon&2) && ((oldkeyon^keyon)&2)) || (forcekeyon&2)) || (isflipkeyon==2))) //Key ON on operator #2 or flip starting the carrier?
300 {
301 if (adlibop[adliboperators[1][channel]&0x1F].volenvstatus==0) //Not retriggering the volume envelope?
302 {
303 adlibop[adliboperators[1][channel]&0x1F].volenv = Silence; //No raw level: silence!
304 adlibop[adliboperators[1][channel]&0x1F].m_env = Silence; //No raw level: Start level!
305 }
306 adlibop[adliboperators[1][channel]&0x1F].volenvstatus = 1; //Start attacking!
307 adlibop[adliboperators[1][channel]&0x1F].gain = ((adlibop[adliboperators[1][channel]].volenv)<<3); //Apply the start gain!
308 adlibop[adliboperators[1][channel]&0x1F].m_counter = 0; //No raw level: Start counter!
309 adlibop[adliboperators[1][channel]&0x1F].phase = 0; //Initialise operator signal!
310 adlibop[adliboperators[1][channel]&0x1F].lastsignal[0] = adlibop[adliboperators[1][channel]&0x1F].lastsignal[1] = 0.0f; //Reset the last signals!
311 EnvelopeGenerator_setAttennuation(&adlibop[adliboperators[1][channel]&0x1F]);
312 EnvelopeGenerator_setAttennuationCustom(&adlibop[adliboperators[1][channel]&0x1F]);
313 if (ispercussionflipping == 2) //Are we flipping on this key-on?
314 {
315 ispercussionflipping = 3; //Start the other percussion flip after we're done!
316 }
317 }
318
319 //Below block is a fix for stuck notes!
320 if ((adliboperators[1][channel] != 0xFF) && (((keyon & 2) == 0) && ((oldkeyon^keyon) & 2) && ((forcekeyon & 2) == 0))) //Key OFF on operator #1?
321 {
322 if (adlibop[adliboperators[1][channel] & 0x1F].volenvstatus == 0) //Not retriggering the volume envelope?
323 {
324 adlibop[adliboperators[1][channel] & 0x1F].volenv = Silence; //No raw level: Start silence!
325 adlibop[adliboperators[1][channel] & 0x1F].m_env = Silence; //No raw level: Start level!
326 }
327 adlibop[adliboperators[1][channel] & 0x1F].volenvstatus = 4; //Start releasing!
328 adlibop[adliboperators[1][channel] & 0x1F].gain = ((adlibop[adliboperators[1][channel]].volenv) << 3); //Apply the start gain!
329 EnvelopeGenerator_setAttennuation(&adlibop[adliboperators[1][channel] & 0x1F]);
330 EnvelopeGenerator_setAttennuationCustom(&adlibop[adliboperators[1][channel] & 0x1F]);
331 }
332
333 //Update keyon information!
334 adlibch[channel].keyon = keyon | forcekeyon; //Key is turned on?
335 if (ispercussionflipping == 3) //Flipping percussion halves?
336 {
337 forcekeyon = 0; //Don't force said key on, if so!
338 channel = (channel == 8) ? 7 : 8; //Flip the channel!
339 keyon = adlibch[channel].keyon; //The channel's actual key-on(so it doesn't detect any changes, so no strange effects)!
340 isflipkeyon = (channel == 7) ? 1 : 2; //Are we to start the modulator(0) or carrier(1) on said channel?
341 ispercussionflipping = 4; //Finish flipping afterwards!
342 goto nextkeyon;
343 }
344}
345
346void writeadlibaddr(byte value)
347{
348 adlibaddr = value; //Set the address!
349}
350
351void writeadlibdata(byte value)
352{
353 word portnum;
354 byte oldval;
355 portnum = adlibaddr;
356 oldval = adlibregmem[portnum]; //Save the old value for reference!
357 if (portnum != 4) adlibregmem[portnum] = value; //Timer control applies it itself, depending on the value!
358 switch (portnum & 0xF0) //What block to handle?
359 {
360 case 0x00:
361 switch (portnum) //What primary port?
362 {
363 case 1: //Waveform select enable
364 wavemask = (adlibregmem[1] & 0x20) ? 3 : 0; //Apply waveform mask!
365 break;
366 case 4: //timer control
367 if (value & 0x80) { //Special case: don't apply the value!
368 adlibstatus &= 0x1F; //Reset status flags needed!
369 }
370 else //Apply value to register?
371 {
372 adlibregmem[portnum] = value; //Apply the value set!
373 if (value & 1) //Timer1 enabled?
374 {
375 timer80 = adlibregmem[2]; //Reload timer!
376 }
377 if (value & 2) //Timer2 enabled?
378 {
379 timer320 = adlibregmem[3]; //Reload timer!
380 }
381 }
382 break;
383 case 8: //CSW/Note-Sel?
384 CSMMode = (adlibregmem[8] & 0x80) ? 1 : 0; //Set CSM mode!
385 NTS = (adlibregmem[8] & 0x40) ? 1 : 0; //Set NTS mode!
386 break;
387 default: //Unknown?
388 break;
389 }
390 case 0x10: //Unused?
391 break;
392 case 0x20:
393 case 0x30:
394 if (portnum <= 0x35) //Various flags
395 {
396 portnum &= 0x1F;
397 adlibop[portnum].ModulatorFrequencyMultiple = calcModulatorFrequencyMultiple(value & 0xF); //Which harmonic to use?
398 adlibop[portnum].ReleaseImmediately = (value & 0x20) ? 0 : 1; //Release when not sustain until release!
399 adlibop[portnum].m_ksr = (value >> 4) & 1; //Keyboard scaling rate!
400 EnvelopeGenerator_setAttennuation(&adlibop[portnum]); //Apply attenuation settings!
401 EnvelopeGenerator_setAttennuationCustom(&adlibop[portnum]); //Apply attenuation settings!
402 }
403 break;
404 case 0x40:
405 case 0x50:
406 if (portnum <= 0x55) //KSL/Output level
407 {
408 portnum &= 0x1F;
409 adlibop[portnum].m_ksl = ((value >> 6) & 3); //Apply KSL!
410 adlibop[portnum].outputlevel = outputtable[value & 0x3F]; //Apply raw output level!
411 EnvelopeGenerator_setAttennuation(&adlibop[portnum]); //Apply attenuation settings!
412 EnvelopeGenerator_setAttennuationCustom(&adlibop[portnum]); //Apply attenuation settings!
413 }
414 break;
415 case 0x60:
416 case 0x70:
417 if (portnum <= 0x75) { //attack/decay
418 portnum &= 0x1F;
419 adlibop[portnum].m_ar = (value >> 4); //Attack rate
420 adlibop[portnum].m_dr = (value & 0xF); //Decay rate
421 EnvelopeGenerator_setAttennuation(&adlibop[portnum]); //Apply attenuation settings!
422 EnvelopeGenerator_setAttennuationCustom(&adlibop[portnum]); //Apply attenuation settings!
423 }
424 break;
425 case 0x80:
426 case 0x90:
427 if (portnum <= 0x95) //sustain/release
428 {
429 portnum &= 0x1F;
430 adlibop[portnum].m_sl = (value >> 4); //Sustain level
431 adlibop[portnum].m_rr = (value & 0xF); //Release rate
432 EnvelopeGenerator_setAttennuation(&adlibop[portnum]); //Apply attenuation settings!
433 EnvelopeGenerator_setAttennuationCustom(&adlibop[portnum]); //Apply attenuation settings!
434 }
435 break;
436 case 0xA0:
437 case 0xB0:
438 if (portnum <= 0xB8)
439 { //octave, freq, key on
440 if ((portnum & 0xF) > 8) return; //Ignore A9-AF!
441 portnum &= 0xF; //Only take the lower nibble (the channel)!
442 writeadlibKeyON((byte)portnum, 0); //Write to this port! Don't force the key on!
443 }
444 else if (portnum == 0xBD) //Percussion settings etc.
445 {
446 adlibpercussion = (value & 0x20) ? 1 : 0; //Percussion enabled?
447 tremolovibrato[0].depth = (value & 0x80) ? 4.8f : 1.0f; //Default: 1dB AM depth, else 4.8dB!
448 tremolovibrato[1].depth = (value & 0x40) ? 14.0f : 7.0f; //Default: 7 cent vibrato depth, else 14 cents!
449 if (((oldval^value) & 0x1F) && adlibpercussion) //Percussion enabled and changed state?
450 {
451 writeadlibKeyON(0x86, 0); //Write to this port(Bass drum)! Don't force the key on!
452 writeadlibKeyON(0x87, 0); //Write to this port(Snare drum/Tom-tom)! Don't force the key on!
453 writeadlibKeyON(0x88, 0); //Write to this port(Cymbal/Hi-hat)! Don't force the key on!
454 }
455 }
456 break;
457 case 0xC0:
458 if (portnum <= 0xC8)
459 {
460 portnum &= 0xF;
461 adlibch[portnum].synthmode = (adlibregmem[0xC0 + portnum] & 1); //Save the synthesis mode!
462 byte feedback;
463 feedback = (adlibregmem[0xC0 + portnum] >> 1) & 7; //Get the feedback value used!
464 adlibch[portnum].feedback = (float)feedbacklookup2[feedback]; //Convert to a feedback of the modulator signal!
465 }
466 break;
467 case 0xE0:
468 case 0xF0:
469 if (portnum <= 0xF5) //waveform select
470 {
471 portnum &= 0x1F;
472 adlibop[portnum].wavesel = value & 3;
473 }
474 break;
475 default: //Unsupported port?
476 break;
477 }
478}
479
480byte readadlibstatus()
481{
482 return adlibstatus; //Give the current status!
483}
484
485byte outadlib (uint16_t portnum, uint8_t value) {
486 if (portnum==adlibport) {
487 writeadlibaddr(value); //Write to the address port!
488 return 1;
489 }
490 if (portnum != (adlibport+1)) return 0; //Don't handle what's not ours!
491 writeadlibdata(value); //Write to the data port!
492 return 1; //We're finished and handled, even non-used registers!
493}
494
495uint8_t inadlib (uint16_t portnum, byte *result) {
496 if (portnum == adlibport) //Status port?
497 {
498 *result = readadlibstatus(); //Give the current status!
499 return 1; //We're handled!
500 }
501 return 0; //Not our port!
502}
503
504//Native OPL2 Sinus Wave!
505OPTINLINE word OPL2SinWave(word r)
506{
507 INLINEREGISTER word index;
508 word entry; //The entry to convert!
509 INLINEREGISTER byte location; //The location in the table to use!
510 byte PIpart;
511 PIpart = 0; //Default: part 0!
512 index = r; //Default: take the index as specified!
513 index &= 0x3FF; //Loop the sinus infinitely!
514 if (index&0x200) //Second half?
515 {
516 PIpart = 2; //Second half!
517 index -= 0x200; //Convert to first half!
518 }
519 if (index&0x100) //Past quarter?
520 {
521 PIpart |= 1; //Second half!
522 index -= 0x100; //Convert to first quarter!
523 }
524 location = (byte)index; //Set the location to use!
525 if (PIpart&1) //Reversed quarter(second and fourth quarter)?
526 {
527 location = ~location; //Reverse us!
528 }
529
530 entry = OPL2_LogSinTable[location]; //Take the full load!
531 if (PIpart&2) //Second half is negative?
532 {
533 entry |= SIGNBIT; //We're negative instead, so toggle the sign bit!
534 }
535 return entry; //Give the processed entry!
536}
537
538OPTINLINE word OPL2SinWavePI(const float r)
539{
540 float index;
541 index = fmodf(r, PI2); //Loop the sinus infinitely!
542 return OPL2SinWave((word)(index*1024)); //Call the native OPL2 sinus wave function with the phase to generate!
543}
544
545word MaximumExponential = 0; //Maximum exponential input!
546
547OPTINLINE DOUBLE OPL2_Exponential_real(word v)
548{
549 //Exponential lookup also reverses the input, since it's a -logSin table!
550 //Exponent = x/256
551 //Significant = ExpTable[v%256]+1024
552 //Output = Significant * (2^Exponent)
553 DOUBLE sign;
554 #ifdef IS_LONGDOUBLE
555 sign = (v&SIGNBIT) ? -1.0L : 1.0L; //Get the sign first before removing it! Reverse the sign to create proper output!
556 #else
557 sign = (v&SIGNBIT) ? -1.0 : 1.0; //Get the sign first before removing it! Reverse the sign to create proper output!
558 #endif
559 v &= SIGNMASK; //Sign off!
560 //Reverse the range given! Input 0=Maximum volume, Input max=No output.
561 if (v>MaximumExponential) v = MaximumExponential; //Limit to the maximum value available!
562 v = MaximumExponential-v; //Reverse our range to get the correct value!
563 #ifdef IS_LONGDOUBLE
564 return sign*(DOUBLE)(OPL2_ExpTable[v & 0xFF] + 1024)*pow(2.0L, (DOUBLE)(v>>8)); //Lookup normally with the specified sign, mantissa(8 bits translated to 10 bits) and exponent(3 bits taken from the high part of the input)!
565 #else
566 return sign*(DOUBLE)(OPL2_ExpTable[v & 0xFF] + 1024)*pow(2.0, (DOUBLE)(v>>8)); //Lookup normally with the specified sign, mantissa(8 bits translated to 10 bits) and exponent(3 bits taken from the high part of the input)!
567 #endif
568}
569
570OPTINLINE float OPL2_Exponential(word v)
571{
572 return OPL2_ExponentialLookup2[v]; //Give the precalculated lookup result!
573}
574
575OPTINLINE float getOPL2TriangleWave(word v)
576{
577 return OPL2_TremoloVibratoLookup[v]; //Give the precalculated lookup result!
578}
579
580OPTINLINE word getOPL2TriangleWavePhase(word v)
581{
582 return OPL2_TremoloVibratoLookupPhase[v]; //Give the precalculated lookup result!
583}
584
585OPTINLINE void stepTremoloVibrato(TREMOLOVIBRATOSIGNAL *signal, float frequency)
586{
587 float temp, dummy;
588 word phasetemp;
589 signal->current = getOPL2TriangleWave(OPL2SinWave((float)1024*frequency*(float)signal->time)); //Apply the signal using the OPL2 Sine Wave, reverse the operation and convert to triangle wave!
590 signal->phase = getOPL2TriangleWavePhase(OPL2SinWave((float)1024 * frequency * (float)signal->time)); //Apply the signal using the OPL2 Sine Wave, reverse the operation and convert to triangle wave!
591
592 signal->time += (float)adlib_sampleLength; //Add 1 sample to the time!
593
594 temp = signal->time*frequency; //Calculate for overflow!
595 if (temp >= 1.0f) { //Overflow?
596 signal->time = modff(temp, &dummy) / frequency;
597 }
598}
599
600OPTINLINE void OPL2_stepTremoloVibrato()
601{
602 //Step to the next value!
603 stepTremoloVibrato(&tremolovibrato[0], 3.7f); //Tremolo at 3.7Hz!
604 stepTremoloVibrato(&tremolovibrato[1], 6.4f); //Vibrato at 6.4Hz!
605
606 //Now the current value of the signal is stored! Apply the active tremolo/vibrato!
607 #ifdef ADLIB_TREMOLOVIBRATO
608 tremolovibrato[0].active = (float)dB2factor(93.0f - (tremolovibrato[0].depth*tremolovibrato[0].current), 93.0f); //Calculate the current tremolo!
609 tremolovibrato[1].active = (100.0f + (tremolovibrato[1].depth*tremolovibrato[1].current))*0.01f*1024.0f; //Calculate the current vibrato!
610 #else
611 tremolovibrato[0].active = tremolovibrato[1].active = 1.0f; //No tremolo/vibrato!
612 #endif
613}
614
615OPTINLINE float OPL2_Vibrato(word phase, byte operatornumber)
616{
617 if (adlibop[operatornumber].vibrato) //Vibrato enabled?
618 {
619 return phase + (tremolovibrato[1].phase * tremolovibrato[1].active); //Apply vibrato!
620 }
621 return phase; //Unchanged frequency!
622}
623
624OPTINLINE float OPL2_Tremolo(byte operator, float f)
625{
626 if (adlibop[operator].tremolo) //Tremolo enabled?
627 {
628 return f*tremolovibrato[0].active; //Apply the current tremolo/vibrato!
629 }
630 return f; //Unchanged!
631}
632
633OPTINLINE word OPL2_Sin(byte signal, word phase) {
634 #ifdef IS_FLOATDOUBLE
635 double dummy;
636 #else
637 DOUBLE dummy;
638 #endif
639 word t;
640 word result;
641 switch (signal) {
642 case 0: //SINE?
643 return OPL2SinWave(phase); //The sinus function!
644 default:
645 t = (phase&0x3FF); //Calculate rest for special signal information!
646 switch (signal) { //What special signal?
647 case 1: // Negative=0?
648 if (t >= 0x200) return OPL2_LogSinTable[0]; //Negative=0!
649 result = OPL2SinWave(phase); //The sinus function!
650 return result; //Positive!
651 case 3: // Absolute with second half=0?
652 if (phase&0x100) return OPL2_LogSinTable[0]; //Are we the second half of the half period? Clear the signal if so!
653 case 2: // Absolute?
654 result = OPL2SinWave(phase); //The sinus function!
655 result &= ~SIGNBIT; //Ignore negative values!
656 return result; //Simply absolute!
657 default: //Unknown signal?
658 return 0;
659 }
660 }
661}
662
663OPTINLINE word calcOPL2Signal(byte wave, float phase, float operatorphase) //Calculates a signal for input to the adlib synth!
664{
665 word ftp;
666 ftp = (word)operatorphase; //Frequency!
667 ftp += (word)phase; //Apply raw phase, in raw units!
668 return OPL2_Sin(wave, ftp); //Give the generated sample!
669}
670
671OPTINLINE void incop(byte operator)
672{
673 if (operator==0xFF) return; //Invalid operator or ignoring timing increase!
674 adlibop[operator].phase += adlibop[operator].increment; //Add 1 sample to the time!
675 adlibop[operator].phase = OPL2_Vibrato(adlibop[operator].phase, operator); //Apply vibrato!
676 adlibop[operator].phase &= 0xFFFFF; //20-bit number!
677}
678
679OPTINLINE word calcModulator(float modulator)
680{
681 return (word)(modulator*1024*4); //Calculate current modulation! 4 full sinus periods range!
682}
683
684OPTINLINE word calcFeedback(byte channel, ADLIBOP *operator)
685{
686 return (word)((operator->lastsignal[0]+operator->lastsignal[1])*0.5f*adlibch[channel].feedback); //Calculate current feedback
687}
688
689//Calculate an operator signal!
690OPTINLINE float calcOperator(byte channel, byte operator, byte timingoperator, byte volenvoperator, float modulator, byte flags)
691{
692 if (operator==0xFF) return 0.0f; //Invalid operator!
693 INLINEREGISTER word result, gain; //The result to give!
694 float result2; //The translated result!
695 float activemodulation=0.0f;
696 //Generate the signal!
697 if ((flags & 0xC0)==0x80) //Apply channel feedback?
698 {
699 activemodulation = calcFeedback(channel, &adlibop[timingoperator]); //Apply this feedback signal!
700 }
701 else if ((flags&0x40)==0) //Apply normal modulation from a previous output?
702 {
703 activemodulation = calcModulator(modulator); //Use the normal modulator!
704 }
705
706 //Generate the correct signal! Ignore time by setting frequency to 0.0f(effectively disables time, keeping it stuck at 0(frequencytime))!
707 if ((flags & 0x40) == 0) //Normal signal?
708 {
709 result = calcOPL2Signal(adlibop[operator].wavesel&wavemask, activemodulation, (adlibop[operator].phase>>10)); //Take the last frequency or current frequency!
710 }
711 else //Raw input/output(don't take a normal signal)!
712 {
713 result = calcOPL2Signal(adlibop[operator].wavesel&wavemask, activemodulation, (adlibop[operator].phase>>10)); //Take the last frequency or current frequency!
714 }
715
716 //Calculate the gain!
717 gain = 0; //Init gain!
718 if (flags&2) //Special: ignore main volume control!
719 {
720 gain += outputtable[0]; //Always maximum volume, ignore the volume control!
721 }
722 else //Normal output level!
723 {
724 gain += adlibop[volenvoperator].outputlevel; //Current gain!
725 }
726 gain += adlibop[volenvoperator].gain; //Apply volume envelope and related calculations!
727 gain += adlibop[volenvoperator].m_kslAdd2; //Add KSL preprocessed!
728
729 //Now apply the gain!
730 result += gain; //Simply add the gain!
731 if (flags&8) //Double the volume?
732 {
733 result = (result&SIGNBIT)|(MIN(((result&SIGNMASK)>>1),SIGNMASK)&SIGNMASK); //Double the volume!
734 }
735 result2 = OPL2_Exponential(result); //Translate to Exponential range!
736
737 if (adlibop[timingoperator].increment && ((flags & 1) == 0)) //Running operator and allowed to update our signal?
738 {
739 adlibop[timingoperator].lastsignal[0] = adlibop[timingoperator].lastsignal[1]; //Previous last signal!
740 adlibop[timingoperator].lastsignal[1] = result2; //Set last signal #0 to #1(shift into the older one)!
741 incop(timingoperator); //Increase time for the operator when allowed to increase (frequency=0 during PCM output)!
742 }
743 result2 = OPL2_Tremolo(operator,result2); //Apply tremolo as well, after applying the new feedback signal(don't include tremolo in it)!
744 return result2; //Give the translated result!
745}
746
747float adlib_scaleFactor = 0.0f; //We're running 9 channels in a 16-bit space, so 1/9 of SHRT_MAX
748
749OPTINLINE float adlibsample(uint8_t curchan, word phase7_1, word phase8_2) {
750 byte op6_1, op6_2, op7_1, op7_2, op8_1, op8_2; //The four slots used during Drum samples!
751 word tempop_phase; //Current phase of an operator!
752 float result;
753 float immresult; //The operator result and the final result!
754 byte op1,op2; //The two operators to use!
755 curchan &= 0xF;
756 if (curchan >= NUMITEMS(adlibch)) return 0; //No sample with invalid channel!
757
758 //Determine the modulator and carrier to use!
759 op1 = adliboperators[0][curchan]; //First operator number!
760 op2 = adliboperators[1][curchan]; //Second operator number!
761 if (adlibpercussion && (curchan >= 6) && (curchan <= 8)) //We're percussion?
762 {
763 #ifndef ADLIB_RHYTHM
764 return 0.0f; //Disable percussion!
765 #else
766 INLINEREGISTER word tempphase;
767 result = 0; //Initialise the result!
768 //Calculations based on http://bisqwit.iki.fi/source/opl3emu.html fmopl.c
769 //Load our four operators for processing!
770 op6_1 = adliboperators[0][6];
771 op6_2 = adliboperators[1][6];
772 op7_1 = adliboperators[0][7];
773 op7_2 = adliboperators[1][7];
774 op8_1 = adliboperators[0][8];
775 op8_2 = adliboperators[1][8];
776 switch (curchan) //What channel?
777 {
778 case 6: //Bass drum?
779 //Generate Bass drum samples!
780 //Special on Bass Drum: Additive synthesis(Operator 1) is ignored.
781
782 //Calculate the frequency to use!
783 result = 0.0f;
784 if (adlibop[op6_2].volenvstatus) //Running?
785 {
786 result = calcOperator(6, op6_1, op6_1, op6_1, 0.0f, 0x00); //Calculate the modulator for feedback!
787
788 if (adlibch[6].synthmode) //Additive synthesis?
789 {
790 result = calcOperator(6, op6_2, op6_2, op6_2, 0.0f, 0x08); //Calculate the carrier without applied modulator additive!
791 }
792 else //FM synthesis?
793 {
794 result = calcOperator(6, op6_2, op6_2, op6_2, result, 0x08); //Calculate the carrier with applied modulator!
795 }
796 }
797
798 return result; //Apply the exponential! The volume is always doubled!
799 break;
800
801 //Comments with information from fmopl.c:
802 /* Phase generation is based on: */
803 /* HH (13) channel 7->slot 1 combined with channel 8->slot 2 (same combination as TOP CYMBAL but different output phases) */
804 /* SD (16) channel 7->slot 1 */
805 /* TOM (14) channel 8->slot 1 */
806 /* TOP (17) channel 7->slot 1 combined with channel 8->slot 2 (same combination as HIGH HAT but different output phases) */
807
808
809 /* Envelope generation based on: */
810 /* HH channel 7->slot1 */
811 /* SD channel 7->slot2 */
812 /* TOM channel 8->slot1 */
813 /* TOP channel 8->slot2 */
814 //So phase modulation is based on the Modulator signal. The volume envelope is in the Carrier signal (Hi-hat/Tom-tom) or Carrier signal().
815 case 7: //Hi-hat(Carrier)/Snare drum(Modulator)? High-hat uses modulator, Snare drum uses Carrier signals.
816 immresult = 0.0f; //Initialize immediate result!
817 if (adlibop[op7_1].volenvstatus) //Hi-hat on Modulator?
818 {
819 //Derive frequency from channel 7(modulator) and 8(carrier).
820 tempop_phase = phase7_1; //Save the phase!
821 tempphase = (tempop_phase>>2);
822 tempphase ^= (tempop_phase>>7);
823 tempphase |= (tempop_phase>>3);
824 tempphase &= 1; //Only 1 bit is used!
825 tempphase = tempphase?(0x200|(0xD0>>2)):0xD0;
826 tempop_phase = phase8_2; //Calculate the phase of channel 8 carrier signal!
827 if (((tempop_phase>>3)^(tempop_phase>>5))&1) tempphase = 0x200|(0xD0>>2);
828 if (tempphase&0x200)
829 {
830 if (OPL2_RNG) tempphase = 0x2D0;
831 }
832 else if (OPL2_RNG) tempphase = (0xD0>>2);
833 result = calcOperator(8, op8_2,op8_2,op7_1,(float)(tempphase), 0x4B); //Calculate the modulator, but only use the current time(position in the sine wave)!
834 immresult += result; //Apply the tremolo!
835 }
836 if (adlibop[op7_2].volenvstatus) //Snare drum on Carrier volume?
837 {
838 //Derive frequency from channel 0.
839 tempphase = 0x100 << ((phase7_1 >> 8) & 1); //Bit8=0(Positive) then 0x100, else 0x200! Based on the phase to generate!
840 tempphase ^= (OPL2_RNG << 8); //Noise bits XOR'es phase by 0x100 when set!
841 result = calcOperator(7, op7_2,op7_2,op7_2,(float)tempphase, 0x40); //Calculate the carrier with applied modulator!
842 immresult += result; //Apply the tremolo!
843 }
844 result = immresult; //Load the resulting channel!
845 //result *= 0.5f; //We only have half(two channels combined)!
846 return result; //Give the result, converted to short!
847 break;
848 case 8: //Tom-tom(Carrier)/Cymbal(Modulator)? Tom-tom uses Modulator, Cymbal uses Carrier signals.
849 immresult = 0.0f; //Initialize immediate result!
850 if (adlibop[op8_1].volenvstatus) //Tom-tom(Modulator)?
851 {
852 result = calcOperator(8, op8_1, op8_1, op8_1, 0.0f, 0xA); //Calculate the carrier without applied modulator additive! Ignore volume!
853 immresult += result; //Apply the exponential!
854 }
855 if (adlibop[op8_2].volenvstatus) //Cymbal(Carrier)?
856 {
857 //Derive frequency from channel 7(modulator) and 8(carrier).
858 tempop_phase = phase7_1; //Save the phase!
859 tempphase = (tempop_phase>>2);
860 tempphase ^= (tempop_phase>>7);
861 tempphase |= (tempop_phase>>3);
862 tempphase &= 1; //Only 1 bit is used!
863 tempphase <<= 9; //0x200 when 1 makes it become 0x300
864 tempphase |= 0x100; //0x100 is always!
865 tempop_phase = phase8_2; //Calculate the phase of channel 8 carrier signal!
866 if (((tempop_phase>>3)^(tempop_phase>>5))&1) tempphase = 0x300;
867
868 result = calcOperator(8, op8_2,op8_2,op8_2, (float)tempphase, 0x41); //Calculate the carrier with applied modulator! Use volume!
869 immresult += result; //Apply the exponential!
870 }
871
872 //Advance the shared percussion channel by 7-1 and 8-2!
873 result = calcOperator(7, op7_1, op7_1, op7_1, 0.0f, 0); //Calculate the modulator, but only use the current time(position in the sine wave)!
874 result = calcOperator(8, op8_2, op8_2, op8_2, 0.0f, 0); //Calculate the carrier with applied modulator! Use volume!
875
876 result = immresult; //Load the resulting channel!
877 //result *= 0.5f; //We only have half(two channels combined)!
878 return result; //Give the result, converted to short!
879 break;
880 default:
881 break;
882 }
883 #endif
884 //Not a percussion channel? Pass through!
885 }
886
887 //Operator 1!
888 //Calculate the frequency to use!
889 result = calcOperator(curchan, op1,op1,op1, 0.0f,0x80); //Calculate the modulator for feedback!
890
891 if (adlibch[curchan].synthmode) //Additive synthesis?
892 {
893 result += calcOperator(curchan, op2,op2,op2, 0.0f,0x00); //Calculate the carrier without applied modulator additive!
894 }
895 else //FM synthesis?
896 {
897 result = calcOperator(curchan, op2,op2,op2, result, 0x00); //Calculate the carrier with applied modulator!
898 }
899
900 return result; //Give the result!
901}
902
903//Timer ticks!
904
905byte ticked80_320 = 0; //80/320 ticked?
906
907OPTINLINE void tick_adlibtimer()
908{
909 if (CSMMode) //CSM enabled?
910 {
911 //Process CSM tick!
912 byte channel=0;
913 for (;;)
914 {
915 writeadlibKeyON(channel,3); //Force the key to turn on!
916 if (++channel==9) break; //Finished!
917 }
918 }
919}
920
921OPTINLINE void adlib_timer320() //Second timer!
922{
923 if (adlibregmem[4] & 2) //Timer2 enabled?
924 {
925 if (++timer320 == 0) //Overflown?
926 {
927 if ((~adlibregmem[4]) & 0x20) //Update status register?
928 {
929 adlibstatus |= 0xA0; //Update status register and set the bits!
930 }
931 timer320 = adlibregmem[3]; //Reload timer!
932 ticked80_320 = 1; //We're ticked!
933 }
934 }
935}
936
937byte ticks80 = 0; //How many timer 80 ticks have been done?
938
939OPTINLINE void adlib_timer80() //First timer!
940{
941 ticked80_320 = 0; //Default: not ticked!
942 if (adlibregmem[4] & 1) //Timer1 enabled?
943 {
944 if (++timer80 == 0) //Overflown?
945 {
946 timer80 = adlibregmem[2]; //Reload timer!
947 if ((~adlibregmem[4]) & 0x40) //Update status?
948 {
949 adlibstatus |= 0xC0; //Update status register and set the bits!
950 }
951 ticked80_320 = 1; //Ticked 320 clock!
952 }
953 }
954 if (++ticks80 == 4) //Every 4 timer 80 ticks gets 1 timer 320 tick!
955 {
956 ticks80 = 0; //Reset counter to count 320us ticks!
957 adlib_timer320(); //Execute a timer 320 tick!
958 }
959 if (ticked80_320) tick_adlibtimer(); //Tick by either timer!
960}
961
962float counter80step = 0.0f; //80us timer tick interval in samples!
963
964OPTINLINE byte adlib_channelplaying(byte channel)
965{
966 if (channel==7) //Drum channels?
967 {
968 if (adlibpercussion) //Percussion mode? Split channels!
969 {
970 return 1; //Percussion channel is always on!
971 }
972 //Melodic?
973 return adlibop[adliboperators[1][7]].volenvstatus; //Melodic, so carrier!
974 }
975 else if (channel==8) //Drum channel?
976 {
977 if (adlibpercussion) //Percussion mode? Split channels!
978 {
979 return 1; //Percussion is always on?
980 }
981 //Melodic?
982 return adlibop[adliboperators[1][8]].volenvstatus; //Melodic, so carrier!
983 }
984 else //0 - 5=Melodic, 6=Melodic, Also drum channel, but no difference here.
985 {
986 return adlibop[adliboperators[1][channel]].volenvstatus; //Melodic, so carrier!
987 }
988 return 0; //Unknown channel!
989}
990
991
992OPTINLINE float adlibgensample() {
993 float adlibaccum = 0.0f;
994 byte channel;
995 byte op7_1;
996 byte op8_2;
997 word phase7_1;
998 word phase8_2;
999 op7_1 = adliboperators[0][7];
1000 op8_2 = adliboperators[1][8];
1001 phase7_1 = (adlibop[op7_1].phase>>10); //Save the current 7_1 phase for usage in drum channels!
1002 phase8_2 = (adlibop[op8_2].phase>>10); //Save the current 8_2 phase for usage in drum channels!
1003
1004 for (channel=0;channel<9;++channel) //Process all channels!
1005 {
1006 if (adlib_channelplaying(channel)) adlibaccum += adlibsample(channel,phase7_1,phase8_2); //Sample when playing!
1007 }
1008 adlibaccum *= adlib_scaleFactor; //Scale according to volume!
1009 return adlibaccum;
1010}
1011
1012void EnvelopeGenerator_setAttennuation(ADLIBOP *operator)
1013{
1014 if( operator->m_ksl == 0 ) {
1015 operator->m_kslAdd = 0;
1016 return;
1017 }
1018
1019 if (!operator->channel) return; //Invalid channel?
1020 // 1.5 dB att. for base 2 of oct. 7
1021 // created by: round(8*log2( 10^(dbMax[msb]/10) ))+8;
1022 // verified from real chip ROM
1023 static const int kslRom[16] = {
1024 0, 32, 40, 45, 48, 51, 53, 55, 56, 58, 59, 60, 61, 62, 63, 64
1025 };
1026 // 7 negated is, by one's complement, effectively -8. To compensate this,
1027 // the ROM's values have an offset of 8.
1028 int tmp = kslRom[operator->channel->m_fnum >> 6] + 8 * ( operator->channel->m_block - 8 );
1029 if( tmp <= 0 ) {
1030 operator->m_kslAdd = 0;
1031 return;
1032 }
1033 operator->m_kslAdd = tmp;
1034 switch( operator->m_ksl ) {
1035 case 1:
1036 // 3 db
1037 operator->m_kslAdd <<= 1;
1038 break;
1039 case 2:
1040 // no change, 1.5 dB
1041 break;
1042 case 3:
1043 // 6 dB
1044 operator->m_kslAdd <<= 2;
1045 break;
1046 default:
1047 break;
1048 }
1049}
1050
1051OPTINLINE byte EnvelopeGenerator_nts(ADLIBOP *operator)
1052{
1053 return NTS; //Give the NTS bit!
1054}
1055
1056OPTINLINE uint8_t EnvelopeGenerator_calculateRate(ADLIBOP *operator, uint8_t rateValue )
1057{
1058 if (!operator->channel) return 0; //Invalid channel?
1059 if( rateValue == 0 ) {
1060 return 0;
1061 }
1062 // calculate key scale number (see NTS in the YMF262 manual)
1063 uint8_t rof = ( operator->channel->m_fnum >> ( EnvelopeGenerator_nts(operator) ? 8 : 9 ) ) & 0x1;
1064 // ...and KSR (see manual, again)
1065 rof |= operator->channel->m_block << 1;
1066 if( !operator->m_ksr ) {
1067 rof >>= 2;
1068 }
1069 // here, rof<=15
1070 // the limit of 60 results in rof=0 if rateValue=15 below
1071 return MIN( 60, rof + (rateValue << 2) );
1072}
1073
1074OPTINLINE uint8_t EnvelopeGenerator_advanceCounter(ADLIBOP *operator, uint8_t rate )
1075{
1076 if (rate >= 16 ) return 0;
1077 if( rate == 0 ) {
1078 return 0;
1079 }
1080 const uint8_t effectiveRate = EnvelopeGenerator_calculateRate(operator, rate );
1081 // rateValue <= 15
1082 const uint8_t rateValue = effectiveRate >> 2;
1083 // rof <= 3
1084 const uint8_t rof = effectiveRate & 3;
1085 // 4 <= Delta <= (7<<15)
1086 operator->m_counter += ((uint_32)(4 | rof )) << rateValue;
1087 // overflow <= 7
1088 uint8_t overflow = operator->m_counter >> 15;
1089 operator->m_counter &= ( 1 << 15 ) - 1;
1090 return overflow;
1091}
1092
1093OPTINLINE void EnvelopeGenerator_attenuate( ADLIBOP *operator,uint8_t rate )
1094{
1095 if( rate >= 64 ) return;
1096 operator->m_env += EnvelopeGenerator_advanceCounter(operator, rate );
1097 if( operator->m_env >= Silence ) {
1098 operator->m_env = Silence;
1099 }
1100}
1101
1102OPTINLINE void EnvelopeGenerator_release(ADLIBOP *operator)
1103{
1104 EnvelopeGenerator_attenuate(operator,operator->m_rr);
1105 if (operator->m_env>=Silence)
1106 {
1107 operator->m_env = Silence;
1108 operator->volenvstatus = 0; //Finished the volume envelope!
1109 }
1110}
1111
1112OPTINLINE void EnvelopeGenerator_decay(ADLIBOP *operator)
1113{
1114 if ((operator->m_env>>4)>=operator->m_sl)
1115 {
1116 operator->volenvstatus = 3; //Start sustaining!
1117 return;
1118 }
1119 EnvelopeGenerator_attenuate(operator,operator->m_dr);
1120}
1121
1122OPTINLINE void EnvelopeGenerator_attack(ADLIBOP *operator)
1123{
1124 if (operator->m_env<=0) //Nothin to attack anymore?
1125 {
1126 operator->volenvstatus = 2; //Start decaying!
1127 }
1128 else if (operator->m_ar==15)
1129 {
1130 operator->m_env = 0;
1131 }
1132 else //Attack!
1133 {
1134 if (operator->m_env<=0) return; //Abort if too high!
1135 byte overflow = EnvelopeGenerator_advanceCounter(operator,operator->m_ar); //Advance with attack rate!
1136 if (!overflow) return;
1137 operator->m_env -= ((operator->m_env*overflow)>>3)+1; //Affect envelope in a curve!
1138 }
1139}
1140
1141OPTINLINE void tickadlib()
1142{
1143 const byte maxop = NUMITEMS(adlibop); //Maximum OP count!
1144 uint8_t curop;
1145 for (curop = 0; curop < maxop; curop++)
1146 {
1147 if (!adlibop[curop].channel) continue; //Skip invalid operators!
1148 if (adlibop[curop].volenvstatus) //Are we a running envelope?
1149 {
1150 switch (adlibop[curop].volenvstatus)
1151 {
1152 case 1: //Attacking?
1153 EnvelopeGenerator_attack(&adlibop[curop]); //New method: Attack!
1154 adlibop[curop].volenv = LIMITRANGE(adlibop[curop].m_env,0,Silence); //Apply the linear curve
1155 adlibop[curop].gain = ((adlibop[curop].volenv)<<3); //Apply the start gain!
1156 break;
1157 case 2: //Decaying?
1158 EnvelopeGenerator_decay(&adlibop[curop]); //New method: Decay!
1159 if (adlibop[curop].volenvstatus==3)
1160 {
1161 goto startsustain; //Start sustaining if needed!
1162 }
1163 adlibop[curop].volenv = LIMITRANGE(adlibop[curop].m_env,0,Silence); //Apply the linear curve
1164 adlibop[curop].gain = ((adlibop[curop].volenv)<<3); //Apply the start gain!
1165 break;
1166 case 3: //Sustaining?
1167 startsustain:
1168 if (adlibop[curop].ReleaseImmediately) //Release entered?
1169 {
1170 ++adlibop[curop].volenvstatus; //Enter next phase!
1171 goto startrelease; //Check again!
1172 }
1173 adlibop[curop].volenv = LIMITRANGE(adlibop[curop].m_env,0,Silence); //Apply the linear curve
1174 adlibop[curop].gain = ((adlibop[curop].volenv)<<3); //Apply the start gain!
1175 break;
1176 case 4: //Releasing?
1177 startrelease:
1178 EnvelopeGenerator_release(&adlibop[curop]); //Release: new method!
1179 adlibop[curop].volenv = LIMITRANGE(adlibop[curop].m_env,0,Silence); //Apply the linear curve
1180 adlibop[curop].gain = ((adlibop[curop].volenv)<<3); //Apply the start gain!
1181 break;
1182 default: //Unknown volume envelope status?
1183 adlibop[curop].volenvstatus = 0; //Disable this volume envelope!
1184 break;
1185 }
1186 }
1187 }
1188}
1189
1190//Check for timer occurrences.
1191void cleanAdlib()
1192{
1193 //Discard the amount of time passed!
1194}
1195
1196//Stuff for the low-pass filter!
1197HIGHLOWPASSFILTER adlibfilter; //Output filter of the OPL2 output!
1198float opl2_currentsample; //Current sample!
1199
1200byte adlib_ticktiming80 = 0; //80us divider!
1201uint_32 adlib_ticktiming=0; //Sound timing!
1202void updateAdlib(uint_32 MHZ14passed)
1203{
1204 //Adlib sound output and counters!
1205 adlib_ticktiming += MHZ14passed; //Get the amount of time passed!
1206 if (adlib_ticktiming>=MHZ14_TICK)
1207 {
1208 do
1209 {
1210 //Adlib timer!
1211 ++adlib_ticktiming80; //Tick 80 divider!
1212 if (adlib_ticktiming80 >= TIMER80_TICK) //Enough time passed?
1213 {
1214 adlib_ticktiming80 -= TIMER80_TICK; //Tick once(never more than once!)
1215 adlib_timer80(); //Tick 80us timer!
1216 }
1217 //Now, process the samples required!
1218 OPL2_stepRNG(); //Tick the RNG!
1219 OPL2_stepTremoloVibrato(); //Step tremolo/vibrato!
1220 byte filled;
1221 float sample;
1222 filled = 0; //Default: not filled!
1223 filled |= adlib_channelplaying(0); //Channel 0?
1224 filled |= adlib_channelplaying(1); //Channel 1?
1225 filled |= adlib_channelplaying(2); //Channel 2?
1226 filled |= adlib_channelplaying(3); //Channel 3?
1227 filled |= adlib_channelplaying(4); //Channel 4?
1228 filled |= adlib_channelplaying(5); //Channel 5?
1229 filled |= adlib_channelplaying(6); //Channel 6?
1230 filled |= adlib_channelplaying(7); //Channel 7?
1231 filled |= adlib_channelplaying(8); //Channel 8?
1232 if (filled) sample = adlibgensample(); //Any sound to generate?
1233 else sample = 0.0f;
1234
1235 #ifdef ADLIB_LOWPASS
1236 opl2_currentsample = sample;
1237 //We're applying the low pass filter for the speaker!
1238 applySoundFilter(&adlibfilter, &opl2_currentsample);
1239 sample = opl2_currentsample; //Convert us back to our range!
1240 #endif
1241
1242 sample = LIMITRANGE(sample, (float)SHRT_MIN, (float)SHRT_MAX); //Clip our data to prevent overflow!
1243 #ifdef WAV_ADLIB
1244 writeWAVMonoSample(adlibout,sample); //Log the samples!
1245 #endif
1246 writeDoubleBufferedSound16(&adlib_soundbuffer,(word)sample); //Output the sample to the renderer!
1247 tickadlib(); //Tick us to the next timing if needed!
1248 adlib_ticktiming -= MHZ14_TICK; //Decrease timer to get time left!
1249 } while (adlib_ticktiming>=MHZ14_TICK);
1250 }
1251}
1252
1253byte adlib_soundGenerator(void* buf, uint_32 length, byte stereo, void *userdata) //Generate a sample!
1254{
1255 if (stereo) return 0; //We don't support stereo!
1256
1257 uint_32 c;
1258 c = length; //Init c!
1259
1260 static short last=0;
1261
1262 short *data_mono;
1263 data_mono = (short *)buf; //The data in correct samples!
1264 for (;;) //Fill it!
1265 {
1266 //Left and right samples are the same: we're a mono signal!
1267 readDoubleBufferedSound16(&adlib_soundbuffer,(word *)&last); //Generate a mono sample if it's available!
1268 *data_mono++ = last; //Load the last generated sample!
1269 if (!--c) return SOUNDHANDLER_RESULT_FILLED; //Next item!
1270 }
1271}
1272
1273//Multicall speedup!
1274#define ADLIBMULTIPLIER 0
1275
1276void initAdlib()
1277{
1278 float current; //Current values for Tremolo/Vibrato lookup table!
1279 float dummy; //Dummy value for Tremolo/Vibrato lookup!
1280 if (__HW_DISABLED) return; //Abort!
1281
1282 //Initialize our timings!
1283 adlib_scaleFactor = SHRT_MAX / (3000.0f*9.0f); //We're running 9 channels in a 16-bit space, so 1/9 of SHRT_MAX
1284 #ifdef IS_LONGDOUBLE
1285 usesamplerate = 14318180.0L / 288.0L; //The sample rate to use for output!
1286 #else
1287 usesamplerate = 14318180.0 / 288.0; //The sample rate to use for output!
1288 #endif
1289
1290 int i;
1291 for (i = 0; i < 9; i++)
1292 {
1293 memset(&adlibch[i],0,sizeof(adlibch[i])); //Initialise all channels!
1294 }
1295
1296 //Build the needed tables!
1297 for (i = 0; i < (int)NUMITEMS(outputtable); ++i)
1298 {
1299 outputtable[i] = (((word)i)<<5); //Multiply the raw value by 5 to get the actual gain: the curve is applied by the register shifted left!
1300 }
1301
1302 for (i = 0; i < (int)NUMITEMS(adlibop); i++) //Process all channels!
1303 {
1304 memset(&adlibop[i],0,sizeof(adlibop[i])); //Initialise the channel!
1305
1306 //Apply default ADSR!
1307 adlibop[i].volenvstatus = 0; //Initialise to unused ADSR!
1308 adlibop[i].ReleaseImmediately = 1; //Release immediately by default!
1309
1310 adlibop[i].outputlevel = outputtable[0]; //Apply default output!
1311 adlibop[i].ModulatorFrequencyMultiple = calcModulatorFrequencyMultiple(0); //Which harmonic to use?
1312 adlibop[i].ReleaseImmediately = 1; //We're defaulting to value being 0=>Release immediately.
1313 adlibop[i].lastsignal[0] = adlibop[i].lastsignal[1] = 0.0f; //Reset the last signals!
1314 if (adliboperatorsreverse[i]!=0xFF) //Valid operator?
1315 {
1316 adlibop[i].channel = &adlibch[adliboperatorsreverse[i]&0x1F]; //The channel this operator belongs to!
1317 }
1318 }
1319
1320 //Source of the Exp and LogSin tables: https://docs.google.com/document/d/18IGx18NQY_Q1PJVZ-bHywao9bhsDoAqoIn1rIm42nwo/edit
1321 for (i = 0;i < 0x100;++i) //Initialise the exponentional and log-sin tables!
1322 {
1323 OPL2_ExpTable[i] = (word)round((pow(2, (float)i / 256.0f) - 1.0f) * 1024.0f);
1324 OPL2_LogSinTable[i] = (word)round(-log(sin((i + 0.5f)*PI / 256.0f / 2.0f)) / log(2.0f) * 256.0f);
1325 }
1326
1327 //Find the maximum volume archievable with exponential lookups!
1328 MaximumExponential = ((0x3F << 5) + (Silence << 3)) + OPL2_LogSinTable[0]; //Highest input to the LogSin input!
1329 DOUBLE maxresult=0.0,buffer=0.0;
1330 uint_32 n;
1331 n = 0;
1332 do
1333 {
1334 buffer = OPL2_Exponential_real((word)n); //Load the current value translated!
1335 OPL2_ExponentialLookup[n] = buffer; //Store the value for fast lookup!
1336 } while (++n<0x10000); //Loop while not finished processing all possibilities!
1337
1338 maxresult = OPL2_Exponential_real(0); //Zero is maximum output to give!
1339 DOUBLE generalmodulatorfactor = 0.0f; //Modulation factor!
1340 //Now, we know the biggest result given!
1341 #ifdef IS_LONGDOUBLE
1342 generalmodulatorfactor = (1.0L/(DOUBLE)maxresult); //General modulation factor, as applied to both modulation methods!
1343 #else
1344 generalmodulatorfactor = (1.0/(DOUBLE)maxresult); //General modulation factor, as applied to both modulation methods!
1345 #endif
1346
1347 n = 0; //Loop through again for te modified table!
1348 do
1349 {
1350 buffer = OPL2_ExponentialLookup[n]; //Load the current value translated!
1351 buffer *= generalmodulatorfactor; //Apply the general modulator factor to it to convert it to -1.0 to 1.0 range!
1352 OPL2_ExponentialLookup2[n] = (float)buffer; //Store the value for fast lookup!
1353 } while (++n<0x10000); //Loop while not finished processing all possibilities!
1354
1355 adlib_scaleFactor = (((float)(SHRT_MAX))/8.0f); //Highest volume conversion Exp table(resulting mix) to SHRT_MAX (8 channels before clipping)!
1356
1357 for (i = 0;i < (int)NUMITEMS(feedbacklookup2);++i) //Process all feedback values!
1358 {
1359 feedbacklookup2[i] = feedbacklookup[i]; //Don't convert for now!
1360 }
1361
1362 for (n=0;n<(int)NUMITEMS(OPL2_TremoloVibratoLookup);++n) //Process all Tremolo/Vibrato outputs!
1363 {
1364 current = modff(asinf(OPL2_Exponential((word)n)) / (float)PI2, &dummy); //Apply the signal using the OPL2 Sine Wave, reverse the operation and convert to triangle time!
1365 current = (current < 0.5f) ? ((current * 2.0f) - 0.5f) : (0.5f - ((current - 0.5f) * 2.0f));
1366 OPL2_TremoloVibratoLookupPhase[n] = ((current > 0.5f) ? 0x200 : 0) | ((fmodf(current, 0.5f) > 0.25f) ? 0x100 : 0) | ((byte)(fmodf(current, 0.25f) * 0x100)); //The raw OPL2 phase output!
1367 OPL2_TremoloVibratoLookup[n] = current; //Set the used Tremolo/Vibrato value!
1368 }
1369
1370 memset(&tremolovibrato,0,sizeof(tremolovibrato)); //Initialise tremolo/vibrato!
1371 tremolovibrato[0].depth = 1.0f; //Default: 1dB AM depth!
1372 tremolovibrato[1].depth = 7.0f; //Default: 7 cent vibrato depth!
1373 NTS = CSMMode = 0; //Reset the global flags!
1374
1375 //RNG support!
1376 OPL2_RNGREG = OPL2_RNG = 0; //Initialise the RNG!
1377 OPL2_RNGREG = 1; //Seed the noise register to a valid value(must be non-zero)!
1378
1379 adlib_ticktiming = 0; //Reset our output timing!
1380 adlib_ticktiming80 = 0; //80us tick timing!
1381
1382 if (__SOUND_ADLIB)
1383 {
1384 if (allocDoubleBufferedSound16(__ADLIB_SAMPLEBUFFERSIZE,&adlib_soundbuffer,0,usesamplerate)) //Valid buffer?
1385 {
1386 if (!addchannel(&adlib_soundGenerator,NULL,"Adlib",(float)usesamplerate,__ADLIB_SAMPLEBUFFERSIZE,0,SMPL16S,1)) //Start the sound emulation (mono) with automatic samples buffer?
1387 {
1388 dolog("adlib","Error registering sound channel for output!");
1389 }
1390 else
1391 {
1392 setVolume(&adlib_soundGenerator,NULL,ADLIB_VOLUME);
1393 }
1394 }
1395 else
1396 {
1397 dolog("adlib","Error registering double buffer for output!");
1398 }
1399 }
1400 //Ignore unregistered channel, we need to be used by software!
1401 register_PORTIN(&inadlib); //Status port (R)
1402 //All output!
1403 register_PORTOUT(&outadlib); //Address port (W)
1404
1405 #ifdef WAV_ADLIB
1406 adlibout = createWAV("captures/adlib.wav",1,usesamplerate); //Start logging!
1407 #endif
1408
1409 #ifdef WAVE_ADLIB
1410 WAVEFILE *w;
1411 float u,f,c,es,dummyfreq0=0.0f,dummytime=0.0f;
1412 uint_32 samples;
1413 samples = (uint_32)usesamplerate; //Load the current sample rate!
1414 word s,wave;
1415 uint_32 currenttime;
1416 c = (float)(SHRT_MAX); //Conversion for Exponential results!
1417 f = (1.0/(float)usesamplerate); //Time of a wave sample!
1418
1419 w = createWAV("captures/adlibwave.wav", 1, usesamplerate); //Start logging one wave! Wave exponential test!
1420 for (wave=0;wave<4;++wave) //Log all waves!
1421 {
1422 u = 0.0; //Reset the current time!
1423 for (currenttime = 0;currenttime<samples;++currenttime) //Process all samples!
1424 {
1425 s = calcOPL2Signal(wave,1.0f,(dummytime*1024.0f)); //Get the sample(1Hz sine wave)!
1426 es = OPL2_Exponential(s); //Get the raw sample at maximum volume!
1427 es *= c; //Apply the destination factor!
1428 writeWAVMonoSample(w,(word)(LIMITRANGE((sword)es,SHRT_MIN,SHRT_MAX))); //Log 1 wave, looked up through exponential input!
1429 dummytime += f; //Add one sample to the time!
1430 }
1431 }
1432 closeWAV(&w); //Close the wave file!
1433 #endif
1434
1435 initSoundFilter(&adlibfilter,0,ADLIB_LOWPASS, (float)usesamplerate); //Initialize our low-pass filter to use!
1436}
1437
1438void doneAdlib()
1439{
1440 if (__HW_DISABLED) return; //Abort!
1441 #ifdef WAV_ADLIB
1442 closeWAV(&adlibout); //Stop logging!
1443 #endif
1444 if (__SOUND_ADLIB)
1445 {
1446 removechannel(&adlib_soundGenerator,NULL,0); //Stop the sound emulation?
1447 freeDoubleBufferedSound(&adlib_soundbuffer); //Free out double buffered sound!
1448 }
1449}