ref: 3b70bbe366fade45f41fed2ef13b87fa675709b5
dir: /opl2.c/
#include <u.h>
#include <libc.h>
typedef char s8int;
typedef short s16int;
typedef int s32int;
typedef struct Envelope Envelope;
typedef struct Phase Phase;
typedef struct Op Op;
typedef struct Chan Chan;
enum{
Rwse = 0x01,
Mwse = 1<<5, /* wave selection enable */
Rcsm = 0x08,
Mnse = 1<<6, /* note selection enable */
Rctl = 0x20,
Mame = 1<<7, /* enable amplitude modulation */
Mvbe = 1<<6, /* enable vibrato */
Msse = 1<<5, /* enable sustain */
Mkse = 1<<4, /* enable keyboard scaling */
Mmfq = 15<<0, /* modulator freq multiple */
Rsca = 0x40,
Mlvl = 63<<0, /* total level */
Mscl = 3<<6, /* scaling level */
Ratk = 0x60,
Mdec = 15<<0, /* decay rate */
Matk = 15<<4, /* attack rate */
Rsus = 0x80,
Mrel = 15<<0, /* release rate */
Msus = 15<<4, /* sustain level */
Rnum = 0xa0, /* f number lsb */
Roct = 0xb0,
Mmsb = 3<<0, /* f number msb */
Moct = 7<<2,
Mkon = 1<<5,
Ropm = 0xbd,
Mamp = 1<<7, /* amplitude mod depth */
Mvib = 1<<6, /* vibrato depth */
Mrms = 63<<0,
Mrhy = 1<<5, /* rhythm enable */
Mbas = 1<<4,
Msna = 1<<3,
Mtom = 1<<2,
Mcym = 1<<1,
Mhat = 1<<0,
Rfed = 0xc0,
Mmod = 1<<0, /* enable operator modulation */
Mfed = 7<<1, /* feedback strength */
Rwav = 0xe0,
Mwav = 3<<0,
Sfreq = 16,
Sfreqd = Sfreq - 10,
Seg = 16,
Slfo = 24,
Stm = 16,
Mfreq = (1 << Sfreq) - 1,
Lampb = 12,
Lsignb = 2,
Ly = Lampb * Lsignb,
Lx = 256,
Lxy = Lx * Ly,
Sinb = 10,
Sinlen = 1<<Sinb,
Sinm = Sinlen - 1,
Nsines = 4,
Erstep = 8,
Equiet = Lxy >> 4,
Eb = 10,
Elen = 1 << Eb,
Nerates = 16 + 16 * 4 + 16, /* infinite, regular, dummy */
Nlfoa = 210,
Attmax = (1 << Eb-1) - 1,
Attmin = 0
};
#define Clk 3579545.0
#define Estep (128.0/Elen)
enum{
Eoff,
Erel,
Esus,
Edec,
Eatk,
};
struct Envelope{
int state;
int key;
int son;
int sus;
int atksh;
int atk;
int decsh;
int dec;
int relsh;
int rel;
int lvl0;
int lvl;
s32int vol;
u32int tl;
};
struct Phase{
u32int fq;
u32int dfq;
int fbv;
int opmodoff;
int out[2];
int *p;
};
struct Op{
Envelope;
Phase;
int Aon;
int φon;
int atkn;
int decn;
int reln;
int mul;
int scl;
int ks;
int kssh;
u16int wav;
};
struct Chan{
Op *op;
u32int scl0;
u32int dfq0;
int fn;
int oct;
int kcode;
};
static int lta[Lxy];
static uint sint[Sinlen * Nsines];
static int wse, nse, rhythm;
static u32int noise, noiseφ, noiseT;
static u32int egtic, egt, egdt, egfdt;
static u32int lfoA, lfoAt, lfoAdt, lfoφt, lfoφdt;
static s32int lfoφ;
static int lfoAd, lfoφd;
static Chan chs[9];
static Op ops[2*nelem(chs)];
static int φmod, tout;
static u32int fn[1024]; /* 20bit φ increment counter */
/* 27 output levels (triangle waveform), 1 level takes one of 192, 256 or 448
* samples. each value is repeated on 64 consecutive samples. total length is
* then 64*210 samples. when am=1 data is used directly, else it is shl 2 before
* use. */
static u8int lfoAs[Nlfoa] = {
0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5,
5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10,
11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15,
15, 15, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19,
20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 24, 24,
24, 24, 25, 25, 25, 25, 26, 26, 26, 25, 25, 25, 25, 24, 24, 24, 24, 23,
23, 23, 23, 22, 22, 22, 22, 21, 21, 21, 21, 20, 20, 20, 20, 19, 19, 19,
19, 18, 18, 18, 18, 17, 17, 17, 17, 16, 16, 16, 16, 15, 15, 15, 15, 14,
14, 14, 14, 13, 13, 13, 13, 12, 12, 12, 12, 11, 11, 11, 11, 10, 10, 10,
10, 9, 9, 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 4, 4, 4,
4, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1
};
/* 8 output 1024 samples long levels (triangle waveform) with 16 values (depth 0
* then depth 1) each */
static s8int lfoφs[8*8*2] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0,
1, 0, 0, 0, -1, 0, 0, 0, 2, 1, 0, -1, -2, -1, 0, 1,
1, 0, 0, 0, -1, 0, 0, 0, 3, 1, 0, -1, -3, -1, 0, 1,
2, 1, 0, -1, -2, -1, 0, 1, 4, 2, 0, -2, -4, -2, 0, 2,
2, 1, 0, -1, -2, -1, 0, 1, 5, 2, 0, -2, -5, -2, 0, 2,
3, 1, 0, -1, -3, -1, 0, 1, 6, 3, 0, -3, -6, -3, 0, 3,
3, 1, 0, -1, -3, -1, 0, 1, 7, 3, 0, -3, -7, -3, 0, 3
};
static uchar mul[16] = {
1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 20, 24, 24, 30, 30
};
#define O (0.1875 / 2.0) /* convert 3 dB/oct → 6 dB/oct */
static u32int lsca[8 * 16] = { /* 0.1875: bit0 weight of op->vol in dB */
0.000/O, 0.000/O, 0.000/O, 0.000/O, 0.000/O, 0.000/O, 0.000/O, 0.000/O,
0.000/O, 0.000/O, 0.000/O, 0.000/O, 0.000/O, 0.000/O, 0.000/O, 0.000/O,
0.000/O, 0.000/O, 0.000/O, 0.000/O, 0.000/O, 0.000/O, 0.000/O, 0.000/O,
0.000/O, 0.750/O, 1.125/O, 1.500/O, 1.875/O, 2.250/O, 2.625/O, 3.000/O,
0.000/O, 0.000/O, 0.000/O, 0.000/O, 0.000/O, 1.125/O, 1.875/O, 2.625/O,
3.000/O, 3.750/O, 4.125/O, 4.500/O, 4.875/O, 5.250/O, 5.625/O, 6.000/O,
0.000/O, 0.000/O, 0.000/O, 1.875/O, 3.000/O, 4.125/O, 4.875/O, 5.625/O,
6.000/O, 6.750/O, 7.125/O, 7.500/O, 7.875/O, 8.250/O, 8.625/O, 9.000/O,
0.000/O, 0.000/O, 3.000/O, 4.875/O, 6.000/O, 7.125/O, 7.875/O, 8.625/O,
9.000/O, 9.750/O, 10.125/O, 10.500/O, 10.875/O, 11.250/O, 11.625/O,
12.000/O,
0.000/O, 3.000/O, 6.000/O, 7.875/O, 9.000/O, 10.125/O, 10.875/O,
11.625/O, 12.000/O, 12.750/O, 13.125/O, 13.500/O, 13.875/O, 14.250/O,
14.625/O, 15.000/O,
0.000/O, 6.000/O, 9.000/O, 10.875/O, 12.000/O, 13.125/O, 13.875/O,
14.625/O, 15.000/O, 15.750/O, 16.125/O, 16.500/O, 16.875/O, 17.250/O,
17.625/O, 18.000/O,
0.000/O, 9.000/O, 12.000/O, 13.875/O, 15.000/O, 16.125/O, 16.875/O,
17.625/O, 18.000/O, 18.750/O, 19.125/O, 19.500/O, 19.875/O, 20.250/O,
20.625/O, 21.000/O
};
#undef O
#define O(n) (n * (2.0/Estep)) /* n*3 dB */
static u32int sust[16] = {
O(0), O(1), O(2), O(3), O(4), O(5), O(6), O(7), O(8), O(9), O(10),
O(11), O(12), O(13), O(14), O(31)
};
#undef O
static uchar estep[15*Erstep] = {
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1,
0, 1, 1, 1, 1, 1, 1, 1, /* rate 0-12 */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2,
1, 2, 2, 2, 1, 2, 2, 2, /* rate 13 */
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4,
2, 4, 4, 4, 2, 4, 4, 4, /* rate 14 */
4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, /* rate 15 + atk */
0, 0, 0, 0, 0, 0, 0, 0, /* rate ∞ (atk/dec) */
};
#define O(n) (n * Erstep)
static uchar erate[Nerates] = { /* O(13) is directly in code */
O(14), O(14), O(14), O(14), O(14), O(14), O(14), O(14), O(14), O(14),
O(14), O(14), O(14), O(14), O(14), O(14), O(0), O(1), O(2), O(3), O(0),
O(1), O(2), O(3), O(0), O(1), O(2), O(3), O(0), O(1), O(2), O(3), O(0),
O(1), O(2), O(3), O(0), O(1), O(2), O(3), O(0), O(1), O(2), O(3), O(0),
O(1), O(2), O(3), O(0), O(1), O(2), O(3), O(0), O(1), O(2), O(3), O(0),
O(1), O(2), O(3), O(0), O(1), O(2), O(3), O(0), O(1), O(2), O(3), O(4),
O(5), O(6), O(7), O(8), O(9), O(10), O(11), O(12), O(12), O(12), O(12),
O(12), O(12), O(12), O(12), O(12), O(12), O(12), O(12), O(12), O(12),
O(12), O(12), O(12), O(12), O(12), O(12)
};
#undef O
static uchar eratesh[Nerates] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 12, 12, 11, 11,
11, 11, 10, 10, 10, 10, 9, 9, 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6,
5, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0
};
/* 23-bit shift register noise generator. T=2²³-2 samples, sampling rate equal
* to that of the chip. */
static void
noiseg(void)
{
int i;
noiseφ += noiseT;
i = noiseφ >> Sfreq;
noiseφ &= Mfreq;
while(i-- > 0){
if(noise & 1)
noise ^= 0x800302;
noise >>= 1;
}
}
static void
advlfo(void)
{
int a;
lfoAt += lfoAdt;
if(lfoAt >= (u32int)Nlfoa << Slfo)
lfoAt -= (u32int)Nlfoa << Slfo;
a = lfoAs[lfoAt >> Slfo];
lfoA = lfoAd ? a : a>>2;
lfoφt += lfoφdt;
lfoφ = lfoφt >> Slfo & 7 | lfoφd;
}
static void
adv(void)
{
int i, f, oc, v;
Chan *c;
Op *o;
egt += egfdt;
while(egt >= egdt){
egt -= egdt;
egtic++;
o = ops;
while(o < ops + nelem(ops)){
switch(o->state){
case Eatk:
if(egtic & (1 << o->atksh)-1)
break;
v = o->atk + (egtic >> o->atksh & 7);
/* sign extend it */
o->vol += (s32int)(~o->vol * estep[v]) >> 3;
if(o->vol <= Attmin){
o->vol = Attmin;
o->state = Edec;
}
break;
case Edec:
if(egtic & (1 << o->decsh)-1)
break;
v = o->dec + (egtic >> o->decsh & 7);
o->vol += estep[v];
if(o->vol >= o->sus)
o->state = Esus;
break;
case Esus:
if(o->son || egtic & (1 << o->relsh)-1)
break;
v = o->rel + (egtic >> o->relsh & 7);
o->vol += estep[v];
if(o->vol >= Attmax)
o->vol = Attmax;
break;
case Erel:
if(egtic & (1 << o->relsh)-1)
break;
v = o->rel + (egtic >> o->relsh & 7);
o->vol += estep[v];
if(o->vol >= Attmax){
o->vol = Attmax;
o->state = Eoff;
}
break;
}
o++;
}
}
o = ops;
while(o < ops + nelem(ops)){
c = chs + (o-ops)/2;
if(o->φon){
f = c->fn;
i = lfoφs[lfoφ + (f >> 7 << 4)];
if(i != 0){
f += i;
oc = 7 - c->oct + (f >> 10);
o->fq += (fn[f & 0x3ff] >> oc) * o->mul;
}else
o->fq += o->dfq;
}else
o->fq += o->dfq;
o++;
}
noiseg();
}
static int
op(u32int φ, u32int v, int dφ, u16int w)
{
u32int p;
p = (v<<4) + sint[w + ((int)((φ & ~Mfreq) + dφ) >> Sfreq & Sinm)];
return p < Lxy ? lta[p] : 0;
}
static void
chan(Op *o)
{
u32int v;
int out;
φmod = 0;
out = o->out[0] + o->out[1];
o->out[0] = o->out[1];
*o->p += o->out[0];
o->out[1] = 0;
v = o->tl;
if(v < Equiet){
if(o->fbv == 0)
out = 0;
o->out[1] = op(o->fq, v, out << o->fbv, o->wav);
}
o++, v = o->tl;
if(v < Equiet)
tout += op(o->fq, v, φmod << 16, o->wav);
}
static void
rchan(void)
{
int out, nr;
u32int u, v;
Op *o;
nr = noise & 1;
φmod = 0;
o = chs[6].op;
out = o->out[0] + o->out[1];
o->out[0] = o->out[1];
if(o->opmodoff == 0)
φmod = o->out[0];
o->out[1] = 0;
v = o->tl;
if(v < Equiet){
if(o->fbv == 0)
out = 0;
o->out[1] = op(o->fq, v, out << o->fbv, o->wav);
}
o++, v = o->tl;
if(v < Equiet)
tout += op(o->fq, v, φmod << 16, o->wav) * 2;
o++, v = o->tl;
if(v < Equiet){
u = ops[17].fq >> Sfreq;
if((u ^ u<<2) & 1<<5)
u = 0x200 | 0xd0 >> 2;
else{
u = o->fq >> Sfreq;
u = ((u ^ u<<5 | u<<4) & 1<<7) ? 0x200 | 0xd0>>2 : 0xd0;
}
if(nr)
u = u & 0x200 ? 0x200 | 0xd0 : 0xd0>>2;
tout += op(u << Sfreq, v, 0, o->wav) * 2;
}
o++, v = o->tl;
if(v < Equiet){
u = (ops[14].fq >> Sfreq & 1<<8) ? 1<<9 : 1<<8;
u = (u ^ nr << 8) << Sfreq;
tout += op(u, v, 0, o->wav) * 2;
}
o++, v = o->tl;
if(v < Equiet)
tout += op(o->fq, v, 0, o->wav) * 2;
o++, v = o->tl;
if(v < Equiet){
u = o->fq >> Sfreq;
if((u ^ u<<2) & 1<<5)
u = 0x300;
else{
u = ops[14].fq >> Sfreq;
u = ((u ^ u<<5 | u<<4) & 1<<7) ? 0x300 : 0x100;
}
tout += op(u << Sfreq, v, 0, o->wav) * 2;
}
}
static void
setk(Op *o, int k, int on)
{
if(on){
if(o->key == 0){
o->fq = 0;
o->state = Eatk;
}
o->key |= k;
}else{
if(o->key == 0)
return;
o->key &= ~k;
if(o->key == 0 && o->state > Erel)
o->state = Erel;
}
}
static void
upop(Chan *c, Op *o)
{
int n;
o->dfq = c->dfq0 * o->mul;
n = c->kcode >> o->kssh;
if(o->ks != n){
o->ks = n;
if(o->atkn + n < 16+62){
o->atksh = eratesh[o->atkn + n];
o->atk = erate[o->atkn + n];
}else{
o->atksh = 0;
o->atk = 13 * Erstep;
}
o->decsh = eratesh[o->decn + n];
o->dec = erate[o->decn + n];
o->relsh = eratesh[o->reln + n];
o->rel = erate[o->reln + n];
}
}
static void
ctl(Chan *c, Op *o, int v)
{
o->mul = mul[v & Mmfq];
o->kssh = v & Mkse ? 0 : 2;
o->son = v & Msse;
o->φon = v & Mvbe;
o->Aon = v & Mame ? ~0 : 0;
upop(c, o);
}
static void
sca(Chan *c, Op *o, int v)
{
uchar u;
u = v >> 6;
o->scl = u ? u % 3 : 31; /* shift to 0, 3, 1.5, 6 dB/oct */
o->lvl0 = (v & Mlvl) << Eb-1-7;
o->lvl = o->lvl0 + (c->scl0 >> o->scl);
}
static void
atkdec(Op *o, int v)
{
int a, n;
n = o->ks;
o->atkn = a = v >> 4 ? 16 + (v >> 4 << 2) : 0;
a += n;
if(a < 16+62){
o->atksh = eratesh[a];
o->atk = erate[a];
}else{
o->atksh = 0;
o->atk = 13 * Erstep;
}
o->decn = a = v & Mdec ? 16 + ((v & Mdec) << 2) : 0;
a += n;
o->decsh = eratesh[a];
o->dec = erate[a];
}
static void
susrel(Op *o, int v)
{
o->sus = sust[v >> 4];
o->reln = v & Mrel ? 16 + ((v & Mrel) << 2) : 0;
o->relsh = eratesh[o->reln + o->ks];
o->rel = erate[o->reln + o->ks];
}
static void
opm(int v)
{
lfoAd = v & Mamp;
lfoφd = v & Mvib ? 8 : 0;
rhythm = v & Mrms;
if(v & ~Mrhy)
v = 0;
setk(chs[6].op, 2, v & Mbas);
setk(chs[6].op+1, 2, v & Mbas);
setk(chs[7].op, 2, v & Mhat);
setk(chs[7].op+1, 2, v & Msna);
setk(chs[8].op, 2, v & Mtom);
setk(chs[8].op+1, 2, v & Mcym);
}
static void
foct(int r, int v)
{
int n, b, o, f;
u32int u;
Chan *c;
Op *op0, *op1;
n = r & 0xf;
if(n > 8)
return;
c = chs+n;
op0 = c->op;
op1 = op0 + 1;
o = c->oct;
if(r & 0x10){ /* Roct */
f = c->fn & 0xff | (v & Mmsb) << 8;
o = (v & Moct) >> 2;
setk(op0, 1, v & Mkon);
setk(op1, 1, v & Mkon);
}else
f = c->fn & 0x300 | v;
b = f | o << 10;
if(c->fn != f || c->oct != o){
c->fn = f;
c->oct = o;
c->scl0 = u = lsca[b >> 6];
c->dfq0 = fn[f] >> 7 - o;
/* ignore manual full of lies */
c->kcode = o << 1 | (nse ? f >> 8 : f >> 9) & 1;
op0->lvl = op0->lvl0 + (u >> op0->scl);
op1->lvl = op1->lvl0 + (u >> op1->scl);
upop(c, op0);
upop(c, op1);
}
}
static void
feedb(int r, int v)
{
int n;
Op *o;
if(r > 8)
return;
n = v & Mmod;
v = (v & Mfed) >> 1;
o = chs[r].op;
o->opmodoff = n;
o->fbv = v ? v + 7 : 0;
o->p = n ? &tout : &φmod;
}
static void
tab(void)
{
int i, x, n, *l, *p;
uint *s;
double o, m;
for(x=0; x<Lx; x++){
m = (1<<16) / pow(2, (x+1) * (Estep/4.0) / 8.0);
m = floor(m);
n = (int)m >> 4; /* always fits in 12 (16) bits */
n = (n>>1) + (n&1) << 1; /* rnr */
l = lta + x*2;
l[0] = n;
l[1] = -n;
for(i=1, p=l; i<12; i++){
p += 2*Lx;
p[0] = n >> i;
p[1] = -(n >> i);
}
}
for(i=0, s=sint; i<Sinlen; i++){
m = sin((i*2+1) * PI / Sinlen);
o = 8 * log((m > 0.0 ? 1.0 : -1.0)/m) / log(2.0); /* dB */
o /= Estep / 4.0;
n = o * 2.0;
n = (n>>1) + (n&1); /* rnr */
*s++ = n*2 + (m >= 0.0 ? 0 : 1);
}
for(i=0, s=sint; i<Sinlen; i++, s++){
/* half-sine, abs-sine, pulse-sine */
s[Sinlen] = i & 1<<Sinb-1 ? Lxy : *s;
s[Sinlen*2] = sint[i & Sinm>>1];
s[Sinlen*3] = i & 1<<Sinb-2 ? Lxy : sint[i & Sinm>>2];
}
}
uchar *
opl2out(uchar *s, int n)
{
int v, r;
uchar *e;
Op *o;
r = rhythm & Mrhy;
e = s + n;
while(s < e){
tout = 0;
advlfo();
for(o=ops; o<ops+nelem(ops); o++)
o->tl = o->lvl + (u32int)o->vol + (lfoA & o->Aon);
for(o=ops; o<ops+nelem(ops); o+=2){
if(o == ops+6*2 && r){
rchan();
break;
}
chan(o);
}
v = tout;
if(v > 32767)
v = 32767;
else if(v < -32768)
v = -32768;
s[0] = s[2] = v;
s[1] = s[3] = v>>8;
s += 4;
adv();
}
return s;
}
void
opl2wr(int r, int v)
{
int n;
Op *o;
Chan *c;
v &= 0xff;
n = r & 0x1f;
c = chs + ((n>>3)+(n>>3<<1) + (n+(n+1>>2&1)&3));
o = c->op + (n + 1 >> 2 & 1);
n = r & 6 ^ 6 && n < 22;
switch(r){
case Rwse: wse = v & Mwse; return;
case Rcsm: nse = v & Mnse; return;
case Ropm: opm(v); return;
}
switch(r & 0xe0){
case Rctl: if(n) ctl(c, o, v); break;
case Rsca: if(n) sca(c, o, v); break;
case Ratk: if(n) atkdec(o, v); break;
case Rsus: if(n) susrel(o, v); break;
case Rnum: foct(r, v); break;
case Rfed: feedb(r & 0xf, v); break;
case Rwav: if(wse && n) o->wav = (v & Mwav) * Sinlen; break;
}
}
void
opl2init(int rate)
{
int i;
u32int *fp;
double f0, n;
Chan *c;
Op *o;
tab();
f0 = (Clk / 72.0) / rate;
fp = fn;
n = 0;
while(fp < fn+nelem(fn))
*fp++ = n++ * 64 * f0 * (1 << Sfreqd);
lfoAdt = (1.0 / 64.0) * (1 << Slfo) * f0;
lfoφdt = (1.0 / 1024.0) * (1 << Slfo) * f0;
noiseT = 1.0 * (1 << Sfreq) * f0;
egfdt = (1 << Seg) * f0;
egdt = 1 << Seg;
noise = 1;
c = chs;
o = ops;
while(c < chs+nelem(chs)){
c++->op = o;
o->state = Eoff;
o++->vol = Attmax;
o->state = Eoff;
o++->vol = Attmax;
}
for(i=Rctl; i<Rwav+22; i++)
opl2wr(i, 0);
}