New sound infrastructure.

Should be added soon:
- mute
- speaker/microphone resampling

To be added a little later:
- compression
- reverb

Needs to be added by someone else:
- coreaudio
- direct
- portaudio
- xaudio2
- js
This commit is contained in:
Olivier Galibert 2025-04-14 11:31:53 +02:00
parent ec636faeba
commit d0f1c15a0f
1092 changed files with 14552 additions and 9900 deletions

View File

@ -944,7 +944,7 @@ the audio output is overdriven. The default is ON (\-compressor).
.TP
.B \-volume, \-vol \fIvalue
Sets the startup volume. It can later be changed with the user interface
(see Keys section). The volume is an attenuation in dB: e.g.,
(see Keys section). The volume is in dB: e.g.,
"\-volume \-12" will start with \-12dB attenuation. The default is 0.
.\" +++++++++++++++++++++++++++++++++++++++++++++++++++++++
.\" SDL specific

View File

@ -2969,7 +2969,7 @@ Core Sound Options
**-volume** / **-vol** *<value>*
Sets the initial sound volume. It can be changed later with the user
interface (see Keys section). The volume is an attenuation in decibels:
interface (see Keys section). The volume is in decibels:
e.g. "**-volume -12**" will start with -12 dB attenuation. Note that if the
volume is changed in the user interface it will be saved to the
configuration file for the system. The value from the configuration file

View File

@ -99,6 +99,13 @@ emu.add_machine_post_load_notifier(callback)
Add a callback to receive notification after the emulated system is restored
to a previously saved state. Returns a
:ref:`notifier subscription <luascript-ref-notifiersub>`.
emu.register_sound_update(callback)
Add a callback to receive new samples that have been created. THe
samples are coming from the sound devices for which the hook
property has been set to true. The callback gets one parameter
which is a hash with device tag as key and a (channel-sized)
vector of (buffer-sized) vector of
samples in the -1..1 range.
emu.print_error(message)
Print an error message.
emu.print_warning(message)

View File

@ -404,9 +404,8 @@ sound.debugger_mute (read/write)
sound.system_mute (read/write)
A Boolean indicating whether sound output is muted at the request of the
emulated system.
sound.attenuation (read/write)
The output volume attenuation in decibels. Should generally be a negative
integer or zero.
sound.volume (read/write)
The output volume in decibels. Should generally be a negative or zero.
sound.recording (read-only)
A Boolean indicating whether sound output is currently being recorded to a
WAV file.

View File

@ -67,6 +67,9 @@ manager.machine.images
manager.machine.slots
Returns a device enumerator that will iterate over
:ref:`slot devices <luascript-ref-dislot>` in the system.
manager.machine.sounds
Returns a device enumerator that will iterate over
:ref:`sound devices <luascript-ref-disound>` in the system.
emu.device_enumerator(device, [depth])
Returns a device enumerator that will iterate over
:ref:`devices <luascript-ref-device>` in the sub-tree starting at the
@ -624,6 +627,52 @@ image.device (read-only)
The underlying :ref:`device <luascript-ref-device>`.
.. _luascript-ref-disound:
Sound device interface
---------------------
Wraps MAMEs ``device_sound_interface`` class which is a mix-in implemented by
devices that inputs and/or ouputs sound.
Instantiation
~~~~~~~~~~~~~
manager.machine.sounds[tag]
Gets an sound device by tag relative to the root machine device, or ``nil``
if no such device exists or it is not a slot device.
Properties
~~~~~~~~~~
sound.inputs (read-only)
Number of sound inputs of the device.
sound.outputs (read-only)
Number of sound outputs of the device.
sound.microphone (read-only)
True if the device is a microphone, false otherwise
sound.speaker (read-only)
True if the device is a speaker, false otherwise
sound.io_positions[] (read-only)
Non-empty only for microphones and speakers, indicates the positions of
the inputs or outputs as (x, y, z) coordinates (f.i. [-0.2, 0.0, 1.0])
sound.io_names[] (read-only)
Non-empty only for microphones and speakers, indicates the positions of
the inputs or outputs as strings (f.i. Front Left)
sound.hook
A boolean indicating whether to tap the output samples of this device in
the global sound hook.
sound.device (read-only)
The underlying :ref:`device <luascript-ref-device>`.
.. _luascript-ref-dislot:
Slot device interface

View File

@ -0,0 +1,147 @@
Audio effects
=============
.. contents:: :local:
1. Generalities
---------------
The audio effects are effects that are applied to the sound between
the speaker devices and the actual sound output. In the current
implementation the effect chain is fixed (but not the effect
parameters), and the parameters are stored in the cfg files. They are
honestly not really designed for extensibility yet, if ever.
Adding an effect requires working on four parts:
* audio_effects/aeffects.* for effect object creation and "publishing"
* audio_effects/youreffect.* for the effect implementation
* frontend/mame/ui/audioeffects.cpp to be able to instantiate the effect configuration menu
* frontend/mame/ui/audioyoureffect.* to implement the effect configuration menu
2. audio_effects/aeffects.*
---------------------------
The audio_effect class in the aeffect sources provides three things:
* an enum value to designate the effect type and which much match its
position in the chain (iow, the effect chain follows the enum order),
in the .h
* the effect name in the audio_effect::effect_names array in the .cpp
* the creation of a correct effect object in audio_effect::create in the .cpp
3. audio_effects/youreffect.*
-----------------------------
This is where you implement the effect. It takes the shape of a
audio_effect_youreffect class which derives from audio_effect.
The methods to implement are:
.. code-block:: C++
audio_effect_youreffect(u32 sample_rate, audio_effect *def);
virtual int type() const override;
virtual void config_load(util::xml::data_node const *ef_node) override;
virtual void config_save(util::xml::data_node *ef_node) const override;
virtual void default_changed() override;
virtual u32 history_size() const; // optional
The constructor must pass the parameters to ``audio_effect`` and
initialize the effect parameters. ``type`` must return the enum value
for the effect. ``config_load`` and ``config_save`` should load or
save the effect parameters from/to the cfg file xml tree.
``default_changed`` is called when the parameters in ``m_default`` are
changed and the parameters may need to be updated. ``history_size``
allows to tell how many samples should still be available of the
previous input frame. Note that this number must not depend on the
parameters and only on the sample rate.
An effect have a number of parameters that can come from three sources:
* fixed default value
* equivalent effect object from the default effect chain
* user setting through the UI
The first two are recognized through the value of ``m_default`` which
gets the value of ``def`` in the constructor. When it's nullptr, the
value to use when not set by the user is the fixed one, otherwise it's
the one in ``m_default``.
At a minimum an effect should have a parameter allowing to bypass it.
Managing a parameter uses four methods:
* ``type param() const;`` returns the current parameter value
* ``void set_param(type value);`` sets the current parameter value and marks it as set by the user
* ``bool isset_param() const;`` returns true is the parameter was set by the user
* ``void reset_param();`` resets the parameter to the default value (from m_default or fixed) and marks it as not set by the user
``config_save`` must only save the user-set parameters.
``config_load`` must retrieve the parameters that are present and mark
them as set by the user and reset all the others.
Finally the actual implementation goes into the ``apply`` method:
.. code-block:: C++
virtual void apply(const emu::detail::output_buffer_flat<sample_t> &src, emu::detail::output_buffer_flat<sample_t> &dest) override;
That method takes two buffers with the same number of channels and has
to apply the effect to ``src`` to produce ``dest``. The
``output_buffer_flat`` is non-interleaved with independant per-channel
buffers.
To make bypassing easier, the ``copy(src, dest)`` method of
audio_effect allows to copy the samples from ``src`` to ``dest``
without changing them.
The effect application part should looks like:
.. code-block:: C++
u32 samples = src.available_samples();
dest.prepare_space(samples);
u32 channels = src.channels();
// generate channels * samples results and put them in dest
dest.commit(samples);
To get pointers to the buffers, one uses:
.. code-block:: C++
const sample_t *source = src.ptrs(channel, source_index); // source_index must be in [-history_size()..samples-1]
sample_t *destination = dest.ptrw(channel, destination_index); // destination_index must be in [0..samples-1]
The samples pointed by source and destination are contiguous. The
number of channels will not change from one apply call to another, the
number of samples will vary though. Also the call happens in a
different thread than the main thread and also in a different thread
than the parameter setting calls are made from.
4. frontend/mame/ui/audioeffects.cpp
------------------------------------
There it suffices to add a creation of the menu
menu_audio_effect_youreffect in menu_audio_effects::handle. The menu
effect will pick the effect names from audio_effect (in aeffect.*).
5. frontend/mame/ui/audioyoureffect.*
-------------------------------------
This is used to implement the configuration menu for the effect. It's
a little complicated because it needs to generate the list of
parameters and their values, set left or right arrow flags depending
on the possible modifications, dim them (FLAG_INVERT) when not set by
the user, and manage the arrows and clear keys to change them. Just
copy an existing one and change it as needed.

View File

@ -0,0 +1,286 @@
The device_sound_interface
==========================
.. contents:: :local:
1. The sound system
-------------------
The device sound interface is the entry point for devices that handle
sound input and/or output. The sound system is built on the concept
of *streams* which connect devices together with resampling and mixing
applied transparently as needed. Microphones (audio input) and
speakers (audio output) are specific known devices which use the same
interface.
2. Devices using device_sound_interface
---------------------------------------
2.1 Initialisation
~~~~~~~~~~~~~~~~~~
Sound streams must be created in the device_start (or
interface_pre_start) method.
.. code-block:: C++
sound_stream *stream_alloc(int inputs, int outputs, int sample_rate, sound_stream_flags flags = STREAM_DEFAULT_FLAGS);
A stream is created with ``stream_alloc``. It takes the number of
input and output channels, the sample rate and optionally flags.
The sample rate can be SAMPLE_RATE_INPUT_ADAPTIVE,
SAMPLE_RATE_OUTPUT_ADAPTIVE or SAMPLE_RATE_ADAPTIVE. In that case the
chosen sample rate is the highest one amongs the inputs, outputs or
both respectively. In case of loop, the chosen sample rate is the
configured global sample rate.
The only available non-default flag is STREAM_SYNCHRONOUS. When set,
the sound generation method will be called for every sample
individually. It's necessary for dsps that run a program on every
sample. but on the other hand it's expensive, so only to be used when
required.
Devices can create multiple streams. It's rare though. Some yamaha
chips should but don't. Inputs and outputs are numbered from 0 and
collate all streams in the order they are created.
2.2 Sound input/output
~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: C++
virtual void sound_stream_update(sound_stream &stream);
This method is required to be implemented to consume the input samples
and/or compute the output ones. The stream to update for is passed as
the parameter. See the streams section, specifically sample access,
to see how to write the method.
2.3 Stream information
~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: C++
int inputs() const;
int outputs() const;
std::pair<sound_stream *, int> input_to_stream_input(int inputnum) const;
std::pair<sound_stream *, int> output_to_stream_output(int outputnum) const;
The method ``inputs`` returns the total number of inputs in the
streams created by the device. The method ``outputs`` similarly
counts the outputs. The other two methods allow to grab the stream
and channel number for the device corresponding to the global input or
output number.
2.4 Gain management
~~~~~~~~~~~~~~~~~~~
.. code-block:: C++
float input_gain(int inputnum) const;
float output_gain(int outputnum) const;
void set_input_gain(int inputnum, float gain);
void set_output_gain(int outputnum, float gain);
void set_route_gain(int source_channel, device_sound_interface *target, int target_channel, float gain);
float user_output_gain() const;
float user_output_gain(int outputnum) const;
void set_user_output_gain(float gain);
void set_user_output_gain(int outputnum, float gain);
Those methods allow to set the gain on every step of the routes
between streams. All gains are multipliers, with default value 1.0.
The steps are, from samples output in ``sound_stream_update`` to
samples read in the next device's ``sound_stream_update``:
* Per-channel output gain
* Per-channel user output gain
* Per-device user output gain
* Per-route gain
* Per-channel input gain
The user gains must not be set from the driver, they're for use by the
user interface (the sliders) and are saved in the game configuration.
The other gains are for driver/device use, and are saved in save
states.
2.5 Routing setup
~~~~~~~~~~~~~~~~~
.. code-block:: C++
device_sound_interface &add_route(u32 output, const device_finder<T, R> &target, double gain, u32 channel = 0)
device_sound_interface &add_route(u32 output, const char *target, double gain, u32 channel = 0);
device_sound_interface &add_route(u32 output, device_sound_interface &target, double gain, u32 channel = 0);
device_sound_interface &reset_routes();
Routes between devices, e.g. between streams, are set at configuration
time. The method ``add_route`` must be called on the source device
and gives the channel on the source device, the target device, the
gain, and optionally the channel on the target device. The constant
``ALL_OUTPUTS`` can be used to add a route from every channel of the
source to a given channel of the destination.
The method ``reset_routes`` is used to remove all the routes setup on
a given source device.
.. code-block:: C++
u32 get_sound_requested_inputs() const;
u32 get_sound_requested_outputs() const;
u64 get_sound_requested_inputs_mask() const;
u64 get_sound_requested_outputs_mask() const;
Those methods are useful for devices which want to behave differently
depending on what routes are setup on them. You get either the max
number of requested channel plus one (which is the number of channels
when all channels are routed, but is more useful when there are gaps)
or a mask of use for channels 0-63. Note that ``ALL_OUTPUTS`` does
not register any specific output or output count.
3. Streams
----------
3.1 Generalities
~~~~~~~~~~~~~~~~
Streams are endpoints associated with devices and, when connected
together, ensure the transmission of audio data between them. A
stream has a number of inputs (which can be zero) and outputs (same)
and one sample rate which is common to all inputs and outputs. The
connections are setup at the machine configuration level and the sound
system ensures mixing and resampling is done transparently.
Samples in streams are encoded as sample_t. In the current
implementation, this is a float. Nominal values are between -1 and 1,
but clamping at the device level is not recommended (unless that's
what happens in hardware of course) because the gain values, volume
and effects can easily avoid saturation.
They are implemented in the class ``sound_stream``.
3.2 Characteristics
~~~~~~~~~~~~~~~~~~~
.. code-block:: C++
device_t &device() const;
bool input_adaptive() const;
bool output_adaptive() const;
bool synchronous() const;
u32 input_count() const;
u32 output_count() const;
u32 sample_rate() const;
attotime sample_period() const;
3.3 Sample access
~~~~~~~~~~~~~~~~~
.. code-block:: C++
s32 samples() const;
void put(s32 output, s32 index, sample_t sample);
void put_clamp(s32 output, s32 index, sample_t sample, sample_t clamp = 1.0);
void put_int(s32 output, s32 index, s32 sample, s32 max);
void put_int_clamp(s32 output, s32 index, s32 sample, s32 maxclamp);
void add(s32 output, s32 index, sample_t sample);
void add_int(s32 output, s32 index, s32 sample, s32 max);
void fill(s32 output, sample_t value, s32 start, s32 count);
void fill(s32 output, sample_t value, s32 start);
void fill(s32 output, sample_t value);
void copy(s32 output, s32 input, s32 start, s32 count);
void copy(s32 output, s32 input, s32 start);
void copy(s32 output, s32 input);
sample_t get(s32 input, s32 index) const;
sample_t get_output(s32 output, s32 index) const;
Those are the methods used to implement ``sound_stream_update``.
First ``samples`` tells how many samples to consume and/or generate.
The to-generate samples, if any, are pre-cleared (e.g. set to zero).
Input samples are retrieved with ``get``, where ``input`` is the
stream channel number and ``index`` the sample number.
Generated samples are written with the put variants. ``put`` sets a
sample_t in channel ``output`` at position ``index``. ``put_clamp``
does the same but first clamps the value to +/-``clamp``. ``put_int``
does it with an integer ``sample`` but pre-divides it by ``max``.
``put_int_clamp`` does the same but also pre-clamps within
-``maxclamp`` and ``maxclamp``-1, which is the normal range for a
2-complement value.
``add`` and ``add_int`` are similar but add the value of the sample to
what's there instead of replacing. ``get_output`` gets the currently
stored output value.
``fill`` sets a range of the an output channel to a given ``value``.
``start`` tells where to start (default index 0), ``count`` how many
(default up to the end of the buffer).
``copy`` does the same as fill but gets its value from the indentical
position in an input channel.
Note that clamping should not be used unless it actually happens in
hardware. Between gains and effects there is a fair chance saturation
can be avoided later in the chain.
3.4 Gain management
~~~~~~~~~~~~~~~~~~~
.. code-block:: C++
float user_output_gain() const;
void set_user_output_gain(float gain);
float user_output_gain(s32 output) const;
void set_user_output_gain(s32 output, float gain);
float input_gain(s32 input) const;
void set_input_gain(s32 input, float gain);
void apply_input_gain(s32 input, float gain);
float output_gain(s32 output) const;
void set_output_gain(s32 output, float gain);
void apply_output_gain(s32 output, float gain);
This is similar to the device gain control, with a twist: apply
multiplies the current gain by the given value.
3.5 Misc. actions
~~~~~~~~~~~~~~~~~
.. code-block:: C++
void set_sample_rate(u32 sample_rate);
void update();
The method ``set_sample_rate`` allows to change the sample rate of the
stream. The method ``update`` triggers a call of
``sound_stream_update`` on the stream and the ones it depends on to
reach the current time in terms of samples.
4. Devices using device_mixer_interface
---------------------------------------
The device mixer interface is used for devices that want to relay
sound in the device tree without acting on it. It's very useful on
for instance slot devices connectors, where the slot device may have
an audio connection with the main system. They are routed like every
other sound device, create the streams automatically and copy input to
output. Nothing needs to be done in the device.

