From: notaz Date: Wed, 5 Feb 2025 21:00:21 +0000 (+0200) Subject: s3k ssz kinda ok X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4b04da1f185a2c32c77617fb41516b476ef11379;p=picodrive.git s3k ssz kinda ok --- diff --git a/pico/sound/sound.c b/pico/sound/sound.c index 34bcdf11..447d9dd2 100644 --- a/pico/sound/sound.c +++ b/pico/sound/sound.c @@ -547,8 +547,8 @@ static void do_note(uint8_t note, int is_down) return; if (is_down) { state[note / 8 / 4] |= 1u << (note % 32u); - ym2612_inject(4, 0, 0, 0); - ym2612_inject(4, note / 12, note % 12, 1); + //ym2612h_inject(4, 0, 0, 0, -1, 0); + ym2612h_inject(4, note / 12, note % 12, 1, 3, 13); } else { state[note / 8 / 4] &= ~(1u << (note % 32u)); @@ -556,14 +556,15 @@ static void do_note(uint8_t note, int is_down) v |= state[i]; release_all = !v; if (release_all) - ym2612_inject(4, 0, 0, 0); + ym2612h_inject(4, 0, 0, 0, 3, 21); } } -static void midi_read(void) +static void mkbd_update(void) { struct pollfd pfds[1] = {{ mkbd_fd, POLLIN, 0 }}; uint8_t status = 0; + uint8_t data[2]; uint8_t byte; struct { @@ -572,6 +573,9 @@ static void midi_read(void) } note; int ret; + ym2612h_adj_step(); + ym2612h_echo_step(); + for (;;) { ret = poll(pfds, ARRAY_SIZE(pfds), 0); @@ -603,6 +607,12 @@ static void midi_read(void) do_off: do_note(note.note, 0); break; + case MIDI_CMD_BENDER: // 0xe0 + if (read(mkbd_fd, &data, sizeof(data)) != sizeof(data)) + cfail("read", NULL); + //printf("p %02x %02x\n", data[0], data[1]); + ym2612h_adj_start(4, 4); + break; case 0xf0: switch (status) { case MIDI_CMD_COMMON_SYSEX: @@ -636,7 +646,7 @@ static int PsndRender(int offset, int length) pprof_start(sound); // mkbd if (offset == 0) - midi_read(); + mkbd_update(); // Add in parts of the PSG output not yet done if (length-psglen > 0 && PicoIn.sndOut) { diff --git a/pico/sound/ym2612.c b/pico/sound/ym2612.c index a924e82f..a7812cb7 100644 --- a/pico/sound/ym2612.c +++ b/pico/sound/ym2612.c @@ -1623,17 +1623,20 @@ static void OPNSetPres(int pres) #include "mkbd.h" static -const char *keys[] = { "c", "c#", "d", "d#", "e", "f", "f#", "g", "g#", "a", "a#", "b" }; +const char *keys[] = { "c", "c#", "d", "d#", "e", "f", "f#", "g", "g#", "a", "a#", "b" }; // 643.8 682.1 722.6 765.6 811.1 859.3 910.4 964.6 1021.9 1082.7 1147.1 1215.3 -static int fns[] = { 644, 682, 723, 766, 813, 860, 910, 965, 1023, 1084, 1148, 1216 }; +static int fns[] = { 644, 682, 723, 766, 811, 860, 910, 965, 1022, 1083, 1147, 1215 }; int mkbd_stolen_channels = (1<<3) | (1<<4); -int mkbd_blk_fn_overide[6+4]; -int mkbd_fn_adj[6+4]; +static int mkbd_blk_fn_overide[6+4]; + +static int mkbd_fn_adj_step[6+4]; +static int mkbd_fn_adj[6+4]; // (144 * fnote * 2^20 / φM) / 2^(B-1) // x *144*2097152/7670443 / 16 -static void handle_blk_fn(int c, UINT8 *blk, UINT32 *fn, int do_log) +//static +void handle_blk_fn(int c, UINT8 *blk, UINT32 *fn, int do_log) { int min_abs = 1<<11; int min_di = 0; @@ -1649,7 +1652,7 @@ static void handle_blk_fn(int c, UINT8 *blk, UINT32 *fn, int do_log) min_di = di; } } - mkbd_fn_adj[c] = min_di; + //mkbd_fn_adj[c] = min_di; if (do_log) { i = snprintf(buf, sizeof(buf), "%s%d", keys[min_i], *blk); @@ -1660,7 +1663,7 @@ static void handle_blk_fn(int c, UINT8 *blk, UINT32 *fn, int do_log) if (!do_log && mkbd_blk_fn_overide[c]) { *blk = mkbd_blk_fn_overide[c] >> 11; - *fn = (mkbd_blk_fn_overide[c] & 0x7ff) + min_di; + *fn = (mkbd_blk_fn_overide[c] & 0x7ff); // + min_di; } } @@ -1672,7 +1675,7 @@ static int is_stolen(int c) static void do_log_note(int c) { #if 0 - int i, chans = (1<<0);// | (1<<4); + int i, chans = (1<<3) | (1<<4); if (chans & (1 << c)) { printf("%-5d ", Pico.m.frame_count); for (i = 0; i < 6; i++) { @@ -1696,28 +1699,120 @@ static void do_key_onoff(int c, int v) static int OPNWriteReg(int r, int v, int injecting); -void ym2612_inject(int c, unsigned int octave, unsigned int key, int is_on) +static void set_blk_fn(int c, int blk_fn) { UINT8 fn_h_saved = ym2612.OPN.ST.fn_h; UINT32 r = c < 3 ? c : (0x100 + (c - 3)); - UINT32 val; + + ym2612.OPN.ST.fn_h = blk_fn >> 8; + OPNWriteReg(r | 0xa0, blk_fn & 0xff, 1); + ym2612.OPN.ST.fn_h = fn_h_saved; +} + +static void echo_add(int c, int blk_fn, int frame_delay); + +void ym2612h_inject(int c, unsigned int octave, unsigned int key, int is_on, + int echo_c, int echo_frames) +{ + UINT32 val = 0; //printf("%s %d %d,%d %d\n", __func__, c, octave, key, is_on); assert(octave < 8); assert(key < ARRAY_SIZE(fns)); if (is_on) { - val = fns[key] + mkbd_fn_adj[c]; + val = fns[key]; // + mkbd_fn_adj[c]; assert(val < (1u << 11)); val |= octave << 11; mkbd_blk_fn_overide[c] = val; - ym2612.OPN.ST.fn_h = val >> 8; - OPNWriteReg(r | 0xa0, val & 0xff, 1); - ym2612.OPN.ST.fn_h = fn_h_saved; + do_key_onoff(c, 0); + set_blk_fn(c, val); } else mkbd_blk_fn_overide[c] = 0; + mkbd_fn_adj[c] = mkbd_fn_adj_step[c] = 0; + do_key_onoff(c, is_on ? 0xf0 : 0); + + if (echo_c >= 0) + echo_add(echo_c, val, echo_frames); +} + +static struct +{ + int c; + int blk_fn; + u32 frame; +} echo_ev[8]; + +#define ECHO_MAX_FRAMES 60u + +static void echo_add(int c, int blk_fn, int frame_delay) +{ + u32 now = Pico.m.frame_count; + int i; + + assert((u32)frame_delay <= ECHO_MAX_FRAMES); + if (now + (u32)frame_delay == 0) + frame_delay++; + if (blk_fn) + memset(echo_ev, 0, sizeof(echo_ev)); + + for (i = 0; i < ARRAY_SIZE(echo_ev); i++) { + if (echo_ev[i].frame != 0 && echo_ev[i].frame - now <= ECHO_MAX_FRAMES) + continue; + + echo_ev[i].c = c; + echo_ev[i].blk_fn = blk_fn; + echo_ev[i].frame = now + frame_delay; + break; + } + if (i == ARRAY_SIZE(echo_ev)) + printf("echo overflow\n"); +} + +void ym2612h_echo_step(void) +{ + u32 now = Pico.m.frame_count; + int i, c, val; + + for (i = 0; i < ARRAY_SIZE(echo_ev); i++) { + if (!echo_ev[i].frame || echo_ev[i].frame != now) + continue; + + c = echo_ev[i].c; + val = echo_ev[i].blk_fn; + if (val) { + mkbd_blk_fn_overide[c] = val; + set_blk_fn(c, val); + do_key_onoff(c, 0); + } + do_key_onoff(c, val ? 0xf0 : 0); + echo_ev[i].frame = 0; + } +} + +void ym2612h_adj_start(int c, int step) +{ + if (mkbd_blk_fn_overide[c] && mkbd_fn_adj_step[c] == 0) + mkbd_fn_adj_step[c] = step; +} + +void ym2612h_adj_step(void) +{ + int c; + + for (c = 0; c < 6; c++) { + if (mkbd_fn_adj_step[c] == 0) + continue; + mkbd_fn_adj[c] += mkbd_fn_adj_step[c]; + //printf("c%d adj %d %d\n", c, mkbd_fn_adj[c], mkbd_fn_adj_step[c]); + if (abs(mkbd_fn_adj[c]) >= 16) + mkbd_fn_adj_step[c] = -mkbd_fn_adj_step[c]; + + assert((mkbd_blk_fn_overide[c] & 0x7ff) + mkbd_fn_adj[c] < 0x800u); + set_blk_fn(c, mkbd_blk_fn_overide[c] + mkbd_fn_adj[c]); + } } /* write a OPN register (0x30-0xff) */ @@ -1781,8 +1876,8 @@ static int OPNWriteReg(int r, int v, int injecting) UINT8 blk = ym2612.OPN.ST.fn_h >> 3; if (!injecting) { - handle_blk_fn(c, &blk, &fn, 0); - //if (is_stolen(c)) break; + //handle_blk_fn(c, &blk, &fn, 0); + if (is_stolen(c)) break; } /* keyscale code */ @@ -1790,13 +1885,13 @@ static int OPNWriteReg(int r, int v, int injecting) /* phase increment counter */ CH->fc = fn_table[fn*2]>>(7-blk); - if (!injecting && CH->block_fnum != ((blk<<11) | fn)) - do_log_note(c); - /* store fnum in clear form for LFO PM calculations */ + int changed = CH->block_fnum != ((blk<<11) | fn); CH->block_fnum = (blk<<11) | fn; CH->SLOT[SLOT1].Incr=-1; + if (!injecting && changed) + do_log_note(c); } break; case 1: /* 0xa4-0xa6 : FNUM2,BLK */ @@ -2074,7 +2169,8 @@ int YM2612Write_(unsigned int a, unsigned int v) if( c == 3 ) { ret=0; break; } if( v&0x04 ) c+=3; if (is_stolen(c)) { ret = 0; break; } - //if (c == 4) printf("konoff %02x\n", v); + //if (c == 3 || c == 4) + // printf("%d %d konoff %02x\n", Pico.m.frame_count, c, v); if(v&0x10) FM_KEYON(c,SLOT1); else FM_KEYOFF(c,SLOT1); if(v&0x20) FM_KEYON(c,SLOT2); else FM_KEYOFF(c,SLOT2); if(v&0x40) FM_KEYON(c,SLOT3); else FM_KEYOFF(c,SLOT3);