summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/sound.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/sound.cpp')
-rw-r--r--src/emu/sound.cpp147
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();
}