View File

@ -15,6 +15,7 @@ MAMEs source or working on scripts that run within the MAME framework.
device_memory_interface
device_rom_interface
device_disasm_interface
device_sound_interface
memory
cpu_device
floppy
@ -22,3 +23,5 @@ MAMEs source or working on scripts that run within the MAME framework.
m6502
uml_instructions
poly_manager
audio_effects
osd_audio

View File

@ -0,0 +1,334 @@
OSD audio support
=================
Introduction
------------
The audio support in Mame tries to allow the user to freely map
between the emulated system audio outputs (called speakers) and the
host system audio. A part of it is the OSD support, where a
host-specific module ensures the interface between Mame and the host.
This is the documentation for that module.
Note: this is currenty output-only, but input should follow.
Capabitilies
------------
The OSD interface is designed to allow three levels of support,
depending on what the API allows and the amount of effort to expend.
Those are:
* Level 1: One or more audio targets, only one stream allowed per target (aka exclusive mode)
* Level 2: One or more audio targets, multiple streams per target
* Level 3: One or more audio targets, multiple streams per target, user-visible per-stream-channel volume control
In any case we support having the user use an external interface to
change the target of a stream and, in level 3, change the volumes. By
support we mean storing the information in the per-game configuration
and keeping in the internal UI in sync.
Terminology
-----------
For this module, we use the terms:
* node: some object we can send audio to. Can be physical, like speakers, or virtual, like an effect system. It should have a unique, user-presentable name for the UI.
* port: a channel of a node, has a name (non-unique, like "front left") and a 3D position
* stream: a connection to a node with allows to send audio to it
Reference documentation
-----------------------
Adding a module
~~~~~~~~~~~~~~~
Adding a module is done by adding a cpp file to src/osd/modules/sound
which follows this structure,
.. code-block:: C++
// License/copyright
#include "sound_module.h"
#include "modules/osdmodules.h"
#ifdef MODULE_SUPPORT_KEY
#include "modules/lib/osdobj_common.h"
// [...]
namespace osd {
namespace {
class sound_module_class : public osd_module, public sound_module
{
sound_module_class() : osd_module(OSD_SOUND_PROVIDER, "module_name"),
sound_module()
// ...
};
}
}
#else
namespace osd { namespace {
MODULE_NOT_SUPPORTED(sound_module_class, OSD_SOUND_PROVIDER, "module_name")
}}
#endif
MODULE_DEFINITION(SOUND_MODULE_KEY, osd::sound_module_class)
In that code, four names must be chosen:
* MODULE_SUPPORT_KEY some #define coming from the genie scripts to tell that this particular module can be compiled (like NO_USE_PIPEWIRE or SDLMAME_MACOSX)
* sound_module_class is the name of the class which makes up the module (like sound_coreaudio)
* module_name is the name to be used in -sound <xxx> to select that particular module (like coreaudio)
* SOUND_MODULE_KEY is a symbol that represents the module internally (like SOUND_COREAUDIO)
The file path needs to be added to scripts/src/osd/modules.lua in
osdmodulesbuild() and the module reference to
src/osd/modules/lib/osdobj_common.cpp in
osd_common_t::register_options with the line:
.. code-block:: C++
REGISTER_MODULE(m_mod_man, SOUND_MODULE_KEY);
This should ensure that the module is reachable through -sound <xxx>
on the appropriate hosts.
Interface
~~~~~~~~~
The full interface is:
.. code-block:: C++
virtual bool split_streams_per_source() const override;
virtual bool external_per_channel_volume() const override;
virtual int init(osd_interface &osd, osd_options const &options) override;
virtual void exit() override;
virtual uint32_t get_generation() override;
virtual osd::audio_info get_information() override;
virtual uint32_t stream_sink_open(uint32_t node, std::string name, uint32_t rate) override;
virtual uint32_t stream_source_open(uint32_t node, std::string name, uint32_t rate) override;
virtual void stream_set_volumes(uint32_t id, const std::vector<float> &db) override;
virtual void stream_close(uint32_t id) override;
virtual void stream_sink_update(uint32_t id, const int16_t *buffer, int samples_this_frame) override;
virtual void stream_source_update(uint32_t id, int16_t *buffer, int samples_this_frame) override;
The class sound_module provides default for minimum capabilities: one
stereo target and stream at default sample rate. To support that,
only *init*, *exit* and *stream_update* need to be implemented.
*init* is called at startup and *exit* when quitting and can do
whatever they need to do. *stream_sink_update* will be called on a
regular basis with a buffer of sample_this_frame*2*int16_t with the
audio to play. From this point in the documentation we'll assume more
than a single stereo channel is wanted.
Capabilities
~~~~~~~~~~~~
Two methods are used by the module to indicate the level of capability
of the module:
* split_streams_per_source() should return true when having multiple streams for one target is expected (e.g. Level 2 or 3)
* external_per_channel_volume() should return true when the streams have per-channel volume control that can be externally controlled (e.g. Level 3)
Hardware information and generations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The core runs on the assumption that the host hardware capabilities
can change at any time (bluetooth devices coming and going, usb
hot-plugging...) and that the module has some way to keep tabs on what
is happening, possibly using multi-threading. To keep it
lightweight-ish, we use the concept of a *generation* which is a
32-bits number that is incremented by the module every time something
changes. The core checks the current generation value at least once
every update (once per frame, usually) and if it changed asks for the
new state and detects and handles the differences. *generation*
should be "eventually stable", e.g. it eventually stops changing when
the user stops changing things all the time. A systematic increment
every frame would be a bad idea.
.. code-block:: C++
virtual uint32_t get_generation() override;
That method returns the current generation number. It's called at a
minimum once per update, which usually means per frame. It whould be
reasonably lightweight when nothing special happens.
.. code-block: C++
virtual osd::audio_info get_information() override;
struct audio_rate_range {
uint32_t m_default_rate;
uint32_t m_min_rate;
uint32_t m_max_rate;
};
struct audio_info {
struct node_info {
std::string m_name;
uint32_t m_id;
audio_rate_range m_rate;
std::vector<std::string> m_port_names;
std::vector<std::array<double, 3>> m_port_positions;
uint32_t m_sinks;
uint32_t m_sources;
};
struct stream_info {
uint32_t m_id;
uint32_t m_node;
std::vector<float> m_volumes;
};
uint32_t m_generation;
uint32_t m_default_sink;
uint32_t m_default_source;
std::vector<node_info> m_nodes;
std::vector<stream_info> m_streams;
};
This method must provide all the information about the current state
of the host and the module. This state is:
* m_generation: The current generation number
* m_nodes: The vector available nodes (*node_info*)
* m_name: The name of the node
* m_id: The numeric ID of the node
* m_rate: The minimum, maximum and preferred sample rate for the node
* m_port_names: The vector of port names
* m_port_positions: The vector of 3D position of the ports. Refer to src/emu/speaker.h for the "standard" positions
* m_sinks: Number of sinks (inputs)
* m_sources: Number of sources (outputs)
* m_default_sink: ID of the node that is the current "system default" for audio output, 0 if there's no such concept
* m_default_source: same for audio input (currently unused)
* m_streams: The vector of active streams (*stream_info*)
* m_id: The numeric ID of the stream
* m_node: The target node of the stream
* m_volumes: empty if *external_per_channel_volume* is false, current volume value per-channel otherwise
IDs, for nodes and streams, are (independant) 32-bit unsigned non-zero
values associated to respectively nodes and streams. IDs should not
be reused. A node that goes away then comes back should get a new ID.
A stream closing does not allow reuse of its ID.
If a node has both sources and sinks, the sources are *monitors* of
the sinks, e.g. they're loopbacks. They should have the same count in
such a case.
When external control exists, a module should change the value of
*stream_info::m_node* when the user changes it, and same for
*stream_info::m_volumes*. Generation number should be incremented
when this happens, so that the core knows to look for changes.
Volumes are floats in dB, where 0 means 100% and -96 means no sound.
audio.h provides osd::db_to_linear and osd::linear_to_db if such a
conversion is needed.
There is an inherent race condition with this system, because things
can change at any point after returning for the method. The idea is
that the information returned must be internally consistent (a stream
should not point to a node ID that does not exist in the structure,
same for default sink) and that any external change from that state
should increment the generation number, but that's it. Through the
generation system the core will eventually be in sync with reality.
Input and output streams
~~~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: C++
virtual uint32_t stream_sink_open(uint32_t node, std::string name, uint32_t rate) override;
virtual uint32_t stream_source_open(uint32_t node, std::string name, uint32_t rate) override;
virtual void stream_set_volumes(uint32_t id, const std::vector<float> &db) override;
virtual void stream_close(uint32_t id) override;
virtual void stream_sink_update(uint32_t id, const int16_t *buffer, int samples_this_frame) override;
virtual void stream_source_update(uint32_t id, int16_t *buffer, int samples_this_frame) override;
Streams are the concept used to send or recieve audio from/to the host
audio system. A stream is first opened through *stream_sink_open* for
speakers and *stream_source_open* for microphones and targets a
specific node at a specific sample rate. It is given a name for use
by the host sound services for user UI purposes (currently the game
name if split_streams_per_source is false, the
speaker_device/microphone_device tag if true). The returned ID must
be a non-zero, never-used-before for streams value in case of success.
Failures, like when the node went away between the get_information
call and the open one, should be silent and return zero.
*stream_set_volumes* is used only when *external_per_channel_volume*
is true and is used by the core to set the per-channel volume. The
call should just be ignored if the stream ID does not exist (or is
zero). Do not try to apply volumes in the module if the host API
doesn't provide for it, let the core handle it.
*stream_close* closes a stream, The call should just be ignored if the
stream ID does not exist (or is zero).
Opening a stream, closing a stream or changing the volume does not
need to touch the generation number.
*stream_sink_update* is the method used to send data to the node
through a given stream. It provides a buffer of *samples_this_frame*
* *node channel count* channel-interleaved int16_t values. The
lifetime of the data in the buffer or the buffer pointer itself is
undefined after return from the method call. The call should just be
ignored if the stream ID does not exist (or is zero).
*stream_source_update* is the equivalent to retrieve data from a node,
writing to the buffer instead of reading from it. The constraints are
identical.
When a stream goes away because the target node is lost it should just
be removed from the information, and the core will pick up the node
departure and close the stream.
Given the assumed raceness of the interface, all the methods should be
tolerant of obsolete or zero IDs being used by the core, and that is
why ID reuse must be avoided. Also the update methods and the
open/close/volume ones may be called at the same time in different
threads.
Helper class *abuffer*
~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: C++
class abuffer {
public:
abuffer(uint32_t channels);
void get(int16_t *data, uint32_t samples);
void push(const int16_t *data, uint32_t samples);
uint32_t channels() const;
};
The class *abuffer* is a helper provided by *sound_module* to buffer
audio in output or output. It automatically drops data when there is
an overflow and duplicates the last sample on underflow. It must
first be initialized with the number of channels, which can be
retrieved with *channels()* if needed. *push* sends
*samples* * *channels* 16-bits samples in the buffer. *get* retrieves
*samples* * *channels* 16-bits samples from the buffer, on a fifo basis.
It is not protected against multithreading, but uses no class
variables. So just don't read and write from one specific abuffer
instance at the same time. The system sound interface mandated
locking should be enough to ensure that.

View File

@ -110,6 +110,14 @@ Network Devices
Shows the Network Devices menu, where you can set up emulated network
adapters that support bridging to a host network. This item is not shown if
there are no network adaptors that support bridging in the running system.
Audio Mixer
Shows the :ref:`Audio Mixer <menus-audiomixer>` menu, where you
decide how to connect your system audio inputs and outputs to the
emulated system's microphones and speakers.
Audio Effects
Shows the :ref:`Audio Effects <menus-audioeffects>` menu, which
allows to configure the audio effects applied between the emulated
system's speakers and the actual system audio outputs.
Slider Controls
Shows the Slider Controls menu, where you can adjust various settings,
including video adjustments and individual sound channel levels.
@ -285,3 +293,101 @@ graphical form below the menu. Digital control states are either zero
ID** to copy the devices ID to the clipboard. This is useful for setting up
:ref:`stable controller IDs <devicemap>` in :ref:`controller configuration files
<ctrlrcfg>`.
.. _menus-audiomixer:
Audio Mixer menu
----------------
The Audio Mixer menu allows to establish connections between emulated
speakers and microphones, and system audio inputs and outputs. It
uses the standard up/down arrows to select a device and/or current
mapping, left/right arrows to change a value (system audio port,
level, channel...) and [ ] to change column. In addition the (by
default) F key adds a full mapping, C a channel mapping, and Delete
clears a mapping.
A full mapping sends all channels of a speaker to the appropriate(s)
channel(s) of the system output, and similarly retrieves all channels
of a microphone from the appropriate(s) input(s) of a system input.
For instance a mono speaker will send audio to both channels of a
stereo system output.
A channel mapping maps between one channel of speaker or a microphone
and one channel of a system input or output. It can be a little
tedious, but it allows for instance to take two mono speakers and turn
it into the left and right channels of a system output, whcih is
useful for some cabinets.
Every mapping has a configurable volume associated.
The mapping configuration is saved in the system cfg file.
Some OSes propose an external interface to change mappings and volumes
dynamically, for instance pipewire on linux. Mame does its best to
follow that and keep the information in the cfg file for future runs.
.. _menus-audioeffects:
Audio Effects menu
------------------
This menu allows to configure the audio effects that are applied to
the speaker outputs between the speaker device and the audio mixer.
In other words, the output channels as seen in the audio mixer are the
outputs of the effect chains. Each speaker has an independant effect
chain applied.
The chain itself is not configurable it is always in order:
* Filter
* Compressor
* Reverb
* EQ
The parameters of each are fully configurable though. A configured
parameter shows as white, a default as grey, and Clear allows to go
back to the default value. The default parameters for the chain of a
given speaker are the parameters of the Default chain, and the default
parameters of the Default chain are fixed. The default chain allows
to create a global setup that one likes and have it applied everywhere
by default.
Filter effect
~~~~~~~~~~~~~
This effect proposes an order-2 high-pass and order-2 low-pass filter.
The high-pass filter allows to remove the DC offset some emulated
hardware has which can create saturation when not needed. The
low-pass filter (defaulting to off) allows to reproduce how muffled
the sound of a number of cabinets and TVs were.
The Q factor defines how sharp the transition is, the higher the
sharper. Over 0.7 the filter starts amplifying the frequencies arount
the cutoff though, which can be surprising.
Compression effect
~~~~~~~~~~~~~~~~~~
Not implemented yet.
Reverb effect
~~~~~~~~~~~~~
Not implemented yet.
EQ effect
~~~~~~~~~
The 5-band parametric equalizer allows to amplify or reduce certains
bands of frequency in the spectrum. The three middle filters, and
also the extreme ones if configured as "Peak", change frequencies
around the cutoff. The Q factor selects the sharpness of the peak,
the higher the sharper. The extreme filters in "Shelf" mode move all
the frequencies under (or over) the cutoff frequency.

View File

@ -34,6 +34,7 @@
# NO_USE_MIDI = 1
# NO_USE_PORTAUDIO = 1
# NO_USE_PULSEAUDIO = 1
# NO_USE_PIPEWIRE = 1
# USE_TAPTUN = 1
# USE_PCAP = 1
# USE_QTDEBUG = 1
@ -734,6 +735,10 @@ ifdef NO_USE_PULSEAUDIO
PARAMS += --NO_USE_PULSEAUDIO='$(NO_USE_PULSEAUDIO)'
endif
ifdef NO_USE_PIPEWIRE
PARAMS += --NO_USE_PIPEWIRE='$(NO_USE_PIPEWIRE)'
endif
ifdef USE_QTDEBUG
PARAMS += --USE_QTDEBUG='$(USE_QTDEBUG)'
endif

View File

@ -5859,3 +5859,17 @@ if (BUSES["AMIGA_CPUSLOT"]~=null) then
MAME_DIR .. "src/devices/bus/amiga/cpuslot/megamix500.h",
}
end
---------------------------------------------------
--
--@src/devices/bus/st/stcart.h,BUSES["STCART_CONNECTOR"] = true
---------------------------------------------------
if (BUSES["STCART_CONNECTOR"]~=null) then
files {
MAME_DIR .. "src/devices/bus/st/stcart.cpp",
MAME_DIR .. "src/devices/bus/st/stcart.h",
MAME_DIR .. "src/devices/bus/st/replay.cpp",
MAME_DIR .. "src/devices/bus/st/replay.h",
}
end

View File

