mirror of
https://github.com/holub/mame
synced 2025-05-20 12:48:53 +03:00
sound docs: small corrections after doing a quick read
This commit is contained in:
parent
57dad8563b
commit
f68b2d87a1
@ -100,12 +100,11 @@ emu.add_machine_post_load_notifier(callback)
|
||||
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.
|
||||
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)
|
||||
|
@ -633,7 +633,7 @@ Sound device interface
|
||||
---------------------
|
||||
|
||||
Wraps MAME’s ``device_sound_interface`` class which is a mix-in implemented by
|
||||
devices that inputs and/or ouputs sound.
|
||||
devices that input and/or output sound.
|
||||
|
||||
Instantiation
|
||||
~~~~~~~~~~~~~
|
||||
@ -659,11 +659,11 @@ sound.speaker (read-only)
|
||||
|
||||
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])
|
||||
the inputs or outputs as (x, y, z) coordinates (e.g. [-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)
|
||||
the inputs or outputs as strings (e.g. Front Left)
|
||||
|
||||
sound.hook
|
||||
A boolean indicating whether to tap the output samples of this device in
|
||||
|
@ -25,7 +25,7 @@ Adding an effect requires working on four parts:
|
||||
|
||||
The audio_effect class in the aeffect sources provides three things:
|
||||
|
||||
* an enum value to designate the effect type and which much match its
|
||||
* an enum value to designate the effect type and which must 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
|
||||
@ -36,7 +36,7 @@ The audio_effect class in the aeffect sources provides three things:
|
||||
3. audio_effects/youreffect.*
|
||||
-----------------------------
|
||||
|
||||
This is where you implement the effect. It takes the shape of a
|
||||
This is where you implement the effect. It takes the shape of an
|
||||
audio_effect_youreffect class which derives from audio_effect.
|
||||
|
||||
The methods to implement are:
|
||||
@ -61,7 +61,7 @@ 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:
|
||||
An effect has a number of parameters that can come from three sources:
|
||||
|
||||
* fixed default value
|
||||
* equivalent effect object from the default effect chain
|
||||
@ -72,7 +72,7 @@ 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.
|
||||
At minimum an effect should have a parameter allowing to bypass it.
|
||||
|
||||
Managing a parameter uses four methods:
|
||||
|
||||
@ -131,7 +131,7 @@ than the parameter setting calls are made from.
|
||||
4. frontend/mame/ui/audioeffects.cpp
|
||||
------------------------------------
|
||||
|
||||
There it suffices to add a creation of the menu
|
||||
Here 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.*).
|
||||
|
||||
|
@ -32,19 +32,19 @@ 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
|
||||
chosen sample rate is the highest one among 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
|
||||
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
|
||||
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.
|
||||
arrange all streams in the order they are created.
|
||||
|
||||
|
||||
2.2 Sound input/output
|
||||
@ -140,7 +140,7 @@ a given source device.
|
||||
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
|
||||
depending on what routes are set up 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
|
||||
@ -158,7 +158,7 @@ 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
|
||||
connections are set up 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
|
||||
@ -226,7 +226,7 @@ does it with an integer ``sample`` but pre-divides it by ``max``.
|
||||
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``.
|
||||
``fill`` sets a range of 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).
|
||||
|
||||
|
@ -92,7 +92,7 @@ At a minimum, the class must include a constructor and an enum picking up the co
|
||||
|
||||
If the CPU has its own dispatch table, the class must also include the declaration (but not definition) of **disasm_entries**, **do_exec_full** and **do_exec_partial**, the declaration and definition of **disasm_disassemble** (identical for all classes but refers to the class-specific **disasm_entries** array) and include the .inc file (which provides the missing definitions). Support for the generation must also be added to CPU.mak.
|
||||
|
||||
If the CPU has in addition its own opcodes, their declaration must be done through a macro, see f.i. m65c02. The .inc file will provide the definitions.
|
||||
If the CPU has in addition its own opcodes, their declaration must be done through a macro, see e.g. m65c02. The .inc file will provide the definitions.
|
||||
|
||||
|
||||
Dispatch tables
|
||||
@ -365,7 +365,7 @@ A negative icount means that the CPU won't be able to do anything for some time
|
||||
Multi-dispatch variants
|
||||
-----------------------
|
||||
|
||||
Some variants currently in the process of being supported change instruction set depending on an internal flag, either switching to a 16-bits mode or changing some register accesses to memory accesses. This is handled by having multiple dispatch tables for the CPU, the d<CPU>.lst not being 257 entries anymore but 256*n+1. The variable **inst_state_base** must select which instruction table to use at a given time. It must be a multiple of 256, and is in fact simply OR-ed to the first instruction byte to get the dispatch table index (aka inst_state).
|
||||
Some variants currently in the process of being supported change instruction set depending on an internal flag, either switching to a 16-bit mode or changing some register accesses to memory accesses. This is handled by having multiple dispatch tables for the CPU, the d<CPU>.lst not being 257 entries anymore but 256*n+1. The variable **inst_state_base** must select which instruction table to use at a given time. It must be a multiple of 256, and is in fact simply OR-ed to the first instruction byte to get the dispatch table index (aka inst_state).
|
||||
|
||||
Current TO-DO:
|
||||
--------------
|
||||
|
@ -20,14 +20,16 @@ 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 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
|
||||
* 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.
|
||||
and keeping the internal UI in sync.
|
||||
|
||||
|
||||
Terminology
|
||||
@ -35,8 +37,11 @@ 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
|
||||
* 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
|
||||
|
||||
|
||||
@ -82,10 +87,14 @@ which follows this structure,
|
||||
|
||||
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)
|
||||
* 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
|
||||
@ -123,12 +132,12 @@ The full interface is:
|
||||
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
|
||||
The class sound_module provides defaults 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
|
||||
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.
|
||||
|
||||
@ -139,8 +148,10 @@ 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)
|
||||
* 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
|
||||
@ -151,7 +162,7 @@ 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
|
||||
32-bit 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*
|
||||
@ -211,17 +222,20 @@ of the host and the module. This state is:
|
||||
* 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_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_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
|
||||
* 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
|
||||
@ -262,7 +276,7 @@ Input and output streams
|
||||
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
|
||||
Streams are the concept used to send or receive 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
|
||||
@ -270,7 +284,7 @@ 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
|
||||
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*
|
||||
@ -321,12 +335,12 @@ Helper class *abuffer*
|
||||
};
|
||||
|
||||
The class *abuffer* is a helper provided by *sound_module* to buffer
|
||||
audio in output or output. It automatically drops data when there is
|
||||
audio input 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.
|
||||
*samples* * *channels* 16-bit samples in the buffer. *get* retrieves
|
||||
*samples* * *channels* 16-bit 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
|
||||
|
@ -317,7 +317,7 @@ 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
|
||||
it into the left and right channels of a system output, which is
|
||||
useful for some cabinets.
|
||||
|
||||
Every mapping has a configurable volume associated.
|
||||
@ -355,6 +355,7 @@ 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
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
@ -365,7 +366,7 @@ 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
|
||||
sharper. Over 0.7 the filter starts amplifying the frequencies around
|
||||
the cutoff though, which can be surprising.
|
||||
|
||||
|
||||
@ -384,7 +385,7 @@ Not implemented yet.
|
||||
EQ effect
|
||||
~~~~~~~~~
|
||||
|
||||
The 5-band parametric equalizer allows to amplify or reduce certains
|
||||
The 5-band parametric equalizer allows to amplify or reduce certain
|
||||
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,
|
||||
|
Loading…
Reference in New Issue
Block a user