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 // ---------------------------------------------------------------------------
30 for (int i=0; i<8; i++)
37 // ---------------------------------------------------------------------------
40 bool OPM::Init(uint c, uint rf, bool ip)
42 if (!SetRate(c, rf, ip))
52 // ---------------------------------------------------------------------------
55 bool OPM::SetRate(uint c, uint r, bool)
66 // ---------------------------------------------------------------------------
67 //
\83`
\83\83\83\93\83l
\83\8b\83}
\83X
\83N
\82Ì
\90Ý
\92è
69 void OPM::SetChannelMask(uint mask)
71 for (int i=0; i<8; i++)
72 ch[i].Mute(!!(mask & (1 << i)));
75 // ---------------------------------------------------------------------------
81 for (i=0x0; i<0x100; i++) SetReg(i, 0);
94 // ---------------------------------------------------------------------------
95 //
\8a\84\82è
\8d\9e\82Ý
\90M
\8d\86\82Ì
\8eæ
\93¾
102 // ---------------------------------------------------------------------------
103 //
\90Ý
\92è
\82É
\88Ë
\91¶
\82·
\82é
\83e
\81[
\83u
\83\8b\82Ì
\8dì
\90¬
105 void OPM::RebuildTimeTable()
107 uint fmclock = clock / 64;
109 assert(fmclock < (0x80000000 >> FM_RATIOBITS));
110 rateratio = ((fmclock << FM_RATIOBITS) + rate/2) / rate;
111 SetTimerPrescaler(64);
113 // FM::MakeTimeTable(rateratio);
114 chip.SetRatio(rateratio);
119 // lfodcount = (16 + (lfofreq & 15)) << (lfofreq >> 4);
120 // lfodcount = lfodcount * rateratio >> FM_RATIOBITS;
123 // ---------------------------------------------------------------------------
124 //
\83^
\83C
\83}
\81[ A
\94
\90¶
\8e\9e\83C
\83x
\83\93\83g (CSM)
130 for (int i=0; i<8; i++)
133 ch[i].KeyControl(0xf);
138 // ---------------------------------------------------------------------------
139 //
\8a\84\82è
\8d\9e\82Ý
\90M
\8d\86\82Ì
\90Ý
\92è
141 void OPM::Intr(bool value)
146 // ---------------------------------------------------------------------------
149 void OPM::SetVolume(int db_l, int db_r)
151 db_l = Min(db_l, 20);
152 db_r = Min(db_r, 20);
155 fmvolume_l = int(16384.0 * pow(10.0, db_l / 40.0));
159 fmvolume_r = int(16384.0 * pow(10.0, db_r / 40.0));
164 // ---------------------------------------------------------------------------
165 //
\83X
\83e
\81[
\83^
\83X
\83t
\83\89\83O
\90Ý
\92è
167 void OPM::SetStatus(uint bits)
169 if (!(status & bits))
176 // ---------------------------------------------------------------------------
177 //
\83X
\83e
\81[
\83^
\83X
\83t
\83\89\83O
\89ð
\8f\9c
179 void OPM::ResetStatus(uint bits)
189 // ---------------------------------------------------------------------------
190 //
\83\8c\83W
\83X
\83^
\83A
\83\8c\83C
\82É
\83f
\81[
\83^
\82ð
\90Ý
\92è
192 void OPM::SetReg(uint addr, uint data)
200 case 0x01: // TEST (lfo restart)
204 lfo_count_prev_ = ~0;
211 ch[data & 7].KeyControl(data >> 3);
215 if (!(data & 0x08)) ch[c].op[0].KeyOff();
216 if (!(data & 0x10)) ch[c].op[1].KeyOff();
217 if (!(data & 0x20)) ch[c].op[2].KeyOff();
218 if (!(data & 0x40)) ch[c].op[3].KeyOff();
222 case 0x10: case 0x11: // CLKA1, CLKA2
223 SetTimerA(addr, data);
230 case 0x14: // CSM, TIMER
231 SetTimerControl(data);
234 case 0x18: // LFRQ(lfo freq)
237 assert(16-4-FM_RATIOBITS >= 0);
240 * ((16 + (lfofreq & 15)) << (16 - 4 - FM_RATIOBITS))
241 / (1 << (15 - (lfofreq >> 4)));
245 case 0x19: // PMD/AMD
246 (data & 0x80 ? pmd : amd) = data & 0x7f;
249 case 0x1b: // CT, W(lfo waveform)
250 lfowaveform = data & 3;
254 case 0x20: case 0x21: case 0x22: case 0x23:
255 case 0x24: case 0x25: case 0x26: case 0x27:
256 ch[c].SetFB((data >> 3) & 7);
257 ch[c].SetAlgorithm(data & 7);
258 pan[c] = (data >> 6) & 3;
262 case 0x28: case 0x29: case 0x2a: case 0x2b:
263 case 0x2c: case 0x2d: case 0x2e: case 0x2f:
265 ch[c].SetKCKF(kc[c], kf[c]);
269 case 0x30: case 0x31: case 0x32: case 0x33:
270 case 0x34: case 0x35: case 0x36: case 0x37:
272 ch[c].SetKCKF(kc[c], kf[c]);
276 case 0x38: case 0x39: case 0x3a: case 0x3b:
277 case 0x3c: case 0x3d: case 0x3e: case 0x3f:
278 ch[c].SetMS((data << 4) | (data >> 4));
281 case 0x0f: // NE/NFRQ (noise)
288 OPM::SetParameter(addr, data);
294 // ---------------------------------------------------------------------------
295 //
\83p
\83\89\83\81\81[
\83^
\83Z
\83b
\83g
297 void OPM::SetParameter(uint addr, uint data)
299 const static uint8 sltable[16] =
301 0, 4, 8, 12, 16, 20, 24, 28,
302 32, 36, 40, 44, 48, 52, 56, 124,
304 const static uint8 slottable[4] = { 0, 2, 1, 3 };
306 uint slot = slottable[(addr >> 3) & 3];
307 Operator* op = &ch[addr & 7].op[slot];
309 switch ((addr >> 5) & 7)
311 case 2: // 40-5F DT1/MULTI
312 op->SetDT((data >> 4) & 0x07);
313 op->SetMULTI(data & 0x0f);
317 op->SetTL(data & 0x7f, (regtc & 0x80) != 0);
320 case 4: // 80-9F KS/AR
321 op->SetKS((data >> 6) & 3);
322 op->SetAR((data & 0x1f) * 2);
325 case 5: // A0-BF DR/AMON(D1R/AMS-EN)
326 op->SetDR((data & 0x1f) * 2);
327 op->SetAMON((data & 0x80) != 0);
330 case 6: // C0-DF SR(D2R), DT2
331 op->SetSR((data & 0x1f) * 2);
332 op->SetDT2((data >> 6) & 3);
335 case 7: // E0-FF SL(D1L)/RR
336 op->SetSL(sltable[(data >> 4) & 15]);
337 op->SetRR((data & 0x0f) * 4 + 2);
342 // ---------------------------------------------------------------------------
345 void OPM::BuildLFOTable()
347 if (amtable[0][0] != -1)
350 for (int type=0; type<4; type++)
353 for (int c=0; c<OPM_LFOENTS; c++)
360 p = (((c + 0x100) & 0x1ff) / 2) - 0x80;
365 a = c < 0x100 ? 0xff : 0;
366 p = c < 0x100 ? 0x7f : -0x80;
370 p = (c + 0x80) & 0x1ff;
371 p = p < 0x100 ? p - 0x80 : 0x17f - p;
372 a = c < 0x100 ? 0xff - c : c - 0x100;
377 r = (rand() / 17) & 0xff;
383 amtable[type][c] = a;
384 pmtable[type][c] = -p-1;
390 // ---------------------------------------------------------------------------
392 inline void OPM::LFO()
394 if (lfowaveform != 3)
396 // if ((lfo_count_ ^ lfo_count_prev_) & ~((1 << 15) - 1))
398 int c = (lfo_count_ >> 15) & 0x1fe;
399 // fprintf(stderr, "%.8x %.2x\n", lfo_count_, c);
400 chip.SetPML(pmtable[lfowaveform][c] * pmd / 128 + 0x80);
401 chip.SetAML(amtable[lfowaveform][c] * amd / 128);
406 if ((lfo_count_ ^ lfo_count_prev_) & ~((1 << 17) - 1))
408 int c = (rand() / 17) & 0xff;
409 chip.SetPML((c - 0x80) * pmd / 128 + 0x80);
410 chip.SetAML(c * amd / 128);
413 lfo_count_prev_ = lfo_count_;
415 if ((lfo_step_ & 7) == 0)
417 lfo_count_ += lfo_count_diff_;
421 inline uint OPM::Noise()
423 noisecount += 2 * rateratio;
424 if (noisecount >= (32 << FM_RATIOBITS))
426 int n = 32 - (noisedelta & 0x1f);
430 noisecount = noisecount - (n << FM_RATIOBITS);
431 if ((noisedelta & 0x1f) == 0x1f)
432 noisecount -= FM_RATIOBITS;
433 noise = (noise >> 1) ^ (noise & 1 ? 0x8408 : 0);
438 // ---------------------------------------------------------------------------
439 //
\8d\87\90¬
\82Ì
\88ê
\95\94
441 inline void OPM::MixSub(int activech, ISample** idest)
443 if (activech & 0x4000) (*idest[0] = ch[0].Calc());
444 if (activech & 0x1000) (*idest[1] += ch[1].Calc());
445 if (activech & 0x0400) (*idest[2] += ch[2].Calc());
446 if (activech & 0x0100) (*idest[3] += ch[3].Calc());
447 if (activech & 0x0040) (*idest[4] += ch[4].Calc());
448 if (activech & 0x0010) (*idest[5] += ch[5].Calc());
449 if (activech & 0x0004) (*idest[6] += ch[6].Calc());
450 if (activech & 0x0001)
452 if (noisedelta & 0x80)
453 *idest[7] += ch[7].CalcN(Noise());
455 *idest[7] += ch[7].Calc();
459 inline void OPM::MixSubL(int activech, ISample** idest)
461 if (activech & 0x4000) (*idest[0] = ch[0].CalcL());
462 if (activech & 0x1000) (*idest[1] += ch[1].CalcL());
463 if (activech & 0x0400) (*idest[2] += ch[2].CalcL());
464 if (activech & 0x0100) (*idest[3] += ch[3].CalcL());
465 if (activech & 0x0040) (*idest[4] += ch[4].CalcL());
466 if (activech & 0x0010) (*idest[5] += ch[5].CalcL());
467 if (activech & 0x0004) (*idest[6] += ch[6].CalcL());
468 if (activech & 0x0001)
470 if (noisedelta & 0x80)
471 *idest[7] += ch[7].CalcLN(Noise());
473 *idest[7] += ch[7].CalcL();
478 // ---------------------------------------------------------------------------
479 //
\8d\87\90¬ (stereo)
481 void OPM::Mix(Sample* buffer, int nsamples)
483 #define IStoSampleL(s) ((Limit(s, 0xffff, -0x10000) * fmvolume_l) >> 14)
484 #define IStoSampleR(s) ((Limit(s, 0xffff, -0x10000) * fmvolume_r) >> 14)
485 //#define IStoSample(s) ((s * fmvolume) >> 14)
487 // odd bits - active, even bits - lfo
489 for (int i=0; i<8; i++)
490 activech = (activech << 2) | ch[i].Prepare();
492 if (activech & 0x5555)
494 // LFO
\94g
\8c`
\8f\89\8aú
\89»
\83r
\83b
\83g = 1
\82È
\82ç
\82Î LFO
\82Í
\82©
\82©
\82ç
\82È
\82¢?
501 idest[0] = &ibuf[pan[0]];
502 idest[1] = &ibuf[pan[1]];
503 idest[2] = &ibuf[pan[2]];
504 idest[3] = &ibuf[pan[3]];
505 idest[4] = &ibuf[pan[4]];
506 idest[5] = &ibuf[pan[5]];
507 idest[6] = &ibuf[pan[6]];
508 idest[7] = &ibuf[pan[7]];
510 Sample* limit = buffer + nsamples * 2;
511 for (Sample* dest = buffer; dest < limit; dest+=2)
513 ibuf[1] = ibuf[2] = ibuf[3] = 0;
514 if (activech & 0xaaaa)
515 LFO(), MixSubL(activech, idest);
517 LFO(), MixSub(activech, idest);
519 StoreSample(dest[0], IStoSampleL(ibuf[1] + ibuf[3]));
520 StoreSample(dest[1], IStoSampleR(ibuf[2] + ibuf[3]));
527 // ---------------------------------------------------------------------------
528 //
\83X
\83e
\81[
\83g
\83Z
\81[
\83u
530 #define OPM_STATE_VERSION 3
532 void OPM::SaveState(void *f)
534 FILEIO *state_fio = (FILEIO *)f;
536 state_fio->FputUint32(OPM_STATE_VERSION);
539 state_fio->FputInt32(fmvolume_l);
540 state_fio->FputInt32(fmvolume_r);
541 state_fio->FputUint32(clock);
542 state_fio->FputUint32(rate);
543 state_fio->FputUint32(pcmrate);
544 state_fio->FputUint32(pmd);
545 state_fio->FputUint32(amd);
546 state_fio->FputUint32(lfocount);
547 state_fio->FputUint32(lfodcount);
548 state_fio->FputUint32(lfo_count_);
549 state_fio->FputUint32(lfo_count_diff_);
550 state_fio->FputUint32(lfo_step_);
551 state_fio->FputUint32(lfo_count_prev_);
552 state_fio->FputUint32(lfowaveform);
553 state_fio->FputUint32(rateratio);
554 state_fio->FputUint32(noise);
555 state_fio->FputInt32(noisecount);
556 state_fio->FputUint32(noisedelta);
557 state_fio->FputBool(interpolation);
558 state_fio->FputUint8(lfofreq);
559 state_fio->FputUint8(status);
560 state_fio->FputBool(interrupt);
561 state_fio->FputUint8(reg01);
562 state_fio->Fwrite(kc, sizeof(kc), 1);
563 state_fio->Fwrite(kf, sizeof(kf), 1);
564 state_fio->Fwrite(pan, sizeof(pan), 1);
565 for(int i = 0; i < 8; i++) {
571 bool OPM::LoadState(void *f)
573 FILEIO *state_fio = (FILEIO *)f;
575 if(state_fio->FgetUint32() != OPM_STATE_VERSION) {
578 if(!Timer::LoadState(f)) {
581 fmvolume_l = state_fio->FgetInt32();
582 fmvolume_r = state_fio->FgetInt32();
583 clock = state_fio->FgetUint32();
584 rate = state_fio->FgetUint32();
585 pcmrate = state_fio->FgetUint32();
586 pmd = state_fio->FgetUint32();
587 amd = state_fio->FgetUint32();
588 lfocount = state_fio->FgetUint32();
589 lfodcount = state_fio->FgetUint32();
590 lfo_count_ = state_fio->FgetUint32();
591 lfo_count_diff_ = state_fio->FgetUint32();
592 lfo_step_ = state_fio->FgetUint32();
593 lfo_count_prev_ = state_fio->FgetUint32();
594 lfowaveform = state_fio->FgetUint32();
595 rateratio = state_fio->FgetUint32();
596 noise = state_fio->FgetUint32();
597 noisecount = state_fio->FgetInt32();
598 noisedelta = state_fio->FgetUint32();
599 interpolation = state_fio->FgetBool();
600 lfofreq = state_fio->FgetUint8();
601 status = state_fio->FgetUint8();
602 interrupt = state_fio->FgetBool();
603 reg01 = state_fio->FgetUint8();
604 state_fio->Fread(kc, sizeof(kc), 1);
605 state_fio->Fread(kf, sizeof(kf), 1);
606 state_fio->Fread(pan, sizeof(pan), 1);
607 for(int i = 0; i < 8; i++) {
608 if(!ch[i].LoadState(f)) {
612 if(!chip.LoadState(f)) {