@ -194,6 +194,8 @@ files {
MAME_DIR .. "src/emu/rendlay.h",
MAME_DIR .. "src/emu/rendutil.cpp",
MAME_DIR .. "src/emu/rendutil.h",
MAME_DIR .. "src/emu/resampler.cpp",
MAME_DIR .. "src/emu/resampler.h",
MAME_DIR .. "src/emu/romload.cpp",
MAME_DIR .. "src/emu/romload.h",
MAME_DIR .. "src/emu/romentry.h",
@ -272,6 +274,16 @@ files {
MAME_DIR .. "src/emu/video/rgbsse.h",
MAME_DIR .. "src/emu/video/rgbvmx.cpp",
MAME_DIR .. "src/emu/video/rgbvmx.h",
MAME_DIR .. "src/emu/audio_effects/aeffect.h",
MAME_DIR .. "src/emu/audio_effects/aeffect.cpp",
MAME_DIR .. "src/emu/audio_effects/filter.h",
MAME_DIR .. "src/emu/audio_effects/filter.cpp",
MAME_DIR .. "src/emu/audio_effects/compressor.h",
MAME_DIR .. "src/emu/audio_effects/compressor.cpp",
MAME_DIR .. "src/emu/audio_effects/reverb.h",
MAME_DIR .. "src/emu/audio_effects/reverb.cpp",
MAME_DIR .. "src/emu/audio_effects/eq.h",
MAME_DIR .. "src/emu/audio_effects/eq.cpp",
}
pchsource(MAME_DIR .. "src/emu/main.cpp")

View File

@ -89,6 +89,14 @@ files {
MAME_DIR .. "src/frontend/mame/ui/about.h",
MAME_DIR .. "src/frontend/mame/ui/analogipt.cpp",
MAME_DIR .. "src/frontend/mame/ui/analogipt.cpp",
MAME_DIR .. "src/frontend/mame/ui/audioeffects.cpp",
MAME_DIR .. "src/frontend/mame/ui/audioeffects.h",
MAME_DIR .. "src/frontend/mame/ui/audiomix.cpp",
MAME_DIR .. "src/frontend/mame/ui/audiomix.h",
MAME_DIR .. "src/frontend/mame/ui/audio_effect_eq.cpp",
MAME_DIR .. "src/frontend/mame/ui/audio_effect_eq.h",
MAME_DIR .. "src/frontend/mame/ui/audio_effect_filter.cpp",
MAME_DIR .. "src/frontend/mame/ui/audio_effect_filter.h",
MAME_DIR .. "src/frontend/mame/ui/auditmenu.cpp",
MAME_DIR .. "src/frontend/mame/ui/auditmenu.h",
MAME_DIR .. "src/frontend/mame/ui/barcode.cpp",

View File

@ -52,6 +52,7 @@ function osdmodulesbuild()
files {
MAME_DIR .. "src/osd/watchdog.cpp",
MAME_DIR .. "src/osd/watchdog.h",
MAME_DIR .. "src/osd/interface/audio.h",
MAME_DIR .. "src/osd/interface/inputcode.h",
MAME_DIR .. "src/osd/interface/inputdev.h",
MAME_DIR .. "src/osd/interface/inputfwd.h",
@ -134,7 +135,9 @@ function osdmodulesbuild()
MAME_DIR .. "src/osd/modules/sound/none.cpp",
MAME_DIR .. "src/osd/modules/sound/pa_sound.cpp",
MAME_DIR .. "src/osd/modules/sound/pulse_sound.cpp",
MAME_DIR .. "src/osd/modules/sound/pipewire_sound.cpp",
MAME_DIR .. "src/osd/modules/sound/sdl_sound.cpp",
MAME_DIR .. "src/osd/modules/sound/sound_module.cpp",
MAME_DIR .. "src/osd/modules/sound/sound_module.h",
MAME_DIR .. "src/osd/modules/sound/xaudio2_sound.cpp",
}
@ -302,6 +305,22 @@ function osdmodulesbuild()
}
end
err = os.execute(pkgconfigcmd() .. " --exists libpipewire-0.3")
if not err then
_OPTIONS["NO_USE_PIPEWIRE"] = "1"
end
if _OPTIONS["NO_USE_PIPEWIRE"]=="1" then
defines {
"NO_USE_PIPEWIRE",
}
else
buildoptions {
backtick(pkgconfigcmd() .. " --cflags libpipewire-0.3"),
}
end
if _OPTIONS["NO_USE_MIDI"]=="1" then
defines {
"NO_USE_MIDI",
@ -564,6 +583,12 @@ function osdmodulestargetconf()
ext_lib("pulse"),
}
end
if _OPTIONS["NO_USE_PIPEWIRE"]=="0" then
local str = backtick(pkgconfigcmd() .. " --libs libpipewire-0.3")
addlibfromstring(str)
addoptionsfromstring(str)
end
end
@ -666,6 +691,23 @@ if not _OPTIONS["NO_USE_PULSEAUDIO"] then
end
end
newoption {
trigger = "NO_USE_PIPEWIRE",
description = "Disable Pipewire interface",
allowed = {
{ "0", "Enable Pipewire" },
{ "1", "Disable Pipewire" },
},
}
if not _OPTIONS["NO_USE_PIPEWIRE"] then
if _OPTIONS["targetos"]=="linux" then
_OPTIONS["NO_USE_PIPEWIRE"] = "0"
else
_OPTIONS["NO_USE_PIPEWIRE"] = "1"
end
end
newoption {
trigger = "MODERN_WIN_API",
description = "Use Modern Windows APIs",

View File

@ -1811,3 +1811,15 @@ if (SOUNDS["MMC5"]~=null) then
MAME_DIR .. "src/devices/sound/mmc5.h",
}
end
---------------------------------------------------
-- ADCs
--@src/devices/sound/adc.h,SOUNDS["ADC"] = true
---------------------------------------------------
if (SOUNDS["ADC"]~=null) then
files {
MAME_DIR .. "src/devices/sound/adc.cpp",
MAME_DIR .. "src/devices/sound/adc.h",
}
end

View File

@ -249,19 +249,16 @@ TIMER_CALLBACK_MEMBER(mcms_device::clr_irq_tick)
m_write_irq(CLEAR_LINE);
}
void mcms_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
void mcms_device::sound_stream_update(sound_stream &stream)
{
int i, v;
uint16_t wptr;
int8_t sample;
int32_t mixL, mixR;
auto &outL = outputs[1];
auto &outR = outputs[0];
if (m_enabled)
{
for (i = 0; i < outL.samples(); i++)
for (i = 0; i < stream.samples(); i++)
{
mixL = mixR = 0;
@ -282,15 +279,10 @@ void mcms_device::sound_stream_update(sound_stream &stream, std::vector<read_str
}
}
outL.put_int(i, mixL * m_mastervol, 32768 << 9);
outR.put_int(i, mixR * m_mastervol, 32768 << 9);
stream.put_int(0, i, mixL * m_mastervol, 32768 << 9);
stream.put_int(1, i, mixR * m_mastervol, 32768 << 9);
}
}
else
{
outL.fill(0);
outR.fill(0);
}
}
void mcms_device::voiceregs_w(offs_t offset, uint8_t data)

View File

@ -41,7 +41,7 @@ protected:
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override;
virtual void sound_stream_update(sound_stream &stream) override;
TIMER_CALLBACK_MEMBER(set_irq_tick);
TIMER_CALLBACK_MEMBER(clr_irq_tick);

View File

@ -154,14 +154,13 @@ void a2bus_ayboard_device::single_via_devices(machine_config &config)
m_via1->writepb_handler().set(FUNC(a2bus_ayboard_device::via1_out_b));
m_via1->irq_handler().set(FUNC(a2bus_ayboard_device::via1_irq_w));
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
SPEAKER(config, "speaker", 2).front();
AY8913(config, m_ay1, 1022727);
m_ay1->add_route(ALL_OUTPUTS, "lspeaker", 0.5);
m_ay1->add_route(ALL_OUTPUTS, "speaker", 0.5, 0);
AY8913(config, m_ay2, 1022727);
m_ay2->add_route(ALL_OUTPUTS, "rspeaker", 0.5);
m_ay2->add_route(ALL_OUTPUTS, "speaker", 0.5, 1);
}
void a2bus_ayboard_device::device_add_mconfig(machine_config &config)
@ -184,8 +183,8 @@ void a2bus_mockingboard_device::device_add_mconfig(machine_config &config)
VOTRAX_SC01A(config, m_sc01, 1022727);
m_sc01->ar_callback().set(m_via1, FUNC(via6522_device::write_cb1));
m_sc01->add_route(ALL_OUTPUTS, "lspeaker", 1.0);
m_sc01->add_route(ALL_OUTPUTS, "rspeaker", 1.0);
m_sc01->add_route(ALL_OUTPUTS, "speaker", 1.0, 0);
m_sc01->add_route(ALL_OUTPUTS, "speaker", 1.0, 1);
}
void a2bus_phasor_device::device_add_mconfig(machine_config &config)
@ -195,16 +194,15 @@ void a2bus_phasor_device::device_add_mconfig(machine_config &config)
m_via1->writepb_handler().set(FUNC(a2bus_phasor_device::via1_out_b));
m_via2->writepb_handler().set(FUNC(a2bus_phasor_device::via2_out_b));
SPEAKER(config, "lspeaker2").front_left();
SPEAKER(config, "rspeaker2").front_right();
SPEAKER(config, "speaker2", 2).front();
m_ay2->reset_routes().add_route(ALL_OUTPUTS, "lspeaker2", 0.5);
m_ay2->reset_routes().add_route(ALL_OUTPUTS, "speaker2", 0.5, 0);
AY8913(config, m_ay3, 1022727);
m_ay3->add_route(ALL_OUTPUTS, "rspeaker", 0.5);
m_ay3->add_route(ALL_OUTPUTS, "speaker", 0.5, 1);
AY8913(config, m_ay4, 1022727);
m_ay4->add_route(ALL_OUTPUTS, "rspeaker2", 0.5);
m_ay4->add_route(ALL_OUTPUTS, "speaker2", 0.5, 1);
}
void a2bus_echoplus_device::device_add_mconfig(machine_config &config)

View File

@ -68,16 +68,15 @@ void a2bus_scsi_device::device_add_mconfig(machine_config &config)
{
// These machines were strictly external CD-ROMs so sound didn't route back into them; the AppleCD SC had
// RCA jacks for connection to speakers/a stereo.
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
SPEAKER(config, "speaker", 2).front();
NSCSI_BUS(config, m_scsibus);
NSCSI_CONNECTOR(config, "scsibus:0", default_scsi_devices, nullptr, false);
NSCSI_CONNECTOR(config, "scsibus:1").option_set("cdrom", NSCSI_CDROM_APPLE).machine_config(
[](device_t *device)
{
device->subdevice<cdda_device>("cdda")->add_route(0, "^^lspeaker", 1.0);
device->subdevice<cdda_device>("cdda")->add_route(1, "^^rspeaker", 1.0);
device->subdevice<cdda_device>("cdda")->add_route(0, "^^speaker", 1.0, 0);
device->subdevice<cdda_device>("cdda")->add_route(1, "^^speaker", 1.0, 1);
});
NSCSI_CONNECTOR(config, "scsibus:2", default_scsi_devices, nullptr, false);
NSCSI_CONNECTOR(config, "scsibus:3", default_scsi_devices, nullptr, false);

View File

@ -120,8 +120,8 @@ void a570_device::device_add_mconfig(machine_config &config)
m_tpi->out_pb_cb().set(FUNC(a570_device::tpi_portb_w));
CR511B(config, m_drive, 0);
m_drive->add_route(0, "lspeaker", 1.0);
m_drive->add_route(1, "rspeaker", 1.0);
m_drive->add_route(0, "speaker", 1.0, 0);
m_drive->add_route(1, "speaker", 1.0, 1);
m_drive->scor_cb().set(m_tpi, FUNC(tpi6525_device::i1_w)).invert();
m_drive->stch_cb().set(m_tpi, FUNC(tpi6525_device::i2_w)).invert();
m_drive->sten_cb().set(m_tpi, FUNC(tpi6525_device::i3_w));
@ -129,8 +129,7 @@ void a570_device::device_add_mconfig(machine_config &config)
m_drive->drq_cb().set(m_tpi, FUNC(tpi6525_device::i4_w));
m_drive->drq_cb().append(FUNC(a570_device::drq_w));
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
SPEAKER(config, "speaker", 2).front();
// TODO: Add stereo input for Amiga sound
}

View File

@ -63,12 +63,11 @@ DEFINE_DEVICE_TYPE(BBC_M87, bbc_m87_device, "bbc_m87", "Peartree Music 87
void bbc_m500_device::add_common_devices(machine_config &config)
{
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
SPEAKER(config, "speaker", 2).front();
HTMUSIC(config, m_hybrid, 12_MHz_XTAL / 2);
m_hybrid->add_route(0, "lspeaker", 1.0);
m_hybrid->add_route(1, "rspeaker", 1.0);
m_hybrid->add_route(0, "speaker", 1.0, 0);
m_hybrid->add_route(1, "speaker", 1.0, 1);
BBC_1MHZBUS_SLOT(config, m_1mhzbus, DERIVED_CLOCK(1, 1), bbc_1mhzbus_devices, nullptr);
m_1mhzbus->irq_handler().set(DEVICE_SELF_OWNER, FUNC(bbc_1mhzbus_slot_device::irq_w));
@ -417,19 +416,15 @@ TIMER_CALLBACK_MEMBER(htmusic_device::dsp_tick)
// sound_stream_update - handle a stream update
//-------------------------------------------------
void htmusic_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
void htmusic_device::sound_stream_update(sound_stream &stream)
{
// reset the output streams
outputs[0].fill(0);
outputs[1].fill(0);
// iterate over channels and accumulate sample data
for (int channel = 0; channel < 16; channel++)
{
for (int sampindex = 0; sampindex < outputs[0].samples(); sampindex++)
for (int sampindex = 0; sampindex < stream.samples(); sampindex++)
{
outputs[0].add_int(sampindex, m_sam_l[channel], 8031 * 16);
outputs[1].add_int(sampindex, m_sam_r[channel], 8031 * 16);
stream.add_int(0, sampindex, m_sam_l[channel], 8031 * 16);
stream.add_int(1, sampindex, m_sam_r[channel], 8031 * 16);
}
}
}

View File

@ -47,7 +47,7 @@ protected:
virtual void device_reset() override ATTR_COLD;
// sound stream update overrides
virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override;
virtual void sound_stream_update(sound_stream &stream) override;
TIMER_CALLBACK_MEMBER(dsp_tick);

View File

@ -45,8 +45,7 @@ void pc9801_118_device::device_add_mconfig(machine_config &config)
// TODO: "ANCHOR" & "MAZE" custom NEC chips
// sourced by 5D clock
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
SPEAKER(config, "speaker", 2).front();
// actually YMF297-F (YMF288 + OPL3 compatible FM sources), unknown clock / divider
// 5B is near both CS-4232 and this
@ -54,8 +53,8 @@ void pc9801_118_device::device_add_mconfig(machine_config &config)
m_opn3->irq_handler().set([this] (int state) { m_bus->int_w<5>(state); });
// m_opn3->port_a_read_callback().set(FUNC(pc9801_118_device::opn_porta_r));
// m_opn3->port_b_write_callback().set(FUNC(pc9801_118_device::opn_portb_w));
m_opn3->add_route(ALL_OUTPUTS, "lspeaker", 1.00);
m_opn3->add_route(ALL_OUTPUTS, "rspeaker", 1.00);
m_opn3->add_route(ALL_OUTPUTS, "speaker", 1.00, 0);
m_opn3->add_route(ALL_OUTPUTS, "speaker", 1.00, 1);
// TODO: DA-15 PC gameport labeled "MIDI / Joystick"
}

View File

@ -84,8 +84,7 @@ void pc9801_86_device::pc9801_86_config(machine_config &config)
INPUT_MERGER_ANY_HIGH(config, m_irqs).output_handler().set([this](int state) { m_bus->int_w<5>(state); });
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
SPEAKER(config, "speaker", 2).front();
YM2608(config, m_opna, 7.987_MHz_XTAL); // actually YM2608B
// shouldn't have one
// m_opna->set_addrmap(0, &pc9801_86_device::opna_map);
@ -100,13 +99,13 @@ void pc9801_86_device::pc9801_86_config(machine_config &config)
m_joy_sel = data;
});
// TODO: confirm mixing
m_opna->add_route(0, "lspeaker", 0.75);
m_opna->add_route(0, "rspeaker", 0.75);
m_opna->add_route(1, "lspeaker", 1.00);
m_opna->add_route(2, "rspeaker", 1.00);
m_opna->add_route(0, "speaker", 0.75, 0);
m_opna->add_route(0, "speaker", 0.75, 1);
m_opna->add_route(1, "speaker", 1.00, 0);
m_opna->add_route(2, "speaker", 1.00, 1);
DAC_16BIT_R2R_TWOS_COMPLEMENT(config, m_ldac, 0).add_route(ALL_OUTPUTS, "lspeaker", 1.0); // burr brown pcm61p
DAC_16BIT_R2R_TWOS_COMPLEMENT(config, m_rdac, 0).add_route(ALL_OUTPUTS, "rspeaker", 1.0); // burr brown pcm61p
DAC_16BIT_R2R_TWOS_COMPLEMENT(config, m_ldac, 0).add_route(ALL_OUTPUTS, "speaker", 1.0); // burr brown pcm61p
DAC_16BIT_R2R_TWOS_COMPLEMENT(config, m_rdac, 0).add_route(ALL_OUTPUTS, "speaker", 1.0); // burr brown pcm61p
// NOTE: 1 DE-9 port only
MSX_GENERAL_PURPOSE_PORT(config, m_joy, msx_general_purpose_port_devices, "joystick");
@ -121,10 +120,10 @@ void pc9801_86_device::device_add_mconfig(machine_config &config)
void pc9801_86_device::opna_reset_routes_config(machine_config &config)
{
m_opna->reset_routes();
m_opna->add_route(0, "lspeaker", 0.125);
m_opna->add_route(0, "rspeaker", 0.125);
m_opna->add_route(1, "lspeaker", 0.50);
m_opna->add_route(2, "rspeaker", 0.50);
m_opna->add_route(0, "speaker", 0.125, 0);
m_opna->add_route(0, "speaker", 0.125, 1);
m_opna->add_route(1, "speaker", 0.50, 0);
m_opna->add_route(2, "speaker", 0.50, 1);
}
// to load a different bios for slots:
@ -544,10 +543,10 @@ void pc9801_speakboard_device::device_add_mconfig(machine_config &config)
YM2608(config, m_opna_slave, 7.987_MHz_XTAL);
m_opna_slave->set_addrmap(0, &pc9801_speakboard_device::opna_map);
m_opna_slave->add_route(0, "lspeaker", 0.50);
m_opna_slave->add_route(0, "rspeaker", 0.50);
m_opna_slave->add_route(1, "lspeaker", 0.50);
m_opna_slave->add_route(2, "rspeaker", 0.50);
m_opna_slave->add_route(0, "speaker", 0.50, 0);
m_opna_slave->add_route(0, "speaker", 0.50, 1);
m_opna_slave->add_route(1, "speaker", 0.50, 0);
m_opna_slave->add_route(2, "speaker", 0.50, 1);
}
void pc9801_speakboard_device::device_start()
@ -613,8 +612,8 @@ void otomichan_kai_device::device_add_mconfig(machine_config &config)
m_opna->set_addrmap(0, &otomichan_kai_device::opna_map);
YM3438(config, m_opn2c, 7.987_MHz_XTAL);
m_opn2c->add_route(0, "lspeaker", 0.50);
m_opn2c->add_route(1, "rspeaker", 0.50);
m_opn2c->add_route(0, "speaker", 0.50, 0);
m_opn2c->add_route(1, "speaker", 0.50, 1);
}
u8 otomichan_kai_device::id_r()

View File

@ -39,15 +39,14 @@ sb16_ct2720_device::sb16_ct2720_device(const machine_config &mconfig, const char
void sb16_ct2720_device::device_add_mconfig(machine_config &config)
{
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
SPEAKER(config, "speaker", 2).front();
CT1745(config, m_mixer);
m_mixer->set_fm_tag(m_opl3);
m_mixer->set_ldac_tag(m_ldac);
m_mixer->set_rdac_tag(m_rdac);
m_mixer->add_route(0, "lspeaker", 1.0);
m_mixer->add_route(1, "rspeaker", 1.0);
m_mixer->add_route(0, "speaker", 1.0, 0);
m_mixer->add_route(1, "speaker", 1.0, 1);
m_mixer->irq_status_cb().set([this] () {
(void)this;
return 0;
@ -59,14 +58,14 @@ void sb16_ct2720_device::device_add_mconfig(machine_config &config)
// MIDI_PORT(config, "mdin", midiin_slot, "midiin").rxd_handler().set(FUNC(sb_device::midi_rx_w));
// MIDI_PORT(config, "mdout", midiout_slot, "midiout");
DAC_16BIT_R2R(config, m_ldac, 0).add_route(ALL_OUTPUTS, m_mixer, 0.5, AUTO_ALLOC_INPUT, 0); // unknown DAC
DAC_16BIT_R2R(config, m_rdac, 0).add_route(ALL_OUTPUTS, m_mixer, 0.5, AUTO_ALLOC_INPUT, 1); // unknown DAC
DAC_16BIT_R2R(config, m_ldac, 0).add_route(ALL_OUTPUTS, m_mixer, 0.5, 0); // unknown DAC
DAC_16BIT_R2R(config, m_rdac, 0).add_route(ALL_OUTPUTS, m_mixer, 0.5, 1); // unknown DAC
YMF262(config, m_opl3, XTAL(14'318'181));
m_opl3->add_route(0, m_mixer, 1.00, AUTO_ALLOC_INPUT, 0);
m_opl3->add_route(1, m_mixer, 1.00, AUTO_ALLOC_INPUT, 1);
m_opl3->add_route(2, m_mixer, 1.00, AUTO_ALLOC_INPUT, 0);
m_opl3->add_route(3, m_mixer, 1.00, AUTO_ALLOC_INPUT, 1);
m_opl3->add_route(0, m_mixer, 1.00, 0);
m_opl3->add_route(1, m_mixer, 1.00, 1);
m_opl3->add_route(2, m_mixer, 1.00, 0);
m_opl3->add_route(3, m_mixer, 1.00, 1);
}
void sb16_ct2720_device::device_start()

View File

@ -92,10 +92,9 @@ centronics_covox_stereo_device::centronics_covox_stereo_device(const machine_con
void centronics_covox_stereo_device::device_add_mconfig(machine_config &config)
{
/* sound hardware */
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
DAC_8BIT_R2R(config, m_ldac, 0).add_route(ALL_OUTPUTS, "lspeaker", 0.5); // unknown DAC
DAC_8BIT_R2R(config, m_rdac, 0).add_route(ALL_OUTPUTS, "rspeaker", 0.5); // unknown DAC
SPEAKER(config, "speaker", 2).front();
DAC_8BIT_R2R(config, m_ldac, 0).add_route(ALL_OUTPUTS, "speaker", 0.5, 0); // unknown DAC
DAC_8BIT_R2R(config, m_rdac, 0).add_route(ALL_OUTPUTS, "speaker", 0.5, 1); // unknown DAC
}
void centronics_covox_stereo_device::device_start()

View File

@ -23,11 +23,10 @@ DEFINE_DEVICE_TYPE(CENTRONICS_SAMDAC, centronics_samdac_device, "centronics_samd
void centronics_samdac_device::device_add_mconfig(machine_config &config)
{
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
SPEAKER(config, "speaker", 2).front();
DAC_8BIT_R2R(config, m_dac[0], 0).add_route(ALL_OUTPUTS, "lspeaker", 0.5);
DAC_8BIT_R2R(config, m_dac[1], 0).add_route(ALL_OUTPUTS, "rspeaker", 0.5);
DAC_8BIT_R2R(config, m_dac[0], 0).add_route(ALL_OUTPUTS, "speaker", 0.5, 0);
DAC_8BIT_R2R(config, m_dac[1], 0).add_route(ALL_OUTPUTS, "speaker", 0.5, 1);
}

View File

@ -116,10 +116,9 @@ namespace
void coco_orch90_device::device_add_mconfig(machine_config &config)
{
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
DAC_8BIT_R2R(config, m_ldac, 0).add_route(ALL_OUTPUTS, "lspeaker", 0.5); // ls374.ic5 + r7 (8x20k) + r9 (8x10k)
DAC_8BIT_R2R(config, m_rdac, 0).add_route(ALL_OUTPUTS, "rspeaker", 0.5); // ls374.ic4 + r6 (8x20k) + r8 (8x10k)
SPEAKER(config, "speaker", 2).front();
DAC_8BIT_R2R(config, m_ldac, 0).add_route(ALL_OUTPUTS, "speaker", 0.5, 0); // ls374.ic5 + r7 (8x20k) + r9 (8x10k)
DAC_8BIT_R2R(config, m_rdac, 0).add_route(ALL_OUTPUTS, "speaker", 0.5, 1); // ls374.ic4 + r6 (8x20k) + r8 (8x10k)
}
//-------------------------------------------------

View File

@ -135,7 +135,7 @@ namespace
virtual void device_start() override ATTR_COLD;
// sound stream update overrides
virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override;
virtual void sound_stream_update(sound_stream &stream) override;
// Power of 2
static constexpr int BUFFER_SIZE = 4;
@ -499,21 +499,18 @@ void cocossc_sac_device::device_start()
// sound_stream_update - handle a stream update
//-------------------------------------------------
void cocossc_sac_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
void cocossc_sac_device::sound_stream_update(sound_stream &stream)
{
auto &src = inputs[0];
auto &dst = outputs[0];
int count = dst.samples();
int count = stream.samples();
m_rms[m_index] = 0;
if( count > 0 )
{
for( int sampindex = 0; sampindex < count; sampindex++ )
{
auto source_sample = src.get(sampindex);
auto source_sample = stream.get(0, sampindex);
m_rms[m_index] += source_sample * source_sample;
dst.put(sampindex, source_sample);
stream.put(0, sampindex, source_sample);
}
m_rms[m_index] = m_rms[m_index] / count;

View File

@ -68,10 +68,9 @@ namespace
void coco_stereo_composer_device::device_add_mconfig(machine_config &config)
{
SPEAKER(config, "sc_lspeaker").front_left();
SPEAKER(config, "sc_rspeaker").front_right();
DAC_8BIT_R2R(config, m_ldac).add_route(ALL_OUTPUTS, "sc_lspeaker", 0.5);
DAC_8BIT_R2R(config, m_rdac).add_route(ALL_OUTPUTS, "sc_rspeaker", 0.5);
SPEAKER(config, "sc_speaker", 2).front();
DAC_8BIT_R2R(config, m_ldac).add_route(ALL_OUTPUTS, "sc_speaker", 0.5, 0);
DAC_8BIT_R2R(config, m_rdac).add_route(ALL_OUTPUTS, "sc_speaker", 0.5, 1);
pia6821_device &pia(PIA6821(config, "sc_pia"));
pia.writepa_handler().set("sc_ldac", FUNC(dac_byte_interface::data_w));

View File

@ -31,12 +31,11 @@ void cpc_playcity_device::device_add_mconfig(machine_config &config)
m_ctc->zc_callback<2>().set(m_ctc, FUNC(z80ctc_device::trg3));
m_ctc->intr_callback().set(FUNC(cpc_playcity_device::ctc_intr_cb));
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
SPEAKER(config, "speaker", 2).front();
YMZ294(config, m_ymz1, DERIVED_CLOCK(1, 1)); // when timer is not set, operates at 4MHz (interally divided by 2, so equivalent to the ST)
m_ymz1->add_route(ALL_OUTPUTS, "rspeaker", 0.30);
m_ymz1->add_route(ALL_OUTPUTS, "speaker", 0.30, 1);
YMZ294(config, m_ymz2, DERIVED_CLOCK(1, 1));
m_ymz2->add_route(ALL_OUTPUTS, "lspeaker", 0.30);
m_ymz2->add_route(ALL_OUTPUTS, "speaker", 0.30, 0);
// pass-through
cpc_expansion_slot_device &exp(CPC_EXPANSION_SLOT(config, "exp", DERIVED_CLOCK(1, 1), cpc_exp_cards, nullptr));

View File

@ -70,14 +70,13 @@ DEFINE_DEVICE_TYPE(ISA8_GAME_BLASTER, isa8_gblaster_device, "isa_gblaster", "Gam
void isa8_gblaster_device::device_add_mconfig(machine_config &config)
{
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
SPEAKER(config, "speaker", 2).front();
SAA1099(config, m_saa1099_1, XTAL(14'318'181) / 2); // or CMS-301, from OSC pin in ISA bus
m_saa1099_1->add_route(0, "lspeaker", 0.50);
m_saa1099_1->add_route(1, "rspeaker", 0.50);
m_saa1099_1->add_route(0, "speaker", 0.50, 0);
m_saa1099_1->add_route(1, "speaker", 0.50, 1);
SAA1099(config, m_saa1099_2, XTAL(14'318'181) / 2); // or CMS-301, from OSC pin in ISA bus
m_saa1099_2->add_route(0, "lspeaker", 0.50);
m_saa1099_2->add_route(1, "rspeaker", 0.50);
m_saa1099_2->add_route(0, "speaker", 0.50, 0);
m_saa1099_2->add_route(1, "speaker", 0.50, 1);
}
//**************************************************************************

View File

@ -242,26 +242,19 @@ TIMER_CALLBACK_MEMBER(gf1_device::dma_tick)
m_drq1_handler(1);
}
void gf1_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
void gf1_device::sound_stream_update(sound_stream &stream)
{
int x;
//uint32_t count;
auto &outputl = outputs[0];
auto &outputr = outputs[1];
outputl.fill(0);
outputr.fill(0);
for(x=0;x<32;x++) // for each voice
{
uint16_t vol = (m_volume_table[(m_voice[x].current_vol & 0xfff0) >> 4]);
for (int sampindex = 0; sampindex < outputl.samples(); sampindex++)
for (int sampindex = 0; sampindex < stream.samples(); sampindex++)
{
uint32_t current = m_voice[x].current_addr >> 9;
// TODO: implement proper panning
outputl.add_int(sampindex, m_voice[x].sample * vol, 32768 * 8192);
outputr.add_int(sampindex, m_voice[x].sample * vol, 32768 * 8192);
stream.add_int(0, sampindex, m_voice[x].sample * vol, 32768 * 8192);
stream.add_int(1, sampindex, m_voice[x].sample * vol, 32768 * 8192);
if((!(m_voice[x].voice_ctrl & 0x40)) && (m_voice[x].current_addr >= m_voice[x].end_addr) && !m_voice[x].rollover && !(m_voice[x].voice_ctrl & 0x01))
{
if(m_voice[x].vol_ramp_ctrl & 0x04)
@ -1238,11 +1231,10 @@ INPUT_PORTS_END
void isa16_gus_device::device_add_mconfig(machine_config &config)
{
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
SPEAKER(config, "speaker", 2).front();
GGF1(config, m_gf1, GF1_CLOCK);
m_gf1->add_route(0, "lspeaker", 0.50);
m_gf1->add_route(1, "rspeaker", 0.50);
m_gf1->add_route(0, "speaker", 0.50, 0);
m_gf1->add_route(1, "speaker", 0.50, 1);
m_gf1->txd_handler().set("mdout", FUNC(midi_port_device::write_txd));
m_gf1->txirq_handler().set(FUNC(isa16_gus_device::midi_txirq));

View File

@ -122,7 +122,7 @@ public:
void eop_w(int state);
// device_sound_interface overrides
virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override;
virtual void sound_stream_update(sound_stream &stream) override;
protected:
// device-level overrides

View File

@ -434,27 +434,26 @@ void sb16_lle_device::device_add_mconfig(machine_config &config)
m_cpu->port_in_cb<2>().set(FUNC(sb16_lle_device::p2_r));
m_cpu->port_out_cb<2>().set(FUNC(sb16_lle_device::p2_w));
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
SPEAKER(config, "speaker", 2).front();
CT1745(config, m_mixer);
m_mixer->set_fm_tag("ymf262");
m_mixer->set_ldac_tag(m_ldac);
m_mixer->set_rdac_tag(m_rdac);
m_mixer->add_route(0, "lspeaker", 1.0);
m_mixer->add_route(1, "rspeaker", 1.0);
m_mixer->add_route(0, "speaker", 1.0, 0);
m_mixer->add_route(1, "speaker", 1.0, 1);
m_mixer->irq_status_cb().set([this] () {
return (m_irq8 << 0) | (m_irq16 << 1) | (m_irq_midi << 2) | (0x8 << 4);
});
DAC_16BIT_R2R(config, m_ldac, 0).add_route(ALL_OUTPUTS, m_mixer, 0.5, AUTO_ALLOC_INPUT, 0); // unknown DAC
DAC_16BIT_R2R(config, m_rdac, 0).add_route(ALL_OUTPUTS, m_mixer, 0.5, AUTO_ALLOC_INPUT, 1); // unknown DAC
DAC_16BIT_R2R(config, m_ldac, 0).add_route(ALL_OUTPUTS, m_mixer, 0.5, 0); // unknown DAC
DAC_16BIT_R2R(config, m_rdac, 0).add_route(ALL_OUTPUTS, m_mixer, 0.5, 1); // unknown DAC
ymf262_device &ymf262(YMF262(config, "ymf262", XTAL(14'318'181)));
ymf262.add_route(0, m_mixer, 1.00, AUTO_ALLOC_INPUT, 0);
ymf262.add_route(1, m_mixer, 1.00, AUTO_ALLOC_INPUT, 1);
ymf262.add_route(2, m_mixer, 1.00, AUTO_ALLOC_INPUT, 0);
ymf262.add_route(3, m_mixer, 1.00, AUTO_ALLOC_INPUT, 1);
ymf262.add_route(0, m_mixer, 1.00, 0);
ymf262.add_route(1, m_mixer, 1.00, 1);
ymf262.add_route(2, m_mixer, 1.00, 0);
ymf262.add_route(3, m_mixer, 1.00, 1);
PC_JOY(config, m_joy);
}

View File

@ -1152,11 +1152,10 @@ DEFINE_DEVICE_TYPE(ISA16_SOUND_BLASTER_16, isa16_sblaster16_device, "isa_sblaste
void sb_device::common(machine_config &config)
{
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
SPEAKER(config, "speaker", 2).front();
DAC_16BIT_R2R(config, m_ldac, 0).add_route(ALL_OUTPUTS, "lspeaker", 0.5); // unknown DAC
DAC_16BIT_R2R(config, m_rdac, 0).add_route(ALL_OUTPUTS, "rspeaker", 0.5); // unknown DAC
DAC_16BIT_R2R(config, m_ldac, 0).add_route(ALL_OUTPUTS, "speaker", 0.5, 0); // unknown DAC
DAC_16BIT_R2R(config, m_rdac, 0).add_route(ALL_OUTPUTS, "speaker", 0.5, 1); // unknown DAC
PC_JOY(config, m_joy);
@ -1169,16 +1168,16 @@ void isa8_sblaster1_0_device::device_add_mconfig(machine_config &config)
common(config);
YM3812(config, m_ym3812, ym3812_StdClock);
m_ym3812->add_route(ALL_OUTPUTS, "lspeaker", 3.0);
m_ym3812->add_route(ALL_OUTPUTS, "rspeaker", 3.0);
m_ym3812->add_route(ALL_OUTPUTS, "speaker", 3.0, 0);
m_ym3812->add_route(ALL_OUTPUTS, "speaker", 3.0, 1);
SAA1099(config, m_saa1099_1, XTAL(14'318'181) / 2); // or CMS-301, from OSC pin in ISA bus
m_saa1099_1->add_route(0, "lspeaker", 0.5);
m_saa1099_1->add_route(1, "rspeaker", 0.5);
m_saa1099_1->add_route(0, "speaker", 0.5, 0);
m_saa1099_1->add_route(1, "speaker", 0.5, 1);
SAA1099(config, m_saa1099_2, XTAL(14'318'181) / 2); // or CMS-301, from OSC pin in ISA bus
m_saa1099_2->add_route(0, "lspeaker", 0.5);
m_saa1099_2->add_route(1, "rspeaker", 0.5);
m_saa1099_2->add_route(0, "speaker", 0.5, 0);
m_saa1099_2->add_route(1, "speaker", 0.5, 1);
}
void isa8_sblaster1_5_device::device_add_mconfig(machine_config &config)
@ -1186,8 +1185,8 @@ void isa8_sblaster1_5_device::device_add_mconfig(machine_config &config)
common(config);
YM3812(config, m_ym3812, ym3812_StdClock);
m_ym3812->add_route(ALL_OUTPUTS, "lspeaker", 1.0);
m_ym3812->add_route(ALL_OUTPUTS, "rspeaker", 1.0);
m_ym3812->add_route(ALL_OUTPUTS, "speaker", 1.0, 0);
m_ym3812->add_route(ALL_OUTPUTS, "speaker", 1.0, 1);
/* no CM/S support (empty sockets) */
}
@ -1196,10 +1195,10 @@ void isa16_sblaster16_device::device_add_mconfig(machine_config &config)
common(config);
ymf262_device &ymf262(YMF262(config, "ymf262", ymf262_StdClock));
ymf262.add_route(0, "lspeaker", 1.0);
ymf262.add_route(1, "rspeaker", 1.0);
ymf262.add_route(2, "lspeaker", 1.0);
ymf262.add_route(3, "rspeaker", 1.0);
ymf262.add_route(0, "speaker", 1.0, 0);
ymf262.add_route(1, "speaker", 1.0, 1);
ymf262.add_route(2, "speaker", 1.0, 0);
ymf262.add_route(3, "speaker", 1.0, 1);
}
//**************************************************************************

View File

@ -124,15 +124,14 @@ void stereo_fx_device::device_add_mconfig(machine_config &config)
m_cpu->port_in_cb<3>().set(FUNC(stereo_fx_device::p3_r));
m_cpu->port_out_cb<3>().set(FUNC(stereo_fx_device::p3_w));
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
SPEAKER(config, "speaker", 2).front();
ym3812_device &ym3812(YM3812(config, "ym3812", XTAL(3'579'545)));
ym3812.add_route(ALL_OUTPUTS, "lspeaker", 1.00);
ym3812.add_route(ALL_OUTPUTS, "rspeaker", 1.00);
ym3812.add_route(ALL_OUTPUTS, "speaker", 1.00, 0);
ym3812.add_route(ALL_OUTPUTS, "speaker", 1.00, 1);
/* no CM/S support (empty sockets) */
DAC_8BIT_R2R(config, "ldac", 0).add_route(ALL_OUTPUTS, "lspeaker", 0.5); // unknown DAC
DAC_8BIT_R2R(config, "rdac", 0).add_route(ALL_OUTPUTS, "rspeaker", 0.5); // unknown DAC
DAC_8BIT_R2R(config, "ldac", 0).add_route(ALL_OUTPUTS, "speaker", 0.5, 0); // unknown DAC
DAC_8BIT_R2R(config, "rdac", 0).add_route(ALL_OUTPUTS, "speaker", 0.5, 1); // unknown DAC
PC_JOY(config, m_joy);
}

View File

@ -57,18 +57,17 @@ void msx_cart_moonsound_device::ymf278b_map(address_map &map)
void msx_cart_moonsound_device::device_add_mconfig(machine_config &config)
{
// The moonsound cartridge has a separate stereo output.
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
SPEAKER(config, "speaker", 2).front();
YMF278B(config, m_ymf278b, 33.8688_MHz_XTAL);
m_ymf278b->set_addrmap(0, &msx_cart_moonsound_device::ymf278b_map);
m_ymf278b->irq_handler().set(FUNC(msx_cart_moonsound_device::irq_w));
m_ymf278b->add_route(0, "lspeaker", 0.50);
m_ymf278b->add_route(1, "rspeaker", 0.50);
m_ymf278b->add_route(2, "lspeaker", 0.40);
m_ymf278b->add_route(3, "rspeaker", 0.40);
m_ymf278b->add_route(4, "lspeaker", 0.50);
m_ymf278b->add_route(5, "rspeaker", 0.50);
m_ymf278b->add_route(0, "speaker", 0.50, 0);
m_ymf278b->add_route(1, "speaker", 0.50, 1);
m_ymf278b->add_route(2, "speaker", 0.40, 0);
m_ymf278b->add_route(3, "speaker", 0.40, 1);
m_ymf278b->add_route(4, "speaker", 0.50, 0);
m_ymf278b->add_route(5, "speaker", 0.50, 1);
}
ROM_START(msx_cart_moonsound)

View File

@ -63,12 +63,11 @@ void msx_cart_sfg_device::device_add_mconfig(machine_config &config)
// YM3012 (DAC)
// YM2148 (MKS)
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
SPEAKER(config, "speaker", 2).front();
ym2151_device &ym2151(YM2151(config, m_ym2151, DERIVED_CLOCK(1, 1))); // The SFG01 uses a YM2151, the SFG05 uses a YM2164, input clock comes from the main cpu frequency
ym2151.irq_handler().set(FUNC(msx_cart_sfg_device::ym2151_irq_w));
ym2151.add_route(0, "lspeaker", 0.80);
ym2151.add_route(1, "rspeaker", 0.80);
ym2151.add_route(0, "speaker", 0.80, 0);
ym2151.add_route(1, "speaker", 0.80, 1);
YM2148(config, m_ym2148, XTAL(4'000'000));
m_ym2148->txd_handler().set("mdout", FUNC(midi_port_device::write_txd));
@ -186,8 +185,8 @@ void msx_cart_sfg05_device::device_add_mconfig(machine_config &config)
ym2164_device &ym2164(YM2164(config.replace(), m_ym2151, DERIVED_CLOCK(1, 1)));
ym2164.irq_handler().set(FUNC(msx_cart_sfg05_device::ym2151_irq_w));
ym2164.add_route(0, "lspeaker", 0.80);
ym2164.add_route(1, "rspeaker", 0.80);
ym2164.add_route(0, "speaker", 0.80, 0);
ym2164.add_route(1, "speaker", 0.80, 1);
}
ROM_START(msx_sfg05)

View File

@ -44,10 +44,10 @@ void gsx8800_device::device_add_mconfig(machine_config &config)
// it's just known that one goes to the left and the other to the right
// cfr. http://mydocuments.g2.xrea.com/html/p8/soundinfo.html
YM2149(config, m_psg[0], psg_x1_clock);
m_psg[0]->add_route(ALL_OUTPUTS, "^^lspeaker", 0.50);
m_psg[0]->add_route(ALL_OUTPUTS, "^^speaker", 0.50, 0);
YM2149(config, m_psg[1], psg_x1_clock);
m_psg[1]->add_route(ALL_OUTPUTS, "^^rspeaker", 0.50);
m_psg[1]->add_route(ALL_OUTPUTS, "^^speaker", 0.50, 1);
// ...->irq_handler().set(FUNC(gsx8800_device::int3_w));

View File

@ -37,6 +37,6 @@ void hmb20_device::device_add_mconfig(machine_config &config)
// TODO: OPM mixing
YM2151(config, m_opm, hmb20_x1_clock);
// m_opm->irq_handler().set(FUNC(hmb20_device::int4_w));
m_opm->add_route(ALL_OUTPUTS, "^^lspeaker", 0.50);
m_opm->add_route(ALL_OUTPUTS, "^^rspeaker", 0.50);
m_opm->add_route(ALL_OUTPUTS, "^^speaker", 0.50, 0);
m_opm->add_route(ALL_OUTPUTS, "^^speaker", 0.50, 1);
}

View File

@ -44,15 +44,15 @@ void jmbx1_device::device_add_mconfig(machine_config &config)
// doesn't seem to have irq mask
YM2151(config, m_opm1, jmb_x1_clock / 2);
m_opm1->irq_handler().set(FUNC(jmbx1_device::int4_w));
m_opm1->add_route(ALL_OUTPUTS, "^^lspeaker", 0.25);
m_opm1->add_route(ALL_OUTPUTS, "^^rspeaker", 0.25);
m_opm1->add_route(ALL_OUTPUTS, "^^speaker", 0.25, 0);
m_opm1->add_route(ALL_OUTPUTS, "^^speaker", 0.25, 1);
YM2151(config, m_opm2, jmb_x1_clock / 2);
m_opm2->add_route(ALL_OUTPUTS, "^^lspeaker", 0.25);
m_opm2->add_route(ALL_OUTPUTS, "^^rspeaker", 0.25);
m_opm2->add_route(ALL_OUTPUTS, "^^speaker", 0.25, 0);
m_opm2->add_route(ALL_OUTPUTS, "^^speaker", 0.25, 1);
YM2149(config, m_ssg, jmb_x1_clock / 4);
// TODO: adds a non-negligible DC offset, likely needs high pass filter
m_ssg->add_route(ALL_OUTPUTS, "^^lspeaker", 0.20);
m_ssg->add_route(ALL_OUTPUTS, "^^rspeaker", 0.20);
m_ssg->add_route(ALL_OUTPUTS, "^^speaker", 0.20, 0);
m_ssg->add_route(ALL_OUTPUTS, "^^speaker", 0.20, 1);
}

View File

@ -50,10 +50,10 @@ void pc8801_23_device::device_add_mconfig(machine_config &config)
// m_opna->port_a_read_callback().set(FUNC(pc8801_23_device::opn_porta_r));
// m_opna->port_b_read_callback().set_ioport("OPN_PB");
// TODO: per-channel mixing is unconfirmed
m_opna->add_route(0, "^^lspeaker", 0.75);
m_opna->add_route(0, "^^rspeaker", 0.75);
m_opna->add_route(1, "^^lspeaker", 0.75);
m_opna->add_route(2, "^^rspeaker", 0.75);
m_opna->add_route(0, "^^speaker", 0.75, 0);
m_opna->add_route(0, "^^speaker", 0.75, 1);
m_opna->add_route(1, "^^speaker", 0.75, 0);
m_opna->add_route(2, "^^speaker", 0.75, 1);
}
void pc8801_23_device::device_start()

View File

@ -46,8 +46,8 @@ void pcg8100_device::device_add_mconfig(machine_config &config)
for (auto &dac1bit : m_dac1bit)
{
SPEAKER_SOUND(config, dac1bit);
dac1bit->add_route(ALL_OUTPUTS, "^^lspeaker", 0.25);
dac1bit->add_route(ALL_OUTPUTS, "^^rspeaker", 0.25);
dac1bit->add_route(ALL_OUTPUTS, "^^speaker", 0.25, 0);
dac1bit->add_route(ALL_OUTPUTS, "^^speaker", 0.25, 1);
}
}

View File

@ -62,18 +62,17 @@ sonicvibes_device::sonicvibes_device(const machine_config &mconfig, const char *
void sonicvibes_device::device_add_mconfig(machine_config &config)
{
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
SPEAKER(config, "speaker", 2).front();
// TODO: (barely visible) only 24'576 xtal on a Turtle Beach PCB, is it really 12-ish MHz?
YMF262(config, m_opl3, XTAL(14'318'181));
m_opl3->add_route(0, "lspeaker", 1.0);
m_opl3->add_route(1, "rspeaker", 1.0);
m_opl3->add_route(2, "lspeaker", 1.0);
m_opl3->add_route(3, "rspeaker", 1.0);
m_opl3->add_route(0, "speaker", 1.0, 0);
m_opl3->add_route(1, "speaker", 1.0, 1);
m_opl3->add_route(2, "speaker", 1.0, 0);
m_opl3->add_route(3, "speaker", 1.0, 1);
// DAC_16BIT_R2R(config, m_ldac, 0).add_route(ALL_OUTPUTS, "lspeaker", 0.5); // unknown DAC
// DAC_16BIT_R2R(config, m_rdac, 0).add_route(ALL_OUTPUTS, "rspeaker", 0.5); // unknown DAC
// DAC_16BIT_R2R(config, m_ldac, 0).add_route(ALL_OUTPUTS, "speaker", 0.5); // unknown DAC
// DAC_16BIT_R2R(config, m_rdac, 0).add_route(ALL_OUTPUTS, "speaker", 0.5); // unknown DAC
PC_JOY(config, m_joy);

View File

@ -83,12 +83,11 @@ void sw1000xg_device::device_add_mconfig(machine_config &config)
H83002(config, m_maincpu, 16_MHz_XTAL);
m_maincpu->set_addrmap(AS_PROGRAM, &sw1000xg_device::h8_map);
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
SPEAKER(config, "speaker", 2).front();
SWP30(config, m_swp30);
m_swp30->set_addrmap(AS_DATA, &sw1000xg_device::swp30_map);
m_swp30->add_route(0, "lspeaker", 1.0);
m_swp30->add_route(1, "rspeaker", 1.0);
m_swp30->add_route(0, "speaker", 1.0, 0);
m_swp30->add_route(1, "speaker", 1.0, 1);
}

View File

@ -67,8 +67,8 @@ void plg100_vl_device::device_add_mconfig(machine_config &config)
m_cpu->write_sci_tx<1>().set([this] (int state) { m_connector->do_midi_tx(state); });
DSPV(config, m_dspv, 22.5792_MHz_XTAL);
m_dspv->add_route(0, DEVICE_SELF_OWNER, 1.0, AUTO_ALLOC_INPUT, 0);
m_dspv->add_route(1, DEVICE_SELF_OWNER, 1.0, AUTO_ALLOC_INPUT, 1);
m_dspv->add_route(0, DEVICE_SELF_OWNER, 1.0, 0);
m_dspv->add_route(1, DEVICE_SELF_OWNER, 1.0, 1);
}
ROM_START( plg100_vl )

View File

@ -12,7 +12,7 @@ DEFINE_DEVICE_TYPE(PLG1X0_CONNECTOR, plg1x0_connector, "plg1x0_connector", "PLG1
plg1x0_connector::plg1x0_connector(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, PLG1X0_CONNECTOR, tag, owner, clock),
device_single_card_slot_interface<device_plg1x0_interface>(mconfig, *this),
device_mixer_interface(mconfig, *this, 2),
device_mixer_interface(mconfig, *this),
m_midi_tx(*this)
{
}

View File

@ -158,14 +158,13 @@ void rc2014_ym2149_device::device_reset()
void rc2014_ym2149_device::device_add_mconfig(machine_config &config)
{
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
SPEAKER(config, "speaker", 2).front();
YM2149(config, m_psg, 0);
m_psg->add_route(0, "rspeaker", 0.25);
m_psg->add_route(2, "rspeaker", 0.25);
m_psg->add_route(1, "lspeaker", 0.25);
m_psg->add_route(2, "lspeaker", 0.25);
m_psg->add_route(0, "speaker", 0.25, 1);
m_psg->add_route(2, "speaker", 0.25, 1);
m_psg->add_route(1, "speaker", 0.25, 0);
m_psg->add_route(2, "speaker", 0.25, 0);
}
//**************************************************************************
@ -190,14 +189,13 @@ rc2014_ay8190_device::rc2014_ay8190_device(const machine_config &mconfig, const
void rc2014_ay8190_device::device_add_mconfig(machine_config &config)
{
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
SPEAKER(config, "speaker", 2).front();
AY8910(config, m_psg, 0);
m_psg->add_route(0, "rspeaker", 0.25);
m_psg->add_route(2, "rspeaker", 0.25);
m_psg->add_route(1, "lspeaker", 0.25);
m_psg->add_route(2, "lspeaker", 0.25);
m_psg->add_route(0, "speaker", 0.25, 1);
m_psg->add_route(2, "speaker", 0.25, 1);
m_psg->add_route(1, "speaker", 0.25, 0);
m_psg->add_route(2, "speaker", 0.25, 0);
}
}

View File

@ -78,12 +78,11 @@ void mockingboard_d_device::device_add_mconfig(machine_config &config)
m_cpu->out_p1_cb().set(FUNC(mockingboard_d_device::p1_w));
m_cpu->out_ser_tx_cb().set(FUNC(mockingboard_d_device::ser_tx_w));
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
SPEAKER(config, "speaker", 2).front();
AY8913(config, m_ay1, 1022727);
m_ay1->add_route(ALL_OUTPUTS, "lspeaker", 0.5);
m_ay1->add_route(ALL_OUTPUTS, "speaker", 0.5, 0);
AY8913(config, m_ay2, 1022727);
m_ay2->add_route(ALL_OUTPUTS, "lspeaker", 0.5);
m_ay2->add_route(ALL_OUTPUTS, "speaker", 0.5, 0);
}
const tiny_rom_entry *mockingboard_d_device::device_rom_region() const

View File

@ -142,12 +142,11 @@ void segaai_soundbox_device::device_add_mconfig(machine_config &config)
m_tmp8255->out_pb_callback().set(FUNC(segaai_soundbox_device::tmp8255_portb_w));
m_tmp8255->out_pc_callback().set(FUNC(segaai_soundbox_device::tmp8255_portc_w));
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
SPEAKER(config, "speaker", 2).front();
YM2151(config, m_ym2151, DERIVED_CLOCK(1,1)); // ~3.58MHz
m_ym2151->irq_handler().set(FUNC(segaai_soundbox_device::ym2151_irq_w));
m_ym2151->add_route(0, "lspeaker", 1.00);
m_ym2151->add_route(1, "rspeaker", 1.00);
m_ym2151->add_route(0, "speaker", 1.00, 0);
m_ym2151->add_route(1, "speaker", 1.00, 1);
}
ROM_START(soundbox)

View File

@ -426,11 +426,10 @@ void neogs_device::device_add_mconfig(machine_config &config)
m_sdcard->set_prefer_sdhc();
m_sdcard->spi_miso_callback().set([this](int state) { m_spi_data_in_latch <<= 1; m_spi_data_in_latch |= state; });
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
SPEAKER(config, "speaker", 2).front();
DAC_16BIT_R2R_TWOS_COMPLEMENT(config, m_dac[0], 0).add_route(ALL_OUTPUTS, "lspeaker", 0.75); // TDA1543
DAC_16BIT_R2R_TWOS_COMPLEMENT(config, m_dac[1], 0).add_route(ALL_OUTPUTS, "rspeaker", 0.75);
DAC_16BIT_R2R_TWOS_COMPLEMENT(config, m_dac[0], 0).add_route(ALL_OUTPUTS, "speaker", 0.75, 0); // TDA1543
DAC_16BIT_R2R_TWOS_COMPLEMENT(config, m_dac[1], 0).add_route(ALL_OUTPUTS, "speaker", 0.75, 1);
}
const tiny_rom_entry *neogs_device::device_rom_region() const

View File

@ -0,0 +1,100 @@
// license:BSD-3-Clause
// copyright-holders: Olivier Galibert
// Microdeal ST Replay
// A 8-bit mono DAC and a 8-bit mono ADC on a cartridge, with a vague
// lowpass filter.
// A peculiarity of the ST cartridge port is that it's readonly. So
// writing to the DAC is done by reading at an appropriate address.
#include "emu.h"
#include "replay.h"
#include "sound/adc.h"
#include "sound/dac.h"
#include "speaker.h"
namespace {
class st_replay_device : public device_t, public device_stcart_interface
{
public:
st_replay_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
virtual ~st_replay_device();
virtual void map(address_space_installer &space) override;
protected:
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
required_device<zn449_device> m_adc;
required_device<zn429e_device> m_dac;
required_device<microphone_device> m_mic;
required_device<speaker_device> m_speaker;
void cartmap(address_map &map) ATTR_COLD;
u16 dac_w(offs_t data);
};
st_replay_device::st_replay_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, ST_REPLAY, tag, owner, clock),
device_stcart_interface(mconfig, *this),
m_adc(*this, "adc"),
m_dac(*this, "dac"),
m_mic(*this, "mic"),
m_speaker(*this, "speaker")
{
}
st_replay_device::~st_replay_device()
{
}
u16 st_replay_device::dac_w(offs_t data)
{
m_dac->write(data);
return 0xffff;
}
void st_replay_device::map(address_space_installer &space)
{
space.install_device(0xfa0000, 0xfbffff, *this, &st_replay_device::cartmap);
}
void st_replay_device::cartmap(address_map &map)
{
map(0x00000, 0x001ff).r(FUNC(st_replay_device::dac_w)).mirror(0xfe00);
map(0x10001, 0x10001).r(m_adc, FUNC(zn449_device::read)).mirror(0xfffe);
}
void st_replay_device::device_add_mconfig(machine_config &config)
{
MICROPHONE(config, m_mic, 1).front_center();
m_mic->add_route(0, m_adc, 1.0, 0);
ZN449(config, m_adc);
// ZN429D the schematics say, not sure if any significant difference
ZN429E(config, m_dac);
m_dac->add_route(0, m_speaker, 1.0, 0);
SPEAKER(config, m_speaker, 1).front_center();
}
void st_replay_device::device_start()
{
}
void st_replay_device::device_reset()
{
}
} // anonymous namespace
DEFINE_DEVICE_TYPE_PRIVATE(ST_REPLAY, device_stcart_interface, st_replay_device, "st_replay", "Microdeal ST Replay")

View File

@ -0,0 +1,15 @@
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert
#ifndef MAME_BUS_ST_REPLAY_H
#define MAME_BUS_ST_REPLAY_H
// Microdeal ST Replay
#pragma once
#include "stcart.h"
DECLARE_DEVICE_TYPE(ST_REPLAY, device_stcart_interface)
#endif // MAME_BUS_ST_REPLAY_H

View File

@ -0,0 +1,40 @@
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert
#include "emu.h"
#include "stcart.h"
#include "replay.h"
DEFINE_DEVICE_TYPE(STCART_CONNECTOR, stcart_connector, "stcart_connector", "Atari ST cartridge connector")
stcart_connector::stcart_connector(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, STCART_CONNECTOR, tag, owner, clock),
device_single_card_slot_interface<device_stcart_interface>(mconfig, *this)
{
}
void stcart_connector::device_start()
{
}
void stcart_connector::map(address_space_installer &space)
{
auto card = get_card_device();
if(card)
card->map(space);
}
void stcart_intf(device_slot_interface &device)
{
device.option_add("replay", ST_REPLAY);
}
device_stcart_interface::device_stcart_interface(const machine_config &mconfig, device_t &device) :
device_interface(device, "stcart")
{
}
device_stcart_interface::~device_stcart_interface()
{
}

View File

@ -0,0 +1,50 @@
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert
// Atari ST cartridges
#ifndef MAME_BUS_ST_STCART_H
#define MAME_BUS_ST_STCART_H
#pragma once
class device_stcart_interface;
class stcart_connector: public device_t, public device_single_card_slot_interface<device_stcart_interface>
{
public:
template <typename T>
stcart_connector(const machine_config &mconfig, const char *tag, device_t *owner, T &&opts, const char *dflt)
: stcart_connector(mconfig, tag, owner, (uint32_t)0)
{
option_reset();
opts(*this);
set_default_option(dflt);
set_fixed(false);
}
stcart_connector(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
void map(address_space_installer &space);
protected:
virtual void device_start() override ATTR_COLD;
};
class device_stcart_interface: public device_interface
{
public:
device_stcart_interface(const machine_config &mconfig, device_t &device);
virtual ~device_stcart_interface();
virtual void map(address_space_installer &space) = 0;
protected:
};
DECLARE_DEVICE_TYPE(STCART_CONNECTOR, stcart_connector)
void stcart_intf(device_slot_interface &device);
#endif // MAME_BUS_ST_STCART_H

View File

@ -71,8 +71,8 @@ void db50xg_device::device_add_mconfig(machine_config &config)
m_cpu->write_sci_tx<0>().set([this] (int state) { m_connector->do_midi_tx(state); });
SWP00(config, m_swp00);
m_swp00->add_route(0, DEVICE_SELF_OWNER, 1.0, AUTO_ALLOC_INPUT, 0);
m_swp00->add_route(1, DEVICE_SELF_OWNER, 1.0, AUTO_ALLOC_INPUT, 1);
m_swp00->add_route(0, DEVICE_SELF_OWNER, 1.0, 0);
m_swp00->add_route(1, DEVICE_SELF_OWNER, 1.0, 1);
}
ROM_START( db50xg )

View File

@ -69,8 +69,8 @@ void db60xg_device::device_add_mconfig(machine_config &config)
m_cpu->write_sci_tx<0>().set([this] (int state) { m_connector->do_midi_tx(state); });
SWP00(config, m_swp00);
m_swp00->add_route(0, DEVICE_SELF_OWNER, 1.0, AUTO_ALLOC_INPUT, 0);
m_swp00->add_route(1, DEVICE_SELF_OWNER, 1.0, AUTO_ALLOC_INPUT, 1);
m_swp00->add_route(0, DEVICE_SELF_OWNER, 1.0, 0);
m_swp00->add_route(1, DEVICE_SELF_OWNER, 1.0, 1);
}
ROM_START( db60xg )

View File

@ -47,8 +47,8 @@ void omniwave_device::midi_rx(int state)
void omniwave_device::device_add_mconfig(machine_config &config)
{
KS0164(config, m_ks0164, 16.9344_MHz_XTAL);
m_ks0164->add_route(0, DEVICE_SELF_OWNER, 1.0, AUTO_ALLOC_INPUT, 0);
m_ks0164->add_route(1, DEVICE_SELF_OWNER, 1.0, AUTO_ALLOC_INPUT, 1);
m_ks0164->add_route(0, DEVICE_SELF_OWNER, 1.0, 0);
m_ks0164->add_route(1, DEVICE_SELF_OWNER, 1.0, 1);
m_ks0164->midi_tx().set([this] (int state) { m_connector->do_midi_tx(state); });
}

View File

@ -15,7 +15,7 @@ DEFINE_DEVICE_TYPE(WAVEBLASTER_CONNECTOR, waveblaster_connector, "waveblaster_co
waveblaster_connector::waveblaster_connector(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, WAVEBLASTER_CONNECTOR, tag, owner, clock),
device_single_card_slot_interface<device_waveblaster_interface>(mconfig, *this),
device_mixer_interface(mconfig, *this, 2),
device_mixer_interface(mconfig, *this),
m_midi_tx(*this)
{
}

View File

@ -77,8 +77,8 @@ void wg130_device::device_add_mconfig(machine_config &config)
{
GT913(config, m_gt913, 30_MHz_XTAL / 2);
m_gt913->set_addrmap(AS_DATA, &wg130_device::map);
m_gt913->add_route(0, DEVICE_SELF_OWNER, 1.0, AUTO_ALLOC_INPUT, 0);
m_gt913->add_route(1, DEVICE_SELF_OWNER, 1.0, AUTO_ALLOC_INPUT, 1);
m_gt913->add_route(0, DEVICE_SELF_OWNER, 1.0, 0);
m_gt913->add_route(1, DEVICE_SELF_OWNER, 1.0, 1);
m_gt913->read_port1().set_constant(0xff);
m_gt913->write_port1().set_nop();
m_gt913->read_port2().set_constant(0xff);

View File

@ -169,7 +169,7 @@ DEFINE_DEVICE_TYPE(H6280, h6280_device, "h6280", "Hudson Soft HuC6280")
h6280_device::h6280_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: cpu_device(mconfig, H6280, tag, owner, clock)
, device_mixer_interface(mconfig, *this, 2)
, device_mixer_interface(mconfig, *this)
, m_program_config("program", ENDIANNESS_LITTLE, 8, 21, 0, 16, 0, address_map_constructor(FUNC(h6280_device::internal_map), this))
, m_io_config("io", ENDIANNESS_LITTLE, 8, 2)
, m_port_in_cb(*this, 0)
@ -232,8 +232,8 @@ const h6280_device::ophandler h6280_device::s_opcodetable[256] =
void h6280_device::device_add_mconfig(machine_config &config)
{
C6280(config, m_psg, DERIVED_CLOCK(1,2));
m_psg->add_route(0, *this, 1.0, AUTO_ALLOC_INPUT, 0);
m_psg->add_route(1, *this, 1.0, AUTO_ALLOC_INPUT, 1);
m_psg->add_route(0, *this, 1.0, 0);
m_psg->add_route(1, *this, 1.0, 1);
}
void h6280_device::device_start()

View File

@ -28,7 +28,7 @@ DEFINE_DEVICE_TYPE(GT913, gt913_device, "gt913", "Casio GT913F")
gt913_device::gt913_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
h8_device(mconfig, GT913, tag, owner, clock, address_map_constructor(FUNC(gt913_device::map), this)),
device_mixer_interface(mconfig, *this, 2),
device_mixer_interface(mconfig, *this),
m_rom(*this, DEVICE_SELF),
m_data_config("data", ENDIANNESS_BIG, 16, 22, 0),
m_write_ple(*this),
@ -102,8 +102,8 @@ void gt913_device::device_add_mconfig(machine_config &config)
GT913_SOUND(config, m_sound, DERIVED_CLOCK(1, 1));
m_sound->set_device_rom_tag(m_rom);
m_sound->add_route(0, *this, 1.0, AUTO_ALLOC_INPUT, 0);
m_sound->add_route(1, *this, 1.0, AUTO_ALLOC_INPUT, 1);
m_sound->add_route(0, *this, 1.0, 0);
m_sound->add_route(1, *this, 1.0, 1);
GT913_KBD_HLE(config, m_kbd, 0);
m_kbd->irq_cb().set([this] (int val) {

View File

@ -7,7 +7,7 @@ DEFINE_DEVICE_TYPE(SWX00, swx00_device, "swx00", "Yamaha SWX00")
swx00_device::swx00_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, u8 mode) :
h8s2000_device(mconfig, SWX00, tag, owner, clock, address_map_constructor(FUNC(swx00_device::map), this)),
device_mixer_interface(mconfig, *this, 2),
device_mixer_interface(mconfig, *this),
m_intc(*this, "intc"),
m_adc(*this, "adc"),
m_dma(*this, "dma"),
@ -316,8 +316,8 @@ void swx00_device::device_add_mconfig(machine_config &config)
SWX00_SOUND(config, m_swx00);
m_swx00->set_space(DEVICE_SELF, AS_S);
m_swx00->add_route(0, DEVICE_SELF, 1.0, AUTO_ALLOC_INPUT, 0);
m_swx00->add_route(1, DEVICE_SELF, 1.0, AUTO_ALLOC_INPUT, 1);
m_swx00->add_route(0, DEVICE_SELF, 1.0, 0);
m_swx00->add_route(1, DEVICE_SELF, 1.0, 1);
}
device_memory_interface::space_config_vector swx00_device::memory_space_config() const

View File

@ -20,7 +20,7 @@ DEFINE_DEVICE_TYPE(GEW12, gew12_device, "gew12", "Yamaha YMW728-F (GEW12)")
gew12_device::gew12_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: m6502_mcu_device_base<w65c02_device>(mconfig, GEW12, tag, owner, clock)
, device_mixer_interface(mconfig, *this, 2)
, device_mixer_interface(mconfig, *this)
, m_in_cb(*this, 0xff), m_out_cb(*this)
, m_rom(*this, DEVICE_SELF)
, m_bank(*this, "bank%u", 0U)

View File

@ -20,7 +20,7 @@ DEFINE_DEVICE_TYPE(GEW7, gew7_device, "gew7", "Yamaha YMW270-F (GEW7)")
gew7_device::gew7_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: m6502_mcu_device_base<w65c02_device>(mconfig, GEW7, tag, owner, clock)
, device_mixer_interface(mconfig, *this, 2)
, device_mixer_interface(mconfig, *this)
, m_in_cb(*this, 0xff), m_out_cb(*this)
, m_rom(*this, DEVICE_SELF)
, m_bank(*this, "bank%u", 0U)
@ -37,8 +37,8 @@ void gew7_device::device_add_mconfig(machine_config &config)
{
GEW7_PCM(config, m_pcm, DERIVED_CLOCK(1, 1));
m_pcm->set_device_rom_tag(m_rom);
m_pcm->add_route(0, *this, 1.0, AUTO_ALLOC_INPUT, 0);
m_pcm->add_route(1, *this, 1.0, AUTO_ALLOC_INPUT, 1);
m_pcm->add_route(0, *this, 1.0, 0);
m_pcm->add_route(1, *this, 1.0, 1);
}
void gew7_device::device_start()

View File

@ -45,7 +45,7 @@ rp2a03_core_device::rp2a03_core_device(const machine_config &mconfig, const char
rp2a03_device::rp2a03_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: rp2a03_core_device(mconfig, type, tag, owner, clock)
, device_mixer_interface(mconfig, *this, 1)
, device_mixer_interface(mconfig, *this)
, m_apu(*this, "nesapu")
{
program_config.m_internal_map = address_map_constructor(FUNC(rp2a03_device::rp2a03_map), this);
@ -84,7 +84,7 @@ void rp2a03_device::device_add_mconfig(machine_config &config)
APU_2A03(config, m_apu, DERIVED_CLOCK(1,1));
m_apu->irq().set(FUNC(rp2a03_device::apu_irq));
m_apu->mem_read().set(FUNC(rp2a03_device::apu_read_mem));
m_apu->add_route(ALL_OUTPUTS, *this, 1.0, AUTO_ALLOC_INPUT, 0);
m_apu->add_route(ALL_OUTPUTS, *this, 1.0, 0);
}
void rp2a03g_device::device_add_mconfig(machine_config &config)
@ -92,7 +92,7 @@ void rp2a03g_device::device_add_mconfig(machine_config &config)
NES_APU(config, m_apu, DERIVED_CLOCK(1,1));
m_apu->irq().set(FUNC(rp2a03g_device::apu_irq));
m_apu->mem_read().set(FUNC(rp2a03g_device::apu_read_mem));
m_apu->add_route(ALL_OUTPUTS, *this, 1.0, AUTO_ALLOC_INPUT, 0);
m_apu->add_route(ALL_OUTPUTS, *this, 1.0, 0);
}

View File

@ -101,25 +101,19 @@ st2302u_device::st2302u_device(const machine_config &mconfig, const char *tag, d
{
}
void st2205u_base_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
void st2205u_base_device::sound_stream_update(sound_stream &stream)
{
// reset the output stream
outputs[0].fill(0);
outputs[1].fill(0);
outputs[2].fill(0);
outputs[3].fill(0);
int samples = outputs[0].samples();
int samples = stream.samples();
int outpos = 0;
while (samples-- != 0)
{
for (int channel = 0; channel < 4; channel++)
{
s16 adpcm_contribution = m_adpcm_level[channel];
outputs[channel].add_int(outpos, adpcm_contribution * 0x10, 32768);
stream.add_int(channel, outpos, adpcm_contribution * 0x10, 32768);
auto psg_contribution = std::sin((double)m_psg_freqcntr[channel]/4096.0f);
outputs[channel].add_int(outpos, psg_contribution * m_psg_amplitude[channel]*0x80,32768);
stream.add_int(channel, outpos, psg_contribution * m_psg_amplitude[channel]*0x80,32768);
}
outpos++;

View File

@ -64,7 +64,7 @@ protected:
virtual void device_reset() override ATTR_COLD;
// sound stream update overrides
virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override;
virtual void sound_stream_update(sound_stream &stream) override;
virtual unsigned st2xxx_bt_divider(int n) const override;
virtual u8 st2xxx_prs_mask() const override { return 0xc0; }

View File

@ -920,21 +920,20 @@ void tms57002_device::execute_run()
icount = 0;
}
void tms57002_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
void tms57002_device::sound_stream_update(sound_stream &stream)
{
assert(inputs[0].samples() == 1);
assert(outputs[0].samples() == 1);
assert(stream.samples() == 1);
stream_buffer::sample_t in_scale = 32767.0 * ((st0 & ST0_SIM) ? 256.0 : 1.0);
si[0] = s32(inputs[0].get(0) * in_scale) & 0xffffff;
si[1] = s32(inputs[1].get(0) * in_scale) & 0xffffff;
si[2] = s32(inputs[2].get(0) * in_scale) & 0xffffff;
si[3] = s32(inputs[3].get(0) * in_scale) & 0xffffff;
sound_stream::sample_t in_scale = 32768.0 * ((st0 & ST0_SIM) ? 256.0 : 1.0);
si[0] = s32(stream.get(0, 0) * in_scale) & 0xffffff;
si[1] = s32(stream.get(1, 0) * in_scale) & 0xffffff;
si[2] = s32(stream.get(2, 0) * in_scale) & 0xffffff;
si[3] = s32(stream.get(3, 0) * in_scale) & 0xffffff;
outputs[0].put_int(0, s32(so[0] << 8) >> 1, 32768 * 32768);
outputs[1].put_int(0, s32(so[1] << 8) >> 1, 32768 * 32768);
outputs[2].put_int(0, s32(so[2] << 8) >> 1, 32768 * 32768);
outputs[3].put_int(0, s32(so[3] << 8) >> 1, 32768 * 32768);
stream.put(0, 0, s32(so[0] << 8) / 2147483648.0);
stream.put(1, 0, s32(so[1] << 8) / 2147483648.0);
stream.put(2, 0, s32(so[2] << 8) / 2147483648.0);
stream.put(3, 0, s32(so[3] << 8) / 2147483648.0);
sync_w(1);
}

View File

@ -36,7 +36,7 @@ public:
protected:
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override;
virtual void sound_stream_update(sound_stream &stream) override;
virtual space_config_vector memory_space_config() const override;
virtual u32 execute_min_cycles() const noexcept override;
virtual u32 execute_max_cycles() const noexcept override;

View File

@ -782,13 +782,11 @@ void upd177x_cpu_device::execute_run()
}
void upd177x_cpu_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
void upd177x_cpu_device::sound_stream_update(sound_stream &stream)
{
auto &buffer = outputs[0];
const int smpl = m_dac_sign ? -m_dac : m_dac;
for (int sampindex = 0; sampindex < buffer.samples(); sampindex++)
for (int sampindex = 0; sampindex < stream.samples(); sampindex++)
{
buffer.put_int(sampindex, smpl, 256);
stream.put_int(0, sampindex, smpl, 256);
}
}

View File

@ -57,7 +57,7 @@ protected:
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override;
virtual void sound_stream_update(sound_stream &stream) override;
void program_map(address_map &map) ATTR_COLD;

View File

@ -448,33 +448,29 @@ std::string cassette_image_device::call_display()
// Cassette sound
//-------------------------------------------------
void cassette_image_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
void cassette_image_device::sound_stream_update(sound_stream &stream)
{
cassette_state state = get_state() & (CASSETTE_MASK_UISTATE | CASSETTE_MASK_MOTOR | CASSETTE_MASK_SPEAKER);
if (exists() && (state == (CASSETTE_PLAY | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_ENABLED)))
{
int samples = stream.samples();
cassette_image *cassette = get_image();
double time_index = get_position();
double duration = ((double) outputs[0].samples()) / outputs[0].sample_rate();
double duration = ((double) samples) / stream.sample_rate();
if (m_samples.size() < outputs[0].samples())
m_samples.resize(outputs[0].samples());
if (m_samples.size() < samples)
m_samples.resize(samples);
const cassette_image::Info info = cassette->get_info();
for (int ch = 0; ch < outputs.size(); ch++)
for (int ch = 0; ch < stream.output_count(); ch++)
{
if (ch < info.channels)
cassette->get_samples(ch, time_index, duration, outputs[0].samples(), 2, &m_samples[0], cassette_image::WAVEFORM_16BIT);
cassette->get_samples(ch, time_index, duration, samples, 2, &m_samples[0], cassette_image::WAVEFORM_16BIT);
else
cassette->get_samples(0, time_index, duration, outputs[0].samples(), 2, &m_samples[0], cassette_image::WAVEFORM_16BIT);
for (int sampindex = 0; sampindex < outputs[ch].samples(); sampindex++)
outputs[ch].put_int(sampindex, m_samples[sampindex], 32768);
cassette->get_samples(0, time_index, duration, samples, 2, &m_samples[0], cassette_image::WAVEFORM_16BIT);
for (int sampindex = 0; sampindex < samples; sampindex++)
stream.put_int(ch, sampindex, m_samples[sampindex], 32768);
}
}
else
{
for (int ch = 0; ch < outputs.size(); ch++)
outputs[ch].fill(0);
}
}

View File

@ -103,7 +103,7 @@ public:
void seek(double time, int origin);
// sound stream update overrides
virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override;
virtual void sound_stream_update(sound_stream &stream) override;
device_sound_interface& set_stereo() { m_stereo = true; return *this; }
protected:

View File

@ -1595,18 +1595,17 @@ void floppy_sound_device::step(int zone)
// sound_stream_update - update the sound stream
//-------------------------------------------------
void floppy_sound_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
void floppy_sound_device::sound_stream_update(sound_stream &stream)
{
// We are using only one stream, unlike the parent class
// Also, there is no need for interpolation, as we only expect
// one sample rate of 44100 for all samples
int16_t out;
auto &samplebuffer = outputs[0];
int m_idx = 0;
int sampleend = 0;
for (int sampindex = 0; sampindex < samplebuffer.samples(); sampindex++)
for (int sampindex = 0; sampindex < stream.samples(); sampindex++)
{
out = 0;
@ -1700,7 +1699,7 @@ void floppy_sound_device::sound_stream_update(sound_stream &stream, std::vector<
}
// Write to the stream buffer
samplebuffer.put_int(sampindex, out, 32768);
stream.put_int(0, sampindex, out, 32768);
}
}

View File

@ -413,7 +413,7 @@ protected:
private:
// device_sound_interface overrides
virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override;
virtual void sound_stream_update(sound_stream &stream) override;
sound_stream* m_sound;
int m_step_base;

View File

@ -65,8 +65,7 @@ acorn_vidc10_device::acorn_vidc10_device(const machine_config &mconfig, device_t
, m_sound_mode(false)
, m_dac(*this, "dac%u", 0)
, m_dac_type(dac_type)
, m_lspeaker(*this, "lspeaker")
, m_rspeaker(*this, "rspeaker")
, m_speaker(*this, "speaker")
, m_vblank_cb(*this)
, m_sound_drq_cb(*this)
, m_pixel_clock(0)
@ -110,12 +109,11 @@ device_memory_interface::space_config_vector acorn_vidc10_device::memory_space_c
void acorn_vidc10_device::device_add_mconfig(machine_config &config)
{
SPEAKER(config, m_lspeaker).front_left();
SPEAKER(config, m_rspeaker).front_right();
SPEAKER(config, m_speaker, 2).front();
for (int i = 0; i < m_sound_max_channels; i++)
{
// custom DAC
DAC_16BIT_R2R_TWOS_COMPLEMENT(config, m_dac[i], 0).add_route(0, m_lspeaker, m_sound_input_gain).add_route(0, m_rspeaker, m_sound_input_gain);
DAC_16BIT_R2R_TWOS_COMPLEMENT(config, m_dac[i], 0).add_route(0, m_speaker, m_sound_input_gain, 0).add_route(0, m_speaker, m_sound_input_gain, 1);
}
}
@ -405,9 +403,8 @@ inline void acorn_vidc10_device::refresh_stereo_image(u8 channel)
const float left_gain[8] = { 1.0f, 2.0f, 1.66f, 1.34f, 1.0f, 0.66f, 0.34f, 0.0f };
const float right_gain[8] = { 1.0f, 0.0f, 0.34f, 0.66f, 1.0f, 1.34f, 1.66f, 2.0f };
m_lspeaker->set_input_gain(channel, left_gain[m_stereo_image[channel]] * m_sound_input_gain);
m_rspeaker->set_input_gain(channel, right_gain[m_stereo_image[channel]] * m_sound_input_gain);
//printf("%d %f %f\n",channel,m_lspeaker->input(channel).gain(),m_rspeaker->input(channel).gain());
m_speaker->set_input_gain(0, left_gain[m_stereo_image[channel]] * m_sound_input_gain);
m_speaker->set_input_gain(1, right_gain[m_stereo_image[channel]] * m_sound_input_gain);
}
@ -582,14 +579,14 @@ void arm_vidc20_device::device_add_mconfig(machine_config &config)
for (int i = 0; i < m_sound_max_channels; i++)
{
m_dac[i]->reset_routes();
m_dac[i]->add_route(0, m_lspeaker, 0.0);
m_dac[i]->add_route(0, m_rspeaker, 0.0);
m_dac[i]->add_route(0, m_speaker, 0.0, 0);
m_dac[i]->add_route(0, m_speaker, 0.0, 1);
}
// For simplicity we separate DACs for 32-bit mode
// TODO: how stereo image copes with this if at all?
DAC_16BIT_R2R_TWOS_COMPLEMENT(config, m_dac32[0], 0).add_route(ALL_OUTPUTS, m_lspeaker, 0.25);
DAC_16BIT_R2R_TWOS_COMPLEMENT(config, m_dac32[1], 0).add_route(ALL_OUTPUTS, m_rspeaker, 0.25);
DAC_16BIT_R2R_TWOS_COMPLEMENT(config, m_dac32[0], 0).add_route(ALL_OUTPUTS, m_speaker, 0.25, 0);
DAC_16BIT_R2R_TWOS_COMPLEMENT(config, m_dac32[1], 0).add_route(ALL_OUTPUTS, m_speaker, 0.25, 1);
}
void arm_vidc20_device::device_config_complete()

View File

@ -90,8 +90,7 @@ protected:
required_device_array<dac_16bit_r2r_twos_complement_device, 8> m_dac;
int m_dac_type;
required_device<speaker_device> m_lspeaker;
required_device<speaker_device> m_rspeaker;
required_device<speaker_device> m_speaker;
virtual void refresh_stereo_image(u8 channel);
const int m_sound_max_channels = 8;

View File

@ -45,7 +45,7 @@ DEFINE_DEVICE_TYPE(CR511B, cr511b_device, "cr511b", "CR-511-B CD-ROM drive")
cr511b_device::cr511b_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
cdrom_image_device(mconfig, CR511B, tag, owner, clock),
device_mixer_interface(mconfig, *this, 2),
device_mixer_interface(mconfig, *this),
m_cdda(*this, "cdda"),
m_stch_cb(*this),
m_sten_cb(*this),
@ -72,8 +72,8 @@ cr511b_device::cr511b_device(const machine_config &mconfig, const char *tag, dev
void cr511b_device::device_add_mconfig(machine_config &config)
{
CDDA(config, m_cdda);
m_cdda->add_route(0, DEVICE_SELF, 1.0, AUTO_ALLOC_INPUT, 0);
m_cdda->add_route(1, DEVICE_SELF, 1.0, AUTO_ALLOC_INPUT, 1);
m_cdda->add_route(0, DEVICE_SELF, 1.0, 0);
m_cdda->add_route(1, DEVICE_SELF, 1.0, 1);
m_cdda->set_cdrom_tag(*this);
m_cdda->audio_end_cb().set(FUNC(cr511b_device::audio_end_cb));
}

View File

@ -27,7 +27,7 @@ DEFINE_DEVICE_TYPE(GCM394, sunplus_gcm394_device, "gcm394", "GeneralPlus GPL1625
sunplus_gcm394_base_device::sunplus_gcm394_base_device(const machine_config& mconfig, device_type type, const char* tag, device_t* owner, uint32_t clock, address_map_constructor internal) :
unsp_20_device(mconfig, type, tag, owner, clock, internal),
device_mixer_interface(mconfig, *this, 2),
device_mixer_interface(mconfig, *this),
m_screen(*this, finder_base::DUMMY_TAG),
m_spg_video(*this, "spgvideo"),
m_spg_audio(*this, "spgaudio"),
@ -1845,8 +1845,8 @@ void sunplus_gcm394_base_device::device_add_mconfig(machine_config &config)
m_spg_audio->write_irq_callback().set(FUNC(sunplus_gcm394_base_device::audioirq_w));
m_spg_audio->space_read_callback().set(FUNC(sunplus_gcm394_base_device::read_space));
m_spg_audio->add_route(0, *this, 1.0, AUTO_ALLOC_INPUT, 0);
m_spg_audio->add_route(1, *this, 1.0, AUTO_ALLOC_INPUT, 1);
m_spg_audio->add_route(0, *this, 1.0, 0);
m_spg_audio->add_route(1, *this, 1.0, 1);
GCM394_VIDEO(config, m_spg_video, DERIVED_CLOCK(1, 1), DEVICE_SELF, m_screen);
m_spg_video->write_video_irq_callback().set(FUNC(sunplus_gcm394_base_device::videoirq_w));

View File

@ -102,9 +102,9 @@ void gt913_sound_device::device_reset()
std::memset(m_voices, 0, sizeof(m_voices));
}
void gt913_sound_device::sound_stream_update(sound_stream& stream, std::vector<read_stream_view> const& inputs, std::vector<write_stream_view>& outputs)
void gt913_sound_device::sound_stream_update(sound_stream& stream)
{
for (int i = 0; i < outputs[0].samples(); i++)
for (int i = 0; i < stream.samples(); i++)
{
s64 left = 0, right = 0;
@ -115,8 +115,8 @@ void gt913_sound_device::sound_stream_update(sound_stream& stream, std::vector<r
mix_sample(voice, left, right);
}
outputs[0].put_int_clamp(i, (left * m_gain) >> 27, 32678);
outputs[1].put_int_clamp(i, (right * m_gain) >> 27, 32768);
stream.put_int_clamp(0, i, (left * m_gain) >> 27, 32678);
stream.put_int_clamp(1, i, (right * m_gain) >> 27, 32768);
}
}

View File

@ -38,7 +38,7 @@ protected:
virtual void device_reset() override ATTR_COLD;
// device_sound_interface overrides
virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override;
virtual void sound_stream_update(sound_stream &stream) override;
// device_rom_interface overrides
virtual void rom_bank_pre_change() override;

View File

@ -59,8 +59,7 @@ void k054321_device::sound_map(address_map &map)
k054321_device::k054321_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, K054321, tag, owner, clock),
m_left(*this, finder_base::DUMMY_TAG),
m_right(*this, finder_base::DUMMY_TAG),
m_speaker(*this, finder_base::DUMMY_TAG),
m_soundlatch(*this, "soundlatch%u", 0)
{
}
@ -68,17 +67,12 @@ k054321_device::k054321_device(const machine_config &mconfig, const char *tag, d
void k054321_device::device_start()
{
// make sure that device_sound_interface is configured
if (!m_left->inputs() && !m_right->inputs())
if (!m_speaker->inputs())
throw device_missing_dependencies();
// remember initial input gains
m_left_gains = std::make_unique<float[]>(m_left->inputs());
m_right_gains = std::make_unique<float[]>(m_right->inputs());
for (int i = 0; i < m_left->inputs(); i++)
m_left_gains[i] = m_left->input_gain(i);
for (int i = 0; i < m_right->inputs(); i++)
m_right_gains[i] = m_right->input_gain(i);
m_left_gain = m_speaker->input_gain(0);
m_right_gain = m_speaker->input_gain(1);
// register for savestates
save_item(NAME(m_volume));
@ -133,8 +127,6 @@ void k054321_device::propagate_volume()
{
double vol = pow(2, (m_volume - 40)/10.0);
for (int i = 0; i < m_left->inputs(); i++)
m_left->set_input_gain(i, m_active & 2 ? vol * m_left_gains[i] : 0.0);
for (int i = 0; i < m_right->inputs(); i++)
m_right->set_input_gain(i, m_active & 1 ? vol * m_right_gains[i] : 0.0);
m_speaker->set_input_gain(0, m_active & 2 ? vol * m_left_gain : 0.0);
m_speaker->set_input_gain(1, m_active & 1 ? vol * m_right_gain : 0.0);
}

View File

@ -11,15 +11,14 @@
class k054321_device : public device_t
{
public:
template<typename T, typename U>
k054321_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&left, U &&right) :
k054321_device(mconfig, tag, owner, 0)
{
m_left.set_tag(std::forward<T>(left));
m_right.set_tag(std::forward<U>(right));
}
k054321_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
k054321_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
template<typename T>
k054321_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&speaker) :
k054321_device(mconfig, tag, owner)
{
m_speaker.set_tag(std::forward<T>(speaker));
}
void main_map(address_map &map) ATTR_COLD;
void sound_map(address_map &map) ATTR_COLD;
@ -30,12 +29,10 @@ protected:
virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
required_device<device_sound_interface> m_left;
required_device<device_sound_interface> m_right;
required_device<device_sound_interface> m_speaker;
required_device_array<generic_latch_8_device, 3> m_soundlatch;
std::unique_ptr<float[]> m_left_gains;
std::unique_ptr<float[]> m_right_gains;
float m_left_gain, m_right_gain;
u8 m_volume;
u8 m_active;

View File

@ -392,7 +392,7 @@ TIMER_CALLBACK_MEMBER(laserdisc_device::fetch_vbi_data)
// laserdiscs
//-------------------------------------------------
void laserdisc_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
void laserdisc_device::sound_stream_update(sound_stream &stream)
{
// compute AND values based on the squelch
int16_t leftand = (m_audiosquelch & 1) ? 0x0000 : 0xffff;
@ -403,17 +403,7 @@ void laserdisc_device::sound_stream_update(sound_stream &stream, std::vector<rea
if (samples_avail < 0)
samples_avail += m_audiobufsize;
// if no attached ld, just clear the buffers
auto &dst0 = outputs[0];
auto &dst1 = outputs[1];
if (samples_avail < outputs[0].samples())
{
dst0.fill(0);
dst1.fill(0);
}
// otherwise, stream from our buffer
else
if (samples_avail >= stream.samples())
{
int16_t *buffer0 = &m_audiobuffer[0][0];
int16_t *buffer1 = &m_audiobuffer[1][0];
@ -421,10 +411,10 @@ void laserdisc_device::sound_stream_update(sound_stream &stream, std::vector<rea
// copy samples, clearing behind us as we go
int sampindex;
for (sampindex = 0; sampout != m_audiobufin && sampindex < outputs[0].samples(); sampindex++)
for (sampindex = 0; sampout != m_audiobufin && sampindex < stream.samples(); sampindex++)
{
dst0.put_int(sampindex, buffer0[sampout] & leftand, 32768);
dst1.put_int(sampindex, buffer1[sampout] & rightand, 32768);
stream.put_int(0, sampindex, buffer0[sampout] & leftand, 32768);
stream.put_int(1, sampindex, buffer1[sampout] & rightand, 32768);
buffer0[sampout] = 0;
buffer1[sampout] = 0;
sampout++;
@ -434,16 +424,16 @@ void laserdisc_device::sound_stream_update(sound_stream &stream, std::vector<rea
m_audiobufout = sampout;
// clear out the rest of the buffer
if (sampindex < outputs[0].samples())
if (sampindex < stream.samples())
{
sampout = (m_audiobufout == 0) ? m_audiobufsize - 1 : m_audiobufout - 1;
s32 fill0 = buffer0[sampout] & leftand;
s32 fill1 = buffer1[sampout] & rightand;
for ( ; sampindex < outputs[0].samples(); sampindex++)
for ( ; sampindex < stream.samples(); sampindex++)
{
dst0.put_int(sampindex, fill0, 32768);
dst1.put_int(sampindex, fill1, 32768);
stream.put_int(0, sampindex, fill0, 32768);
stream.put_int(1, sampindex, fill1, 32768);
}
}
}

View File

@ -213,7 +213,7 @@ protected:
virtual void device_validity_check(validity_checker &valid) const override;
// device_sound_interface overrides
virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override;
virtual void sound_stream_update(sound_stream &stream) override;
virtual TIMER_CALLBACK_MEMBER(fetch_vbi_data);

View File

@ -813,16 +813,16 @@ void netlist_mame_stream_output_device::device_reset()
LOGDEVCALLS("reset %s\n", name());
}
void netlist_mame_stream_output_device::sound_update_fill(write_stream_view &target)
void netlist_mame_stream_output_device::sound_update_fill(sound_stream &stream, int output)
{
if (target.samples() < m_buffer.size())
osd_printf_warning("sound %s: samples %d less bufsize %d\n", name(), target.samples(), m_buffer.size());
if (stream.samples() < m_buffer.size())
osd_printf_warning("sound %s: samples %d less bufsize %d\n", name(), stream.samples(), m_buffer.size());
int sampindex;
for (sampindex = 0; sampindex < m_buffer.size(); sampindex++)
target.put(sampindex, m_buffer[sampindex]);
if (sampindex < target.samples())
target.fill(m_cur, sampindex);
stream.put(output, sampindex, m_buffer[sampindex]);
if (sampindex < stream.samples())
stream.fill(output, m_cur, sampindex);
}
@ -860,7 +860,7 @@ void netlist_mame_stream_output_device::process(netlist::netlist_time_ext tim, n
// throw emu_fatalerror("sound %s: pos %d exceeded bufsize %d\n", name().c_str(), pos, m_bufsize);
while (m_buffer.size() < pos )
{
m_buffer.push_back(static_cast<stream_buffer::sample_t>(m_cur));
m_buffer.push_back(static_cast<sound_stream::sample_t>(m_cur));
}
m_cur = val;
@ -1396,7 +1396,7 @@ void netlist_mame_sound_device::device_start()
m_inbuffer.resize(m_in.size());
/* initialize the stream(s) */
m_stream = stream_alloc(m_in.size(), m_out.size(), m_sound_clock, STREAM_DISABLE_INPUT_RESAMPLING);
m_stream = stream_alloc(m_in.size(), m_out.size(), m_sound_clock);
LOGDEVCALLS("sound device_start exit\n");
}
@ -1439,23 +1439,23 @@ void netlist_mame_sound_device::update_to_current_time()
LOGTIMING("%s : %f us before machine time\n", this->name(), (cur - mtime).as_double() * 1000000.0);
}
void netlist_mame_sound_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
void netlist_mame_sound_device::sound_stream_update(sound_stream &stream)
{
for (auto &e : m_in)
{
auto clock_period = inputs[e.first].sample_period();
auto clock_period = stream.sample_period();
auto sample_time = netlist::netlist_time::from_raw(static_cast<netlist::netlist_time::internal_type>(nltime_from_attotime(clock_period).as_raw()));
m_inbuffer[e.first] = netlist_mame_sound_input_buffer(inputs[e.first]);
e.second->buffer_reset(sample_time, m_inbuffer[e.first].samples(), &m_inbuffer[e.first]);
m_inbuffer[e.first] = netlist_mame_sound_input_buffer(stream, e.first);
e.second->buffer_reset(sample_time, stream.samples(), &m_inbuffer[e.first]);
}
int samples = outputs[0].samples();
int samples = stream.samples();
LOGDEBUG("samples %d\n", samples);
// end_time() is the time at the END of the last sample we're generating
// however, the sample value is the value at the START of that last sample,
// so subtract one sample period so that we only process up to the minimum
auto nl_target_time = nltime_from_attotime(outputs[0].end_time() - outputs[0].sample_period());
auto nl_target_time = nltime_from_attotime(stream.end_time() - stream.sample_period());
auto nltime(netlist().exec().time());
if (nltime < nl_target_time)
@ -1465,7 +1465,7 @@ void netlist_mame_sound_device::sound_stream_update(sound_stream &stream, std::v
for (auto &e : m_out)
{
e.second->sound_update_fill(outputs[e.first]);
e.second->sound_update_fill(stream, e.first);
e.second->buffer_reset(nl_target_time);
}

View File

@ -249,19 +249,20 @@ private:
// ----------------------------------------------------------------------------------------
// netlist_mame_sound_input_buffer
//
// This is a wrapper device to provide operator[] on read_stream_view.
// This is a wrapper device to provide operator[] on an input stream.
// ----------------------------------------------------------------------------------------
class netlist_mame_sound_input_buffer : public read_stream_view
class netlist_mame_sound_input_buffer
{
public:
netlist_mame_sound_input_buffer() :
read_stream_view() { }
sound_stream *m_stream = nullptr;
int m_stream_input = 0;
netlist_mame_sound_input_buffer(read_stream_view const &src) :
read_stream_view(src) { }
netlist_mame_sound_input_buffer() {}
stream_buffer::sample_t operator[](std::size_t index) { return get(index); }
netlist_mame_sound_input_buffer(sound_stream &stream, int input) : m_stream(&stream), m_stream_input(input) { }
sound_stream::sample_t operator[](std::size_t index) { return m_stream->get(m_stream_input, index); }
};
// ----------------------------------------------------------------------------------------
@ -302,7 +303,7 @@ protected:
// device_t overrides
virtual void device_start() override ATTR_COLD;
// device_sound_interface overrides
virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override;
virtual void sound_stream_update(sound_stream &stream) override;
virtual void device_validity_check(validity_checker &valid) const override;
//virtual void device_reset() override ATTR_COLD;
@ -634,7 +635,7 @@ public:
m_buffer.clear();
}
void sound_update_fill(write_stream_view &target);
void sound_update_fill(sound_stream &stream, int output);
void set_sample_time(netlist::netlist_time t) { m_sample_time = t; }
@ -649,7 +650,7 @@ private:
uint32_t m_channel;
const char * m_out_name;
std::vector<stream_buffer::sample_t> m_buffer;
std::vector<sound_stream::sample_t> m_buffer;
double m_cur;
netlist::netlist_time m_sample_time;

View File

@ -265,11 +265,10 @@ void pxa255_periphs_device::device_add_mconfig(machine_config &config)
PALETTE(config, m_palette).set_entries(256);
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
SPEAKER(config, "speaker", 2).front();
DMADAC(config, m_dmadac[0]).add_route(ALL_OUTPUTS, "lspeaker", 1.0);
DMADAC(config, m_dmadac[1]).add_route(ALL_OUTPUTS, "rspeaker", 1.0);
DMADAC(config, m_dmadac[0]).add_route(ALL_OUTPUTS, "speaker", 1.0, 0);
DMADAC(config, m_dmadac[1]).add_route(ALL_OUTPUTS, "speaker", 1.0, 1);
}
/*

View File

@ -441,10 +441,9 @@ void s2636_device::write_intack(int state)
// sound_stream_update - generate audio output
//-------------------------------------------------
void s2636_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
void s2636_device::sound_stream_update(sound_stream &stream)
{
auto &buffer = outputs[0];
for (int sampindex = 0; sampindex < buffer.samples(); sampindex++)
for (int sampindex = 0; sampindex < stream.samples(); sampindex++)
{
if (!m_sample_cnt)
{
@ -460,7 +459,7 @@ void s2636_device::sound_stream_update(sound_stream &stream, std::vector<read_st
}
}
buffer.put(sampindex, m_sound_lvl ? 1.0 : 0.0);
stream.put(0, sampindex, m_sound_lvl ? 1.0 : 0.0);
m_sample_cnt--;
}
}

View File

@ -60,7 +60,7 @@ protected:
virtual void device_start() override ATTR_COLD;
// sound stream update overrides
virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override;
virtual void sound_stream_update(sound_stream &stream) override;
private:
enum

View File

@ -18,7 +18,7 @@ DEFINE_DEVICE_TYPE(SPG110, spg110_device, "spg110", "SPG110 System-on-a-Chip")
spg110_device::spg110_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor internal) :
unsp_device(mconfig, type, tag, owner, clock, internal),
device_mixer_interface(mconfig, *this, 2),
device_mixer_interface(mconfig, *this),
m_screen(*this, finder_base::DUMMY_TAG),
m_spg_io(*this, "spg_io"),
m_spg_video(*this, "spg_video"),
@ -132,8 +132,8 @@ void spg110_device::device_add_mconfig(machine_config &config)
m_spg_audio->write_irq_callback().set(FUNC(spg110_device::audioirq_w));
m_spg_audio->space_read_callback().set(FUNC(spg110_device::space_r));
m_spg_audio->add_route(0, *this, 1.0, AUTO_ALLOC_INPUT, 0);
m_spg_audio->add_route(1, *this, 1.0, AUTO_ALLOC_INPUT, 1);
m_spg_audio->add_route(0, *this, 1.0, 0);
m_spg_audio->add_route(1, *this, 1.0, 1);
}
void spg110_device::internal_map(address_map &map)

View File

@ -21,7 +21,7 @@ DEFINE_DEVICE_TYPE(SPG28X, spg28x_device, "spg28x", "SPG280-series Syste
spg2xx_device::spg2xx_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint16_t sprite_limit, address_map_constructor internal) :
unsp_device(mconfig, type, tag, owner, clock, internal),
device_mixer_interface(mconfig, *this, 2),
device_mixer_interface(mconfig, *this),
m_spg_audio(*this, "spgaudio"),
m_spg_io(*this, "spgio"),
m_spg_sysdma(*this, "spgsysdma"),
@ -193,8 +193,8 @@ void spg24x_device::device_add_mconfig(machine_config &config)
m_spg_audio->channel_irq_callback().set(FUNC(spg24x_device::audiochirq_w));
m_spg_audio->space_read_callback().set(FUNC(spg24x_device::space_r));
m_spg_audio->add_route(0, *this, 1.0, AUTO_ALLOC_INPUT, 0);
m_spg_audio->add_route(1, *this, 1.0, AUTO_ALLOC_INPUT, 1);
m_spg_audio->add_route(0, *this, 1.0, 0);
m_spg_audio->add_route(1, *this, 1.0, 1);
SPG24X_IO(config, m_spg_io, DERIVED_CLOCK(1, 1), DEVICE_SELF, m_screen);

View File

@ -871,12 +871,9 @@ void spg2xx_audio_device::audio_w(offs_t offset, uint16_t data)
}
}
void spg2xx_audio_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
void spg2xx_audio_device::sound_stream_update(sound_stream &stream)
{
auto &out_l = outputs[0];
auto &out_r = outputs[1];
for (int i = 0; i < out_l.samples(); i++)
for (int i = 0; i < stream.samples(); i++)
{
int32_t left_total = 0;
int32_t right_total = 0;
@ -976,8 +973,8 @@ void spg2xx_audio_device::sound_stream_update(sound_stream &stream, std::vector<
int32_t left_final = (int16_t)((left_total * (int16_t)m_audio_ctrl_regs[AUDIO_MAIN_VOLUME]) >> 7);
int32_t right_final = (int16_t)((right_total * (int16_t)m_audio_ctrl_regs[AUDIO_MAIN_VOLUME]) >> 7);
out_l.put_int(i, int16_t(left_final), 32768);
out_r.put_int(i, int16_t(right_final), 32768);
stream.put_int(0, i, int16_t(left_final), 32768);
stream.put_int(1, i, int16_t(right_final), 32768);
}
}

View File

@ -33,7 +33,7 @@ public:
protected:
// sound stream update overrides
virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override;
virtual void sound_stream_update(sound_stream &stream) override;
TIMER_CALLBACK_MEMBER(irq_tick);
TIMER_CALLBACK_MEMBER(audio_beat_tick);

View File

@ -42,8 +42,7 @@ vrender0soc_device::vrender0soc_device(const machine_config &mconfig, const char
m_palette(*this, "palette"),
m_vr0vid(*this, "vr0vid"),
m_vr0snd(*this, "vr0snd"),
m_lspeaker(*this, "lspeaker"),
m_rspeaker(*this, "rspeaker"),
m_speaker(*this, "speaker"),
m_uart(*this, "uart%u", 0),
m_crtcregs(*this, "crtcregs"),
write_tx(*this)
@ -135,15 +134,14 @@ void vrender0soc_device::device_add_mconfig(machine_config &config)
PALETTE(config, m_palette, palette_device::RGB_565);
SPEAKER(config, m_lspeaker).front_left();
SPEAKER(config, m_rspeaker).front_right();
SPEAKER(config, m_speaker, 2).front();
SOUND_VRENDER0(config, m_vr0snd, DERIVED_CLOCK(1,1)); // Correct?
m_vr0snd->set_addrmap(vr0sound_device::AS_TEXTURE, &vrender0soc_device::texture_map);
m_vr0snd->set_addrmap(vr0sound_device::AS_FRAME, &vrender0soc_device::frame_map);
m_vr0snd->irq_callback().set(FUNC(vrender0soc_device::soundirq_cb));
m_vr0snd->add_route(0, m_lspeaker, 1.0);
m_vr0snd->add_route(1, m_rspeaker, 1.0);
m_vr0snd->add_route(0, m_speaker, 1.0, 0);
m_vr0snd->add_route(1, m_speaker, 1.0, 1);
}

View File

@ -110,8 +110,7 @@ private:
required_device <palette_device> m_palette;
required_device <vr0video_device> m_vr0vid;
required_device <vr0sound_device> m_vr0snd;
required_device <speaker_device> m_lspeaker;
required_device <speaker_device> m_rspeaker;
required_device <speaker_device> m_speaker;
required_device_array <vr0uart_device, 2> m_uart;
required_shared_ptr <uint32_t> m_crtcregs;
std::unique_ptr<uint16_t []> m_textureram;

View File

@ -23,10 +23,9 @@ ad1848_device::ad1848_device(const machine_config &mconfig, const char *tag, dev
void ad1848_device::device_add_mconfig(machine_config &config)
{
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
DAC_16BIT_R2R(config, m_ldac, 0).add_route(ALL_OUTPUTS, "lspeaker", 0.5); // unknown DAC
DAC_16BIT_R2R(config, m_rdac, 0).add_route(ALL_OUTPUTS, "rspeaker", 0.5); // unknown DAC
SPEAKER(config, "speaker", 2).front();
DAC_16BIT_R2R(config, m_ldac, 0).add_route(ALL_OUTPUTS, "speaker", 0.5, 0); // unknown DAC
DAC_16BIT_R2R(config, m_rdac, 0).add_route(ALL_OUTPUTS, "speaker", 0.5, 1); // unknown DAC
}

Some files were not shown because too many files have changed in this diff Show More