return;\r
if (is_down) {\r
state[note / 8 / 4] |= 1u << (note % 32u);\r
- ym2612_inject(4, 0, 0, 0);\r
- ym2612_inject(4, note / 12, note % 12, 1);\r
+ //ym2612h_inject(4, 0, 0, 0, -1, 0);\r
+ ym2612h_inject(4, note / 12, note % 12, 1, 3, 13);\r
}\r
else {\r
state[note / 8 / 4] &= ~(1u << (note % 32u));\r
v |= state[i];\r
release_all = !v;\r
if (release_all)\r
- ym2612_inject(4, 0, 0, 0);\r
+ ym2612h_inject(4, 0, 0, 0, 3, 21);\r
}\r
}\r
\r
-static void midi_read(void)\r
+static void mkbd_update(void)\r
{\r
struct pollfd pfds[1] = {{ mkbd_fd, POLLIN, 0 }};\r
uint8_t status = 0;\r
+ uint8_t data[2];\r
uint8_t byte;\r
struct\r
{\r
} note;\r
int ret;\r
\r
+ ym2612h_adj_step();\r
+ ym2612h_echo_step();\r
+\r
for (;;)\r
{\r
ret = poll(pfds, ARRAY_SIZE(pfds), 0);\r
do_off:\r
do_note(note.note, 0);\r
break;\r
+ case MIDI_CMD_BENDER: // 0xe0\r
+ if (read(mkbd_fd, &data, sizeof(data)) != sizeof(data))\r
+ cfail("read", NULL);\r
+ //printf("p %02x %02x\n", data[0], data[1]);\r
+ ym2612h_adj_start(4, 4);\r
+ break;\r
case 0xf0:\r
switch (status) {\r
case MIDI_CMD_COMMON_SYSEX:\r
pprof_start(sound);\r
// mkbd\r
if (offset == 0)\r
- midi_read();\r
+ mkbd_update();\r
\r
// Add in parts of the PSG output not yet done\r
if (length-psglen > 0 && PicoIn.sndOut) {\r
#include "mkbd.h"\r
\r
static\r
-const char *keys[] = { "c", "c#", "d", "d#", "e", "f", "f#", "g", "g#", "a", "a#", "b" };\r
+const char *keys[] = { "c", "c#", "d", "d#", "e", "f", "f#", "g", "g#", "a", "a#", "b" };\r
// 643.8 682.1 722.6 765.6 811.1 859.3 910.4 964.6 1021.9 1082.7 1147.1 1215.3\r
-static int fns[] = { 644, 682, 723, 766, 813, 860, 910, 965, 1023, 1084, 1148, 1216 };\r
+static int fns[] = { 644, 682, 723, 766, 811, 860, 910, 965, 1022, 1083, 1147, 1215 };\r
\r
int mkbd_stolen_channels = (1<<3) | (1<<4);\r
-int mkbd_blk_fn_overide[6+4];\r
-int mkbd_fn_adj[6+4];\r
+static int mkbd_blk_fn_overide[6+4];\r
+\r
+static int mkbd_fn_adj_step[6+4];\r
+static int mkbd_fn_adj[6+4];\r
\r
// (144 * fnote * 2^20 / φM) / 2^(B-1)\r
// x *144*2097152/7670443 / 16\r
-static void handle_blk_fn(int c, UINT8 *blk, UINT32 *fn, int do_log)\r
+//static\r
+void handle_blk_fn(int c, UINT8 *blk, UINT32 *fn, int do_log)\r
{\r
int min_abs = 1<<11;\r
int min_di = 0;\r
min_di = di;\r
}\r
}\r
- mkbd_fn_adj[c] = min_di;\r
+ //mkbd_fn_adj[c] = min_di;\r
\r
if (do_log) {\r
i = snprintf(buf, sizeof(buf), "%s%d", keys[min_i], *blk);\r
\r
if (!do_log && mkbd_blk_fn_overide[c]) {\r
*blk = mkbd_blk_fn_overide[c] >> 11;\r
- *fn = (mkbd_blk_fn_overide[c] & 0x7ff) + min_di;\r
+ *fn = (mkbd_blk_fn_overide[c] & 0x7ff); // + min_di;\r
}\r
}\r
\r
static void do_log_note(int c)\r
{\r
#if 0\r
- int i, chans = (1<<0);// | (1<<4);\r
+ int i, chans = (1<<3) | (1<<4);\r
if (chans & (1 << c)) {\r
printf("%-5d ", Pico.m.frame_count);\r
for (i = 0; i < 6; i++) {\r
\r
static int OPNWriteReg(int r, int v, int injecting);\r
\r
-void ym2612_inject(int c, unsigned int octave, unsigned int key, int is_on)\r
+static void set_blk_fn(int c, int blk_fn)\r
{\r
UINT8 fn_h_saved = ym2612.OPN.ST.fn_h;\r
UINT32 r = c < 3 ? c : (0x100 + (c - 3));\r
- UINT32 val;\r
+\r
+ ym2612.OPN.ST.fn_h = blk_fn >> 8;\r
+ OPNWriteReg(r | 0xa0, blk_fn & 0xff, 1);\r
+ ym2612.OPN.ST.fn_h = fn_h_saved;\r
+}\r
+\r
+static void echo_add(int c, int blk_fn, int frame_delay);\r
+\r
+void ym2612h_inject(int c, unsigned int octave, unsigned int key, int is_on,\r
+ int echo_c, int echo_frames)\r
+{\r
+ UINT32 val = 0;\r
\r
//printf("%s %d %d,%d %d\n", __func__, c, octave, key, is_on);\r
assert(octave < 8);\r
assert(key < ARRAY_SIZE(fns));\r
if (is_on) {\r
- val = fns[key] + mkbd_fn_adj[c];\r
+ val = fns[key]; // + mkbd_fn_adj[c];\r
assert(val < (1u << 11));\r
val |= octave << 11;\r
mkbd_blk_fn_overide[c] = val;\r
- ym2612.OPN.ST.fn_h = val >> 8;\r
- OPNWriteReg(r | 0xa0, val & 0xff, 1);\r
- ym2612.OPN.ST.fn_h = fn_h_saved;\r
+ do_key_onoff(c, 0);\r
+ set_blk_fn(c, val);\r
}\r
else\r
mkbd_blk_fn_overide[c] = 0;\r
\r
+ mkbd_fn_adj[c] = mkbd_fn_adj_step[c] = 0;\r
+\r
do_key_onoff(c, is_on ? 0xf0 : 0);\r
+\r
+ if (echo_c >= 0)\r
+ echo_add(echo_c, val, echo_frames);\r
+}\r
+\r
+static struct\r
+{\r
+ int c;\r
+ int blk_fn;\r
+ u32 frame;\r
+} echo_ev[8];\r
+\r
+#define ECHO_MAX_FRAMES 60u\r
+\r
+static void echo_add(int c, int blk_fn, int frame_delay)\r
+{\r
+ u32 now = Pico.m.frame_count;\r
+ int i;\r
+\r
+ assert((u32)frame_delay <= ECHO_MAX_FRAMES);\r
+ if (now + (u32)frame_delay == 0)\r
+ frame_delay++;\r
+ if (blk_fn)\r
+ memset(echo_ev, 0, sizeof(echo_ev));\r
+\r
+ for (i = 0; i < ARRAY_SIZE(echo_ev); i++) {\r
+ if (echo_ev[i].frame != 0 && echo_ev[i].frame - now <= ECHO_MAX_FRAMES)\r
+ continue;\r
+\r
+ echo_ev[i].c = c;\r
+ echo_ev[i].blk_fn = blk_fn;\r
+ echo_ev[i].frame = now + frame_delay;\r
+ break;\r
+ }\r
+ if (i == ARRAY_SIZE(echo_ev))\r
+ printf("echo overflow\n");\r
+}\r
+\r
+void ym2612h_echo_step(void)\r
+{\r
+ u32 now = Pico.m.frame_count;\r
+ int i, c, val;\r
+\r
+ for (i = 0; i < ARRAY_SIZE(echo_ev); i++) {\r
+ if (!echo_ev[i].frame || echo_ev[i].frame != now)\r
+ continue;\r
+\r
+ c = echo_ev[i].c;\r
+ val = echo_ev[i].blk_fn;\r
+ if (val) {\r
+ mkbd_blk_fn_overide[c] = val;\r
+ set_blk_fn(c, val);\r
+ do_key_onoff(c, 0);\r
+ }\r
+ do_key_onoff(c, val ? 0xf0 : 0);\r
+ echo_ev[i].frame = 0;\r
+ }\r
+}\r
+\r
+void ym2612h_adj_start(int c, int step)\r
+{\r
+ if (mkbd_blk_fn_overide[c] && mkbd_fn_adj_step[c] == 0)\r
+ mkbd_fn_adj_step[c] = step;\r
+}\r
+\r
+void ym2612h_adj_step(void)\r
+{\r
+ int c;\r
+\r
+ for (c = 0; c < 6; c++) {\r
+ if (mkbd_fn_adj_step[c] == 0)\r
+ continue;\r
+ mkbd_fn_adj[c] += mkbd_fn_adj_step[c];\r
+ //printf("c%d adj %d %d\n", c, mkbd_fn_adj[c], mkbd_fn_adj_step[c]);\r
+ if (abs(mkbd_fn_adj[c]) >= 16)\r
+ mkbd_fn_adj_step[c] = -mkbd_fn_adj_step[c];\r
+\r
+ assert((mkbd_blk_fn_overide[c] & 0x7ff) + mkbd_fn_adj[c] < 0x800u);\r
+ set_blk_fn(c, mkbd_blk_fn_overide[c] + mkbd_fn_adj[c]);\r
+ }\r
}\r
\r
/* write a OPN register (0x30-0xff) */\r
UINT8 blk = ym2612.OPN.ST.fn_h >> 3;\r
\r
if (!injecting) {\r
- handle_blk_fn(c, &blk, &fn, 0);\r
- //if (is_stolen(c)) break;\r
+ //handle_blk_fn(c, &blk, &fn, 0);\r
+ if (is_stolen(c)) break;\r
}\r
\r
/* keyscale code */\r
/* phase increment counter */\r
CH->fc = fn_table[fn*2]>>(7-blk);\r
\r
- if (!injecting && CH->block_fnum != ((blk<<11) | fn))\r
- do_log_note(c);\r
-\r
/* store fnum in clear form for LFO PM calculations */\r
+ int changed = CH->block_fnum != ((blk<<11) | fn);\r
CH->block_fnum = (blk<<11) | fn;\r
\r
CH->SLOT[SLOT1].Incr=-1;\r
+ if (!injecting && changed)\r
+ do_log_note(c);\r
}\r
break;\r
case 1: /* 0xa4-0xa6 : FNUM2,BLK */\r
if( c == 3 ) { ret=0; break; }\r
if( v&0x04 ) c+=3;\r
if (is_stolen(c)) { ret = 0; break; }\r
- //if (c == 4) printf("konoff %02x\n", v);\r
+ //if (c == 3 || c == 4)\r
+ // printf("%d %d konoff %02x\n", Pico.m.frame_count, c, v);\r
if(v&0x10) FM_KEYON(c,SLOT1); else FM_KEYOFF(c,SLOT1);\r
if(v&0x20) FM_KEYON(c,SLOT2); else FM_KEYOFF(c,SLOT2);\r
if(v&0x40) FM_KEYON(c,SLOT3); else FM_KEYOFF(c,SLOT3);\r