mirror of
https://github.com/holub/mame
synced 2025-05-16 10:52:43 +03:00
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:
parent
ec636faeba
commit
d0f1c15a0f
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
|
@ -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 MAME’s ``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
|
||||
|
147
docs/source/techspecs/audio_effects.rst
Normal file
147
docs/source/techspecs/audio_effects.rst
Normal 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.
|
286
docs/source/techspecs/device_sound_interface.rst
Normal file
286
docs/source/techspecs/device_sound_interface.rst
Normal 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.
|
@ -15,6 +15,7 @@ MAME’s 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 @@ MAME’s source or working on scripts that run within the MAME framework.
|
||||
m6502
|
||||
uml_instructions
|
||||
poly_manager
|
||||
audio_effects
|
||||
osd_audio
|
||||
|
334
docs/source/techspecs/osd_audio.rst
Normal file
334
docs/source/techspecs/osd_audio.rst
Normal 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.
|
@ -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 device’s 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.
|
||||
|
||||
|
5
makefile
5
makefile
@ -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
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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"
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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()
|
||||
|
@ -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()
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 )
|
||||
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
100
src/devices/bus/st/replay.cpp
Normal file
100
src/devices/bus/st/replay.cpp
Normal 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")
|
15
src/devices/bus/st/replay.h
Normal file
15
src/devices/bus/st/replay.h
Normal 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
|
40
src/devices/bus/st/stcart.cpp
Normal file
40
src/devices/bus/st/stcart.cpp
Normal 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()
|
||||
{
|
||||
}
|
50
src/devices/bus/st/stcart.h
Normal file
50
src/devices/bus/st/stcart.h
Normal 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
|
@ -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 )
|
||||
|
@ -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 )
|
||||
|
@ -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); });
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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()
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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++;
|
||||
|
@ -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; }
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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()
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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--;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user