mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-23 16:54:03 +02:00
Add support for disabling denormals on the audio thread.
This is configurable on a per-device basis. Denormals will be disabled by default.
This commit is contained in:
+58
@@ -3370,6 +3370,7 @@ struct ma_device_config
|
|||||||
ma_performance_profile performanceProfile;
|
ma_performance_profile performanceProfile;
|
||||||
ma_bool8 noPreSilencedOutputBuffer; /* When set to true, the contents of the output buffer passed into the data callback will be left undefined rather than initialized to silence. */
|
ma_bool8 noPreSilencedOutputBuffer; /* When set to true, the contents of the output buffer passed into the data callback will be left undefined rather than initialized to silence. */
|
||||||
ma_bool8 noClip; /* When set to true, the contents of the output buffer passed into the data callback will be clipped after returning. Only applies when the playback sample format is f32. */
|
ma_bool8 noClip; /* When set to true, the contents of the output buffer passed into the data callback will be clipped after returning. Only applies when the playback sample format is f32. */
|
||||||
|
ma_bool8 noDisableDenormals; /* Do not disable denormals when firing the data callback. */
|
||||||
ma_device_data_proc dataCallback;
|
ma_device_data_proc dataCallback;
|
||||||
ma_stop_proc stopCallback;
|
ma_stop_proc stopCallback;
|
||||||
void* pUserData;
|
void* pUserData;
|
||||||
@@ -4033,6 +4034,7 @@ struct ma_device
|
|||||||
ma_bool8 isOwnerOfContext; /* When set to true, uninitializing the device will also uninitialize the context. Set to true when NULL is passed into ma_device_init(). */
|
ma_bool8 isOwnerOfContext; /* When set to true, uninitializing the device will also uninitialize the context. Set to true when NULL is passed into ma_device_init(). */
|
||||||
ma_bool8 noPreSilencedOutputBuffer;
|
ma_bool8 noPreSilencedOutputBuffer;
|
||||||
ma_bool8 noClip;
|
ma_bool8 noClip;
|
||||||
|
ma_bool8 noDisableDenormals;
|
||||||
MA_ATOMIC float masterVolumeFactor; /* Linear 0..1. Can be read and written simultaneously by different threads. Must be used atomically. */
|
MA_ATOMIC float masterVolumeFactor; /* Linear 0..1. Can be read and written simultaneously by different threads. Must be used atomically. */
|
||||||
ma_duplex_rb duplexRB; /* Intermediary buffer for duplex device on asynchronous backends. */
|
ma_duplex_rb duplexRB; /* Intermediary buffer for duplex device on asynchronous backends. */
|
||||||
struct
|
struct
|
||||||
@@ -4888,6 +4890,9 @@ then be set directly on the structure. Below are the members of the `ma_device_c
|
|||||||
contents of the output buffer are left alone after returning and it will be left up to the backend itself to decide whether or not the clip. This only
|
contents of the output buffer are left alone after returning and it will be left up to the backend itself to decide whether or not the clip. This only
|
||||||
applies when the playback sample format is f32.
|
applies when the playback sample format is f32.
|
||||||
|
|
||||||
|
noDisableDenormals
|
||||||
|
By default, miniaudio will disable denormals when the data callback is called. Setting this to true will prevent the disabling of denormals.
|
||||||
|
|
||||||
dataCallback
|
dataCallback
|
||||||
The callback to fire whenever data is ready to be delivered to or from the device.
|
The callback to fire whenever data is ready to be delivered to or from the device.
|
||||||
|
|
||||||
@@ -6915,6 +6920,32 @@ static MA_INLINE void ma_yield()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static MA_INLINE unsigned int ma_disable_denormals()
|
||||||
|
{
|
||||||
|
unsigned int prevState;
|
||||||
|
|
||||||
|
#if defined(MA_X86) || defined(MA_X64)
|
||||||
|
prevState = _mm_getcsr();
|
||||||
|
_mm_setcsr(prevState | _MM_DENORMALS_ZERO_MASK | _MM_FLUSH_ZERO_MASK);
|
||||||
|
#else
|
||||||
|
/* Unknown or unsupported architecture. No-op. */
|
||||||
|
prevState = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return prevState;
|
||||||
|
}
|
||||||
|
|
||||||
|
static MA_INLINE void ma_restore_denormals(unsigned int prevState)
|
||||||
|
{
|
||||||
|
#if defined(MA_X86) || defined(MA_X64)
|
||||||
|
_mm_setcsr(prevState);
|
||||||
|
#else
|
||||||
|
/* Unknown or unsupported architecture. No-op. */
|
||||||
|
(void)prevState;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef MA_COINIT_VALUE
|
#ifndef MA_COINIT_VALUE
|
||||||
#define MA_COINIT_VALUE 0 /* 0 = COINIT_MULTITHREADED */
|
#define MA_COINIT_VALUE 0 /* 0 = COINIT_MULTITHREADED */
|
||||||
@@ -11921,6 +11952,29 @@ static ma_uint32 ma_get_closest_standard_sample_rate(ma_uint32 sampleRateIn)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static MA_INLINE unsigned int ma_device_disable_denormals(ma_device* pDevice)
|
||||||
|
{
|
||||||
|
MA_ASSERT(pDevice != NULL);
|
||||||
|
|
||||||
|
if (pDevice->noDisableDenormals) {
|
||||||
|
return ma_disable_denormals();
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static MA_INLINE void ma_device_restore_denormals(ma_device* pDevice, unsigned int prevState)
|
||||||
|
{
|
||||||
|
MA_ASSERT(pDevice != NULL);
|
||||||
|
|
||||||
|
if (pDevice->noDisableDenormals) {
|
||||||
|
ma_restore_denormals(prevState);
|
||||||
|
} else {
|
||||||
|
/* Do nothing. */
|
||||||
|
(void)prevState;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void ma_device__on_data(ma_device* pDevice, void* pFramesOut, const void* pFramesIn, ma_uint32 frameCount)
|
static void ma_device__on_data(ma_device* pDevice, void* pFramesOut, const void* pFramesIn, ma_uint32 frameCount)
|
||||||
{
|
{
|
||||||
float masterVolumeFactor;
|
float masterVolumeFactor;
|
||||||
@@ -11928,6 +11982,8 @@ static void ma_device__on_data(ma_device* pDevice, void* pFramesOut, const void*
|
|||||||
ma_device_get_master_volume(pDevice, &masterVolumeFactor); /* Use ma_device_get_master_volume() to ensure the volume is loaded atomically. */
|
ma_device_get_master_volume(pDevice, &masterVolumeFactor); /* Use ma_device_get_master_volume() to ensure the volume is loaded atomically. */
|
||||||
|
|
||||||
if (pDevice->onData) {
|
if (pDevice->onData) {
|
||||||
|
unsigned int prevDenormalState = ma_device_disable_denormals(pDevice);
|
||||||
|
{
|
||||||
if (!pDevice->noPreSilencedOutputBuffer && pFramesOut != NULL) {
|
if (!pDevice->noPreSilencedOutputBuffer && pFramesOut != NULL) {
|
||||||
ma_silence_pcm_frames(pFramesOut, frameCount, pDevice->playback.format, pDevice->playback.channels);
|
ma_silence_pcm_frames(pFramesOut, frameCount, pDevice->playback.format, pDevice->playback.channels);
|
||||||
}
|
}
|
||||||
@@ -11967,6 +12023,8 @@ static void ma_device__on_data(ma_device* pDevice, void* pFramesOut, const void*
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ma_device_restore_denormals(pDevice, prevDenormalState);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user