mirror of https://github.com/snes9xgit/snes9x.git
Revert to higher APU clock.
This commit is contained in:
parent
b590ec10ab
commit
f70e072bd9
12
apu/apu.cpp
12
apu/apu.cpp
|
@ -14,12 +14,12 @@
|
||||||
|
|
||||||
#include "bapu/snes/snes.hpp"
|
#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_SAMPLE_BLOCK = 48;
|
||||||
static const int APU_NUMERATOR_NTSC = 5632;
|
static const int APU_NUMERATOR_NTSC = 15664;
|
||||||
static const int APU_DENOMINATOR_NTSC = 118125;
|
static const int APU_DENOMINATOR_NTSC = 328125;
|
||||||
static const int APU_NUMERATOR_PAL = 35527;
|
static const int APU_NUMERATOR_PAL = 34176;
|
||||||
static const int APU_DENOMINATOR_PAL = 738343;
|
static const int APU_DENOMINATOR_PAL = 709379;
|
||||||
|
|
||||||
// Max number of samples we'll ever generate before call to port API and
|
// Max number of samples we'll ever generate before call to port API and
|
||||||
// moving the samples to the resampler.
|
// moving the samples to the resampler.
|
||||||
|
@ -184,7 +184,7 @@ static void UpdatePlaybackRate(void)
|
||||||
|
|
||||||
if (Settings.MSU1)
|
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);
|
msu::resampler->time_ratio(time_ratio);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -347,7 +347,7 @@
|
||||||
Settings.MultiPlayer5Master = true;<br>
|
Settings.MultiPlayer5Master = true;<br>
|
||||||
Settings.FrameTimePAL = 20000;<br>
|
Settings.FrameTimePAL = 20000;<br>
|
||||||
Settings.FrameTimeNTSC = 16667;<br>
|
Settings.FrameTimeNTSC = 16667;<br>
|
||||||
Settings.SoundPlaybackRate = 32000;<br>
|
Settings.SoundPlaybackRate = 32040;<br>
|
||||||
Settings.SoundInputRate = 31947;<br>
|
Settings.SoundInputRate = 31947;<br>
|
||||||
Settings.SupportHiRes = true;<br>
|
Settings.SupportHiRes = true;<br>
|
||||||
Settings.Transparency = 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.
|
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>
|
||||||
<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>
|
||||||
<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>
|
</p>
|
||||||
<h3><code>Settings.DynamicRateControl</code> and <code>S9xUpdateDynamicRate(int numerator, int denominator)</code></h3>
|
<h3><code>Settings.DynamicRateControl</code> and <code>S9xUpdateDynamicRate(int numerator, int denominator)</code></h3>
|
||||||
<p>
|
<p>
|
||||||
|
|
|
@ -427,7 +427,7 @@ event_input_rate_changed (GtkRange *range, gpointer data)
|
||||||
{
|
{
|
||||||
char text[256];
|
char text[256];
|
||||||
GtkLabel *label = GTK_LABEL (data);
|
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);
|
snprintf (text, 256, "%.4f hz", value);
|
||||||
|
|
||||||
|
|
|
@ -1579,9 +1579,9 @@ Snes9xWindow::get_auto_input_rate ()
|
||||||
if (refresh_rate > 239.0 && refresh_rate < 241.0)
|
if (refresh_rate > 239.0 && refresh_rate < 241.0)
|
||||||
refresh_rate /= 4.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;
|
new_input_rate = 0.0;
|
||||||
|
|
||||||
return new_input_rate;
|
return new_input_rate;
|
||||||
|
|
|
@ -133,7 +133,7 @@ S9xPortSoundInit ()
|
||||||
Settings.SoundInputRate = top_level->get_auto_input_rate ();
|
Settings.SoundInputRate = top_level->get_auto_input_rate ();
|
||||||
if (Settings.SoundInputRate == 0.0)
|
if (Settings.SoundInputRate == 0.0)
|
||||||
{
|
{
|
||||||
Settings.SoundInputRate = 31920;
|
Settings.SoundInputRate = 31950;
|
||||||
gui_config->auto_input_rate = 0;
|
gui_config->auto_input_rate = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_width = MAX_SNES_WIDTH_NTSC;
|
||||||
info->geometry.max_height = MAX_SNES_HEIGHT;
|
info->geometry.max_height = MAX_SNES_HEIGHT;
|
||||||
info->geometry.aspect_ratio = get_aspect_ratio(width, 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;
|
info->timing.fps = retro_get_region() == RETRO_REGION_NTSC ? 21477272.0 / 357366.0 : 21281370.0 / 425568.0;
|
||||||
|
|
||||||
g_screen_gun_width = width;
|
g_screen_gun_width = width;
|
||||||
|
@ -1254,8 +1254,8 @@ void retro_init(void)
|
||||||
Settings.FrameTimeNTSC = 16667;
|
Settings.FrameTimeNTSC = 16667;
|
||||||
Settings.SixteenBitSound = TRUE;
|
Settings.SixteenBitSound = TRUE;
|
||||||
Settings.Stereo = TRUE;
|
Settings.Stereo = TRUE;
|
||||||
Settings.SoundPlaybackRate = 32000;
|
Settings.SoundPlaybackRate = 32040;
|
||||||
Settings.SoundInputRate = 32000;
|
Settings.SoundInputRate = 32040;
|
||||||
Settings.SupportHiRes = TRUE;
|
Settings.SupportHiRes = TRUE;
|
||||||
Settings.Transparency = TRUE;
|
Settings.Transparency = TRUE;
|
||||||
Settings.AutoDisplayMessages = TRUE;
|
Settings.AutoDisplayMessages = TRUE;
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
<dt>Effect...</dt>
|
<dt>Effect...</dt>
|
||||||
<dd>Opens 'Sound Effect' dialog.</dd>
|
<dd>Opens 'Sound Effect' dialog.</dd>
|
||||||
<dt>Playback Rate</dt>
|
<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>
|
<dt>Output Interval</dt>
|
||||||
<dd>Make sure this value is smaller than the mix buffer length.</dd>
|
<dd>Make sure this value is smaller than the mix buffer length.</dd>
|
||||||
<dt>Mix Buffer Length</dt>
|
<dt>Mix Buffer Length</dt>
|
||||||
|
|
|
@ -29607,7 +29607,7 @@
|
||||||
<integer value="0" key="controlSize"/>
|
<integer value="0" key="controlSize"/>
|
||||||
<integer value="0" key="command"/>
|
<integer value="0" key="command"/>
|
||||||
<nil key="helpTagExtendedText"/>
|
<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"/>
|
<integer value="0" key="helpTagDisplaySide"/>
|
||||||
<object class="NSArray" key="auxiliaryProperties">
|
<object class="NSArray" key="auxiliaryProperties">
|
||||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||||
|
|
6
msu1.cpp
6
msu1.cpp
|
@ -230,7 +230,7 @@ void S9xMSU1Generate(size_t sample_count)
|
||||||
{
|
{
|
||||||
partial_frames += 4410 * (sample_count / 2);
|
partial_frames += 4410 * (sample_count / 2);
|
||||||
|
|
||||||
while (partial_frames >= 3200)
|
while (partial_frames >= 3204)
|
||||||
{
|
{
|
||||||
if (MSU1.MSU1_STATUS & AudioPlaying && audioStream)
|
if (MSU1.MSU1_STATUS & AudioPlaying && audioStream)
|
||||||
{
|
{
|
||||||
|
@ -246,7 +246,7 @@ void S9xMSU1Generate(size_t sample_count)
|
||||||
|
|
||||||
msu_resampler->push_sample(*left, *right);
|
msu_resampler->push_sample(*left, *right);
|
||||||
MSU1.MSU1_AUDIO_POS += 4;
|
MSU1.MSU1_AUDIO_POS += 4;
|
||||||
partial_frames -= 3200;
|
partial_frames -= 3204;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (bytes_read >= 0)
|
if (bytes_read >= 0)
|
||||||
|
@ -270,7 +270,7 @@ void S9xMSU1Generate(size_t sample_count)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MSU1.MSU1_STATUS &= ~(AudioPlaying | AudioRepeating);
|
MSU1.MSU1_STATUS &= ~(AudioPlaying | AudioRepeating);
|
||||||
partial_frames -= 3200;
|
partial_frames -= 3204;
|
||||||
msu_resampler->push_sample(0, 0);
|
msu_resampler->push_sample(0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -239,7 +239,7 @@ void S9xLoadConfigFiles (char **argv, int argc)
|
||||||
Settings.Stereo = conf.GetBool("Sound::Stereo", true);
|
Settings.Stereo = conf.GetBool("Sound::Stereo", true);
|
||||||
Settings.ReverseStereo = conf.GetBool("Sound::ReverseStereo", false);
|
Settings.ReverseStereo = conf.GetBool("Sound::ReverseStereo", false);
|
||||||
Settings.SoundPlaybackRate = conf.GetUInt("Sound::Rate", 48000);
|
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.Mute = conf.GetBool("Sound::Mute", false);
|
||||||
Settings.DynamicRateControl = conf.GetBool("Sound::DynamicRateControl", false);
|
Settings.DynamicRateControl = conf.GetBool("Sound::DynamicRateControl", false);
|
||||||
Settings.DynamicRateLimit = conf.GetInt ("Sound::DynamicRateLimit", 5);
|
Settings.DynamicRateLimit = conf.GetInt ("Sound::DynamicRateLimit", 5);
|
||||||
|
|
|
@ -1441,7 +1441,7 @@ int main (int argc, char **argv)
|
||||||
Settings.SixteenBitSound = TRUE;
|
Settings.SixteenBitSound = TRUE;
|
||||||
Settings.Stereo = TRUE;
|
Settings.Stereo = TRUE;
|
||||||
Settings.SoundPlaybackRate = 48000;
|
Settings.SoundPlaybackRate = 48000;
|
||||||
Settings.SoundInputRate = 31920;
|
Settings.SoundInputRate = 31950;
|
||||||
Settings.SupportHiRes = TRUE;
|
Settings.SupportHiRes = TRUE;
|
||||||
Settings.Transparency = TRUE;
|
Settings.Transparency = TRUE;
|
||||||
Settings.AutoDisplayMessages = TRUE;
|
Settings.AutoDisplayMessages = TRUE;
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit c9e03360e2a78a95a8571292aefa5ddbdbf66daf
|
Subproject commit a51d3d9f223361165127ded3cd2e59d81e22d91f
|
|
@ -842,7 +842,7 @@ void WinRegisterConfigItems()
|
||||||
#define CATEGORY "Sound"
|
#define CATEGORY "Sound"
|
||||||
AddIntC("Sync", Settings.SoundSync, 1, "1 to sync emulation to sound output, 0 to disable.");
|
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("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)");
|
AddBoolC("Mute", GUI.Mute, false, "true to mute sound output (does not disable the sound CPU)");
|
||||||
AddBool("DynamicRateControl", Settings.DynamicRateControl, false);
|
AddBool("DynamicRateControl", Settings.DynamicRateControl, false);
|
||||||
AddBool("AutomaticInputRate", GUI.AutomaticInputRate, true);
|
AddBool("AutomaticInputRate", GUI.AutomaticInputRate, true);
|
||||||
|
|
|
@ -648,9 +648,9 @@ int WinGetAutomaticInputRate(void)
|
||||||
if (refreshRate > 239.0 && refreshRate < 241.0)
|
if (refreshRate > 239.0 && refreshRate < 241.0)
|
||||||
refreshRate /= 4.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;
|
newInputRate = 0.0;
|
||||||
|
|
||||||
return (int)newInputRate;
|
return (int)newInputRate;
|
||||||
|
|
|
@ -41,7 +41,7 @@ bool ReInitSound()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GUI.AutomaticInputRate = false;
|
GUI.AutomaticInputRate = false;
|
||||||
Settings.SoundInputRate = 31920;
|
Settings.SoundInputRate = 31950;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue