}\r
\r
\r
+//static\r
+void SN76496_set_clockrate(int clock,int sample_rate)\r
+{\r
+ struct SN76496 *R = &ono_sn;\r
+\r
+ R->SampleRate = sample_rate;\r
+ SN76496_set_clock(R,clock);\r
+}\r
+\r
//static\r
int SN76496_init(int clock,int sample_rate)\r
{\r
\r
//R->Channel = stream_create(0,1, sample_rate,R,SN76496Update);\r
\r
- R->SampleRate = sample_rate;\r
- SN76496_set_clock(R,clock);\r
+ SN76496_set_clockrate(clock,sample_rate);\r
\r
for (i = 0;i < 4;i++) R->Volume[i] = 0;\r
\r
\r
// ym2413\r
static OPLL *opll = NULL;\r
-static OPLL old_opll;\r
static struct {\r
uint32_t adr;\r
uint8_t reg[sizeof(opll->reg)];\r
return YM2612UpdateOne(buffer, length, stereo, is_buf_empty);\r
}\r
\r
+static int ymclock;\r
+static int ymrate;\r
+static int ymopts;\r
+\r
// to be called after changing sound rate or chips\r
void PsndRerate(int preserve_state)\r
{\r
int target_fps = Pico.m.pal ? 50 : 60;\r
int target_lines = Pico.m.pal ? 313 : 262;\r
int sms_clock = Pico.m.pal ? OSC_PAL/15 : OSC_NTSC/15;\r
+ int ym2413_rate = (sms_clock + 36) / 72;\r
int ym2612_clock = Pico.m.pal ? OSC_PAL/7 : OSC_NTSC/7;\r
int ym2612_rate = YM2612_NATIVE_RATE();\r
- int ym2413_rate = (sms_clock + 36) / 72;\r
+ int ym2612_init = !preserve_state;\r
\r
- if (preserve_state) {\r
+ // don't init YM2612 if preserve_state and no parameter changes\r
+ ym2612_init |= ymclock != ym2612_clock || ymopts != (PicoIn.opt & (POPT_DIS_FM_SSGEG|POPT_EN_FM_DAC));\r
+ ym2612_init |= ymrate != (PicoIn.opt & POPT_EN_FM_FILTER ? ym2612_rate : PicoIn.sndRate);\r
+ ymclock = ym2612_clock;\r
+ ymrate = (PicoIn.opt & POPT_EN_FM_FILTER ? ym2612_rate : PicoIn.sndRate);\r
+ ymopts = PicoIn.opt & (POPT_DIS_FM_SSGEG|POPT_EN_FM_DAC);\r
+\r
+ if (preserve_state && ym2612_init) {\r
state = malloc(0x204);\r
if (state == NULL) return;\r
ym2612_pack_state();\r
memcpy(state, YM2612GetRegs(), 0x204);\r
-\r
- if (opll != NULL)\r
- memcpy(&old_opll, opll, sizeof(OPLL)); // remember old state\r
}\r
+\r
if (PicoIn.AHW & PAHW_SMS) {\r
OPLL_setRate(opll, ym2413_rate);\r
- OPLL_reset(opll);\r
+ if (!preserve_state)\r
+ OPLL_reset(opll);\r
YMFM_setup_FIR(ym2413_rate, PicoIn.sndRate, 0);\r
PsndFMUpdate = YM2413UpdateFIR;\r
} else if ((PicoIn.opt & POPT_EN_FM_FILTER) && ym2612_rate != PicoIn.sndRate) {\r
// polyphase FIR resampler, resampling directly from native to output rate\r
- YM2612Init(ym2612_clock, ym2612_rate,\r
+ if (ym2612_init)\r
+ YM2612Init(ym2612_clock, ym2612_rate,\r
((PicoIn.opt&POPT_DIS_FM_SSGEG) ? 0 : ST_SSG) |\r
((PicoIn.opt&POPT_EN_FM_DAC) ? ST_DAC : 0));\r
YMFM_setup_FIR(ym2612_rate, PicoIn.sndRate, PicoIn.opt & POPT_EN_STEREO);\r
PsndFMUpdate = YM2612UpdateFIR;\r
} else {\r
- YM2612Init(ym2612_clock, PicoIn.sndRate,\r
+ if (ym2612_init)\r
+ YM2612Init(ym2612_clock, PicoIn.sndRate,\r
((PicoIn.opt&POPT_DIS_FM_SSGEG) ? 0 : ST_SSG) |\r
((PicoIn.opt&POPT_EN_FM_DAC) ? ST_DAC : 0));\r
PsndFMUpdate = YM2612UpdateONE;\r
}\r
- if (preserve_state) {\r
+\r
+ if (preserve_state && ym2612_init) {\r
// feed it back it's own registers, just like after loading state\r
memcpy(YM2612GetRegs(), state, 0x204);\r
ym2612_unpack_state();\r
-\r
- if (opll != NULL) {\r
- memcpy(&opll->adr, &old_opll.adr, sizeof(OPLL)-20); // restore old state\r
- OPLL_forceRefresh(opll);\r
- }\r
+ free(state);\r
}\r
\r
- if (preserve_state) memcpy(state, sn76496_regs, 28*4); // remember old state\r
- SN76496_init(Pico.m.pal ? OSC_PAL/15 : OSC_NTSC/15, PicoIn.sndRate);\r
- if (preserve_state) memcpy(sn76496_regs, state, 28*4); // restore old state\r
-\r
- if (state)\r
- free(state);\r
+ if (preserve_state)\r
+ SN76496_set_clockrate(Pico.m.pal ? OSC_PAL/15 : OSC_NTSC/15, PicoIn.sndRate);\r
+ else\r
+ SN76496_init(Pico.m.pal ? OSC_PAL/15 : OSC_NTSC/15, PicoIn.sndRate);\r
\r
// calculate Pico.snd.len\r
Pico.snd.len = PicoIn.sndRate / target_fps;\r
/* sin waveform table in 'decibel' scale (use only period/4 values) */\r
static UINT16 ym_sin_tab[256];\r
\r
+static int ym_init_tab;\r
+\r
/* sustain level table (3dB per step) */\r
/* bit0, bit1, bit2, bit3, bit4, bit5, bit6 */\r
/* 1, 2, 4, 8, 16, 32, 64 (value)*/\r
signed int n;\r
double o,m;\r
\r
+ if (ym_init_tab) return;\r
+ ym_init_tab = 1;\r
+\r
for (i=0; i < 256; i++)\r
{\r
/* non-standard sinus */\r