mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-21 15:56:58 +02:00
Set up some infrastructure for some future optimizations.
This changes the way backends update the internal data format in response to a device reroute. With this change we'll be able to remove the `channelMap` and `internalChannel` map members from the `ma_device` struct which should reduce its size by ~1KB.
This commit is contained in:
+330
-191
@@ -9605,6 +9605,46 @@ the two. Use `ma_device_type_playback` for the playback side, or `ma_device_type
|
||||
MA_API void ma_device_get_internal_channel_map(const ma_device* pDevice, ma_device_type deviceType, ma_channel* pChannelMap, size_t channelMapCap);
|
||||
|
||||
|
||||
/*
|
||||
Updates the public and internal device descriptors.
|
||||
|
||||
A normal application should never be calling this directly. It would only be called by device backends in response to a device reroute.
|
||||
|
||||
Information describing a device, such as its ID, data format and period size is specified in a structure referred to as a "descriptor".
|
||||
Where this function matters is with the data format. With the sample format, channel count, sample rate and channel map, there is the
|
||||
public facing data format which the application requests, and then there is the actual data format that is used by the backend internally.
|
||||
Sitting between these two is a data converter. The public descriptor will never change after initialization, but sometimes the backend
|
||||
will change the internal descriptor. When this happens, the data converter needs to be reinitialized, and that is when a backend would
|
||||
want to call this function.
|
||||
|
||||
|
||||
Parameters
|
||||
----------
|
||||
pDevice (in)
|
||||
A pointer to the device whose descriptor is being updated.
|
||||
|
||||
deviceType (in)
|
||||
Either `ma_device_type_playback` or `ma_device_type_capture` specifying which side of the device whose descriptor is being updated.
|
||||
|
||||
pPublicDescriptor (in, optional)
|
||||
A pointer to the public facing descriptor. This should always be NULL.
|
||||
|
||||
pInternalDescriptor (in)
|
||||
A pointer to the new internal descriptor. This cannot be NULL.
|
||||
|
||||
|
||||
Return Value
|
||||
------------
|
||||
`MA_SUCCESS` if successful; any other result code if an error occurs.
|
||||
|
||||
|
||||
Remarks
|
||||
-------
|
||||
If you are a normal consumer of miniaudio, do not ever call this function. It should only be called by device backends.
|
||||
*/
|
||||
MA_API ma_result ma_device_update_descriptor(ma_device* pDevice, ma_device_type deviceType, const ma_device_descriptor* pPublicDescriptor, const ma_device_descriptor* pInternalDescriptor);
|
||||
|
||||
|
||||
/*
|
||||
Performs post backend initialization routines for setting up internal data conversion.
|
||||
|
||||
@@ -9651,7 +9691,7 @@ is specified as a parameter rather than deriving it from the device.
|
||||
You do not need to call this manually unless you are doing a custom backend, in which case you need
|
||||
only do it if you're manually performing rerouting or reinitialization.
|
||||
*/
|
||||
MA_API ma_result ma_device_post_init(ma_device* pDevice, ma_device_type deviceType, const ma_device_descriptor* pPlaybackDescriptor, const ma_device_descriptor* pCaptureDescriptor);
|
||||
MA_API ma_result ma_device_post_init(ma_device* pDevice, ma_device_type deviceType, const ma_device_descriptor* pPublicDescriptorPlayback, const ma_device_descriptor* pPublicDescriptorCapture, const ma_device_descriptor* pInternalPlaybackDescriptor, const ma_device_descriptor* pInternalCaptureDescriptor);
|
||||
|
||||
|
||||
/*
|
||||
@@ -21115,7 +21155,7 @@ MA_API ma_uint32 ma_get_format_priority_index(ma_format format) /* Lower = bette
|
||||
return (ma_uint32)-1;
|
||||
}
|
||||
|
||||
static ma_result ma_device__post_init_setup(ma_device* pDevice, ma_device_type deviceType);
|
||||
static ma_result ma_device__post_init_setup(ma_device* pDevice, ma_device_type deviceType, const ma_device_descriptor* pPublicDescriptorPlayback, const ma_device_descriptor* pPublicDescriptorCapture, const ma_device_descriptor* pInternalDescriptorPlayback, const ma_device_descriptor* pInternalDescriptorCapture);
|
||||
|
||||
static ma_bool32 ma_device_descriptor_is_valid(const ma_device_descriptor* pDeviceDescriptor)
|
||||
{
|
||||
@@ -24227,6 +24267,7 @@ static ma_result ma_device_reinit__wasapi(ma_device* pDevice, ma_device_type dev
|
||||
ma_device_state_wasapi* pDeviceStateWASAPI = ma_device_get_backend_state__wasapi(pDevice);
|
||||
ma_device_init_internal_data__wasapi data;
|
||||
ma_result result;
|
||||
ma_device_descriptor internalDescriptor;
|
||||
const ma_device_id* pDeviceID = NULL;
|
||||
|
||||
MA_ASSERT(pDevice != NULL);
|
||||
@@ -24264,20 +24305,17 @@ static ma_result ma_device_reinit__wasapi(ma_device* pDevice, ma_device_type dev
|
||||
|
||||
|
||||
if (deviceType == ma_device_type_playback) {
|
||||
pDeviceID = pDevice->playback.pID;
|
||||
data.formatIn = pDevice->playback.format;
|
||||
data.channelsIn = pDevice->playback.channels;
|
||||
MA_COPY_MEMORY(data.channelMapIn, pDevice->playback.channelMap, sizeof(pDevice->playback.channelMap));
|
||||
data.shareMode = pDevice->playback.shareMode;
|
||||
pDeviceID = pDevice->playback.pID;
|
||||
data.shareMode = pDevice->playback.shareMode;
|
||||
} else {
|
||||
pDeviceID = pDevice->playback.pID;
|
||||
data.formatIn = pDevice->capture.format;
|
||||
data.channelsIn = pDevice->capture.channels;
|
||||
MA_COPY_MEMORY(data.channelMapIn, pDevice->capture.channelMap, sizeof(pDevice->capture.channelMap));
|
||||
data.shareMode = pDevice->capture.shareMode;
|
||||
pDeviceID = pDevice->playback.pID;
|
||||
data.shareMode = pDevice->capture.shareMode;
|
||||
}
|
||||
|
||||
data.sampleRateIn = pDevice->sampleRate;
|
||||
data.formatIn = ma_device_get_format(pDevice, deviceType);
|
||||
data.channelsIn = ma_device_get_channels(pDevice, deviceType);
|
||||
data.sampleRateIn = ma_device_get_sample_rate(pDevice);
|
||||
ma_device_get_channel_map(pDevice, deviceType, data.channelMapIn, ma_countof(data.channelMapIn));
|
||||
data.periodSizeInFramesIn = pDeviceStateWASAPI->originalPeriodSizeInFrames;
|
||||
data.periodSizeInMillisecondsIn = pDeviceStateWASAPI->originalPeriodSizeInMilliseconds;
|
||||
data.periodsIn = pDeviceStateWASAPI->originalPeriods;
|
||||
@@ -24293,15 +24331,8 @@ static ma_result ma_device_reinit__wasapi(ma_device* pDevice, ma_device_type dev
|
||||
|
||||
/* At this point we have some new objects ready to go. We need to uninitialize the previous ones and then set the new ones. */
|
||||
if (deviceType == ma_device_type_capture || deviceType == ma_device_type_loopback) {
|
||||
pDeviceStateWASAPI->pAudioClientCapture = data.pAudioClient;
|
||||
pDeviceStateWASAPI->pCaptureClient = data.pCaptureClient;
|
||||
|
||||
pDevice->capture.internalFormat = data.formatOut;
|
||||
pDevice->capture.internalChannels = data.channelsOut;
|
||||
pDevice->capture.internalSampleRate = data.sampleRateOut;
|
||||
MA_COPY_MEMORY(pDevice->capture.internalChannelMap, data.channelMapOut, sizeof(data.channelMapOut));
|
||||
pDevice->capture.internalPeriodSizeInFrames = data.periodSizeInFramesOut;
|
||||
pDevice->capture.internalPeriods = data.periodsOut;
|
||||
pDeviceStateWASAPI->pAudioClientCapture = data.pAudioClient;
|
||||
pDeviceStateWASAPI->pCaptureClient = data.pCaptureClient;
|
||||
|
||||
ma_IAudioClient_SetEventHandle((ma_IAudioClient*)pDeviceStateWASAPI->pAudioClientCapture, (HANDLE)pDeviceStateWASAPI->hEventCapture);
|
||||
|
||||
@@ -24313,15 +24344,8 @@ static ma_result ma_device_reinit__wasapi(ma_device* pDevice, ma_device_type dev
|
||||
}
|
||||
|
||||
if (deviceType == ma_device_type_playback) {
|
||||
pDeviceStateWASAPI->pAudioClientPlayback = data.pAudioClient;
|
||||
pDeviceStateWASAPI->pRenderClient = data.pRenderClient;
|
||||
|
||||
pDevice->playback.internalFormat = data.formatOut;
|
||||
pDevice->playback.internalChannels = data.channelsOut;
|
||||
pDevice->playback.internalSampleRate = data.sampleRateOut;
|
||||
MA_COPY_MEMORY(pDevice->playback.internalChannelMap, data.channelMapOut, sizeof(data.channelMapOut));
|
||||
pDevice->playback.internalPeriodSizeInFrames = data.periodSizeInFramesOut;
|
||||
pDevice->playback.internalPeriods = data.periodsOut;
|
||||
pDeviceStateWASAPI->pAudioClientPlayback = data.pAudioClient;
|
||||
pDeviceStateWASAPI->pRenderClient = data.pRenderClient;
|
||||
|
||||
ma_IAudioClient_SetEventHandle((ma_IAudioClient*)pDeviceStateWASAPI->pAudioClientPlayback, (HANDLE)pDeviceStateWASAPI->hEventPlayback);
|
||||
|
||||
@@ -24332,6 +24356,20 @@ static ma_result ma_device_reinit__wasapi(ma_device* pDevice, ma_device_type dev
|
||||
ma_strcpy_s_WCHAR(pDevice->playback.id.wasapi, sizeof(pDevice->playback.id.wasapi), data.id.wasapi);
|
||||
}
|
||||
|
||||
/* The internal data converter needs to be reinitialized. */
|
||||
MA_ZERO_OBJECT(&internalDescriptor);
|
||||
internalDescriptor.format = data.formatOut;
|
||||
internalDescriptor.channels = data.channelsOut;
|
||||
internalDescriptor.sampleRate = data.sampleRateOut;
|
||||
MA_COPY_MEMORY(internalDescriptor.channelMap, data.channelMapOut, sizeof(data.channelMapOut));
|
||||
internalDescriptor.periodSizeInFrames = data.periodSizeInFramesOut;
|
||||
internalDescriptor.periodCount = data.periodsOut;
|
||||
|
||||
result = ma_device_update_descriptor(pDevice, deviceType, NULL, &internalDescriptor);
|
||||
if (result != MA_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -24706,7 +24744,6 @@ static ma_result ma_device_reroute__wasapi(ma_device* pDevice, ma_device_type de
|
||||
return result;
|
||||
}
|
||||
|
||||
ma_device__post_init_setup(pDevice, deviceType);
|
||||
ma_device_post_notification_rerouted(pDevice);
|
||||
|
||||
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "=== DEVICE CHANGED ===");
|
||||
@@ -39741,6 +39778,7 @@ static ma_result ma_device_reinit_internal__coreaudio(ma_device* pDevice, ma_dev
|
||||
ma_device_state_coreaudio* pDeviceStateCoreAudio = ma_device_get_backend_state__coreaudio(pDevice);
|
||||
ma_context_state_coreaudio* pContextStateCoreAudio = ma_context_get_backend_state__coreaudio(ma_device_get_context(pDevice));
|
||||
ma_device_init_internal_data__coreaudio data;
|
||||
ma_device_descriptor internalDescriptor;
|
||||
ma_result result;
|
||||
|
||||
/* This should only be called for playback or capture, not duplex. */
|
||||
@@ -39751,12 +39789,8 @@ static ma_result ma_device_reinit_internal__coreaudio(ma_device* pDevice, ma_dev
|
||||
data.allowNominalSampleRateChange = MA_FALSE; /* Don't change the nominal sample rate when switching devices. */
|
||||
|
||||
if (deviceType == ma_device_type_capture) {
|
||||
data.formatIn = pDevice->capture.format;
|
||||
data.channelsIn = pDevice->capture.channels;
|
||||
data.sampleRateIn = pDevice->sampleRate;
|
||||
MA_COPY_MEMORY(data.channelMapIn, pDevice->capture.channelMap, sizeof(pDevice->capture.channelMap));
|
||||
data.shareMode = pDevice->capture.shareMode;
|
||||
data.registerStopEvent = MA_TRUE;
|
||||
data.shareMode = pDevice->capture.shareMode;
|
||||
data.registerStopEvent = MA_TRUE;
|
||||
|
||||
if (disposePreviousAudioUnit) {
|
||||
pContextStateCoreAudio->AudioOutputUnitStop(pDeviceStateCoreAudio->audioUnitCapture);
|
||||
@@ -39766,18 +39800,19 @@ static ma_result ma_device_reinit_internal__coreaudio(ma_device* pDevice, ma_dev
|
||||
ma_free(pDeviceStateCoreAudio->pAudioBufferList, ma_device_get_allocation_callbacks(pDevice));
|
||||
}
|
||||
} else if (deviceType == ma_device_type_playback) {
|
||||
data.formatIn = pDevice->playback.format;
|
||||
data.channelsIn = pDevice->playback.channels;
|
||||
data.sampleRateIn = pDevice->sampleRate;
|
||||
MA_COPY_MEMORY(data.channelMapIn, pDevice->playback.channelMap, sizeof(pDevice->playback.channelMap));
|
||||
data.shareMode = pDevice->playback.shareMode;
|
||||
data.registerStopEvent = (pDevice->type != ma_device_type_duplex);
|
||||
data.shareMode = pDevice->playback.shareMode;
|
||||
data.registerStopEvent = (pDevice->type != ma_device_type_duplex);
|
||||
|
||||
if (disposePreviousAudioUnit) {
|
||||
pContextStateCoreAudio->AudioOutputUnitStop(pDeviceStateCoreAudio->audioUnitPlayback);
|
||||
pContextStateCoreAudio->AudioComponentInstanceDispose(pDeviceStateCoreAudio->audioUnitPlayback);
|
||||
}
|
||||
}
|
||||
|
||||
data.formatIn = ma_device_get_format(pDevice, deviceType);
|
||||
data.channelsIn = ma_device_get_channels(pDevice, deviceType);
|
||||
data.sampleRateIn = ma_device_get_sample_rate(pDevice);
|
||||
ma_device_get_channel_map(pDevice, deviceType, data.channelMapIn, ma_countof(data.channelMapIn));
|
||||
data.periodSizeInFramesIn = pDeviceStateCoreAudio->originalPeriodSizeInFrames;
|
||||
data.periodSizeInMillisecondsIn = pDeviceStateCoreAudio->originalPeriodSizeInMilliseconds;
|
||||
data.periodsIn = pDeviceStateCoreAudio->originalPeriods;
|
||||
@@ -39792,6 +39827,22 @@ static ma_result ma_device_reinit_internal__coreaudio(ma_device* pDevice, ma_dev
|
||||
return result;
|
||||
}
|
||||
|
||||
/* The device's internal descriptor needs to be updated. */
|
||||
MA_ZERO_OBJECT(&internalDescriptor);
|
||||
internalDescriptor.format = data.formatOut;
|
||||
internalDescriptor.channels = data.channelsOut;
|
||||
internalDescriptor.sampleRate = data.sampleRateOut;
|
||||
MA_COPY_MEMORY(internalDescriptor.channelMap, data.channelMapOut, sizeof(data.channelMapOut));
|
||||
internalDescriptor.periodSizeInFrames = data.periodSizeInFramesOut;
|
||||
internalDescriptor.periodCount = data.periodsOut;
|
||||
|
||||
result = ma_device_update_descriptor(pDevice, deviceType, NULL, &internalDescriptor);
|
||||
if (result != MA_SUCCESS) {
|
||||
ma_device_uninit__coreaudio(pDevice);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
We need to reinitialize our async state object to account for the new internal format and
|
||||
buffer configuration. To do this we'll need to set up a dummy descriptor.
|
||||
@@ -39806,26 +39857,12 @@ static ma_result ma_device_reinit_internal__coreaudio(ma_device* pDevice, ma_dev
|
||||
pDeviceStateCoreAudio->audioUnitCapture = data.audioUnit;
|
||||
pDeviceStateCoreAudio->pAudioBufferList = data.pAudioBufferList;
|
||||
pDeviceStateCoreAudio->audioBufferCapInFrames = data.periodSizeInFramesOut;
|
||||
|
||||
pDevice->capture.internalFormat = data.formatOut;
|
||||
pDevice->capture.internalChannels = data.channelsOut;
|
||||
pDevice->capture.internalSampleRate = data.sampleRateOut;
|
||||
MA_COPY_MEMORY(pDevice->capture.internalChannelMap, data.channelMapOut, sizeof(data.channelMapOut));
|
||||
pDevice->capture.internalPeriodSizeInFrames = data.periodSizeInFramesOut;
|
||||
pDevice->capture.internalPeriods = data.periodsOut;
|
||||
} else if (deviceType == ma_device_type_playback) {
|
||||
#if defined(MA_APPLE_DESKTOP)
|
||||
pDeviceStateCoreAudio->deviceObjectIDPlayback = (ma_uint32)data.deviceObjectID;
|
||||
ma_get_AudioObject_uid(pDevice->pContext, pDeviceStateCoreAudio->deviceObjectIDPlayback, sizeof(pDevice->playback.id.coreaudio), pDevice->playback.id.coreaudio);
|
||||
#endif
|
||||
pDeviceStateCoreAudio->audioUnitPlayback = data.audioUnit;
|
||||
|
||||
pDevice->playback.internalFormat = data.formatOut;
|
||||
pDevice->playback.internalChannels = data.channelsOut;
|
||||
pDevice->playback.internalSampleRate = data.sampleRateOut;
|
||||
MA_COPY_MEMORY(pDevice->playback.internalChannelMap, data.channelMapOut, sizeof(data.channelMapOut));
|
||||
pDevice->playback.internalPeriodSizeInFrames = data.periodSizeInFramesOut;
|
||||
pDevice->playback.internalPeriods = data.periodsOut;
|
||||
}
|
||||
|
||||
{
|
||||
@@ -39833,18 +39870,18 @@ static ma_result ma_device_reinit_internal__coreaudio(ma_device* pDevice, ma_dev
|
||||
ma_device_descriptor descriptorCapture;
|
||||
|
||||
MA_ZERO_OBJECT(&descriptorPlayback);
|
||||
descriptorPlayback.format = pDevice->playback.internalFormat;
|
||||
descriptorPlayback.channels = pDevice->playback.internalChannels;
|
||||
descriptorPlayback.sampleRate = pDevice->playback.internalSampleRate;
|
||||
descriptorPlayback.format = ma_device_get_internal_format(pDevice, ma_device_type_playback);
|
||||
descriptorPlayback.channels = ma_device_get_internal_channels(pDevice, ma_device_type_playback);
|
||||
descriptorPlayback.sampleRate = ma_device_get_internal_sample_rate(pDevice, ma_device_type_playback);
|
||||
descriptorPlayback.periodSizeInFrames = pDevice->playback.internalPeriodSizeInFrames;
|
||||
descriptorPlayback.periodCount = pDevice->playback.internalPeriods;
|
||||
|
||||
MA_ZERO_OBJECT(&descriptorCapture);
|
||||
descriptorCapture.format = pDevice->capture.internalFormat;
|
||||
descriptorCapture.channels = pDevice->capture.internalChannels;
|
||||
descriptorCapture.sampleRate = pDevice->capture.internalSampleRate;
|
||||
descriptorCapture.periodSizeInFrames = pDevice->capture.internalPeriodSizeInFrames;
|
||||
descriptorCapture.periodCount = pDevice->capture.internalPeriods;
|
||||
descriptorCapture.format = ma_device_get_internal_format(pDevice, ma_device_type_capture);
|
||||
descriptorCapture.channels = ma_device_get_internal_channels(pDevice, ma_device_type_capture);
|
||||
descriptorCapture.sampleRate = ma_device_get_internal_sample_rate(pDevice, ma_device_type_capture);
|
||||
descriptorCapture.periodSizeInFrames = pDevice->capture.internalPeriodSizeInFrames;
|
||||
descriptorCapture.periodCount = pDevice->capture.internalPeriods;
|
||||
|
||||
result = ma_device_state_async_init(ma_device_get_type(pDevice), &descriptorPlayback, &descriptorCapture, ma_device_get_allocation_callbacks(pDevice), &pDeviceStateCoreAudio->async);
|
||||
if (result != MA_SUCCESS) {
|
||||
@@ -40120,8 +40157,6 @@ static ma_result ma_device_step_extra__coreaudio(ma_device* pDevice)
|
||||
}
|
||||
|
||||
if (wasReinitialized && result == MA_SUCCESS) {
|
||||
ma_device__post_init_setup(pDevice, deviceType);
|
||||
|
||||
/* Restart the device if required. If this fails we need to stop the device entirely. */
|
||||
if (ma_device_get_status(pDevice) == ma_device_status_started) {
|
||||
OSStatus status;
|
||||
@@ -44620,7 +44655,7 @@ static ma_result ma_device_reinit__aaudio(ma_device* pDevice, ma_device_type dev
|
||||
/* The first thing to do is close the streams. */
|
||||
ma_close_streams__aaudio(pDevice);
|
||||
|
||||
/* Now we need to reinitialize each streams. The hardest part with this is just filling output the config and descriptors. */
|
||||
/* Now we need to reinitialize each streams. The hardest part with this is just filling out the config and descriptors. */
|
||||
deviceConfigAAudio = ma_device_config_aaudio_init();
|
||||
deviceConfigAAudio.usage = pDeviceStateAAudio->usage;
|
||||
deviceConfigAAudio.contentType = pDeviceStateAAudio->contentType;
|
||||
@@ -44631,9 +44666,9 @@ static ma_result ma_device_reinit__aaudio(ma_device* pDevice, ma_device_type dev
|
||||
if (deviceType == ma_device_type_capture || deviceType == ma_device_type_duplex || deviceType == ma_device_type_loopback) {
|
||||
descriptorCapture.pDeviceID = NULL; /* Only doing rerouting with default devices. */
|
||||
descriptorCapture.shareMode = pDevice->capture.shareMode;
|
||||
descriptorCapture.format = pDevice->capture.format;
|
||||
descriptorCapture.channels = pDevice->capture.channels;
|
||||
descriptorCapture.sampleRate = pDevice->sampleRate;
|
||||
descriptorCapture.format = ma_device_get_format(pDevice, ma_device_type_capture);
|
||||
descriptorCapture.channels = ma_device_get_channels(pDevice, ma_device_type_capture);
|
||||
descriptorCapture.sampleRate = ma_device_get_sample_rate(pDevice);
|
||||
descriptorCapture.periodSizeInFrames = pDevice->capture.internalPeriodSizeInFrames;
|
||||
descriptorCapture.periodCount = 1;
|
||||
}
|
||||
@@ -44641,9 +44676,9 @@ static ma_result ma_device_reinit__aaudio(ma_device* pDevice, ma_device_type dev
|
||||
if (deviceType == ma_device_type_playback || deviceType == ma_device_type_duplex) {
|
||||
descriptorPlayback.pDeviceID = NULL; /* Only doing rerouting with default devices. */
|
||||
descriptorPlayback.shareMode = pDevice->playback.shareMode;
|
||||
descriptorPlayback.format = pDevice->playback.format;
|
||||
descriptorPlayback.channels = pDevice->playback.channels;
|
||||
descriptorPlayback.sampleRate = pDevice->sampleRate;
|
||||
descriptorPlayback.format = ma_device_get_format(pDevice, ma_device_type_playback);
|
||||
descriptorPlayback.channels = ma_device_get_channels(pDevice, ma_device_type_playback);
|
||||
descriptorPlayback.sampleRate = ma_device_get_sample_rate(pDevice);
|
||||
descriptorPlayback.periodSizeInFrames = pDevice->playback.internalPeriodSizeInFrames;
|
||||
descriptorPlayback.periodCount = 1;
|
||||
}
|
||||
@@ -44651,16 +44686,26 @@ static ma_result ma_device_reinit__aaudio(ma_device* pDevice, ma_device_type dev
|
||||
result = ma_device_init_streams__aaudio(pDevice, pDeviceStateAAudio, &deviceConfigAAudio, &descriptorPlayback, &descriptorCapture);
|
||||
if (result != MA_SUCCESS) {
|
||||
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_WARNING, "[AAudio] Failed to create stream after route change.");
|
||||
/* Reroute failed! */
|
||||
break;
|
||||
}
|
||||
|
||||
result = ma_device_post_init(pDevice, deviceType, &descriptorPlayback, &descriptorCapture);
|
||||
if (result != MA_SUCCESS) {
|
||||
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_WARNING, "[AAudio] Failed to initialize device after route change.");
|
||||
ma_close_streams__aaudio(pDevice);
|
||||
/* Reroute failed! */
|
||||
break;
|
||||
/* The internal data converters need to be updated. */
|
||||
if (deviceType == ma_device_type_capture || deviceType == ma_device_type_duplex || deviceType == ma_device_type_loopback) {
|
||||
result = ma_device_update_descriptor(pDevice, ma_device_type_capture, NULL, &descriptorCapture);
|
||||
if (result != MA_SUCCESS) {
|
||||
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_WARNING, "[AAudio] Failed to initialize device after route change.");
|
||||
ma_close_streams__aaudio(pDevice);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (deviceType == ma_device_type_playback || deviceType == ma_device_type_duplex) {
|
||||
result = ma_device_update_descriptor(pDevice, ma_device_type_playback, NULL, &descriptorPlayback);
|
||||
if (result != MA_SUCCESS) {
|
||||
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_WARNING, "[AAudio] Failed to initialize device after route change.");
|
||||
ma_close_streams__aaudio(pDevice);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* We'll only ever do this in response to a reroute. */
|
||||
@@ -47387,81 +47432,101 @@ static ma_bool32 ma__is_channel_map_valid(const ma_channel* pChannelMap, ma_uint
|
||||
}
|
||||
|
||||
|
||||
static ma_result ma_device__post_init_setup(ma_device* pDevice, ma_device_type deviceType)
|
||||
MA_API ma_result ma_device_update_descriptor(ma_device* pDevice, ma_device_type deviceType, const ma_device_descriptor* pPublicDescriptor, const ma_device_descriptor* pInternalDescriptor)
|
||||
{
|
||||
ma_result result;
|
||||
ma_device_descriptor publicDescriptor;
|
||||
ma_device_descriptor internalDescriptor;
|
||||
ma_data_converter_config converterConfig;
|
||||
|
||||
MA_ASSERT(pDevice != NULL);
|
||||
|
||||
if (deviceType == ma_device_type_capture || deviceType == ma_device_type_duplex || deviceType == ma_device_type_loopback) {
|
||||
if (pDevice->capture.format == ma_format_unknown) {
|
||||
pDevice->capture.format = pDevice->capture.internalFormat;
|
||||
}
|
||||
if (pDevice->capture.channels == 0) {
|
||||
pDevice->capture.channels = pDevice->capture.internalChannels;
|
||||
}
|
||||
if (pDevice->capture.channelMap[0] == MA_CHANNEL_NONE) {
|
||||
MA_ASSERT(pDevice->capture.channels <= MA_MAX_CHANNELS);
|
||||
if (pDevice->capture.internalChannels == pDevice->capture.channels) {
|
||||
ma_channel_map_copy(pDevice->capture.channelMap, pDevice->capture.internalChannelMap, pDevice->capture.channels);
|
||||
} else {
|
||||
if (pDevice->capture.channelMixMode == ma_channel_mix_mode_simple) {
|
||||
ma_channel_map_init_blank(pDevice->capture.channelMap, pDevice->capture.channels);
|
||||
} else {
|
||||
ma_channel_map_init_standard(ma_standard_channel_map_default, pDevice->capture.channelMap, ma_countof(pDevice->capture.channelMap), pDevice->capture.channels);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pDevice == NULL || pInternalDescriptor == NULL) {
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (deviceType == ma_device_type_playback || deviceType == ma_device_type_duplex) {
|
||||
if (pDevice->playback.format == ma_format_unknown) {
|
||||
pDevice->playback.format = pDevice->playback.internalFormat;
|
||||
}
|
||||
if (pDevice->playback.channels == 0) {
|
||||
pDevice->playback.channels = pDevice->playback.internalChannels;
|
||||
}
|
||||
if (pDevice->playback.channelMap[0] == MA_CHANNEL_NONE) {
|
||||
MA_ASSERT(pDevice->playback.channels <= MA_MAX_CHANNELS);
|
||||
if (pDevice->playback.internalChannels == pDevice->playback.channels) {
|
||||
ma_channel_map_copy(pDevice->playback.channelMap, pDevice->playback.internalChannelMap, pDevice->playback.channels);
|
||||
} else {
|
||||
if (pDevice->playback.channelMixMode == ma_channel_mix_mode_simple) {
|
||||
ma_channel_map_init_blank(pDevice->playback.channelMap, pDevice->playback.channels);
|
||||
} else {
|
||||
ma_channel_map_init_standard(ma_standard_channel_map_default, pDevice->playback.channelMap, ma_countof(pDevice->playback.channelMap), pDevice->playback.channels);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* This function should never be called with ma_device_type_duplex. It should be called once for each side. */
|
||||
if (deviceType == ma_device_type_duplex) {
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (pDevice->sampleRate == 0) {
|
||||
if (deviceType == ma_device_type_capture || deviceType == ma_device_type_duplex || deviceType == ma_device_type_loopback) {
|
||||
pDevice->sampleRate = pDevice->capture.internalSampleRate;
|
||||
/* The public descriptor can be null only if the device has already been initialized, in which case we can synthesise it from existing info. */
|
||||
if (pPublicDescriptor == NULL) {
|
||||
if (ma_device_get_status(pDevice) == ma_device_status_uninitialized) {
|
||||
return MA_INVALID_ARGS; /* Can't know what the public format it. */
|
||||
}
|
||||
|
||||
publicDescriptor.format = ma_device_get_format(pDevice, deviceType);
|
||||
publicDescriptor.channels = ma_device_get_channels(pDevice, deviceType);
|
||||
publicDescriptor.sampleRate = ma_device_get_sample_rate(pDevice);
|
||||
ma_device_get_channel_map(pDevice, deviceType, publicDescriptor.channelMap, ma_countof(publicDescriptor.channelMap));
|
||||
} else {
|
||||
publicDescriptor = *pPublicDescriptor;
|
||||
}
|
||||
|
||||
if (pInternalDescriptor == NULL) {
|
||||
return MA_INVALID_ARGS; /* Internal format must always be provided. */
|
||||
} else {
|
||||
internalDescriptor = *pInternalDescriptor;
|
||||
}
|
||||
|
||||
|
||||
/* At this point we should not be needing to access `pPublic/InternalDescriptor`. We should be accessing `public/internalDescriptor` instead. We'll clear this to null so we can catch any errors. */
|
||||
pPublicDescriptor = NULL;
|
||||
pInternalDescriptor = NULL;
|
||||
|
||||
/* Make sure we have valid values for everything on the public side. */
|
||||
if (publicDescriptor.format == ma_format_unknown) {
|
||||
publicDescriptor.format = internalDescriptor.format;
|
||||
}
|
||||
|
||||
if (publicDescriptor.channels == 0) {
|
||||
publicDescriptor.channels = internalDescriptor.channels;
|
||||
}
|
||||
|
||||
if (publicDescriptor.sampleRate == 0) {
|
||||
publicDescriptor.sampleRate = internalDescriptor.sampleRate;
|
||||
}
|
||||
|
||||
if (publicDescriptor.channelMap[0] == MA_CHANNEL_NONE) {
|
||||
MA_ASSERT(publicDescriptor.channels <= MA_MAX_CHANNELS);
|
||||
|
||||
if (publicDescriptor.channels == internalDescriptor.channels) {
|
||||
ma_channel_map_copy(publicDescriptor.channelMap, internalDescriptor.channelMap, internalDescriptor.channels);
|
||||
} else {
|
||||
pDevice->sampleRate = pDevice->playback.internalSampleRate;
|
||||
ma_channel_mix_mode channelMixMode;
|
||||
if (deviceType == ma_device_type_capture || deviceType == ma_device_type_loopback) {
|
||||
channelMixMode = pDevice->capture.channelMixMode;
|
||||
} else {
|
||||
channelMixMode = pDevice->playback.channelMixMode;
|
||||
}
|
||||
|
||||
if (channelMixMode == ma_channel_mix_mode_simple) {
|
||||
ma_channel_map_init_blank(publicDescriptor.channelMap, publicDescriptor.channels);
|
||||
} else {
|
||||
ma_channel_map_init_standard(ma_standard_channel_map_default, publicDescriptor.channelMap, ma_countof(publicDescriptor.channelMap), publicDescriptor.channels);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Data converters. */
|
||||
if (deviceType == ma_device_type_capture || deviceType == ma_device_type_duplex || deviceType == ma_device_type_loopback) {
|
||||
/* Converting from internal device format to client format. */
|
||||
ma_data_converter_config converterConfig = ma_data_converter_config_init_default();
|
||||
converterConfig.formatIn = pDevice->capture.internalFormat;
|
||||
converterConfig.channelsIn = pDevice->capture.internalChannels;
|
||||
converterConfig.sampleRateIn = pDevice->capture.internalSampleRate;
|
||||
converterConfig.pChannelMapIn = pDevice->capture.internalChannelMap;
|
||||
converterConfig.formatOut = pDevice->capture.format;
|
||||
converterConfig.channelsOut = pDevice->capture.channels;
|
||||
converterConfig.sampleRateOut = pDevice->sampleRate;
|
||||
converterConfig.pChannelMapOut = pDevice->capture.channelMap;
|
||||
|
||||
/* The data converter can now be initialized. */
|
||||
converterConfig = ma_data_converter_config_init_default();
|
||||
converterConfig.allowDynamicSampleRate = MA_FALSE;
|
||||
converterConfig.resampling.algorithm = pDevice->resampling.algorithm;
|
||||
converterConfig.resampling.linear.lpfOrder = pDevice->resampling.linear.lpfOrder;
|
||||
converterConfig.resampling.pBackendVTable = pDevice->resampling.pBackendVTable;
|
||||
converterConfig.resampling.pBackendUserData = pDevice->resampling.pBackendUserData;
|
||||
|
||||
if (deviceType == ma_device_type_capture || deviceType == ma_device_type_loopback) {
|
||||
converterConfig.formatIn = internalDescriptor.format;
|
||||
converterConfig.channelsIn = internalDescriptor.channels;
|
||||
converterConfig.sampleRateIn = internalDescriptor.sampleRate;
|
||||
converterConfig.pChannelMapIn = internalDescriptor.channelMap;
|
||||
converterConfig.formatOut = publicDescriptor.format;
|
||||
converterConfig.channelsOut = publicDescriptor.channels;
|
||||
converterConfig.sampleRateOut = publicDescriptor.sampleRate;
|
||||
converterConfig.pChannelMapOut = publicDescriptor.channelMap;
|
||||
converterConfig.channelMixMode = pDevice->capture.channelMixMode;
|
||||
converterConfig.calculateLFEFromSpatialChannels = pDevice->capture.calculateLFEFromSpatialChannels;
|
||||
converterConfig.allowDynamicSampleRate = MA_FALSE;
|
||||
converterConfig.resampling.algorithm = pDevice->resampling.algorithm;
|
||||
converterConfig.resampling.linear.lpfOrder = pDevice->resampling.linear.lpfOrder;
|
||||
converterConfig.resampling.pBackendVTable = pDevice->resampling.pBackendVTable;
|
||||
converterConfig.resampling.pBackendUserData = pDevice->resampling.pBackendUserData;
|
||||
|
||||
/* Make sure the old converter is uninitialized first. */
|
||||
if (ma_device_get_status(pDevice) != ma_device_status_uninitialized) {
|
||||
@@ -47472,26 +47537,17 @@ static ma_result ma_device__post_init_setup(ma_device* pDevice, ma_device_type d
|
||||
if (result != MA_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (deviceType == ma_device_type_playback || deviceType == ma_device_type_duplex) {
|
||||
/* Converting from client format to device format. */
|
||||
ma_data_converter_config converterConfig = ma_data_converter_config_init_default();
|
||||
converterConfig.formatIn = pDevice->playback.format;
|
||||
converterConfig.channelsIn = pDevice->playback.channels;
|
||||
converterConfig.sampleRateIn = pDevice->sampleRate;
|
||||
converterConfig.pChannelMapIn = pDevice->playback.channelMap;
|
||||
converterConfig.formatOut = pDevice->playback.internalFormat;
|
||||
converterConfig.channelsOut = pDevice->playback.internalChannels;
|
||||
converterConfig.sampleRateOut = pDevice->playback.internalSampleRate;
|
||||
converterConfig.pChannelMapOut = pDevice->playback.internalChannelMap;
|
||||
converterConfig.channelMixMode = pDevice->playback.channelMixMode;
|
||||
converterConfig.calculateLFEFromSpatialChannels = pDevice->playback.calculateLFEFromSpatialChannels;
|
||||
converterConfig.allowDynamicSampleRate = MA_FALSE;
|
||||
converterConfig.resampling.algorithm = pDevice->resampling.algorithm;
|
||||
converterConfig.resampling.linear.lpfOrder = pDevice->resampling.linear.lpfOrder;
|
||||
converterConfig.resampling.pBackendVTable = pDevice->resampling.pBackendVTable;
|
||||
converterConfig.resampling.pBackendUserData = pDevice->resampling.pBackendUserData;
|
||||
} else {
|
||||
converterConfig.formatIn = publicDescriptor.format;
|
||||
converterConfig.channelsIn = publicDescriptor.channels;
|
||||
converterConfig.sampleRateIn = publicDescriptor.sampleRate;
|
||||
converterConfig.pChannelMapIn = publicDescriptor.channelMap;
|
||||
converterConfig.formatOut = internalDescriptor.format;
|
||||
converterConfig.channelsOut = internalDescriptor.channels;
|
||||
converterConfig.sampleRateOut = internalDescriptor.sampleRate;
|
||||
converterConfig.pChannelMapOut = internalDescriptor.channelMap;
|
||||
converterConfig.channelMixMode = pDevice->capture.channelMixMode;
|
||||
converterConfig.calculateLFEFromSpatialChannels = pDevice->capture.calculateLFEFromSpatialChannels;
|
||||
|
||||
/* Make sure the old converter is uninitialized first. */
|
||||
if (ma_device_get_status(pDevice) != ma_device_status_uninitialized) {
|
||||
@@ -47505,6 +47561,7 @@ static ma_result ma_device__post_init_setup(ma_device* pDevice, ma_device_type d
|
||||
}
|
||||
|
||||
|
||||
/* TODO: Reassess this. Doesn't feel right that this needs to be done here. Why can we not just used a fixed sized buffer like 1024? */
|
||||
/*
|
||||
If the device is doing playback (ma_device_type_playback or ma_device_type_duplex), there's
|
||||
a couple of situations where we'll need a heap allocated cache.
|
||||
@@ -47524,7 +47581,7 @@ static ma_result ma_device__post_init_setup(ma_device* pDevice, ma_device_type d
|
||||
in fixed sized chunks and then cache any residual unused input frames, those of which will be
|
||||
processed at a later stage.
|
||||
*/
|
||||
if (deviceType == ma_device_type_playback || deviceType == ma_device_type_duplex) {
|
||||
if (deviceType == ma_device_type_playback) {
|
||||
ma_uint64 unused;
|
||||
|
||||
pDevice->playback.inputCacheConsumed = 0;
|
||||
@@ -47538,9 +47595,9 @@ static ma_result ma_device__post_init_setup(ma_device* pDevice, ma_device_type d
|
||||
ma_uint64 newInputCacheCap;
|
||||
ma_uint64 newInputCacheSizeInBytes;
|
||||
|
||||
newInputCacheCap = ma_calculate_frame_count_after_resampling(pDevice->playback.internalSampleRate, pDevice->sampleRate, pDevice->playback.internalPeriodSizeInFrames);
|
||||
newInputCacheCap = ma_calculate_frame_count_after_resampling(ma_device_get_internal_sample_rate(pDevice, ma_device_type_playback), ma_device_get_sample_rate(pDevice), pDevice->playback.internalPeriodSizeInFrames);
|
||||
|
||||
newInputCacheSizeInBytes = newInputCacheCap * ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels);
|
||||
newInputCacheSizeInBytes = newInputCacheCap * ma_get_bytes_per_frame(ma_device_get_format(pDevice, ma_device_type_playback), ma_device_get_channels(pDevice, ma_device_type_playback));
|
||||
if (newInputCacheSizeInBytes > MA_SIZE_MAX) {
|
||||
ma_free(pDevice->playback.pInputCache, ma_device_get_allocation_callbacks(pDevice));
|
||||
pDevice->playback.pInputCache = NULL;
|
||||
@@ -47566,53 +47623,115 @@ static ma_result ma_device__post_init_setup(ma_device* pDevice, ma_device_type d
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Update the internal format, channels, rate, map. */
|
||||
if (deviceType == ma_device_type_capture || deviceType == ma_device_type_loopback) {
|
||||
pDevice->capture.internalFormat = internalDescriptor.format;
|
||||
pDevice->capture.internalChannels = internalDescriptor.channels;
|
||||
pDevice->capture.internalSampleRate = internalDescriptor.sampleRate;
|
||||
pDevice->capture.internalPeriodSizeInFrames = internalDescriptor.periodSizeInFrames;
|
||||
pDevice->capture.internalPeriods = internalDescriptor.periodCount;
|
||||
}
|
||||
|
||||
if (deviceType == ma_device_type_playback) {
|
||||
pDevice->playback.internalFormat = internalDescriptor.format;
|
||||
pDevice->playback.internalChannels = internalDescriptor.channels;
|
||||
pDevice->playback.internalSampleRate = internalDescriptor.sampleRate;
|
||||
pDevice->playback.internalPeriodSizeInFrames = internalDescriptor.periodSizeInFrames;
|
||||
pDevice->playback.internalPeriods = internalDescriptor.periodCount;
|
||||
}
|
||||
|
||||
/* Update the public format, channels, rate. */
|
||||
if (deviceType == ma_device_type_capture || deviceType == ma_device_type_loopback) {
|
||||
pDevice->capture.format = publicDescriptor.format;
|
||||
pDevice->capture.channels = publicDescriptor.channels;
|
||||
}
|
||||
|
||||
if (deviceType == ma_device_type_playback) {
|
||||
pDevice->playback.format = publicDescriptor.format;
|
||||
pDevice->playback.channels = publicDescriptor.channels;
|
||||
}
|
||||
|
||||
pDevice->sampleRate = publicDescriptor.sampleRate;
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
MA_API ma_result ma_device_post_init(ma_device* pDevice, ma_device_type deviceType, const ma_device_descriptor* pDescriptorPlayback, const ma_device_descriptor* pDescriptorCapture)
|
||||
|
||||
static ma_result ma_device__post_init_setup(ma_device* pDevice, ma_device_type deviceType, const ma_device_descriptor* pPublicDescriptorPlayback, const ma_device_descriptor* pPublicDescriptorCapture, const ma_device_descriptor* pInternalDescriptorPlayback, const ma_device_descriptor* pInternalDescriptorCapture)
|
||||
{
|
||||
ma_result result;
|
||||
|
||||
MA_ASSERT(pDevice != NULL);
|
||||
|
||||
if (deviceType == ma_device_type_capture || deviceType == ma_device_type_duplex || deviceType == ma_device_type_loopback) {
|
||||
result = ma_device_update_descriptor(pDevice, ma_device_type_capture, pPublicDescriptorCapture, pInternalDescriptorCapture);
|
||||
if (result != MA_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (deviceType == ma_device_type_playback || deviceType == ma_device_type_duplex) {
|
||||
result = ma_device_update_descriptor(pDevice, ma_device_type_playback, pPublicDescriptorPlayback, pInternalDescriptorPlayback);
|
||||
if (result != MA_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
MA_API ma_result ma_device_post_init(ma_device* pDevice, ma_device_type deviceType, const ma_device_descriptor* pPublicDescriptorPlayback, const ma_device_descriptor* pPublicDescriptorCapture, const ma_device_descriptor* pInternalDescriptorPlayback, const ma_device_descriptor* pInternalDescriptorCapture)
|
||||
{
|
||||
ma_result result;
|
||||
|
||||
if (pDevice == NULL) {
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
/* Capture. */
|
||||
if (deviceType == ma_device_type_capture || deviceType == ma_device_type_duplex || deviceType == ma_device_type_loopback) {
|
||||
if (ma_device_descriptor_is_valid(pDescriptorCapture) == MA_FALSE) {
|
||||
if (ma_device_descriptor_is_valid(pInternalDescriptorCapture) == MA_FALSE) {
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
pDevice->capture.internalFormat = pDescriptorCapture->format;
|
||||
pDevice->capture.internalChannels = pDescriptorCapture->channels;
|
||||
pDevice->capture.internalSampleRate = pDescriptorCapture->sampleRate;
|
||||
MA_COPY_MEMORY(pDevice->capture.internalChannelMap, pDescriptorCapture->channelMap, sizeof(pDescriptorCapture->channelMap));
|
||||
pDevice->capture.internalPeriodSizeInFrames = pDescriptorCapture->periodSizeInFrames;
|
||||
pDevice->capture.internalPeriods = pDescriptorCapture->periodCount;
|
||||
pDevice->capture.internalFormat = pInternalDescriptorCapture->format;
|
||||
pDevice->capture.internalChannels = pInternalDescriptorCapture->channels;
|
||||
pDevice->capture.internalSampleRate = pInternalDescriptorCapture->sampleRate;
|
||||
MA_COPY_MEMORY(pDevice->capture.internalChannelMap, pInternalDescriptorCapture->channelMap, sizeof(pInternalDescriptorCapture->channelMap));
|
||||
pDevice->capture.internalPeriodSizeInFrames = pInternalDescriptorCapture->periodSizeInFrames;
|
||||
pDevice->capture.internalPeriods = pInternalDescriptorCapture->periodCount;
|
||||
|
||||
if (pDevice->capture.internalPeriodSizeInFrames == 0) {
|
||||
pDevice->capture.internalPeriodSizeInFrames = ma_calculate_buffer_size_in_frames_from_milliseconds(pDescriptorCapture->periodSizeInMilliseconds, pDescriptorCapture->sampleRate);
|
||||
pDevice->capture.internalPeriodSizeInFrames = ma_calculate_buffer_size_in_frames_from_milliseconds(pInternalDescriptorCapture->periodSizeInMilliseconds, pInternalDescriptorCapture->sampleRate);
|
||||
}
|
||||
}
|
||||
|
||||
/* Playback. */
|
||||
if (deviceType == ma_device_type_playback || deviceType == ma_device_type_duplex) {
|
||||
if (ma_device_descriptor_is_valid(pDescriptorPlayback) == MA_FALSE) {
|
||||
if (ma_device_descriptor_is_valid(pInternalDescriptorPlayback) == MA_FALSE) {
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
pDevice->playback.internalFormat = pDescriptorPlayback->format;
|
||||
pDevice->playback.internalChannels = pDescriptorPlayback->channels;
|
||||
pDevice->playback.internalSampleRate = pDescriptorPlayback->sampleRate;
|
||||
MA_COPY_MEMORY(pDevice->playback.internalChannelMap, pDescriptorPlayback->channelMap, sizeof(pDescriptorPlayback->channelMap));
|
||||
pDevice->playback.internalPeriodSizeInFrames = pDescriptorPlayback->periodSizeInFrames;
|
||||
pDevice->playback.internalPeriods = pDescriptorPlayback->periodCount;
|
||||
pDevice->playback.internalFormat = pInternalDescriptorPlayback->format;
|
||||
pDevice->playback.internalChannels = pInternalDescriptorPlayback->channels;
|
||||
pDevice->playback.internalSampleRate = pInternalDescriptorPlayback->sampleRate;
|
||||
MA_COPY_MEMORY(pDevice->playback.internalChannelMap, pInternalDescriptorPlayback->channelMap, sizeof(pInternalDescriptorPlayback->channelMap));
|
||||
pDevice->playback.internalPeriodSizeInFrames = pInternalDescriptorPlayback->periodSizeInFrames;
|
||||
pDevice->playback.internalPeriods = pInternalDescriptorPlayback->periodCount;
|
||||
|
||||
if (pDevice->playback.internalPeriodSizeInFrames == 0) {
|
||||
pDevice->playback.internalPeriodSizeInFrames = ma_calculate_buffer_size_in_frames_from_milliseconds(pDescriptorPlayback->periodSizeInMilliseconds, pDescriptorPlayback->sampleRate);
|
||||
pDevice->playback.internalPeriodSizeInFrames = ma_calculate_buffer_size_in_frames_from_milliseconds(pInternalDescriptorPlayback->periodSizeInMilliseconds, pInternalDescriptorPlayback->sampleRate);
|
||||
}
|
||||
}
|
||||
|
||||
/* Update data conversion. */
|
||||
return ma_device__post_init_setup(pDevice, deviceType); /* TODO: Should probably rename ma_device__post_init_setup() to something better. */
|
||||
result = ma_device__post_init_setup(pDevice, deviceType, pPublicDescriptorPlayback, pPublicDescriptorCapture, pInternalDescriptorPlayback, pInternalDescriptorCapture); /* TODO: Should probably rename ma_device__post_init_setup() to something better. */
|
||||
if (result != MA_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -48817,6 +48936,8 @@ MA_API ma_result ma_device_init(ma_context* pContext, const ma_device_config* pC
|
||||
{
|
||||
ma_result result;
|
||||
ma_device_backend_info backendInfo;
|
||||
ma_device_descriptor publicDescriptorPlayback;
|
||||
ma_device_descriptor publicDescriptorCapture;
|
||||
ma_device_descriptor descriptorPlayback;
|
||||
ma_device_descriptor descriptorCapture;
|
||||
ma_threading_mode threadingMode;
|
||||
@@ -48973,6 +49094,14 @@ MA_API ma_result ma_device_init(ma_context* pContext, const ma_device_config* pC
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
The backend will change the descriptor from the public format to its internal format. We need to keep track of the
|
||||
public descriptors in order to know how to initialize the data converter later on.
|
||||
*/
|
||||
publicDescriptorPlayback = descriptorPlayback;
|
||||
publicDescriptorCapture = descriptorCapture;
|
||||
|
||||
/* We are now ready to initialize the backend. */
|
||||
initParams.init.pDeviceBackendConfig = ma_device_config_find_backend_config(pConfig, pContext->pVTable);
|
||||
initParams.init.pDescriptorPlayback = &descriptorPlayback;
|
||||
initParams.init.pDescriptorCapture = &descriptorCapture;
|
||||
@@ -49037,7 +49166,7 @@ MA_API ma_result ma_device_init(ma_context* pContext, const ma_device_config* pC
|
||||
}
|
||||
}
|
||||
|
||||
result = ma_device_post_init(pDevice, pConfig->deviceType, &descriptorPlayback, &descriptorCapture);
|
||||
result = ma_device_post_init(pDevice, pConfig->deviceType, &publicDescriptorPlayback, &publicDescriptorCapture, &descriptorPlayback, &descriptorCapture);
|
||||
if (result != MA_SUCCESS) {
|
||||
ma_device_uninit(pDevice);
|
||||
return result;
|
||||
@@ -49141,11 +49270,16 @@ MA_API ma_result ma_device_init(ma_context* pContext, const ma_device_config* pC
|
||||
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Resampling: %s", pDevice->capture.converter.hasResampler ? "YES" : "NO");
|
||||
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Passthrough: %s", pDevice->capture.converter.isPassthrough ? "YES" : "NO");
|
||||
{
|
||||
ma_channel internalChannelMap[MA_MAX_CHANNELS];
|
||||
ma_channel publicChannelMap[MA_MAX_CHANNELS];
|
||||
char channelMapStr[1024];
|
||||
ma_channel_map_to_string(pDevice->capture.internalChannelMap, pDevice->capture.internalChannels, channelMapStr, sizeof(channelMapStr));
|
||||
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Channel Map In: {%s}", channelMapStr);
|
||||
|
||||
ma_channel_map_to_string(pDevice->capture.channelMap, pDevice->capture.channels, channelMapStr, sizeof(channelMapStr));
|
||||
ma_device_get_internal_channel_map(pDevice, ma_device_type_capture, internalChannelMap, ma_countof(internalChannelMap));
|
||||
ma_channel_map_to_string(internalChannelMap, ma_device_get_internal_channels(pDevice, ma_device_type_capture), channelMapStr, sizeof(channelMapStr));
|
||||
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Channel Map In: {%s}", channelMapStr);
|
||||
|
||||
ma_device_get_channel_map(pDevice, ma_device_type_capture, publicChannelMap, ma_countof(publicChannelMap));
|
||||
ma_channel_map_to_string(publicChannelMap, ma_device_get_channels(pDevice, ma_device_type_capture), channelMapStr, sizeof(channelMapStr));
|
||||
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Channel Map Out: {%s}", channelMapStr);
|
||||
}
|
||||
}
|
||||
@@ -49165,11 +49299,16 @@ MA_API ma_result ma_device_init(ma_context* pContext, const ma_device_config* pC
|
||||
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Resampling: %s", pDevice->playback.converter.hasResampler ? "YES" : "NO");
|
||||
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Passthrough: %s", pDevice->playback.converter.isPassthrough ? "YES" : "NO");
|
||||
{
|
||||
ma_channel publicChannelMap[MA_MAX_CHANNELS];
|
||||
ma_channel internalChannelMap[MA_MAX_CHANNELS];
|
||||
char channelMapStr[1024];
|
||||
ma_channel_map_to_string(pDevice->playback.channelMap, pDevice->playback.channels, channelMapStr, sizeof(channelMapStr));
|
||||
|
||||
ma_device_get_channel_map(pDevice, ma_device_type_playback, publicChannelMap, ma_countof(publicChannelMap));
|
||||
ma_channel_map_to_string(publicChannelMap, ma_device_get_channels(pDevice, ma_device_type_playback), channelMapStr, sizeof(channelMapStr));
|
||||
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Channel Map In: {%s}", channelMapStr);
|
||||
|
||||
ma_channel_map_to_string(pDevice->playback.internalChannelMap, pDevice->playback.internalChannels, channelMapStr, sizeof(channelMapStr));
|
||||
ma_device_get_internal_channel_map(pDevice, ma_device_type_playback, internalChannelMap, ma_countof(internalChannelMap));
|
||||
ma_channel_map_to_string(internalChannelMap, ma_device_get_internal_channels(pDevice, ma_device_type_playback), channelMapStr, sizeof(channelMapStr));
|
||||
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Channel Map Out: {%s}", channelMapStr);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user