s3k ssz kinda ok
authornotaz <notasas@gmail.com>
Wed, 5 Feb 2025 21:00:21 +0000 (23:00 +0200)
committernotaz <notasas@gmail.com>
Wed, 19 Feb 2025 20:04:16 +0000 (22:04 +0200)
pico/sound/sound.c
pico/sound/ym2612.c

index 34bcdf1..447d9dd 100644 (file)
@@ -547,8 +547,8 @@ static void do_note(uint8_t note, int is_down)
     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
@@ -556,14 +556,15 @@ static void do_note(uint8_t note, int is_down)
       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
@@ -572,6 +573,9 @@ static void midi_read(void)
   } 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
@@ -603,6 +607,12 @@ static void midi_read(void)
         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
@@ -636,7 +646,7 @@ static int PsndRender(int offset, int length)
   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
index a924e82..a7812cb 100644 (file)
@@ -1623,17 +1623,20 @@ static void OPNSetPres(int pres)
 #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
@@ -1649,7 +1652,7 @@ static void handle_blk_fn(int c, UINT8 *blk, UINT32 *fn, int do_log)
                        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
@@ -1660,7 +1663,7 @@ static void handle_blk_fn(int c, UINT8 *blk, UINT32 *fn, int do_log)
 \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
@@ -1672,7 +1675,7 @@ static int is_stolen(int c)
 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
@@ -1696,28 +1699,120 @@ static void do_key_onoff(int c, int v)
 \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
@@ -1781,8 +1876,8 @@ static int OPNWriteReg(int r, int v, int injecting)
                                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
@@ -1790,13 +1885,13 @@ static int OPNWriteReg(int r, int v, int injecting)
                                /* 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
@@ -2074,7 +2169,8 @@ int YM2612Write_(unsigned int a, unsigned int v)
                                        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