diff options
Diffstat (limited to 'src/emu/sound.cpp')
-rw-r--r-- | src/emu/sound.cpp | 147 |
1 files changed, 98 insertions, 49 deletions
diff --git a/src/emu/sound.cpp b/src/emu/sound.cpp index 56b7d7ef071..c9626855197 100644 --- a/src/emu/sound.cpp +++ b/src/emu/sound.cpp @@ -9,32 +9,30 @@ ***************************************************************************/ #include "emu.h" -#include "speaker.h" -#include "emuopts.h" -#include "osdepend.h" + #include "config.h" +#include "emuopts.h" +#include "main.h" +#include "speaker.h" + #include "wavwrite.h" +#include "xmlfile.h" +#include "osdepend.h" //************************************************************************** // DEBUGGING //************************************************************************** -#define VERBOSE (0) +//#define VERBOSE 1 +#define LOG_OUTPUT_FUNC osd_printf_debug -#define VPRINTF(x) do { if (VERBOSE) osd_printf_debug x; } while (0) +#include "logmacro.h" #define LOG_OUTPUT_WAV (0) - -//************************************************************************** -// CONSTANTS -//************************************************************************** - - - //************************************************************************** // GLOBAL VARIABLES //************************************************************************** @@ -42,7 +40,6 @@ const attotime sound_manager::STREAMS_UPDATE_ATTOTIME = attotime::from_hz(STREAMS_UPDATE_FREQUENCY); - //************************************************************************** // STREAM BUFFER //************************************************************************** @@ -560,6 +557,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 +576,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++) @@ -602,7 +602,7 @@ sound_stream::sound_stream(device_t &device, u32 inputs, u32 outputs, u32 output // create an update timer for synchronous streams if (synchronous()) - m_sync_timer = m_device.machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sound_stream::sync_update), this)); + m_sync_timer = m_device.timer_alloc(FUNC(sound_stream::sync_update), this); // force an update to the sample rates sample_rate_changed(); @@ -648,8 +648,8 @@ void sound_stream::set_sample_rate(u32 new_rate) void sound_stream::set_input(int index, sound_stream *input_stream, int output_index, float gain) { - VPRINTF(("stream_set_input(%p, '%s', %d, %p, %d, %f)\n", (void *)this, m_device.tag(), - index, (void *)input_stream, output_index, (double) gain)); + LOG("stream_set_input(%p, '%s', %d, %p, %d, %f)\n", (void *)this, m_device.tag(), + index, (void *)input_stream, output_index, gain); // make sure it's a valid input if (index >= m_input.size()) @@ -704,7 +704,7 @@ read_stream_view sound_stream::update_view(attotime start, attotime end, u32 out if (start > end) start = end; - g_profiler.start(PROFILER_SOUND); + auto profile = g_profiler.start(PROFILER_SOUND); // reposition our start to coincide with the current buffer end attotime update_start = m_output[outputnum].end_time(); @@ -752,7 +752,6 @@ read_stream_view sound_stream::update_view(attotime start, attotime end, u32 out #endif } } - g_profiler.stop(); // return the requested view return read_stream_view(m_output_view[outputnum], start); @@ -857,14 +856,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 @@ -885,7 +894,7 @@ void sound_stream::reprime_sync_timer() // synchronous stream //------------------------------------------------- -void sound_stream::sync_update(void *, s32) +void sound_stream::sync_update(s32) { update(); reprime_sync_timer(); @@ -1076,18 +1085,10 @@ sound_manager::sound_manager(running_machine &machine) : m_wavfile(), m_first_reset(true) { - // get filename for WAV file or AVI file if specified - const char *wavfile = machine.options().wav_write(); - const char *avifile = machine.options().avi_write(); - - // handle -nosound and lower sample rate if not recording WAV or AVI - if (m_nosound_mode && wavfile[0] == 0 && avifile[0] == 0) - machine.m_sample_rate = 11025; - // count the mixers #if VERBOSE mixer_interface_enumerator iter(machine.root_device()); - VPRINTF(("total mixers = %d\n", iter.count())); + LOG("total mixers = %d\n", iter.count()); #endif // register callbacks @@ -1366,16 +1367,44 @@ void sound_manager::config_load(config_type cfg_type, config_level cfg_level, ut if ((cfg_type != config_type::SYSTEM) || !parentnode) return; + // master volume attenuation + if (util::xml::data_node const *node = parentnode->get_child("attenuation")) + { + // treat source INI files or more specific as higher priority than CFG + // FIXME: leaky abstraction - this depends on a front-end implementation detail + if ((OPTION_PRIORITY_NORMAL + 5) > machine().options().get_entry(OPTION_VOLUME)->priority()) + set_attenuation(std::clamp(int(node->get_attribute_int("value", 0)), -32, 0)); + } + // iterate over channel nodes - for (util::xml::data_node const *channelnode = parentnode->get_child("channel"); channelnode != nullptr; channelnode = channelnode->get_next_sibling("channel")) + for (util::xml::data_node const *node = parentnode->get_child("channel"); node != nullptr; node = node->get_next_sibling("channel")) { mixer_input info; - if (indexed_mixer_input(channelnode->get_attribute_int("index", -1), info)) + if (indexed_mixer_input(node->get_attribute_int("index", -1), info)) + { + // note that this doesn't disallow out-of-range values + float value = node->get_attribute_float("value", std::nanf("")); + + if (!std::isnan(value)) + info.stream->input(info.inputnum).set_user_gain(value); + } + } + + // iterate over speaker panning nodes + for (util::xml::data_node const *node = parentnode->get_child("panning"); node != nullptr; node = node->get_next_sibling("panning")) + { + char const *const tag = node->get_attribute_string("tag", nullptr); + if (tag != nullptr) { - float defvol = channelnode->get_attribute_float("defvol", 1.0f); - float newvol = channelnode->get_attribute_float("newvol", -1000.0f); - if (newvol != -1000.0f) - info.stream->input(info.inputnum).set_user_gain(newvol / defvol); + for (speaker_device &speaker : speaker_device_enumerator(machine().root_device())) + { + if (!strcmp(tag, speaker.tag())) + { + float value = node->get_attribute_float("value", speaker.defpan()); + speaker.set_pan(value); + break; + } + } } } } @@ -1392,21 +1421,43 @@ void sound_manager::config_save(config_type cfg_type, util::xml::data_node *pare if (cfg_type != config_type::SYSTEM) return; - // iterate over mixer channels + // master volume attenuation + if (m_attenuation != machine().options().volume()) + { + if (util::xml::data_node *const node = parentnode->add_child("attenuation", nullptr)) + node->set_attribute_int("value", m_attenuation); + } + + // iterate over mixer channels for per-channel volume for (int mixernum = 0; ; mixernum++) { mixer_input info; if (!indexed_mixer_input(mixernum, info)) break; - float const newvol = info.stream->input(info.inputnum).user_gain(); - if (newvol != 1.0f) + float const value = info.stream->input(info.inputnum).user_gain(); + if (value != 1.0f) { - util::xml::data_node *const channelnode = parentnode->add_child("channel", nullptr); - if (channelnode) + util::xml::data_node *const node = parentnode->add_child("channel", nullptr); + if (node) { - channelnode->set_attribute_int("index", mixernum); - channelnode->set_attribute_float("newvol", newvol); + node->set_attribute_int("index", mixernum); + node->set_attribute_float("value", value); + } + } + } + + // iterate over speakers for panning + for (speaker_device &speaker : speaker_device_enumerator(machine().root_device())) + { + float const value = speaker.pan(); + if (value != speaker.defpan()) + { + util::xml::data_node *const node = parentnode->add_child("panning", nullptr); + if (node) + { + node->set_attribute("tag", speaker.tag()); + node->set_attribute_float("value", value); } } } @@ -1457,11 +1508,11 @@ stream_buffer::sample_t sound_manager::adjust_toward_compressor_scale(stream_buf // and send it to the OSD layer //------------------------------------------------- -void sound_manager::update(void *ptr, int param) +void sound_manager::update(s32 param) { - VPRINTF(("sound_update\n")); + LOG("sound_update\n"); - g_profiler.start(PROFILER_SOUND); + auto profile = g_profiler.start(PROFILER_SOUND); // determine the duration of this update attotime update_period = machine().time() - m_last_update; @@ -1597,6 +1648,4 @@ void sound_manager::update(void *ptr, int param) // notify that new samples have been generated emulator_info::sound_hook(); - - g_profiler.stop(); } |