sound.cpp: Fix missed samples due to state save (#9917) (#9918)

* sound.cpp: Fix missed samples due to state save (#9917)

The PR address #9917. A save state may occur between time slices.
Sound devices through sound.cpp are updated during a timer call every
20ms. When the state is saved, these devices are not updated to the
current machine time. Consequently after a state load the devices have
have a "time lag" since in postload buffer end time is forced to
machine time.
This change will save the last buffer end time so that all outstanding
samples are processed.

This is a core change. I tested it on some drivers. This needs a very
thorough review and I post the PR primarily to document a possible
solution.

* sound.cpp: use "stream.sound_stream" as module name for save_item

* sound.cpp: use presave handler to store end_time()
This commit is contained in:
couriersud 2022-06-15 12:39:00 +02:00 committed by GitHub
parent ac042242b7
commit fe1e26a9fb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 22 additions and 4 deletions

View File

@ -15,7 +15,7 @@
#include "config.h"
#include "wavwrite.h"
#include <vector>
//**************************************************************************
// DEBUGGING
@ -560,6 +560,7 @@ sound_stream::sound_stream(device_t &device, u32 inputs, u32 outputs, u32 output
m_synchronous((flags & STREAM_SYNCHRONOUS) != 0),
m_resampling_disabled((flags & STREAM_DISABLE_INPUT_RESAMPLING) != 0),
m_sync_timer(nullptr),
m_last_update_end_time(attotime::zero),
m_input(inputs),
m_input_view(inputs),
m_empty_buffer(100),
@ -578,8 +579,10 @@ sound_stream::sound_stream(device_t &device, u32 inputs, u32 outputs, u32 output
// create a unique tag for saving
std::string state_tag = string_format("%d", m_device.machine().sound().unique_id());
auto &save = m_device.machine().save();
save.save_item(&m_device, "stream.sample_rate", state_tag.c_str(), 0, NAME(m_sample_rate));
save.save_item(&m_device, "stream.sound_stream", state_tag.c_str(), 0, NAME(m_sample_rate));
save.save_item(&m_device, "stream.sound_stream", state_tag.c_str(), 0, NAME(m_last_update_end_time));
save.register_postload(save_prepost_delegate(FUNC(sound_stream::postload), this));
save.register_presave(save_prepost_delegate(FUNC(sound_stream::presave), this));
// initialize all inputs
for (unsigned int inputnum = 0; inputnum < m_input.size(); inputnum++)
@ -857,14 +860,24 @@ void sound_stream::sample_rate_changed()
void sound_stream::postload()
{
// set the end time of all of our streams to now
// set the end time of all of our streams to the value saved in m_last_update_end_time
for (auto &output : m_output)
output.set_end_time(m_device.machine().time());
output.set_end_time(m_last_update_end_time);
// recompute the sample rate information
sample_rate_changed();
}
//-------------------------------------------------
// presave - save/restore callback
//-------------------------------------------------
void sound_stream::presave()
{
// save the stream end time
m_last_update_end_time = m_output[0].end_time();
}
//-------------------------------------------------
// reprime_sync_timer - set up the next sync

View File

@ -670,6 +670,9 @@ private:
// handle updates after a save state load
void postload();
// handle updates before a save state load
void presave();
// re-print the synchronization timer
void reprime_sync_timer();
@ -693,6 +696,8 @@ private:
bool m_resampling_disabled; // is resampling of input streams disabled?
emu_timer *m_sync_timer; // update timer for synchronous streams
attotime m_last_update_end_time; // last end_time() in update
// input information
std::vector<sound_stream_input> m_input; // list of streams we directly depend upon
std::vector<read_stream_view> m_input_view; // array of output views for passing to the callback