sound, add native rate mode, change resampling
authorkub <derkub@gmail.com>
Sun, 6 Mar 2022 20:40:50 +0000 (20:40 +0000)
committerkub <derkub@gmail.com>
Thu, 31 Mar 2022 17:51:03 +0000 (19:51 +0200)
pico/pico_int.h
pico/sound/sound.c
pico/sound/ym2612.c
pico/sound/ym2612_arm.S
platform/common/config_file.c
platform/common/emu.c
platform/common/menu_pico.c
platform/gp2x/emu.c
platform/libretro/libretro.c
platform/libretro/libretro_core_options.h
platform/psp/emu.c

index 85df6c5..e95060b 100644 (file)
@@ -853,6 +853,8 @@ extern short cdda_out_buffer[2*1152];
 \r
 void cdda_start_play(int lba_base, int lba_offset, int lb_len);\r
 \r
+#define YM2612_NATIVE_RATE() (((Pico.m.pal?OSC_PAL:OSC_NTSC)/7 + 3*24) / (6*24))\r
+\r
 void ym2612_sync_timers(int z80_cycles, int mode_old, int mode_new);\r
 void ym2612_pack_state(void);\r
 void ym2612_unpack_state(void);\r
index 06d3625..591a029 100644 (file)
@@ -18,7 +18,7 @@ void (*PsndMix_32_to_16l)(s16 *dest, s32 *src, int count) = mix_32_to_16l_stereo
 \r
 // master int buffer to mix to\r
 // +1 for a fill triggered by an instruction overhanging into the next scanline\r
-static s32 PsndBuffer[2*(44100+100)/50+2];\r
+static s32 PsndBuffer[2*(53267+100)/50+2];\r
 \r
 // cdda output buffer\r
 s16 cdda_out_buffer[2*1152];\r
index 95dca6a..e7e3a8a 100644 (file)
@@ -974,7 +974,6 @@ static int update_algo_channel(chan_rend_context *ct, unsigned int eg_out, unsig
                                ct->mem = op_calc(ct->phase2, eg_out2, c1);\r
                        }\r
                        else ct->mem = 0;\r
-                       if (ct->eg_timer >= (1<<EG_SH)) break;\r
 \r
                        if( eg_out  < ENV_QUIET ) {             /* SLOT 3 */\r
                                c2  = op_calc(ct->phase3, eg_out,  m2);\r
@@ -993,7 +992,6 @@ static int update_algo_channel(chan_rend_context *ct, unsigned int eg_out, unsig
                        if( eg_out2 < ENV_QUIET ) {             /* SLOT 2 */\r
                                ct->mem+= op_calc(ct->phase2, eg_out2, 0);\r
                        }\r
-                       if (ct->eg_timer >= (1<<EG_SH)) break;\r
 \r
                        if( eg_out  < ENV_QUIET ) {             /* SLOT 3 */\r
                                c2  = op_calc(ct->phase3, eg_out,  m2);\r
@@ -1013,7 +1011,6 @@ static int update_algo_channel(chan_rend_context *ct, unsigned int eg_out, unsig
                                ct->mem = op_calc(ct->phase2, eg_out2, 0);\r
                        }\r
                        else ct->mem = 0;\r
-                       if (ct->eg_timer >= (1<<EG_SH)) break;\r
 \r
                        if( eg_out  < ENV_QUIET ) {             /* SLOT 3 */\r
                                c2 += op_calc(ct->phase3, eg_out,  m2);\r
@@ -1033,7 +1030,6 @@ static int update_algo_channel(chan_rend_context *ct, unsigned int eg_out, unsig
                                ct->mem = op_calc(ct->phase2, eg_out2, c1);\r
                        }\r
                        else ct->mem = 0;\r
-                       if (ct->eg_timer >= (1<<EG_SH)) break;\r
 \r
                        if( eg_out  < ENV_QUIET ) {             /* SLOT 3 */\r
                                c2 += op_calc(ct->phase3, eg_out,  0);\r
@@ -1048,7 +1044,6 @@ static int update_algo_channel(chan_rend_context *ct, unsigned int eg_out, unsig
                        /* M1---C1-+-OUT */\r
                        /* M2---C2-+     */\r
                        /* MEM: not used */\r
-                       if (ct->eg_timer >= (1<<EG_SH)) break;\r
 \r
                        c1 = ct->op1_out>>16;\r
                        if( eg_out  < ENV_QUIET ) {             /* SLOT 3 */\r
@@ -1069,7 +1064,6 @@ static int update_algo_channel(chan_rend_context *ct, unsigned int eg_out, unsig
                        /*    +----C2----+     */\r
                        m2 = ct->mem;\r
                        ct->mem = c1 = c2 = ct->op1_out>>16;\r
-                       if (ct->eg_timer >= (1<<EG_SH)) break;\r
 \r
                        if( eg_out < ENV_QUIET ) {              /* SLOT 3 */\r
                                smp = op_calc(ct->phase3, eg_out, m2);\r
@@ -1088,7 +1082,6 @@ static int update_algo_channel(chan_rend_context *ct, unsigned int eg_out, unsig
                        /*      M2-+-OUT */\r
                        /*      C2-+     */\r
                        /* MEM: not used */\r
-                       if (ct->eg_timer >= (1<<EG_SH)) break;\r
 \r
                        c1 = ct->op1_out>>16;\r
                        if( eg_out < ENV_QUIET ) {              /* SLOT 3 */\r
@@ -1109,7 +1102,6 @@ static int update_algo_channel(chan_rend_context *ct, unsigned int eg_out, unsig
                        /* M2-+     */\r
                        /* C2-+     */\r
                        /* MEM: not used*/\r
-                       if (ct->eg_timer >= (1<<EG_SH)) break;\r
 \r
                        smp = ct->op1_out>>16;\r
                        if( eg_out < ENV_QUIET ) {              /* SLOT 3 */\r
@@ -1139,20 +1131,6 @@ static void chan_render_loop(chan_rend_context *ct, s32 *buffer, int length)
 \r
                ct->eg_timer += ct->eg_timer_add;\r
 \r
-               if (ct->eg_timer >= 3<<EG_SH && !(ct->pack&0xf000)) {\r
-                       int cnt = (ct->eg_timer>>EG_SH)-2;\r
-                       if (ct->pack & 8) { /* LFO enabled ? (test Earthworm Jim in between demo 1 and 2) */\r
-                               int inc = cnt*ct->lfo_inc;\r
-                               ct->pack = (ct->pack&0xffff) | (advance_lfo(ct->pack >> 16, ct->lfo_cnt, ct->lfo_cnt + inc) << 16);\r
-                               ct->lfo_cnt += inc;\r
-                       }\r
-\r
-                       ct->phase1 += cnt*ct->incr1;\r
-                       ct->phase2 += cnt*ct->incr2;\r
-                       ct->phase3 += cnt*ct->incr3;\r
-                       ct->phase4 += cnt*ct->incr4;\r
-               }\r
-\r
                while (ct->eg_timer >= 1<<EG_SH) {\r
                        ct->eg_timer -= 1<<EG_SH;\r
 \r
@@ -1168,61 +1146,55 @@ static void chan_render_loop(chan_rend_context *ct, s32 *buffer, int length)
 \r
                                update_eg_phase_channel(ct);\r
                        }\r
+               }\r
 \r
-                       ct->vol_out1 =  ct->CH->SLOT[SLOT1].vol_out;\r
-                       ct->vol_out2 =  ct->CH->SLOT[SLOT2].vol_out;\r
-                       ct->vol_out3 =  ct->CH->SLOT[SLOT3].vol_out;\r
-                       ct->vol_out4 =  ct->CH->SLOT[SLOT4].vol_out;\r
-\r
-                       if (ct->eg_timer < (2<<EG_SH) || (ct->pack&0xf000)) {\r
-                               if (ct->pack & 4) goto disabled; /* output disabled */\r
+               ct->vol_out1 =  ct->CH->SLOT[SLOT1].vol_out;\r
+               ct->vol_out2 =  ct->CH->SLOT[SLOT2].vol_out;\r
+               ct->vol_out3 =  ct->CH->SLOT[SLOT3].vol_out;\r
+               ct->vol_out4 =  ct->CH->SLOT[SLOT4].vol_out;\r
 \r
-                               if (ct->pack & 8) { /* LFO enabled ? (test Earthworm Jim in between demo 1 and 2) */\r
-                                       ct->pack = (ct->pack&0xffff) | (advance_lfo(ct->pack >> 16, ct->lfo_cnt, ct->lfo_cnt + ct->lfo_inc) << 16);\r
-                                       ct->lfo_cnt += ct->lfo_inc;\r
-                               }\r
+               if (ct->pack & 4) goto disabled; /* output disabled */\r
 \r
-                               /* calculate channel sample */\r
-                               eg_out = ct->vol_out1;\r
-                               if ( (ct->pack & 8) && (ct->pack&(1<<(SLOT1+8))) )\r
-                                       eg_out += ct->pack >> (((ct->pack&0xc0)>>6)+24);\r
+               if (ct->pack & 8) { /* LFO enabled ? (test Earthworm Jim in between demo 1 and 2) */\r
+                       ct->pack = (ct->pack&0xffff) | (advance_lfo(ct->pack >> 16, ct->lfo_cnt, ct->lfo_cnt + ct->lfo_inc) << 16);\r
+                       ct->lfo_cnt += ct->lfo_inc;\r
+               }\r
 \r
-                               if( eg_out < ENV_QUIET )        /* SLOT 1 */\r
-                               {\r
-                                       int out = 0;\r
+               /* calculate channel sample */\r
+               eg_out = ct->vol_out1;\r
+               if ( (ct->pack & 8) && (ct->pack&(1<<(SLOT1+8))) )\r
+                       eg_out += ct->pack >> (((ct->pack&0xc0)>>6)+24);\r
 \r
-                                       if (ct->pack&0xf000) out = ((ct->op1_out + (ct->op1_out<<16))>>16) << ((ct->pack&0xf000)>>12); /* op1_out0 + op1_out1 */\r
-                                       ct->op1_out <<= 16;\r
-                                       ct->op1_out |= (unsigned short)op_calc1(ct->phase1, eg_out, out);\r
-                               } else {\r
-                                       ct->op1_out <<= 16; /* op1_out0 = op1_out1; op1_out1 = 0; */\r
-                               }\r
+               if( eg_out < ENV_QUIET )        /* SLOT 1 */\r
+               {\r
+                       int out = 0;\r
 \r
-                               if (ct->eg_timer < (2<<EG_SH)) {\r
-                                       eg_out  = ct->vol_out3; // volume_calc(&CH->SLOT[SLOT3]);\r
-                                       eg_out2 = ct->vol_out2; // volume_calc(&CH->SLOT[SLOT2]);\r
-                                       eg_out4 = ct->vol_out4; // volume_calc(&CH->SLOT[SLOT4]);\r
+                       if (ct->pack&0xf000) out = ((ct->op1_out + (ct->op1_out<<16))>>16) << ((ct->pack&0xf000)>>12); /* op1_out0 + op1_out1 */\r
+                       ct->op1_out <<= 16;\r
+                       ct->op1_out |= (unsigned short)op_calc1(ct->phase1, eg_out, out);\r
+               } else {\r
+                       ct->op1_out <<= 16; /* op1_out0 = op1_out1; op1_out1 = 0; */\r
+               }\r
 \r
-                                       if (ct->pack & 8) {\r
-                                               unsigned int add = ct->pack >> (((ct->pack&0xc0)>>6)+24);\r
-                                               if (ct->pack & (1<<(SLOT3+8))) eg_out  += add;\r
-                                               if (ct->pack & (1<<(SLOT2+8))) eg_out2 += add;\r
-                                               if (ct->pack & (1<<(SLOT4+8))) eg_out4 += add;\r
-                                       }\r
+               eg_out  = ct->vol_out3; // volume_calc(&CH->SLOT[SLOT3]);\r
+               eg_out2 = ct->vol_out2; // volume_calc(&CH->SLOT[SLOT2]);\r
+               eg_out4 = ct->vol_out4; // volume_calc(&CH->SLOT[SLOT4]);\r
 \r
-                                       smp = update_algo_channel(ct, eg_out, eg_out2, eg_out4);\r
-                               }\r
-                               /* done calculating channel sample */\r
+               if (ct->pack & 8) {\r
+                       unsigned int add = ct->pack >> (((ct->pack&0xc0)>>6)+24);\r
+                       if (ct->pack & (1<<(SLOT3+8))) eg_out  += add;\r
+                       if (ct->pack & (1<<(SLOT2+8))) eg_out2 += add;\r
+                       if (ct->pack & (1<<(SLOT4+8))) eg_out4 += add;\r
+               }\r
 \r
+               smp = update_algo_channel(ct, eg_out, eg_out2, eg_out4);\r
+               /* done calculating channel sample */\r
 disabled:\r
-                               /* update phase counters AFTER output calculations */\r
-                               ct->phase1 += ct->incr1;\r
-                               ct->phase2 += ct->incr2;\r
-                               ct->phase3 += ct->incr3;\r
-                               ct->phase4 += ct->incr4;\r
-                       }\r
-\r
-               }\r
+               /* update phase counters AFTER output calculations */\r
+               ct->phase1 += ct->incr1;\r
+               ct->phase2 += ct->incr2;\r
+               ct->phase3 += ct->incr3;\r
+               ct->phase4 += ct->incr4;\r
 \r
                /* mix sample to output buffer */\r
                if (smp) {\r
@@ -1615,7 +1587,7 @@ static void OPNSetPres(int pres)
        double freqbase = (ym2612.OPN.ST.rate) ? ((double)ym2612.OPN.ST.clock / ym2612.OPN.ST.rate) / pres : 0;\r
 \r
        ym2612.OPN.eg_timer_add  = (1<<EG_SH) * freqbase;\r
-       ym2612.OPN.ST.freqbase = 1.0; // freqbase\r
+       ym2612.OPN.ST.freqbase = freqbase;\r
 \r
        /* make time tables */\r
        init_timetables( dt_tab );\r
index 16b3833..0a27767 100644 (file)
 @ r0-r2=scratch, r3=sin_tab, r5=scratch, r6-r7=vol_out[4], r10=op1_out
 .macro upd_algo0_m
 
-    cmp     r8, #(1<<EG_SH)
-    bge     1f
-
     @ SLOT3
     make_eg_out SLOT3
     cmp     r1, #ENV_QUIET
 
 .macro upd_algo1_m
 
-    cmp     r8, #(1<<EG_SH)
-    bge     1f
-
     @ SLOT3
     make_eg_out SLOT3
     cmp     r1, #ENV_QUIET
 
 .macro upd_algo2_m
 
-    cmp     r8, #(1<<EG_SH)
-    bge     1f
-
     @ SLOT3
     make_eg_out SLOT3
     cmp     r1, #ENV_QUIET
 
 .macro upd_algo3_m
 
-    cmp     r8, #(1<<EG_SH)
-    bge     1f
-
     @ SLOT3
     make_eg_out SLOT3
     cmp     r1, #ENV_QUIET
 
 .macro upd_algo4_m
 
-    cmp     r8, #(1<<EG_SH)
-    bge     2f
-
     @ SLOT3
     make_eg_out SLOT3
     cmp     r1, #ENV_QUIET
 
 .macro upd_algo5_m
 
-    cmp     r8, #(1<<EG_SH)
-    bge     2f
-
     @ SLOT3
     make_eg_out SLOT3
     cmp     r1, #ENV_QUIET
 
 .macro upd_algo6_m
 
-    cmp     r8, #(1<<EG_SH)
-    bge     2f
-
     @ SLOT3
     make_eg_out SLOT3
     cmp     r1, #ENV_QUIET
 
 .macro upd_algo7_m
 
-    cmp     r8, #(1<<EG_SH)
-    bge     2f
-
     @ SLOT3
     make_eg_out SLOT3
     cmp     r1, #ENV_QUIET
@@ -709,53 +685,15 @@ crl_loop:
     mov     r0, #0
     add     r8, r8, r9
     subs    r8, r8, #(1<<EG_SH)
-    blt     crl_smp_loop_end
-
-    cmp     r8, #(2<<EG_SH)      @ calculate only for operator memory, sample,
-    tstge   r12, #0xf000         @ ...feedback
-    bne     crl_smp_loop
-
-    @ -- LFO+PHASE UPDATE, FF --
-    mov     r0, r8, lsr #EG_SH
-    sub     r0, r0, #1
-
-    tst     r12, #8              @ lfo?
-    beq     lfo_done_ff
-
-    ldr     r2, [lr, #0x34]      @ lfo_inc
-    ldr     r1, [lr, #0x30]      @ lfo_cnt
-    mul     r2, r0, r2
-
-    add     r2, r2, r1
-    str     r2, [lr, #0x30]
-
-    @ r12=lfo_ampm[31:16], r1=lfo_cnt_old, r2=lfo_cnt
-    advance_lfo_m
-
-lfo_done_ff:
-    add     lr, lr, #0x10
-    ldmia   lr, {r1-r3,r5-r7}
-    mul     r6, r0, r6
-    mul     r7, r0, r7
-    add     r1, r1, r6
-    add     r2, r2, r7
-    ldr     r6, [lr, #0x18]
-    ldr     r7, [lr, #0x1c]
-    mul     r6, r0, r6
-    mul     r7, r0, r7
-    add     r3, r3, r6
-    add     r5, r5, r7
-    stmia   lr, {r1-r3,r5}
-    sub     lr, lr, #0x10
+    blt     eg_loop_done
 
-crl_smp_loop:
+crl_eg_loop:
     ldr     r5, [lr, #0x40]      @ CH
 #if defined(SSG_EG)
     tst     r12, #0x02              @ ssg_enabled?
     beq     ssg_done
 
     @ -- SSG --
-ssg_loop:
     mov     r6, #4
 ssg_upd_loop:
     @ use lr as a pointer to the slot phases stored in the context
@@ -808,9 +746,11 @@ eg_upd_loop:
     sub     r5, r5, #SLOT_STRUCT_SIZE*3
 
 eg_done:
-    cmp     r8, #(2<<EG_SH)      @ calculate only for operator memory, sample,
-    tstge   r12, #0xf000         @ ...feedback
-    beq     crl_ff
+    subs    r8, r8, #(1<<EG_SH)
+    bge     crl_eg_loop
+
+eg_loop_done:
+    add     r8, r8, #(1<<EG_SH)
 
     @ -- disabled? --
     mov     r0, #0
@@ -847,9 +787,6 @@ lfo_done:
     upd_slot1_m
 
     @ -- SLOT2+ --
-    cmp     r8, #(2<<EG_SH)      @ op mem or sample?
-    bge     crl_algo_done
-
     and     r0, r4, #7
     PIC_XB(,r0, lsl #2)
     nop
@@ -915,13 +852,7 @@ crl_algo_done:
     stmia   lr, {r1-r3,r5}
     sub     lr, lr, #0x10
 
-crl_ff:
-    subs    r8, r8, #(1<<EG_SH)
-    bge     crl_smp_loop
-
 crl_smp_loop_end:
-    add     r8, r8, #(1<<EG_SH)
-
     @ -- WRITE SAMPLE --
     tst     r0, r0
     beq     ctl_sample_skip
index e15d918..1c4b00c 100644 (file)
@@ -275,7 +275,7 @@ static int custom_read(menu_entry *me, const char *var, const char *val)
                case MA_OPT_SOUND_QUALITY:
                        if (strcasecmp(var, "Sound Quality") != 0) return 0;
                        PicoIn.sndRate = strtoul(val, &tmp, 10);
-                       if (PicoIn.sndRate < 8000 || PicoIn.sndRate > 44100)
+                       if (PicoIn.sndRate < 8000 || PicoIn.sndRate > 53267)
                                PicoIn.sndRate = 22050;
                        if (*tmp == 'H' || *tmp == 'h') tmp++;
                        if (*tmp == 'Z' || *tmp == 'z') tmp++;
index b233050..63a10a3 100644 (file)
@@ -57,7 +57,7 @@ int pico_inp_mode;
 int flip_after_sync;\r
 int engineState = PGS_Menu;\r
 \r
-static short __attribute__((aligned(4))) sndBuffer[2*44100/50];\r
+static short __attribute__((aligned(4))) sndBuffer[2*53267/50];\r
 \r
 /* tmp buff to reduce stack usage for plats with small stack */\r
 static char static_buff[512];\r
@@ -1328,6 +1328,9 @@ void emu_sound_start(void)
 {\r
        PicoIn.sndOut = NULL;\r
 \r
+       // auto-select rate?\r
+       if (PicoIn.sndRate > 52000)\r
+               PicoIn.sndRate = YM2612_NATIVE_RATE();\r
        if (currentConfig.EmuOpt & EOPT_EN_SOUND)\r
        {\r
                int is_stereo = (PicoIn.opt & POPT_EN_STEREO) ? 1 : 0;\r
index 65e08a0..fc9e769 100644 (file)
@@ -595,24 +595,24 @@ static int menu_loop_adv_options(int id, int keys)
 
 static int sndrate_prevnext(int rate, int dir)
 {
-       static const int rates[] = { 8000, 11025, 16000, 22050, 44100 };
+       static const int rates[] = { 8000, 11025, 16000, 22050, 44100, 53000 };
        int i;
 
-       for (i = 0; i < 5; i++)
+       for (i = 0; i < 6; i++)
                if (rates[i] == rate) break;
 
        i += dir ? 1 : -1;
-       if (i > 4) {
+       if (i > 5) {
                if (!(PicoIn.opt & POPT_EN_STEREO)) {
                        PicoIn.opt |= POPT_EN_STEREO;
                        return rates[0];
                }
-               return rates[4];
+               return rates[5];
        }
        if (i < 0) {
                if (PicoIn.opt & POPT_EN_STEREO) {
                        PicoIn.opt &= ~POPT_EN_STEREO;
-                       return rates[4];
+                       return rates[5];
                }
                return rates[0];
        }
@@ -630,7 +630,9 @@ static const char *mgn_opt_sound(int id, int *offs)
        const char *str2;
        *offs = -8;
        str2 = (PicoIn.opt & POPT_EN_STEREO) ? "stereo" : "mono";
-       sprintf(static_buff, "%5iHz %s", PicoIn.sndRate, str2);
+       if (PicoIn.sndRate > 52000)
+               sprintf(static_buff, "native %s\n", str2);
+       else    sprintf(static_buff, "%5iHz %s", PicoIn.sndRate, str2);
        return static_buff;
 }
 
@@ -652,12 +654,14 @@ static const char *mgn_opt_alpha(int id, int *offs)
        return static_buff;
 }
 
+static const char h_quality[] = "native is the FM sound chip rate (53267/52781 Hz),\n"
+                               "select this for the best FM sound quality";
 static const char h_lowpass[] = "Low pass filter for sound closer to real hardware";
 
 static menu_entry e_menu_snd_options[] =
 {
        mee_onoff     ("Enable sound",    MA_OPT_ENABLE_SOUND,  currentConfig.EmuOpt, EOPT_EN_SOUND),
-       mee_cust      ("Sound Quality",   MA_OPT_SOUND_QUALITY, mh_opt_snd, mgn_opt_sound),
+       mee_cust_h    ("Sound Quality",   MA_OPT_SOUND_QUALITY, mh_opt_snd, mgn_opt_sound, h_quality),
        mee_onoff_h   ("Sound filter",    MA_OPT_SOUND_FILTER,  PicoIn.opt, POPT_EN_SNDFILTER, h_lowpass),
        mee_cust      ("Filter strength", MA_OPT_SOUND_ALPHA,   mh_opt_alpha, mgn_opt_alpha),
        mee_end,
@@ -667,6 +671,8 @@ static int menu_loop_snd_options(int id, int keys)
 {
        static int sel = 0;
 
+       if (PicoIn.sndRate > 52000)
+               PicoIn.sndRate = 53000;
        me_loop(e_menu_snd_options, &sel);
 
        return 0;
index 37ee82c..92ea2ec 100644 (file)
@@ -731,7 +731,7 @@ void pemu_sound_start(void)
        }\r
 }\r
 \r
-static const int sound_rates[] = { 44100, 32000, 22050, 16000, 11025, 8000 };\r
+static const int sound_rates[] = { 53000, 44100, 32000, 22050, 16000, 11025, 8000 };\r
 \r
 void pemu_sound_stop(void)\r
 {\r
index 99fc826..00cf4da 100644 (file)
@@ -1316,6 +1316,8 @@ bool retro_load_game(const struct retro_game_info *info)
    PicoIn.writeSound = snd_write;
    memset(sndBuffer, 0, sizeof(sndBuffer));
    PicoIn.sndOut = sndBuffer;
+   if (PicoIn.sndRate > 52000)
+      PicoIn.sndRate = YM2612_NATIVE_RATE();
    PsndRerate(0);
 
    apply_renderer();
@@ -1566,7 +1568,9 @@ static void update_variables(bool first_run)
    {
       PicoDetectRegion();
       PicoLoopPrepare();
-      PsndRerate(1);
+      if (PicoIn.sndRate > 52000)
+         PicoIn.sndRate = YM2612_NATIVE_RATE();
+      PsndRerate(!first_run);
    }
 
    old_vout_aspect = vout_aspect;
@@ -1687,10 +1691,12 @@ static void update_variables(bool first_run)
    var.key = "picodrive_sound_rate";
    if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
       new_sound_rate = atoi(var.value);
+      if (!strcmp(var.value, "native"))
+        new_sound_rate = YM2612_NATIVE_RATE();
       if (new_sound_rate != PicoIn.sndRate) {
          /* Update the sound rate */
          PicoIn.sndRate = new_sound_rate;
-         PsndRerate(1);
+         PsndRerate(!first_run);
          struct retro_system_av_info av_info;
          retro_get_system_av_info(&av_info);
          environ_cb(RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO, &av_info);
index 6e627d4..4a8a9d4 100644 (file)
@@ -207,7 +207,7 @@ struct retro_core_option_v2_definition option_defs_us[] = {
       "picodrive_sound_rate",
       "Audio Sample Rate (Hz)",
       "Sample Rate (Hz)",
-      "Higher values increase sound quality. Lower values may increase performance.",
+      "Higher values increase sound quality. Lower values may increase performance. Native is the FM sound chip rate, either 53267 Hz for NTSC or 52781 Hz for PAL. Select this if you want the most accurate audio.",
       NULL,
       "audio",
       {
@@ -215,6 +215,7 @@ struct retro_core_option_v2_definition option_defs_us[] = {
          { "22050", NULL },
          { "32000", NULL },
          { "44100", NULL },
+         { "native", NULL },
          { NULL, NULL },
       },
       "44100"
index b6d1a34..9c86203 100644 (file)
@@ -487,6 +487,8 @@ void pemu_sound_start(void)
                }
        }
 
+       if (PicoIn.sndRate > 52000)
+               PicoIn.sndRate = YM2612_NATIVE_RATE();
        ret = POPT_EN_FM|POPT_EN_PSG|POPT_EN_STEREO;
        if (PicoIn.sndRate != PsndRate_old || (PicoIn.opt&ret) != (PicoOpt_old&ret) || Pico.m.pal != pal_old) {
                PsndRerate(Pico.m.frame_count ? 1 : 0);