1 // ---------------------------------------------------------------------------
3 // Copyright (C) cisc 1998, 2003.
4 // ---------------------------------------------------------------------------
5 // $Id: opm.cpp,v 1.26 2003/08/25 13:53:08 cisc Exp $
12 #include "../../fileio.h"
14 //#define LOGNAME "opm"
19 int OPM::amtable[4][OPM_LFOENTS] = { -1, };
20 int OPM::pmtable[4][OPM_LFOENTS];
22 // ---------------------------------------------------------------------------
32 for (int i=0; i<8; i++)
39 // ---------------------------------------------------------------------------
42 bool OPM::Init(uint c, uint rf, bool ip)
44 if (!SetRate(c, rf, ip))
54 // ---------------------------------------------------------------------------
57 bool OPM::SetRate(uint c, uint r, bool)
68 // ---------------------------------------------------------------------------
69 //
\83`
\83\83\83\93\83l
\83\8b\83}
\83X
\83N
\82Ì
\90Ý
\92è
71 void OPM::SetChannelMask(uint mask)
73 for (int i=0; i<8; i++)
74 ch[i].Mute(!!(mask & (1 << i)));
77 // ---------------------------------------------------------------------------
83 for (i=0x0; i<0x100; i++) SetReg(i, 0);
96 // ---------------------------------------------------------------------------
97 //
\8a\84\82è
\8d\9e\82Ý
\90M
\8d\86\82Ì
\8eæ
\93¾
104 // ---------------------------------------------------------------------------
105 //
\90Ý
\92è
\82É
\88Ë
\91¶
\82·
\82é
\83e
\81[
\83u
\83\8b\82Ì
\8dì
\90¬
107 void OPM::RebuildTimeTable()
109 uint fmclock = clock / 64;
111 assert(fmclock < (0x80000000 >> FM_RATIOBITS));
112 rateratio = ((fmclock << FM_RATIOBITS) + rate/2) / rate;
113 SetTimerPrescaler(64);
115 // FM::MakeTimeTable(rateratio);
116 chip.SetRatio(rateratio);
121 // lfodcount = (16 + (lfofreq & 15)) << (lfofreq >> 4);
122 // lfodcount = lfodcount * rateratio >> FM_RATIOBITS;
125 // ---------------------------------------------------------------------------
126 //
\83^
\83C
\83}
\81[ A
\94
\90¶
\8e\9e\83C
\83x
\83\93\83g (CSM)
132 for (int i=0; i<8; i++)
135 ch[i].KeyControl(0xf);
140 // ---------------------------------------------------------------------------
141 //
\8a\84\82è
\8d\9e\82Ý
\90M
\8d\86\82Ì
\90Ý
\92è
143 void OPM::Intr(bool value)
148 // ---------------------------------------------------------------------------
151 void OPM::SetVolume(int db_l, int db_r)
153 db_l = Min(db_l, 20);
154 db_r = Min(db_r, 20);
157 fmvolume_l = int(16384.0 * pow(10.0, db_l / 40.0));
161 fmvolume_r = int(16384.0 * pow(10.0, db_r / 40.0));
166 // ---------------------------------------------------------------------------
167 //
\83X
\83e
\81[
\83^
\83X
\83t
\83\89\83O
\90Ý
\92è
169 void OPM::SetStatus(uint bits)
171 if (!(status & bits))
178 // ---------------------------------------------------------------------------
179 //
\83X
\83e
\81[
\83^
\83X
\83t
\83\89\83O
\89ð
\8f\9c
181 void OPM::ResetStatus(uint bits)
191 // ---------------------------------------------------------------------------
192 //
\83\8c\83W
\83X
\83^
\83A
\83\8c\83C
\82É
\83f
\81[
\83^
\82ð
\90Ý
\92è
194 void OPM::SetReg(uint addr, uint data)
202 case 0x01: // TEST (lfo restart)
206 lfo_count_prev_ = ~0;
213 ch[data & 7].KeyControl(data >> 3);
217 if (!(data & 0x08)) ch[c].op[0].KeyOff();
218 if (!(data & 0x10)) ch[c].op[1].KeyOff();
219 if (!(data & 0x20)) ch[c].op[2].KeyOff();
220 if (!(data & 0x40)) ch[c].op[3].KeyOff();
224 case 0x10: case 0x11: // CLKA1, CLKA2
225 SetTimerA(addr, data);
232 case 0x14: // CSM, TIMER
233 SetTimerControl(data);
236 case 0x18: // LFRQ(lfo freq)
239 assert(16-4-FM_RATIOBITS >= 0);
242 * ((16 + (lfofreq & 15)) << (16 - 4 - FM_RATIOBITS))
243 / (1 << (15 - (lfofreq >> 4)));
247 case 0x19: // PMD/AMD
248 (data & 0x80 ? pmd : amd) = data & 0x7f;
251 case 0x1b: // CT, W(lfo waveform)
252 lfowaveform = data & 3;
256 case 0x20: case 0x21: case 0x22: case 0x23:
257 case 0x24: case 0x25: case 0x26: case 0x27:
258 ch[c].SetFB((data >> 3) & 7);
259 ch[c].SetAlgorithm(data & 7);
260 pan[c] = (data >> 6) & 3;
264 case 0x28: case 0x29: case 0x2a: case 0x2b:
265 case 0x2c: case 0x2d: case 0x2e: case 0x2f:
267 ch[c].SetKCKF(kc[c], kf[c]);
271 case 0x30: case 0x31: case 0x32: case 0x33:
272 case 0x34: case 0x35: case 0x36: case 0x37:
274 ch[c].SetKCKF(kc[c], kf[c]);
278 case 0x38: case 0x39: case 0x3a: case 0x3b:
279 case 0x3c: case 0x3d: case 0x3e: case 0x3f:
280 ch[c].SetMS((data << 4) | (data >> 4));
283 case 0x0f: // NE/NFRQ (noise)
290 OPM::SetParameter(addr, data);
296 // ---------------------------------------------------------------------------
297 //
\83p
\83\89\83\81\81[
\83^
\83Z
\83b
\83g
299 void OPM::SetParameter(uint addr, uint data)
301 const static uint8 sltable[16] =
303 0, 4, 8, 12, 16, 20, 24, 28,
304 32, 36, 40, 44, 48, 52, 56, 124,
306 const static uint8 slottable[4] = { 0, 2, 1, 3 };
308 uint slot = slottable[(addr >> 3) & 3];
309 Operator* op = &ch[addr & 7].op[slot];
311 switch ((addr >> 5) & 7)
313 case 2: // 40-5F DT1/MULTI
314 op->SetDT((data >> 4) & 0x07);
315 op->SetMULTI(data & 0x0f);
319 op->SetTL(data & 0x7f, (regtc & 0x80) != 0);
322 case 4: // 80-9F KS/AR
323 op->SetKS((data >> 6) & 3);
324 op->SetAR((data & 0x1f) * 2);
327 case 5: // A0-BF DR/AMON(D1R/AMS-EN)
328 op->SetDR((data & 0x1f) * 2);
329 op->SetAMON((data & 0x80) != 0);
332 case 6: // C0-DF SR(D2R), DT2
333 op->SetSR((data & 0x1f) * 2);
334 op->SetDT2((data >> 6) & 3);
337 case 7: // E0-FF SL(D1L)/RR
338 op->SetSL(sltable[(data >> 4) & 15]);
339 op->SetRR((data & 0x0f) * 4 + 2);
344 // ---------------------------------------------------------------------------
347 void OPM::BuildLFOTable()
349 if (amtable[0][0] != -1)
352 for (int type=0; type<4; type++)
355 for (int c=0; c<OPM_LFOENTS; c++)
362 p = (((c + 0x100) & 0x1ff) / 2) - 0x80;
367 a = c < 0x100 ? 0xff : 0;
368 p = c < 0x100 ? 0x7f : -0x80;
372 p = (c + 0x80) & 0x1ff;
373 p = p < 0x100 ? p - 0x80 : 0x17f - p;
374 a = c < 0x100 ? 0xff - c : c - 0x100;
379 r = (rand() / 17) & 0xff;
385 amtable[type][c] = a;
386 pmtable[type][c] = -p-1;
392 // ---------------------------------------------------------------------------
394 inline void OPM::LFO()
396 if (lfowaveform != 3)
398 // if ((lfo_count_ ^ lfo_count_prev_) & ~((1 << 15) - 1))
400 int c = (lfo_count_ >> 15) & 0x1fe;
401 // fprintf(stderr, "%.8x %.2x\n", lfo_count_, c);
402 chip.SetPML(pmtable[lfowaveform][c] * pmd / 128 + 0x80);
403 chip.SetAML(amtable[lfowaveform][c] * amd / 128);
408 if ((lfo_count_ ^ lfo_count_prev_) & ~((1 << 17) - 1))
410 int c = (rand() / 17) & 0xff;
411 chip.SetPML((c - 0x80) * pmd / 128 + 0x80);
412 chip.SetAML(c * amd / 128);
415 lfo_count_prev_ = lfo_count_;
417 if ((lfo_step_ & 7) == 0)
419 lfo_count_ += lfo_count_diff_;
423 inline uint OPM::Noise()
425 noisecount += 2 * rateratio;
426 if (noisecount >= (32 << FM_RATIOBITS))
428 int n = 32 - (noisedelta & 0x1f);
432 noisecount = noisecount - (n << FM_RATIOBITS);
433 if ((noisedelta & 0x1f) == 0x1f)
434 noisecount -= FM_RATIOBITS;
435 noise = (noise >> 1) ^ (noise & 1 ? 0x8408 : 0);
440 // ---------------------------------------------------------------------------
441 //
\8d\87\90¬
\82Ì
\88ê
\95\94
443 inline void OPM::MixSub(int activech, ISample** idest)
445 if (activech & 0x4000) (*idest[0] = ch[0].Calc());
446 if (activech & 0x1000) (*idest[1] += ch[1].Calc());
447 if (activech & 0x0400) (*idest[2] += ch[2].Calc());
448 if (activech & 0x0100) (*idest[3] += ch[3].Calc());
449 if (activech & 0x0040) (*idest[4] += ch[4].Calc());
450 if (activech & 0x0010) (*idest[5] += ch[5].Calc());
451 if (activech & 0x0004) (*idest[6] += ch[6].Calc());
452 if (activech & 0x0001)
454 if (noisedelta & 0x80)
455 *idest[7] += ch[7].CalcN(Noise());
457 *idest[7] += ch[7].Calc();
461 inline void OPM::MixSubL(int activech, ISample** idest)
463 if (activech & 0x4000) (*idest[0] = ch[0].CalcL());
464 if (activech & 0x1000) (*idest[1] += ch[1].CalcL());
465 if (activech & 0x0400) (*idest[2] += ch[2].CalcL());
466 if (activech & 0x0100) (*idest[3] += ch[3].CalcL());
467 if (activech & 0x0040) (*idest[4] += ch[4].CalcL());
468 if (activech & 0x0010) (*idest[5] += ch[5].CalcL());
469 if (activech & 0x0004) (*idest[6] += ch[6].CalcL());
470 if (activech & 0x0001)
472 if (noisedelta & 0x80)
473 *idest[7] += ch[7].CalcLN(Noise());
475 *idest[7] += ch[7].CalcL();
480 // ---------------------------------------------------------------------------
481 //
\8d\87\90¬ (stereo)
483 void OPM::Mix(Sample* buffer, int nsamples)
485 #define IStoSampleL(s) ((Limit(s, 0xffff, -0x10000) * fmvolume_l) >> 14)
486 #define IStoSampleR(s) ((Limit(s, 0xffff, -0x10000) * fmvolume_r) >> 14)
487 //#define IStoSample(s) ((s * fmvolume) >> 14)
489 // odd bits - active, even bits - lfo
491 for (int i=0; i<8; i++)
492 activech = (activech << 2) | ch[i].Prepare();
494 if (activech & 0x5555)
496 // LFO
\94g
\8c`
\8f\89\8aú
\89»
\83r
\83b
\83g = 1
\82È
\82ç
\82Î LFO
\82Í
\82©
\82©
\82ç
\82È
\82¢?
503 idest[0] = &ibuf[pan[0]];
504 idest[1] = &ibuf[pan[1]];
505 idest[2] = &ibuf[pan[2]];
506 idest[3] = &ibuf[pan[3]];
507 idest[4] = &ibuf[pan[4]];
508 idest[5] = &ibuf[pan[5]];
509 idest[6] = &ibuf[pan[6]];
510 idest[7] = &ibuf[pan[7]];
512 Sample* limit = buffer + nsamples * 2;
513 for (Sample* dest = buffer; dest < limit; dest+=2)
515 ibuf[1] = ibuf[2] = ibuf[3] = 0;
516 if (activech & 0xaaaa)
517 LFO(), MixSubL(activech, idest);
519 LFO(), MixSub(activech, idest);
521 StoreSample(dest[0], IStoSampleL(ibuf[1] + ibuf[3]));
522 StoreSample(dest[1], IStoSampleR(ibuf[2] + ibuf[3]));
529 // ---------------------------------------------------------------------------
530 //
\83X
\83e
\81[
\83g
\83Z
\81[
\83u
532 #define OPM_STATE_VERSION 3
534 bool OPM::ProcessState(void *f, bool loading)
536 FILEIO *state_fio = (FILEIO *)f;
538 if(!state_fio->StateCheckUint32(OPM_STATE_VERSION)) {
541 if(!Timer::ProcessState(f, loading)) {
544 state_fio->StateInt32(fmvolume_l);
545 state_fio->StateInt32(fmvolume_r);
546 state_fio->StateUint32(clock);
547 state_fio->StateUint32(rate);
548 state_fio->StateUint32(pcmrate);
549 state_fio->StateUint32(pmd);
550 state_fio->StateUint32(amd);
551 state_fio->StateUint32(lfocount);
552 state_fio->StateUint32(lfodcount);
553 state_fio->StateUint32(lfo_count_);
554 state_fio->StateUint32(lfo_count_diff_);
555 state_fio->StateUint32(lfo_step_);
556 state_fio->StateUint32(lfo_count_prev_);
557 state_fio->StateUint32(lfowaveform);
558 state_fio->StateUint32(rateratio);
559 state_fio->StateUint32(noise);
560 state_fio->StateInt32(noisecount);
561 state_fio->StateUint32(noisedelta);
562 state_fio->StateBool(interpolation);
563 state_fio->StateUint8(lfofreq);
564 state_fio->StateUint8(status);
565 state_fio->StateBool(interrupt);
566 state_fio->StateUint8(reg01);
567 state_fio->StateBuffer(kc, sizeof(kc), 1);
568 state_fio->StateBuffer(kf, sizeof(kf), 1);
569 state_fio->StateBuffer(pan, sizeof(pan), 1);
570 for(int i = 0; i < 8; i++) {
571 if(!ch[i].ProcessState(f, loading)) {
575 if(!chip.ProcessState(f, loading)) {