From 3a732c9b1c32cdb7522eff092d179d3adc3bef7a Mon Sep 17 00:00:00 2001 From: smf- Date: Sun, 29 Jul 2018 13:32:24 +0100 Subject: Fix setting sample rate back to zero & crash for synchronous streams when rate is zero. This fixes all reported bugs. (nw) --- src/emu/schedule.cpp | 51 ++++++++++++++++++++++--------------------- src/emu/sound.cpp | 61 ++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 71 insertions(+), 41 deletions(-) diff --git a/src/emu/schedule.cpp b/src/emu/schedule.cpp index d281446d6c6..ba6c5e79302 100644 --- a/src/emu/schedule.cpp +++ b/src/emu/schedule.cpp @@ -452,7 +452,12 @@ void device_scheduler::timeslice() { // only process if this CPU is executing or truly halted (not yielding) // and if our target is later than the CPU's current time (coarse check) - if (EXPECTED((exec->m_suspend == 0 || exec->m_eatcycles) && target.seconds() >= exec->m_localtime.seconds())) + if (exec->m_suspend != 0) + { + if (exec->m_eatcycles) + exec->m_localtime = target; + } + else if (target.seconds() >= exec->m_localtime.seconds()) { // compute how many attoseconds to execute this CPU attoseconds_t delta = target.attoseconds() - exec->m_localtime.attoseconds(); @@ -467,33 +472,29 @@ void device_scheduler::timeslice() int ran = exec->m_cycles_running = divu_64x32(u64(delta) >> exec->m_divshift, exec->m_divisor); LOG((" cpu '%s': %d (%d cycles)\n", exec->device().tag(), delta, exec->m_cycles_running)); - // if we're not suspended, actually execute - if (exec->m_suspend == 0) + g_profiler.start(exec->m_profiler); + + // note that this global variable cycles_stolen can be modified + // via the call to cpu_execute + exec->m_cycles_stolen = 0; + m_executing_device = exec; + *exec->m_icountptr = exec->m_cycles_running; + if (!call_debugger) + exec->run(); + else { - g_profiler.start(exec->m_profiler); - - // note that this global variable cycles_stolen can be modified - // via the call to cpu_execute - exec->m_cycles_stolen = 0; - m_executing_device = exec; - *exec->m_icountptr = exec->m_cycles_running; - if (!call_debugger) - exec->run(); - else - { - exec->debugger_start_cpu_hook(target); - exec->run(); - exec->debugger_stop_cpu_hook(); - } - - // adjust for any cycles we took back - assert(ran >= *exec->m_icountptr); - ran -= *exec->m_icountptr; - assert(ran >= exec->m_cycles_stolen); - ran -= exec->m_cycles_stolen; - g_profiler.stop(); + exec->debugger_start_cpu_hook(target); + exec->run(); + exec->debugger_stop_cpu_hook(); } + // adjust for any cycles we took back + assert(ran >= *exec->m_icountptr); + ran -= *exec->m_icountptr; + assert(ran >= exec->m_cycles_stolen); + ran -= exec->m_cycles_stolen; + g_profiler.stop(); + // account for these cycles exec->m_totalcycles += ran; diff --git a/src/emu/sound.cpp b/src/emu/sound.cpp index 775d85057dd..ce72846a9c3 100644 --- a/src/emu/sound.cpp +++ b/src/emu/sound.cpp @@ -53,7 +53,7 @@ sound_stream::sound_stream(device_t &device, int inputs, int outputs, int sample : m_device(device), m_next(nullptr), m_sample_rate(sample_rate), - m_new_sample_rate(0), + m_new_sample_rate(0xffffffff), m_attoseconds_per_sample(0), m_max_samples_per_update(0), m_input(inputs), @@ -264,6 +264,9 @@ void sound_stream::set_input(int index, sound_stream *input_stream, int output_i void sound_stream::update() { + if (!m_attoseconds_per_sample) + return; + // determine the number of samples since the start of this second attotime time = m_device.machine().time(); s32 update_sampindex = s32(time.attoseconds() / m_attoseconds_per_sample); @@ -427,25 +430,35 @@ void sound_stream::update_with_accounting(bool second_tick) void sound_stream::apply_sample_rate_changes() { // skip if nothing to do - if (m_new_sample_rate == 0) + if (m_new_sample_rate == 0xffffffff) return; // update to the new rate and remember the old rate u32 old_rate = m_sample_rate; m_sample_rate = m_new_sample_rate; - m_new_sample_rate = 0; + m_new_sample_rate = 0xffffffff; // recompute all the data recompute_sample_rate_data(); // reset our sample indexes to the current time - m_output_sampindex = s64(m_output_sampindex) * s64(m_sample_rate) / old_rate; - m_output_update_sampindex = s64(m_output_update_sampindex) * s64(m_sample_rate) / old_rate; + if (old_rate) + { + m_output_sampindex = s64(m_output_sampindex) * s64(m_sample_rate) / old_rate; + m_output_update_sampindex = s64(m_output_update_sampindex) * s64(m_sample_rate) / old_rate; + } + else + { + m_output_sampindex = m_attoseconds_per_sample ? m_device.machine().sound().last_update().attoseconds() / m_attoseconds_per_sample : 0; + m_output_update_sampindex = m_output_sampindex; + } + m_output_base_sampindex = m_output_sampindex - m_max_samples_per_update; // clear out the buffer - for (auto & elem : m_output) - memset(&elem.m_buffer[0], 0, m_max_samples_per_update * sizeof(elem.m_buffer[0])); + if (m_max_samples_per_update) + for (auto & elem : m_output) + memset(&elem.m_buffer[0], 0, m_max_samples_per_update * sizeof(elem.m_buffer[0])); } @@ -471,15 +484,22 @@ void sound_stream::recompute_sample_rate_data() throw emu_fatalerror("Incompatible sample rates as input of a synchronous stream: %d and %d\n", m_sample_rate, input.m_source->m_stream->m_sample_rate); } } - if (!m_sample_rate) - m_sample_rate = 1000; } // recompute the timing parameters attoseconds_t update_attoseconds = m_device.machine().sound().update_attoseconds(); - m_attoseconds_per_sample = ATTOSECONDS_PER_SECOND / m_sample_rate; - m_max_samples_per_update = (update_attoseconds + m_attoseconds_per_sample - 1) / m_attoseconds_per_sample; + + if (m_sample_rate) + { + m_attoseconds_per_sample = ATTOSECONDS_PER_SECOND / m_sample_rate; + m_max_samples_per_update = (update_attoseconds + m_attoseconds_per_sample - 1) / m_attoseconds_per_sample; + } + else + { + m_attoseconds_per_sample = 0; + m_max_samples_per_update = 0; + } // update resample and output buffer sizes allocate_resample_buffers(); @@ -490,7 +510,7 @@ void sound_stream::recompute_sample_rate_data() { // if we have a source, see if its sample rate changed - if (input.m_source != nullptr) + if (input.m_source != nullptr && input.m_source->m_stream->m_sample_rate) { // okay, we have a new sample rate; recompute the latency to be the maximum // sample period between us and our input @@ -511,14 +531,23 @@ void sound_stream::recompute_sample_rate_data() input.m_latency_attoseconds = std::max(input.m_latency_attoseconds, latency); assert(input.m_latency_attoseconds < update_attoseconds); } + else + { + input.m_latency_attoseconds = 0; + } } // If synchronous, prime the timer if (m_synchronous) { attotime time = m_device.machine().time(); - attoseconds_t next_edge = m_attoseconds_per_sample - (time.attoseconds() % m_attoseconds_per_sample); - m_sync_timer->adjust(attotime(0, next_edge)); + if (m_attoseconds_per_sample) + { + attoseconds_t next_edge = m_attoseconds_per_sample - (time.attoseconds() % m_attoseconds_per_sample); + m_sync_timer->adjust(attotime(0, next_edge)); + } + else + m_sync_timer->adjust(attotime::never); } } @@ -587,7 +616,7 @@ void sound_stream::postload() memset(&elem.m_buffer[0], 0, m_output_bufalloc * sizeof(elem.m_buffer[0])); // recompute the sample indexes to make sense - m_output_sampindex = m_device.machine().sound().last_update().attoseconds() / m_attoseconds_per_sample; + m_output_sampindex = m_attoseconds_per_sample ? m_device.machine().sound().last_update().attoseconds() / m_attoseconds_per_sample : 0; m_output_update_sampindex = m_output_sampindex; m_output_base_sampindex = m_output_sampindex - m_max_samples_per_update; } @@ -653,7 +682,7 @@ stream_sample_t *sound_stream::generate_resampled_data(stream_input &input, u32 { // if we don't have an output to pull data from, generate silence stream_sample_t *dest = &input.m_resample[0]; - if (input.m_source == nullptr) + if (input.m_source == nullptr || input.m_source->m_stream->m_attoseconds_per_sample == 0) { memset(dest, 0, numsamples * sizeof(*dest)); return &input.m_resample[0]; -- cgit v1.2.3