diff --git a/apu/apu.cpp b/apu/apu.cpp index dd67838a..4c54f2b8 100644 --- a/apu/apu.cpp +++ b/apu/apu.cpp @@ -14,12 +14,12 @@ #include "bapu/snes/snes.hpp" -static const int APU_DEFAULT_INPUT_RATE = 31920; // ~59.94Hz +static const int APU_DEFAULT_INPUT_RATE = 31950; // ~59.94Hz static const int APU_SAMPLE_BLOCK = 48; -static const int APU_NUMERATOR_NTSC = 5632; -static const int APU_DENOMINATOR_NTSC = 118125; -static const int APU_NUMERATOR_PAL = 35527; -static const int APU_DENOMINATOR_PAL = 738343; +static const int APU_NUMERATOR_NTSC = 15664; +static const int APU_DENOMINATOR_NTSC = 328125; +static const int APU_NUMERATOR_PAL = 34176; +static const int APU_DENOMINATOR_PAL = 709379; // Max number of samples we'll ever generate before call to port API and // moving the samples to the resampler. @@ -184,7 +184,7 @@ static void UpdatePlaybackRate(void) if (Settings.MSU1) { - time_ratio = (44100.0 / Settings.SoundPlaybackRate) * (Settings.SoundInputRate / 32000.0); + time_ratio = (44100.0 / Settings.SoundPlaybackRate) * (Settings.SoundInputRate / 32040.0); msu::resampler->time_ratio(time_ratio); } } diff --git a/docs/porting.html b/docs/porting.html index db4537e7..cde540dd 100644 --- a/docs/porting.html +++ b/docs/porting.html @@ -347,7 +347,7 @@ Settings.MultiPlayer5Master = true;
Settings.FrameTimePAL = 20000;
Settings.FrameTimeNTSC = 16667;
- Settings.SoundPlaybackRate = 32000;
+ Settings.SoundPlaybackRate = 32040;
Settings.SoundInputRate = 31947;
Settings.SupportHiRes = true;
Settings.Transparency = true;
@@ -361,10 +361,10 @@ Adjusts the sound rate through resampling. For every Settings.SoundInputRate samples generated by the SNES, Settings.SoundPlaybackRate samples will be produced.

- On a NTSC SNES, the video refresh rate is usually 60.09881Hz, while the audio output is 32000Hz. This means for every video frame displayed, 532.4565 sound frames are produced. A modern computer display or television will usually provide one of two video rates, 60.00Hz exactly or 59.94Hz to support broadcast television. The sound output, however, is usually fixed at exact values like 32000Hz, 44100Hz, or 48000Hz. This means that the closest video-to-sound ratio we can achieve, with 60.00Hz and 32000Hz, is 1.0/533.3333. This discrepancy means if we wait for vertical sync and update once per refresh, we will experience a sound deficit of 0.87 samples every frame, eventually causing a sound underrun and producing audio problems.
+ On a NTSC SNES, the video refresh rate is usually 60.09881Hz, while the audio output is 32040Hz. This means for every video frame displayed, 532.4565 sound frames are produced. A modern computer display or television will usually provide one of two video rates, 60.00Hz exactly or 59.94Hz to support broadcast television. The sound output, however, is usually fixed at exact values like 32000Hz, 44100Hz, or 48000Hz. This means that the closest video-to-sound ratio we can achieve, with 60.00Hz and 32000Hz, is 1.0/533.3333. This discrepancy means if we wait for vertical sync and update once per refresh, we will experience a sound deficit of 0.87 samples every frame, eventually causing a sound underrun and producing audio problems.

- Settings.SoundInputRate can be set to a value such that the ratio with the video rate matches the SNES output. A 60.00Hz display, for example, should be set to 60.00 / 60.09881 * 32000, which is about 31947. The Snes9x resampler will then stretch the sound samples to fit this ratio. It may be beneficial to provide an option for users to configure Settings.SoundInputRate to suit their own systems. Setting Settings.SoundInputRate to a value that matches the actual output rate (i.e. 31915hz for 59.94Hz) or lower will allow the users to eliminate crackling. A range of 31000hz to 33000hz should be inclusive enough for all displays. Use of this setting paired with the S9xSyncSound function can eliminate sound discontinuity. However, this concept is difficult for most users to understand. If possible, read the display's refresh rate and automatically calculate the appropriate input rate by default. In practice, few displays exceed a target of 60.00Hz, so a good default would be no greater than 31947Hz, but probably lower. + Settings.SoundInputRate can be set to a value such that the ratio with the video rate matches the SNES output. A 60.00Hz display, for example, should be set to 60.00 / 60.09881 * 32040, which is about 31987. The Snes9x resampler will then stretch the sound samples to fit this ratio. It may be beneficial to provide an option for users to configure Settings.SoundInputRate to suit their own systems. Setting Settings.SoundInputRate to a value that matches the actual output rate (i.e. 31915hz for 59.94Hz) or lower will allow the users to eliminate crackling. A range of 31000hz to 33000hz should be inclusive enough for all displays. Use of this setting paired with the S9xSyncSound function can eliminate sound discontinuity. However, this concept is difficult for most users to understand. If possible, read the display's refresh rate and automatically calculate the appropriate input rate by default. In practice, few displays exceed a target of 60.00Hz, so a good default would be no greater than 31950Hz, but probably lower.

