Commit 12b16b68 authored by Dwedit's avatar Dwedit
Browse files

Fixes audio samples in the output buffer being destroyed after saving and loading state.

parent 2a15fe27
......@@ -738,6 +738,25 @@ void S9xAPUSaveState (uint8 *block)
ptr += sizeof(int32);
memcpy (ptr, SNES::cpu.registers, 4);
ptr += sizeof(int32);
//sample count within buffer
int sampleCount = SNES::dsp.spc_dsp.sample_count();
SNES::set_le32(ptr, sampleCount);
ptr += sizeof(int32);
//samples remaining in landing buffer
int maxSize = SPC_SAVE_STATE_BLOCK_SIZE - (ptr - block);
int copySize = sampleCount * sizeof(SNES::SPC_DSP::sample_t);
if (copySize > maxSize) copySize = maxSize;
if (SNES::dsp.spc_dsp.GetOutputBufferBase() != NULL)
{
memcpy(ptr, SNES::dsp.spc_dsp.GetOutputBufferBase(), copySize);
}
else
{
memset(ptr, 0, copySize);
}
ptr += copySize;
memset (ptr, 0, SPC_SAVE_STATE_BLOCK_SIZE-(ptr-block));
}
......@@ -756,6 +775,19 @@ void S9xAPULoadState (uint8 *block)
SNES::dsp.clock = SNES::get_le32(ptr);
ptr += sizeof(int32);
memcpy (SNES::cpu.registers, ptr, 4);
ptr += 4;
//sample count within buffer
int sampleCount = SNES::get_le32(ptr);
if (sampleCount > 160) sampleCount = 160;
if (sampleCount < 0) sampleCount = 0;
ptr += sizeof(int32);
//samples for landing buffer
if (sampleCount > 0)
{
SNES::dsp.spc_dsp.EnqueueSamples((const SNES::SPC_DSP::sample_t*)ptr, sampleCount);
}
}
static void to_var_from_buf (uint8 **buf, void *var, size_t size)
......
......@@ -1061,3 +1061,14 @@ int SPC_DSP::envx_value( int ch )
{
return m.voices[ch].env;
}
bool SPC_DSP::EnqueueSamples(const sample_t *samples, int sampleCount)
{
//used to restore samples back to the output buffer when loading state
if (m.out_begin == NULL) return false;
int samplesRemaining = m.out_end - m.out;
if (sampleCount > samplesRemaining) return false;
memcpy(m.out, samples, sampleCount * sizeof(sample_t));
m.out += sampleCount;
return true;
}
......@@ -244,6 +244,15 @@ private:
void echo_30();
void soft_reset_common();
public:
//Used to read samples from the output buffer when saving state.
const sample_t *GetOutputBufferBase()
{
return m.out_begin;
}
//Used to place samples in the output buffer when loading state
bool EnqueueSamples(const sample_t *samples, int sampleCount);
};
#include <assert.h>
......
......@@ -66,6 +66,13 @@ class HermiteResampler : public Resampler
void
read (short *data, int num_samples)
{
//If we are outputting the exact same ratio as the input, pull directly from the input buffer
if (r_step == 1.0)
{
ring_buffer::pull((unsigned char*)data, num_samples * sizeof(short));
return;
}
int i_position = start >> 1;
int max_samples = buffer_size >> 1;
short *internal_buffer = (short *) buffer;
......@@ -120,7 +127,13 @@ class HermiteResampler : public Resampler
inline int
avail (void)
{
return (int) floor (((size >> 2) - r_frac) / r_step) * 2;
//If we are outputting the exact same ratio as the input, find out directly from the input buffer
if (r_step == 1.0)
{
return (ring_buffer::space_filled() + sizeof(short) - 1) / sizeof(short);
}
return (int) floor (((size >> 2) - r_frac) / r_step) * 2;
}
};
......
......@@ -315,13 +315,25 @@ static void update_variables(void)
static void S9xAudioCallback(void*)
{
// Just pick a big buffer. We won't use it all.
static int16_t audio_buf[0x20000];
const int BUFFER_SIZE = 256;
// This is called every time 128 to 132 samples are generated, which happens about 8 times per frame. A buffer size of 256 samples is enough here.
static int16_t audio_buf[BUFFER_SIZE];
S9xFinalizeSamples();
size_t avail = S9xGetSampleCount();
S9xMixSamples((uint8*)audio_buf, avail);
audio_batch_cb(audio_buf,avail >> 1);
while (avail >= BUFFER_SIZE)
{
//this loop will never be entered, but handle oversized sample counts just in case
S9xMixSamples((uint8*)audio_buf, BUFFER_SIZE);
audio_batch_cb(audio_buf, BUFFER_SIZE >> 1);
avail -= BUFFER_SIZE;
}
if (avail > 0)
{
S9xMixSamples((uint8*)audio_buf, avail);
audio_batch_cb(audio_buf, avail >> 1);
}
}
void retro_get_system_info(struct retro_system_info *info)
......@@ -790,7 +802,7 @@ void retro_init(void)
//increasing the buffer size does not cause extra lag(tested with 1000ms buffer)
//bool8 S9xInitSound (int buffer_ms, int lag_ms)
S9xInitSound(1000, 0);//just give it a 1 second buffer
S9xInitSound(32, 0); //give it a 1.9 frame long buffer, or 1026 samples. The audio buffer is flushed every 128-132 samples anyway, so it won't get anywhere near there.
S9xSetSoundMute(FALSE);
S9xSetSamplesAvailableCallback(S9xAudioCallback, NULL);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment