This was setting the previous pointer of newly attached nodes to NULL
instead of a pointer to the dummy head node. This then results in the
dummy head node never being updated when the node is detached which in
turn results in an uninitialized node being dereferenced.
This provides an optimization by allowing processing to bypass the
resampler. Audio data needs to pass through the resampler even for the
case where pitch=1 because it needs to update internal buffers which if
it didn't do, would result in a glitch when moving away from 1.
In practice most sounds won't require individual pitch control, however
in the interest in being consistent with miniaudio's philosophy of
things "Just Working", pitching is enabled by default. Pitching can be
disabled with MA_SOUND_FLAG_DISABLE_PITCH in ma_sound_init_*() and
ma_sound_group_init().
This is the first step towards decoupling the ma_effect API from the
engine for the eventual removal.
This also fixes bugs regarding channel conversion when processing an
engine node.
This is mainly for consistency with the node API, but also because it
more clearly indicates that it's an absolute time rather than a delay
which sounds more like a relative time.
This changes ma_sound_set_start/stop_delay() to take an absolute time
in frames based on the global clock. Previously these took a relative
time in milliseconds. To use a relative time, add it to the value
returned by ma_engine_get_time(). To use milliseconds, use a standard
sample rate to milliseconds conversion.
These changes are in preparation for fixing some issues relating to
retrieval of channel counts from data sources. The problem relates to
the asynchronous nature of the resource manager and how data sources
may be in the middle of loading when trying to initialize a sound which
results in the channel count not yet being available. The channel count
is necessary in order for the engine to be able to convert the data
source to the channel count of the final output.
This is a simplified and somewhat more intuitive way of handling fades.
With these APIs, fades are applied immediately, whereas with the old
fading APIs the fades were scheduled. The old APIs still exist, but may
be removed.
The ma_sound_set_fade_in_frames/milliseconds() API sets the fade which
will be applied immediately. If the starting volume is negative, the
fade will start from the current fade volume. This will also overwrite
any existing fade that is already happening.
The ma_sound_get_current_fade_volume() API allows you to retrieve the
current volume of the fade.
The fade is layered on top of the normal volume parameter. I.e. they
are configured and applied to the signal interdependently.
Currently, all fades are applied linearly.