summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author smf- <smf-@users.noreply.github.com>2018-07-29 13:32:24 +0100
committer smf- <smf-@users.noreply.github.com>2018-07-29 13:47:56 +0100
commit3a732c9b1c32cdb7522eff092d179d3adc3bef7a (patch)
treee8eef508b3cee6cd9180f2be48b4c5456c43bb11
parent64afd77e7c7ae7399373dcdff6ecb20ee8d50532 (diff)
Fix setting sample rate back to zero & crash for synchronous streams when rate is zero. This fixes all reported bugs. (nw)
-rw-r--r--src/emu/schedule.cpp51
-rw-r--r--src/emu/sound.cpp61
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];