mus: fix note volume and channel selection; simplify

- fix overwriting channel 10 with channel 9
- fix using channel volume instead of last volume when setting note
  (fixes d_doom and others)
- remove useless state
This commit is contained in:
qwx 2018-06-26 10:35:23 +02:00
parent 07b237b10c
commit deae5c854b
2 changed files with 24 additions and 72 deletions

View file

@ -20,4 +20,4 @@ or from standard input, and produces a MIDI format file on standard output.
.B /sys/src/games/mus.c .B /sys/src/games/mus.c
.SH HISTORY .SH HISTORY
.I Mus .I Mus
appeared first for 9front (September, 2015). first appeared in 9front (September, 2015).

View file

@ -2,20 +2,12 @@
#include <libc.h> #include <libc.h>
typedef struct Trk Trk; typedef struct Trk Trk;
typedef struct Ch Ch;
struct Ch{
uchar n[128];
uchar pitch;
uchar ctl[10];
};
struct Trk{ struct Trk{
u32int len; u32int len;
uchar *dat; uchar *dat;
uchar *p; uchar *p;
uchar *end; uchar *end;
Ch c[16]; uchar v[16];
long delay;
int done; int done;
}; };
Trk t; Trk t;
@ -38,19 +30,15 @@ r8(void)
return *t.p++; return *t.p++;
} }
u32int void
delay(void) delay(void)
{ {
u32int t;
uchar v; uchar v;
t = 0;
do{ do{
v = r8(); v = r8();
t = t << 7 | v & 0x7f;
*mp++ = v; *mp++ = v;
}while(v & 0x80); }while(v & 0x80);
return t;
} }
void void
@ -69,71 +57,41 @@ putcmd(uchar *cmd, int n)
void void
ev(void) ev(void)
{ {
uchar e, v; uchar e, v, cmd[3], *p;
Ch *c;
uchar cmd[3], *p;
e = r8(); e = r8();
c = &t.c[e & 15];
p = cmd; p = cmd;
switch(e >> 4 & 7){ switch(e >> 4 & 7){
case 0: case 0:
v = r8() & 0x7f; v = r8() & 0x7f;
c->n[v] = 0;
*p++ = e | 0x80; *p++ = e | 0x80;
*p++ = v; *p++ = v;
*p++ = 0x40; *p++ = 0x40;
break; break;
case 1: case 1:
v = r8(); v = r8();
if(v & 0x80){
c->n[v] = r8() & 0x7f;
c->ctl[3] = c->n[v];
}else
c->n[v] = c->ctl[3];
*p++ = e | 0x80; *p++ = e | 0x80;
*p++ = v & 0x7f; *p++ = v & 0x7f;
*p++ = c->n[v]; if(v & 0x80)
t.v[e & 15] = r8() & 0x7f;
*p++ = t.v[e & 15];
break; break;
case 2: case 2:
c->pitch = r8(); v = r8();
*p++ = e | 0xc0; *p++ = e | 0xc0;
PBIT16(p, c->pitch << 7 & 0x7f7f); PBIT16(p, v << 7 & 0x7f7f);
p += 2; p += 2;
break; break;
case 3: case 3:
v = r8(); v = r8();
*p++ = 0xb | e & 15; *p++ = 0xb | e & 15;
switch(v){ switch(v){
case 10: case 10: *p++ = 0x78; break;
for(v=0; v<128; v++) case 11: *p++ = 0x7b; break;
c->n[v] = 0; case 12: *p++ = 0x7e; break;
*p++ = 0x78; case 13: *p++ = 0x7f; break;
break; case 14: *p++ = 0x79; break;
case 11: default: sysfatal("unknown system event %ux\n", v);
for(v=0; v<128; v++)
c->n[v] = 0;
*p++ = 0x7b;
break;
case 12:
*p++ = 0x7e;
break;
case 13:
*p++ = 0x7f;
break;
case 14:
memset(c->n, 0, sizeof c->n);
memset(c->ctl, 0, sizeof c->ctl);
c->ctl[3] = 0x7f;
c->ctl[4] = 64;
if((e & 15) == 15)
c->pitch = 60;
else
c->pitch = 128;
*p++ = 0x79;
break;
default:
sysfatal("unknown system event %ux\n", v);
} }
*p++ = 0; *p++ = 0;
break; break;
@ -141,7 +99,6 @@ ev(void)
v = r8(); v = r8();
if(v > 9) if(v > 9)
sysfatal("unknown controller %ux\n", v); sysfatal("unknown controller %ux\n", v);
c->ctl[v] = r8() & 0x7f;
*p++ = 0xb0 | e & 15; *p++ = 0xb0 | e & 15;
switch(v){ switch(v){
case 1: *p++ = 0x00; break; case 1: *p++ = 0x00; break;
@ -154,7 +111,7 @@ ev(void)
case 8: *p++ = 0x40; break; case 8: *p++ = 0x40; break;
case 9: *p++ = 0x43; break; case 9: *p++ = 0x43; break;
} }
*p++ = c->ctl[v]; *p++ = r8() & 0x7f;
if(v == 0) if(v == 0)
cmd[0] += 0x10; cmd[0] += 0x10;
break; break;
@ -168,13 +125,12 @@ ev(void)
sysfatal("unknown event %ux\n", e >> 4 & 7); sysfatal("unknown event %ux\n", e >> 4 & 7);
} }
if((e & 15) == 9) if((e & 15) == 9)
cmd[0] += 1; cmd[0] |= 6;
if((e & 15) == 15) if((e & 15) == 15)
cmd[0] &= ~6; cmd[0] &= ~6;
putcmd(cmd, p-cmd); putcmd(cmd, p-cmd);
t.delay = 0;
if(e & 0x80) if(e & 0x80)
t.delay = delay(); delay();
else else
*mp++ = 0; *mp++ = 0;
} }
@ -182,16 +138,7 @@ ev(void)
void void
reset(void) reset(void)
{ {
Ch *c; memset(t.v, 0x7f, sizeof t.v);
c = t.c;
while(c < t.c + nelem(t.c)){
c->pitch = 128;
c->ctl[3] = 0x7f;
c->ctl[4] = 64;
c++;
}
t.c[15].pitch = 60;
mcmd = mallocz(t.len * 2, 1); mcmd = mallocz(t.len * 2, 1);
if(mcmd == nil) if(mcmd == nil)
sysfatal("mallocz: %r"); sysfatal("mallocz: %r");
@ -221,6 +168,11 @@ barf(void)
0x00, 0xb8, 0x07, 0x7f, 0x00, 0xb8, 0x07, 0x7f,
0x00, 0xb9, 0x07, 0x7f, 0x00, 0xb9, 0x07, 0x7f,
0x00, 0xba, 0x07, 0x7f, 0x00, 0xba, 0x07, 0x7f,
0x00, 0xbb, 0x07, 0x7f,
0x00, 0xbc, 0x07, 0x7f,
0x00, 0xbd, 0x07, 0x7f,
0x00, 0xbe, 0x07, 0x7f,
0x00, 0xbf, 0x07, 0x7f,
0x00, 0xff, 0x51, 0x03, 0x1b, 0x8a, 0x06, 0x00, 0xff, 0x51, 0x03, 0x1b, 0x8a, 0x06,
0x00 0x00
}; };