Revert to higher APU clock.

This commit is contained in:
Brandon Wright 2019-04-12 12:10:51 -05:00
parent b590ec10ab
commit f70e072bd9
15 changed files with 28 additions and 28 deletions

View File

@ -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);
}
}

View File

@ -347,7 +347,7 @@
Settings.MultiPlayer5Master = true;<br>
Settings.FrameTimePAL = 20000;<br>
Settings.FrameTimeNTSC = 16667;<br>
Settings.SoundPlaybackRate = 32000;<br>
Settings.SoundPlaybackRate = 32040;<br>
Settings.SoundInputRate = 31947;<br>
Settings.SupportHiRes = true;<br>
Settings.Transparency = true;<br>
@ -361,10 +361,10 @@
Adjusts the sound rate through resampling. For every <code>Settings.SoundInputRate</code> samples generated by the SNES, <code>Settings.SoundPlaybackRate</code> samples will be produced.
</p>
<p>
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. <br>
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. <br>
</p>
<p>
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 <code>Settings.SoundInputRate</code> to suit their own systems. Setting <code>Settings.SoundInputRate</code> 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 <code>S9xSyncSound</code> 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 <code>Settings.SoundInputRate</code> to suit their own systems. Setting <code>Settings.SoundInputRate</code> 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 <code>S9xSyncSound</code> 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.
</p>
<h3><code>Settings.DynamicRateControl</code> and <code>S9xUpdateDynamicRate(int numerator, int denominator)</code></h3>
<p>

View File

@ -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);

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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;

View File

@ -56,7 +56,7 @@
<dt>Effect...</dt>
<dd>Opens 'Sound Effect' dialog.</dd>
<dt>Playback Rate</dt>
<dd>The real SNES is 32000 Hz. Any values other than 32000 Hz will cause resampling.</dd>
<dd>The real SNES is 32040 Hz. Any values other than 32040 Hz will cause resampling.</dd>
<dt>Output Interval</dt>
<dd>Make sure this value is smaller than the mix buffer length.</dd>
<dt>Mix Buffer Length</dt>

View File

@ -29607,7 +29607,7 @@
<integer value="0" key="controlSize"/>
<integer value="0" key="command"/>
<nil key="helpTagExtendedText"/>
<string key="helpTagText">The real SNES is 32000 Hz. Any values other than 32000 Hz will cause resampling.</string>
<string key="helpTagText">The real SNES is 32040 Hz. Any values other than 32040 Hz will cause resampling.</string>
<integer value="0" key="helpTagDisplaySide"/>
<object class="NSArray" key="auxiliaryProperties">
<bool key="EncodedWithXMLCoder">YES</bool>

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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;

@ -1 +1 @@
Subproject commit c9e03360e2a78a95a8571292aefa5ddbdbf66daf
Subproject commit a51d3d9f223361165127ded3cd2e59d81e22d91f

View File

@ -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);

View File

@ -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;

View File

@ -41,7 +41,7 @@ bool ReInitSound()
else
{
GUI.AutomaticInputRate = false;
Settings.SoundInputRate = 31920;
Settings.SoundInputRate = 31950;
}
}