ma_resource_manager_data_buffer_node_unacquire frees the node synchronously
when it observes a non-MA_BUSY result (the "sound isn't loading" branch). But
a decoded-paged node publishes result == MA_SUCCESS as soon as it is playable,
while ma_job_process__resource_manager__page_data_buffer_node jobs keep running
to decode the remaining pages. Those jobs reference the node and increment its
executionPointer at their tail, several instructions after the result becomes
observable. A concurrent unacquire that sees a non-BUSY result therefore frees
the node out from under the page job tail, which then reads and atomically
increments freed (and possibly recycled) memory.
The node carries the same order / executionPointer ticket scheme as the data
buffer, and the MA_BUSY branch already relies on it (it posts an ordered
FREE_DATA_BUFFER_NODE job). Only the synchronous shortcut skipped it. Make it
wait for executionPointer to catch up to executionCounter before freeing, so no
job is still referencing the node -- the same fix as
ma_resource_manager_data_buffer_uninit for the buffer level, one level down.
Caught by ThreadSanitizer.
When the data format of the capture device changes via the Audio MIDI
Setup settings, miniaudio will now reroute the device to take the new
data format into account. Prior to this commit AudioUnitRender() will
just keep failing forever.
Public issue https://github.com/mackron/miniaudio/issues/1136
ma_resource_manager_data_buffer_uninit takes a synchronous teardown path as
soon as it observes result == MA_SUCCESS, freeing the buffer. But the load
job (ma_job_process__resource_manager__load_data_buffer) publishes that
result code via a CAS several instructions before it finishes referencing
the buffer: it still reads has_connector() and does the executionPointer
increment afterward. A concurrent uninit that observes MA_SUCCESS therefore
frees the buffer out from under the job tail, which then reads and
atomically increments freed (and possibly recycled) memory.
The asynchronous free path is safe because it waits on the order /
executionPointer ticket scheme; the synchronous shortcut bypassed it. Make
the synchronous path wait for executionPointer to catch up to
executionCounter before tearing down, so no job is still referencing the
buffer. Caught by ThreadSanitizer.
Support for custom attenuation models has been added.
Attenuation models are now a callback rather than an enumerator. The
callback takes a user data pointer in case the standard distance/rolloff
variables do not suffice. The following APIs have changed in order to
accommodate this:
ma_spatializer_set_attenuation_model()
ma_sound_set_attenuation_model()
ma_sound_group_set_attenuation_model()
These now take an extra parameter for the user data pointer. For stock
attenuation models this should always be set to NULL:
ma_sound_set_attenuation_model(&sound,
ma_attenuation_model_linear, NULL);
To plug in a custom model, just implement a callback and plug it in:
float your_custom_attenuation_model(
void* pUserData,
float distance,
float minDistance,
float maxDistance,
float rolloff)
{
// Return a value between 0 (silence) and 1 (full volume).
}
...
ma_sound_set_attenuation_model(&sound,
your_custom_attenuation_model, &userDataIfRequiredByYourModel);
Previously, setting the attenuation model to none would disable
spatialization completely. This behaviour has changed and now
spatialization will still be applied in this case. You should use
`ma_sound_set_spatialization_enabled(&sound, MA_FALSE)` instead if you
want to disable spatialization.
Prior to this commit, the number of frames read was always reported as
the whole frame count. This is incorrect for leaf nodes which don't
always produce the full frame count (an example being when the end of a
sound is reached).
This addresses a case when PulseAudio may negotiate S24_32 which is not
a format supported by miniaudio. This commit does two things to guard
against this:
* The requested format is now explicitly used instead of using the
queried format from `pa_context_get_source_info_by_name()`.
* The `PA_STREAM_FIX_FORMAT` stream flag is no longer used as that can
possibly negotiate something different to what we request. I.e., it
can possibly give us S24_32 which is not usable.