summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/disound.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/disound.c')
-rw-r--r--src/emu/disound.c226
1 files changed, 226 insertions, 0 deletions
diff --git a/src/emu/disound.c b/src/emu/disound.c
new file mode 100644
index 00000000000..c34523eae4d
--- /dev/null
+++ b/src/emu/disound.c
@@ -0,0 +1,226 @@
+/***************************************************************************
+
+ disound.c
+
+ Device sound interfaces.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "streams.h"
+
+
+
+//**************************************************************************
+// DEVICE CONFIG SOUND INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_config_sound_interface - constructor
+//-------------------------------------------------
+
+device_config_sound_interface::device_config_sound_interface(const machine_config &mconfig, device_config &devconfig)
+ : device_config_interface(mconfig, devconfig),
+ m_route_list(NULL)
+{
+}
+
+
+//-------------------------------------------------
+// ~device_config_sound_interface - destructor
+//-------------------------------------------------
+
+device_config_sound_interface::~device_config_sound_interface()
+{
+ reset_routes();
+}
+
+
+//-------------------------------------------------
+// interface_process_token - token processing for
+// the sound interface
+//-------------------------------------------------
+
+bool device_config_sound_interface::interface_process_token(UINT32 entrytype, const machine_config_token *&tokens)
+{
+ switch (entrytype)
+ {
+ // custom config 1 is a new route
+ case MCONFIG_TOKEN_DISOUND_ROUTE:
+ {
+ // put back the token that was originally fetched so we can grab a packed 64-bit token
+ TOKEN_UNGET_UINT32(tokens);
+
+ // extract data
+ int output, input;
+ UINT32 gain;
+ TOKEN_GET_UINT64_UNPACK4(tokens, entrytype, 8, output, 12, input, 12, gain, 32);
+ float fgain = (float)gain * (1.0f / (float)(1 << 24));
+ const char *target = TOKEN_GET_STRING(tokens);
+
+ // allocate a new route
+ sound_route **routeptr;
+ for (routeptr = &m_route_list; *routeptr != NULL; routeptr = &(*routeptr)->m_next) ;
+ *routeptr = global_alloc(sound_route(output, input, fgain, target));
+ return true;
+ }
+
+ // custom config 2 resets the sound routes
+ case MCONFIG_TOKEN_DISOUND_RESET:
+ reset_routes();
+ return true;
+ }
+
+ return false;
+}
+
+
+//-------------------------------------------------
+// interface_validity_check - validation for a
+// device after the configuration has been
+// constructed
+//-------------------------------------------------
+
+bool device_config_sound_interface::interface_validity_check(const game_driver &driver) const
+{
+ bool error = false;
+
+ // loop over all the routes
+ for (const sound_route *route = m_route_list; route != NULL; route = route->m_next)
+ {
+ // find a device with the requested tag
+ const device_config *target = m_machine_config.devicelist.find(route->m_target);
+ if (target == NULL)
+ {
+ mame_printf_error("%s: %s attempting to route sound to non-existant device '%s'\n", driver.source_file, driver.name, route->m_target);
+ error = true;
+ }
+
+ // if it's not a speaker or a sound device, error
+ const device_config_sound_interface *sound;
+ if (target->type() != SPEAKER && !target->interface(sound))
+ {
+ mame_printf_error("%s: %s attempting to route sound to a non-sound device '%s' (%s)\n", driver.source_file, driver.name, route->m_target, target->name());
+ error = true;
+ }
+ }
+ return error;
+}
+
+
+//-------------------------------------------------
+// reset_routes - free up all allocated routes
+// in this configuration
+//-------------------------------------------------
+
+void device_config_sound_interface::reset_routes()
+{
+ // loop until all are gone
+ while (m_route_list != NULL)
+ {
+ sound_route *temp = m_route_list;
+ m_route_list = temp->m_next;
+ global_free(temp);
+ }
+}
+
+
+//-------------------------------------------------
+// sound_route - constructor
+//-------------------------------------------------
+
+device_config_sound_interface::sound_route::sound_route(int output, int input, float gain, const char *target)
+ : m_next(NULL),
+ m_output(output),
+ m_input(input),
+ m_gain(gain),
+ m_target(target)
+{
+}
+
+
+
+//**************************************************************************
+// DEVICE CONFIG SOUND INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_sound_interface - constructor
+//-------------------------------------------------
+
+device_sound_interface::device_sound_interface(running_machine &machine, const device_config &config, device_t &device)
+ : device_interface(machine, config, device),
+ m_outputs(0),
+ m_sound_config(dynamic_cast<const device_config_sound_interface &>(config))
+{
+}
+
+
+//-------------------------------------------------
+// ~device_sound_interface - destructor
+//-------------------------------------------------
+
+device_sound_interface::~device_sound_interface()
+{
+}
+
+
+//-------------------------------------------------
+// interface_post_start - verify that state was
+// properly set up
+//-------------------------------------------------
+
+void device_sound_interface::interface_post_start()
+{
+ // count the outputs
+ for (int outputnum = 0; outputnum < MAX_OUTPUTS; outputnum++)
+ {
+ // stop when we run out of streams
+ sound_stream *stream = stream_find_by_device(&m_device, outputnum);
+ if (stream == NULL)
+ break;
+
+ // accumulate the number of outputs from this stream
+ int numoutputs = stream_get_outputs(stream);
+ assert(m_outputs + numoutputs < MAX_OUTPUTS);
+
+ // fill in the array
+ for (int curoutput = 0; curoutput < numoutputs; curoutput++)
+ {
+ sound_output *output = &m_output[m_outputs++];
+ output->stream = stream;
+ output->output = curoutput;
+ }
+ }
+}