apu: Clean up a bit.

Also fixes MSU not reflecting input rate setting.
This commit is contained in:
BearOso 2023-02-16 15:51:16 -06:00
parent 49b7d45fd0
commit eb24fd599f
1 changed files with 51 additions and 90 deletions

View File

@ -5,6 +5,7 @@
\*****************************************************************************/ \*****************************************************************************/
#include <cmath> #include <cmath>
#include <vector>
#include "../snes9x.h" #include "../snes9x.h"
#include "apu.h" #include "apu.h"
#include "../msu1.h" #include "../msu1.h"
@ -36,10 +37,10 @@ namespace spc {
static apu_callback callback = NULL; static apu_callback callback = NULL;
static void *callback_data = NULL; static void *callback_data = NULL;
static bool8 sound_in_sync = TRUE; static bool8 sound_in_sync = true;
static bool8 sound_enabled = FALSE; static bool8 sound_enabled = false;
static Resampler *resampler = NULL; static Resampler resampler;
static int32 reference_time; static int32 reference_time;
static uint32 remainder; static uint32 remainder;
@ -56,9 +57,8 @@ static double dynamic_rate_multiplier = 1.0;
namespace msu { namespace msu {
// Always 16-bit, Stereo; 1.5x dsp buffer to never overflow // Always 16-bit, Stereo; 1.5x dsp buffer to never overflow
static Resampler *resampler = NULL; static Resampler resampler;
static int16 *resample_buffer = NULL; static std::vector<int16_t> resampler_buffer;
static int resample_buffer_size = 0;
} // namespace msu } // namespace msu
static void UpdatePlaybackRate(void); static void UpdatePlaybackRate(void);
@ -74,44 +74,32 @@ bool8 S9xMixSamples(uint8 *dest, int sample_count)
{ {
memset(out, 0, sample_count << 1); memset(out, 0, sample_count << 1);
S9xClearSamples(); S9xClearSamples();
spc::sound_in_sync = true;
return true;
} }
else
if (spc::resampler.avail() < sample_count)
{ {
if (spc::resampler->avail() >= sample_count) memset(out, 0, sample_count << 1);
{ return false;
spc::resampler->read((short *)out, sample_count); }
if (Settings.MSU1) spc::resampler.read((short *)out, sample_count);
{
if (msu::resampler->avail() >= sample_count) if (Settings.MSU1)
{ {
if (msu::resample_buffer_size < sample_count) if ((int)msu::resampler_buffer.size() < sample_count)
{ msu::resampler_buffer.resize(sample_count);
if (msu::resample_buffer)
delete[] msu::resample_buffer; msu::resampler.read(msu::resampler_buffer.data(), sample_count);
msu::resample_buffer = new int16[sample_count]; for (int i = 0; i < sample_count; ++i)
msu::resample_buffer_size = sample_count;
}
msu::resampler->read(msu::resample_buffer,
sample_count);
for (int i = 0; i < sample_count; ++i)
{
int32 mixed = (int32)out[i] + msu::resample_buffer[i];
out[i] = ((int16)mixed != mixed) ? (mixed >> 31) ^ 0x7fff : mixed;
}
}
else // should never occur
assert(0);
}
}
else
{ {
memset(out, 0, sample_count << 1); int32 mixed = (int32)out[i] + msu::resampler_buffer[i];
return false; out[i] = ((int16)mixed != mixed) ? (mixed >> 31) ^ 0x7fff : mixed;
} }
} }
if (spc::resampler->space_empty() >= 535 * 2 || !Settings.SoundSync || if (spc::resampler.space_empty() >= 535 * 2 || !Settings.SoundSync ||
Settings.TurboMode || Settings.Mute) Settings.TurboMode || Settings.Mute)
spc::sound_in_sync = true; spc::sound_in_sync = true;
else else
@ -122,9 +110,9 @@ bool8 S9xMixSamples(uint8 *dest, int sample_count)
int S9xGetSampleCount(void) int S9xGetSampleCount(void)
{ {
int avail = spc::resampler->avail(); int avail = spc::resampler.avail();
if (Settings.MSU1) // return minimum available samples, otherwise we can run into the assert above due to partial sample generation in msu1 if (Settings.MSU1) // return minimum available samples, otherwise we can run into the assert above due to partial sample generation in msu1
avail = Resampler::min(avail, msu::resampler->avail()); avail = Resampler::min(avail, msu::resampler.avail());
return avail; return avail;
} }
@ -133,7 +121,7 @@ void S9xLandSamples(void)
if (spc::callback != NULL) if (spc::callback != NULL)
spc::callback(spc::callback_data); spc::callback(spc::callback_data);
if (spc::resampler->space_empty() >= 535 * 2 || !Settings.SoundSync || if (spc::resampler.space_empty() >= 535 * 2 || !Settings.SoundSync ||
Settings.TurboMode || Settings.Mute) Settings.TurboMode || Settings.Mute)
spc::sound_in_sync = true; spc::sound_in_sync = true;
else else
@ -142,15 +130,15 @@ void S9xLandSamples(void)
void S9xClearSamples(void) void S9xClearSamples(void)
{ {
spc::resampler->clear(); spc::resampler.clear();
if (Settings.MSU1) if (Settings.MSU1)
msu::resampler->clear(); msu::resampler.clear();
} }
bool8 S9xSyncSound(void) bool8 S9xSyncSound(void)
{ {
if (!Settings.SoundSync || spc::sound_in_sync) if (!Settings.SoundSync || spc::sound_in_sync)
return (TRUE); return true;
S9xLandSamples(); S9xLandSamples();
@ -183,12 +171,12 @@ static void UpdatePlaybackRate(void)
time_ratio *= spc::dynamic_rate_multiplier; time_ratio *= spc::dynamic_rate_multiplier;
} }
spc::resampler->time_ratio(time_ratio); spc::resampler.time_ratio(time_ratio);
if (Settings.MSU1) if (Settings.MSU1)
{ {
time_ratio = (44100.0 / Settings.SoundPlaybackRate) * (Settings.SoundInputRate / 32040.0); time_ratio = time_ratio * 44100 / 32040;
msu::resampler->time_ratio(time_ratio); msu::resampler.time_ratio(time_ratio);
} }
} }
@ -201,27 +189,11 @@ bool8 S9xInitSound(int buffer_ms)
if (requested_buffer_size_samples > buffer_size_samples) if (requested_buffer_size_samples > buffer_size_samples)
buffer_size_samples = requested_buffer_size_samples; buffer_size_samples = requested_buffer_size_samples;
if (!spc::resampler) spc::resampler.resize(buffer_size_samples);
{ msu::resampler.resize(buffer_size_samples * 3 / 2);
spc::resampler = new Resampler(buffer_size_samples);
if (!spc::resampler)
return (FALSE);
}
else
spc::resampler->resize(buffer_size_samples);
SNES::dsp.spc_dsp.set_output(&spc::resampler);
if (!msu::resampler) S9xMSU1SetOutput(&msu::resampler);
{
msu::resampler = new Resampler(buffer_size_samples * 3 / 2);
if (!msu::resampler)
return (FALSE);
}
else
msu::resampler->resize(buffer_size_samples * 3 / 2);
SNES::dsp.spc_dsp.set_output(spc::resampler);
S9xMSU1SetOutput(msu::resampler);
UpdatePlaybackRate(); UpdatePlaybackRate();
@ -239,7 +211,7 @@ void S9xSetSoundMute(bool8 mute)
{ {
Settings.Mute = mute; Settings.Mute = mute;
if (!spc::sound_enabled) if (!spc::sound_enabled)
Settings.Mute = TRUE; Settings.Mute = true;
} }
void S9xDumpSPCSnapshot(void) void S9xDumpSPCSnapshot(void)
@ -255,27 +227,16 @@ static void SPCSnapshotCallback(void)
bool8 S9xInitAPU(void) bool8 S9xInitAPU(void)
{ {
spc::resampler = NULL; spc::resampler.clear();
msu::resampler = NULL; msu::resampler.clear();
return (TRUE); return true;
} }
void S9xDeinitAPU(void) void S9xDeinitAPU(void)
{ {
if (spc::resampler)
{
delete spc::resampler;
spc::resampler = NULL;
}
if (msu::resampler)
{
delete msu::resampler;
msu::resampler = NULL;
}
S9xMSU1DeInit(); S9xMSU1DeInit();
msu::resampler_buffer.clear();
} }
static inline int S9xAPUGetClock(int32 cpucycles) static inline int S9xAPUGetClock(int32 cpucycles)
@ -309,10 +270,10 @@ void S9xAPUSetReferenceTime(int32 cpucycles)
void S9xAPUExecute(void) void S9xAPUExecute(void)
{ {
SNES::smp.clock -= S9xAPUGetClock(CPU.Cycles); int cycles = S9xAPUGetClock(CPU.Cycles);
SNES::smp.enter();
spc::remainder = S9xAPUGetClockRemainder(CPU.Cycles); spc::remainder = S9xAPUGetClockRemainder(CPU.Cycles);
SNES::smp.clock -= cycles;
SNES::smp.enter();
S9xAPUSetReferenceTime(CPU.Cycles); S9xAPUSetReferenceTime(CPU.Cycles);
} }
@ -322,7 +283,7 @@ void S9xAPUEndScanline(void)
S9xAPUExecute(); S9xAPUExecute();
SNES::dsp.synchronize(); SNES::dsp.synchronize();
if (spc::resampler->space_filled() >= APU_SAMPLE_BLOCK || !spc::sound_in_sync) if (spc::resampler.space_filled() >= APU_SAMPLE_BLOCK)
S9xLandSamples(); S9xLandSamples();
} }
@ -518,9 +479,9 @@ bool8 S9xSPCDump(const char *filename)
fs = fopen(filename, "wb"); fs = fopen(filename, "wb");
if (!fs) if (!fs)
return (FALSE); return false;
S9xSetSoundMute(TRUE); S9xSetSoundMute(true);
SNES::smp.save_spc(buf); SNES::smp.save_spc(buf);
@ -533,7 +494,7 @@ bool8 S9xSPCDump(const char *filename)
fclose(fs); fclose(fs);
S9xSetSoundMute(FALSE); S9xSetSoundMute(false);
return (TRUE); return true;
} }