Settings.DynamicRateControl and S9xUpdateDynamicRate(int numerator, int denominator)

diff --git a/gtk/src/gtk_preferences.cpp b/gtk/src/gtk_preferences.cpp index 73588606..41b1b3b1 100644 --- a/gtk/src/gtk_preferences.cpp +++ b/gtk/src/gtk_preferences.cpp @@ -427,7 +427,7 @@ event_input_rate_changed (GtkRange *range, gpointer data) { char text[256]; GtkLabel *label = GTK_LABEL (data); - double value = gtk_range_get_value (range) / 32000.0 * 60.09881389744051; + double value = gtk_range_get_value (range) / 32040.0 * 60.09881389744051; snprintf (text, 256, "%.4f hz", value); diff --git a/gtk/src/gtk_s9xwindow.cpp b/gtk/src/gtk_s9xwindow.cpp index d036170e..0a79ca12 100644 --- a/gtk/src/gtk_s9xwindow.cpp +++ b/gtk/src/gtk_s9xwindow.cpp @@ -1579,9 +1579,9 @@ Snes9xWindow::get_auto_input_rate () if (refresh_rate > 239.0 && refresh_rate < 241.0) refresh_rate /= 4.0; - double new_input_rate = refresh_rate * 32000.0 / 60.09881389744051 + 0.5; + double new_input_rate = refresh_rate * 32040.0 / 60.09881389744051 + 0.5; - if (new_input_rate > 32000.0 * 1.05 || new_input_rate < 32000.0 * 0.95) + if (new_input_rate > 32040.0 * 1.05 || new_input_rate < 32040.0 * 0.95) new_input_rate = 0.0; return new_input_rate; diff --git a/gtk/src/gtk_sound.cpp b/gtk/src/gtk_sound.cpp index 9a24a3f3..28d46a9e 100644 --- a/gtk/src/gtk_sound.cpp +++ b/gtk/src/gtk_sound.cpp @@ -133,7 +133,7 @@ S9xPortSoundInit () Settings.SoundInputRate = top_level->get_auto_input_rate (); if (Settings.SoundInputRate == 0.0) { - Settings.SoundInputRate = 31920; + Settings.SoundInputRate = 31950; gui_config->auto_input_rate = 0; } } diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index 855fb40d..1c933487 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -749,7 +749,7 @@ void retro_get_system_av_info(struct retro_system_av_info *info) info->geometry.max_width = MAX_SNES_WIDTH_NTSC; info->geometry.max_height = MAX_SNES_HEIGHT; info->geometry.aspect_ratio = get_aspect_ratio(width, height); - info->timing.sample_rate = 32000; + info->timing.sample_rate = 32040; info->timing.fps = retro_get_region() == RETRO_REGION_NTSC ? 21477272.0 / 357366.0 : 21281370.0 / 425568.0; g_screen_gun_width = width; @@ -1254,8 +1254,8 @@ void retro_init(void) Settings.FrameTimeNTSC = 16667; Settings.SixteenBitSound = TRUE; Settings.Stereo = TRUE; - Settings.SoundPlaybackRate = 32000; - Settings.SoundInputRate = 32000; + Settings.SoundPlaybackRate = 32040; + Settings.SoundInputRate = 32040; Settings.SupportHiRes = TRUE; Settings.Transparency = TRUE; Settings.AutoDisplayMessages = TRUE; diff --git a/macosx/English.lproj/Snes9x Help/pgs/14.html b/macosx/English.lproj/Snes9x Help/pgs/14.html index e157ce9e..a1c3d064 100644 --- a/macosx/English.lproj/Snes9x Help/pgs/14.html +++ b/macosx/English.lproj/Snes9x Help/pgs/14.html @@ -56,7 +56,7 @@

Effect...
Opens 'Sound Effect' dialog.
Playback Rate
-
The real SNES is 32000 Hz. Any values other than 32000 Hz will cause resampling.
+
The real SNES is 32040 Hz. Any values other than 32040 Hz will cause resampling.
Output Interval
Make sure this value is smaller than the mix buffer length.
Mix Buffer Length
diff --git a/macosx/English.lproj/Snes9x.xib b/macosx/English.lproj/Snes9x.xib index ddadc9d3..ea042e01 100644 --- a/macosx/English.lproj/Snes9x.xib +++ b/macosx/English.lproj/Snes9x.xib @@ -29607,7 +29607,7 @@ - The real SNES is 32000 Hz. Any values other than 32000 Hz will cause resampling. + The real SNES is 32040 Hz. Any values other than 32040 Hz will cause resampling. YES diff --git a/msu1.cpp b/msu1.cpp index c51238d9..f0481c06 100644 --- a/msu1.cpp +++ b/msu1.cpp @@ -230,7 +230,7 @@ void S9xMSU1Generate(size_t sample_count) { partial_frames += 4410 * (sample_count / 2); - while (partial_frames >= 3200) + while (partial_frames >= 3204) { if (MSU1.MSU1_STATUS & AudioPlaying && audioStream) { @@ -246,7 +246,7 @@ void S9xMSU1Generate(size_t sample_count) msu_resampler->push_sample(*left, *right); MSU1.MSU1_AUDIO_POS += 4; - partial_frames -= 3200; + partial_frames -= 3204; } else if (bytes_read >= 0) @@ -270,7 +270,7 @@ void S9xMSU1Generate(size_t sample_count) else { MSU1.MSU1_STATUS &= ~(AudioPlaying | AudioRepeating); - partial_frames -= 3200; + partial_frames -= 3204; msu_resampler->push_sample(0, 0); } } diff --git a/snes9x.cpp b/snes9x.cpp index dcebe76e..2ce2919f 100644 --- a/snes9x.cpp +++ b/snes9x.cpp @@ -239,7 +239,7 @@ void S9xLoadConfigFiles (char **argv, int argc) Settings.Stereo = conf.GetBool("Sound::Stereo", true); Settings.ReverseStereo = conf.GetBool("Sound::ReverseStereo", false); Settings.SoundPlaybackRate = conf.GetUInt("Sound::Rate", 48000); - Settings.SoundInputRate = conf.GetUInt("Sound::InputRate", 31920); + Settings.SoundInputRate = conf.GetUInt("Sound::InputRate", 31950); Settings.Mute = conf.GetBool("Sound::Mute", false); Settings.DynamicRateControl = conf.GetBool("Sound::DynamicRateControl", false); Settings.DynamicRateLimit = conf.GetInt ("Sound::DynamicRateLimit", 5); diff --git a/unix/unix.cpp b/unix/unix.cpp index e4596cc2..cef2ba94 100644 --- a/unix/unix.cpp +++ b/unix/unix.cpp @@ -1441,7 +1441,7 @@ int main (int argc, char **argv) Settings.SixteenBitSound = TRUE; Settings.Stereo = TRUE; Settings.SoundPlaybackRate = 48000; - Settings.SoundInputRate = 31920; + Settings.SoundInputRate = 31950; Settings.SupportHiRes = TRUE; Settings.Transparency = TRUE; Settings.AutoDisplayMessages = TRUE; diff --git a/win32/glslang/src b/win32/glslang/src index c9e03360..a51d3d9f 160000 --- a/win32/glslang/src +++ b/win32/glslang/src @@ -1 +1 @@ -Subproject commit c9e03360e2a78a95a8571292aefa5ddbdbf66daf +Subproject commit a51d3d9f223361165127ded3cd2e59d81e22d91f diff --git a/win32/wconfig.cpp b/win32/wconfig.cpp index 6a9119ef..838b6b88 100644 --- a/win32/wconfig.cpp +++ b/win32/wconfig.cpp @@ -842,7 +842,7 @@ void WinRegisterConfigItems() #define CATEGORY "Sound" AddIntC("Sync", Settings.SoundSync, 1, "1 to sync emulation to sound output, 0 to disable."); AddUIntC("Rate", Settings.SoundPlaybackRate, 48000, "sound playback quality, in Hz"); - AddUIntC("InputRate", Settings.SoundInputRate, 31920, "for each 'Input rate' samples generated by the SNES, 'Playback rate' samples will produced. If you experience crackling you can try to lower this setting."); + AddUIntC("InputRate", Settings.SoundInputRate, 31950, "for each 'Input rate' samples generated by the SNES, 'Playback rate' samples will produced. If you experience crackling you can try to lower this setting."); AddBoolC("Mute", GUI.Mute, false, "true to mute sound output (does not disable the sound CPU)"); AddBool("DynamicRateControl", Settings.DynamicRateControl, false); AddBool("AutomaticInputRate", GUI.AutomaticInputRate, true); diff --git a/win32/win32_display.cpp b/win32/win32_display.cpp index d6110e13..cb6b2c24 100644 --- a/win32/win32_display.cpp +++ b/win32/win32_display.cpp @@ -648,9 +648,9 @@ int WinGetAutomaticInputRate(void) if (refreshRate > 239.0 && refreshRate < 241.0) refreshRate /= 4.0; - double newInputRate = refreshRate * 32000.0 / 60.09881389744051 + 0.5; + double newInputRate = refreshRate * 32040.0 / 60.09881389744051 + 0.5; - if (newInputRate > 32000.0 * 1.05 || newInputRate < 32000.0 * 0.95) + if (newInputRate > 32040.0 * 1.05 || newInputRate < 32040.0 * 0.95) newInputRate = 0.0; return (int)newInputRate; diff --git a/win32/win32_sound.cpp b/win32/win32_sound.cpp index 4aaad3f0..4f349a0c 100644 --- a/win32/win32_sound.cpp +++ b/win32/win32_sound.cpp @@ -41,7 +41,7 @@ bool ReInitSound() else { GUI.AutomaticInputRate = false; - Settings.SoundInputRate = 31920; + Settings.SoundInputRate = 31950; } }