ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "[WASAPI] IAudioClient3_InitializeSharedAudioStream failed. Falling back to IAudioClient.\n");
ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "[WASAPI] IAudioClient3_InitializeSharedAudioStream failed. Falling back to IAudioClient.\n");
}
}
...
@@ -9620,7 +9688,7 @@ static ma_result ma_device_reinit__wasapi(ma_device* pDevice, ma_device_type dev
...
@@ -9620,7 +9688,7 @@ static ma_result ma_device_reinit__wasapi(ma_device* pDevice, ma_device_type dev
/* At this point we have input and output data in client format. All we need to do now is convert it to the output device format. This may take a few passes. */
/* At this point we have input and output data in client format. All we need to do now is convert it to the output device format. This may take a few passes. */
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[DirectSound] (Duplex/Playback) WARNING: Play cursor has moved in front of the write cursor (same loop iterations). physicalPlayCursorInBytes=%ld, virtualWriteCursorInBytes=%ld.\n", physicalPlayCursorInBytes, virtualWriteCursorInBytesPlayback);
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_WARNING, "[DirectSound] (Duplex/Playback): Play cursor has moved in front of the write cursor (same loop iteration). physicalPlayCursorInBytes=%ld, virtualWriteCursorInBytes=%ld.\n", physicalPlayCursorInBytes, virtualWriteCursorInBytesPlayback);
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[DirectSound] (Duplex/Playback) WARNING: Write cursor has moved behind the play cursor (different loop iterations). physicalPlayCursorInBytes=%ld, virtualWriteCursorInBytes=%ld.\n", physicalPlayCursorInBytes, virtualWriteCursorInBytesPlayback);
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_WARNING, "[DirectSound] (Duplex/Playback): Write cursor has moved behind the play cursor (different loop iterations). physicalPlayCursorInBytes=%ld, virtualWriteCursorInBytes=%ld.\n", physicalPlayCursorInBytes, virtualWriteCursorInBytesPlayback);
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[DirectSound] (Playback) WARNING: Play cursor has moved in front of the write cursor (same loop iterations). physicalPlayCursorInBytes=%ld, virtualWriteCursorInBytes=%ld.\n", physicalPlayCursorInBytes, virtualWriteCursorInBytesPlayback);
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_WARNING, "[DirectSound] (Playback): Play cursor has moved in front of the write cursor (same loop iterations). physicalPlayCursorInBytes=%ld, virtualWriteCursorInBytes=%ld.\n", physicalPlayCursorInBytes, virtualWriteCursorInBytesPlayback);
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[DirectSound] (Playback) WARNING: Write cursor has moved behind the play cursor (different loop iterations). physicalPlayCursorInBytes=%ld, virtualWriteCursorInBytes=%ld.\n", physicalPlayCursorInBytes, virtualWriteCursorInBytesPlayback);
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_WARNING, "[DirectSound] (Playback): Write cursor has moved behind the play cursor (different loop iterations). physicalPlayCursorInBytes=%ld, virtualWriteCursorInBytes=%ld.\n", physicalPlayCursorInBytes, virtualWriteCursorInBytesPlayback);
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[PulseAudio] WARNING: sample_spec.format not supported by miniaudio. Defaulting to PA_SAMPLE_RATE_FLOAT32\n");
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, "[PulseAudio] sample_spec.format not supported by miniaudio. Defaulting to PA_SAMPLE_FLOAT32.\n");
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[PulseAudio] WARNING: sample_spec.format not supported by miniaudio. Defaulting to PA_SAMPLE_RATE_FLOAT32\n");
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, "[PulseAudio] sample_spec.format not supported by miniaudio. Defaulting to PA_SAMPLE_FLOAT32.\n");
if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
/* We need to fill some data before uncorking. Not doing this will result in the write callback never getting fired. */
/*
result = ma_device_write_to_stream__pulse(pDevice, (ma_pa_stream*)(pDevice->pulse.pStreamPlayback), NULL);
We need to fill some data before uncorking. Not doing this will result in the write callback
if (result != MA_SUCCESS) {
never getting fired. We're not going to abort if writing fails because I still want the device
return result; /* Failed to write data. Not sure what to do here... Just aborting. */
to get uncorked.
}
*/
ma_device_write_to_stream__pulse(pDevice, (ma_pa_stream*)(pDevice->pulse.pStreamPlayback), NULL); /* No need to check the result here. Always want to fall through an uncork.*/
result = ma_device__cork_stream__pulse(pDevice, ma_device_type_playback, 0);
result = ma_device__cork_stream__pulse(pDevice, ma_device_type_playback, 0);
/* We need to check whether or not we are outputting interleaved or non-interleaved samples. The way we do this is slightly different for each type. */
/* We need to check whether or not we are outputting interleaved or non-interleaved samples. The way we do this is slightly different for each type. */
ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_WARNING, "Failed to initialize mutex for device info retrieval. ma_context_get_device_info() is not thread safe.\n");
ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_WARNING, "Failed to initialize mutex for device info retrieval. ma_context_get_device_info() is not thread safe.\n");
if (pDevice->capture.pIntermediaryBuffer == NULL) {
ma_device_uninit(pDevice);
return MA_OUT_OF_MEMORY;
}
}
if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
ma_uint64 intermediaryBufferSizeInBytes;
pDevice->playback.intermediaryBufferLen = 0;
if (pConfig->deviceType == ma_device_type_duplex) {
pDevice->playback.intermediaryBufferCap = pDevice->capture.intermediaryBufferCap; /* In duplex mode, make sure the intermediary buffer is always the same size as the capture side. */
case ma_format_unknown: return MA_INVALID_OPERATION; /* <-- this should never be hit because initialization would just fall back to supported format. */
case ma_format_unknown: return MA_INVALID_OPERATION; /* <-- this should never be hit because initialization would just fall back to a supported format. */
Log levels are only used to give logging callbacks some context as to the severity of a log message
Log levels are only used to give logging callbacks some context as to the severity of a log message
so they can do filtering. All log levels will be posted to registered logging callbacks, except for
so they can do filtering. All log levels will be posted to registered logging callbacks. If you
MA_LOG_LEVEL_DEBUG which will only get processed if MA_DEBUG_OUTPUT is enabled.
don't want to output a certain log level you can discriminate against the log level in the callback.
MA_LOG_LEVEL_DEBUG
MA_LOG_LEVEL_DEBUG
Used for debugging. These log messages are only posted when `MA_DEBUG_OUTPUT` is enabled.
Used for debugging. Useful for debug and test builds, but should be disabled in release builds.
MA_LOG_LEVEL_INFO
MA_LOG_LEVEL_INFO
Informational logging. Useful for debugging. This will also enable warning and error logs. This
Informational logging. Useful for debugging. This will never be called from within the data
will never be called from within the data callback.
callback.
MA_LOG_LEVEL_WARNING
MA_LOG_LEVEL_WARNING
Warnings. You should enable this in you development builds and action them when encounted. This
Warnings. You should enable this in you development builds and action them when encounted. These
will also enable error logs. These logs usually indicate a potential problem or
logs usually indicate a potential problem or misconfiguration, but still allow you to keep
misconfiguration, but still allow you to keep running. This will never be called from within
running. This will never be called from within the data callback.
the data callback.
MA_LOG_LEVEL_ERROR
MA_LOG_LEVEL_ERROR
Error logging. This will be fired when an operation fails and is subsequently aborted. This can
Error logging. This will be fired when an operation fails and is subsequently aborted. This can
be fired from within the data callback, in which case the device will be stopped. You should
be fired from within the data callback, in which case the device will be stopped. You should
always have this log level enabled.
always have this log level enabled.
*/
*/
#define MA_LOG_LEVEL_DEBUG 4
typedefenum
#define MA_LOG_LEVEL_INFO 3
{
#define MA_LOG_LEVEL_WARNING 2
MA_LOG_LEVEL_DEBUG=4,
#define MA_LOG_LEVEL_ERROR 1
MA_LOG_LEVEL_INFO=3,
MA_LOG_LEVEL_WARNING=2,
MA_LOG_LEVEL_ERROR=1
}ma_log_level;
/*
/*
Variables needing to be accessed atomically should be declared with this macro for two reasons:
Variables needing to be accessed atomically should be declared with this macro for two reasons:
...
@@ -2476,6 +2478,7 @@ struct ma_device_config
...
@@ -2476,6 +2478,7 @@ struct ma_device_config
ma_bool8noPreSilencedOutputBuffer;/* 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_bool8noPreSilencedOutputBuffer;/* 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_bool8noClip;/* 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_bool8noClip;/* 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_bool8noDisableDenormals;/* Do not disable denormals when firing the data callback. */
ma_bool8noDisableDenormals;/* Do not disable denormals when firing the data callback. */
ma_bool8noFixedSizedCallback;/* Disables strict fixed-sized data callbacks. Setting this to true will result in the period size being treated only as a hint to the backend. This is an optimization for those who don't need fixed sized callbacks. */
ma_device_data_procdataCallback;
ma_device_data_procdataCallback;
ma_device_notification_procnotificationCallback;
ma_device_notification_procnotificationCallback;
ma_stop_procstopCallback;
ma_stop_procstopCallback;
...
@@ -3151,6 +3154,7 @@ struct ma_device
...
@@ -3151,6 +3154,7 @@ struct ma_device
ma_bool8noPreSilencedOutputBuffer;
ma_bool8noPreSilencedOutputBuffer;
ma_bool8noClip;
ma_bool8noClip;
ma_bool8noDisableDenormals;
ma_bool8noDisableDenormals;
ma_bool8noFixedSizedCallback;
MA_ATOMIC(4,float)masterVolumeFactor;/* Linear 0..1. Can be read and written simultaneously by different threads. Must be used atomically. */
MA_ATOMIC(4,float)masterVolumeFactor;/* Linear 0..1. Can be read and written simultaneously by different threads. Must be used atomically. */
ma_duplex_rbduplexRB;/* Intermediary buffer for duplex device on asynchronous backends. */
ma_duplex_rbduplexRB;/* Intermediary buffer for duplex device on asynchronous backends. */
struct
struct
...
@@ -3165,6 +3169,7 @@ struct ma_device
...
@@ -3165,6 +3169,7 @@ struct ma_device
}resampling;
}resampling;
struct
struct
{
{
ma_device_id*pID;/* Set to NULL if using default ID, otherwise set to the address of "id". */
ma_device_idid;/* If using an explicit device, will be set to a copy of the ID used for initialization. Otherwise cleared to 0. */
ma_device_idid;/* If using an explicit device, will be set to a copy of the ID used for initialization. Otherwise cleared to 0. */
charname[MA_MAX_DEVICE_NAME_LENGTH+1];/* Maybe temporary. Likely to be replaced with a query API. */
charname[MA_MAX_DEVICE_NAME_LENGTH+1];/* Maybe temporary. Likely to be replaced with a query API. */
ma_share_modeshareMode;/* Set to whatever was passed in when the device was initialized. */
ma_share_modeshareMode;/* Set to whatever was passed in when the device was initialized. */
...
@@ -3179,6 +3184,9 @@ struct ma_device
...
@@ -3179,6 +3184,9 @@ struct ma_device
ma_uint32internalPeriods;
ma_uint32internalPeriods;
ma_channel_mix_modechannelMixMode;
ma_channel_mix_modechannelMixMode;
ma_data_converterconverter;
ma_data_converterconverter;
void*pIntermediaryBuffer;/* For implementing fixed sized buffer callbacks. Will be null if using variable sized callbacks. */
ma_uint32intermediaryBufferCap;
ma_uint32intermediaryBufferLen;/* How many valid frames are sitting in the intermediary buffer. */
void*pInputCache;/* In external format. Can be null. */
void*pInputCache;/* In external format. Can be null. */
ma_uint64inputCacheCap;
ma_uint64inputCacheCap;
ma_uint64inputCacheConsumed;
ma_uint64inputCacheConsumed;
...
@@ -3186,6 +3194,7 @@ struct ma_device
...
@@ -3186,6 +3194,7 @@ struct ma_device
}playback;
}playback;
struct
struct
{
{
ma_device_id*pID;/* Set to NULL if using default ID, otherwise set to the address of "id". */
ma_device_idid;/* If using an explicit device, will be set to a copy of the ID used for initialization. Otherwise cleared to 0. */
ma_device_idid;/* If using an explicit device, will be set to a copy of the ID used for initialization. Otherwise cleared to 0. */
charname[MA_MAX_DEVICE_NAME_LENGTH+1];/* Maybe temporary. Likely to be replaced with a query API. */
charname[MA_MAX_DEVICE_NAME_LENGTH+1];/* Maybe temporary. Likely to be replaced with a query API. */
ma_share_modeshareMode;/* Set to whatever was passed in when the device was initialized. */
ma_share_modeshareMode;/* Set to whatever was passed in when the device was initialized. */
...
@@ -3200,6 +3209,9 @@ struct ma_device
...
@@ -3200,6 +3209,9 @@ struct ma_device
ma_uint32internalPeriods;
ma_uint32internalPeriods;
ma_channel_mix_modechannelMixMode;
ma_channel_mix_modechannelMixMode;
ma_data_converterconverter;
ma_data_converterconverter;
void*pIntermediaryBuffer;/* For implementing fixed sized buffer callbacks. Will be null if using variable sized callbacks. */
ma_uint32intermediaryBufferCap;
ma_uint32intermediaryBufferLen;/* How many valid frames are sitting in the intermediary buffer. */
}capture;
}capture;
union
union
...
@@ -4028,6 +4040,11 @@ then be set directly on the structure. Below are the members of the `ma_device_c
...
@@ -4028,6 +4040,11 @@ then be set directly on the structure. Below are the members of the `ma_device_c
noDisableDenormals
noDisableDenormals
By default, miniaudio will disable denormals when the data callback is called. Setting this to true will prevent the disabling of denormals.
By default, miniaudio will disable denormals when the data callback is called. Setting this to true will prevent the disabling of denormals.
noFixedSizedCallback
Allows miniaudio to fire the data callback with any frame count. When this is set to true, the data callback will be fired with a consistent frame
count as specified by `periodSizeInFrames` or `periodSizeInMilliseconds`. When set to false, miniaudio will fire the callback with whatever the
backend requests, which could be anything.
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.