Commit 3391a482 authored by David Reid's avatar David Reid

OpenSL: Migrate over to the new backend callback system.

parent 375b942f
......@@ -4227,7 +4227,6 @@ struct ma_device
ma_uint32 currentBufferIndexCapture;
ma_uint8* pBufferPlayback; /* This is malloc()'d and is used for storing audio data. Typed as ma_uint8 for easy offsetting. */
ma_uint8* pBufferCapture;
ma_pcm_rb duplexRB;
} opensl;
#endif
#ifdef MA_SUPPORT_WEBAUDIO
......@@ -30422,7 +30421,45 @@ return_default_device:;
return MA_SUCCESS;
}
static ma_result ma_context_get_device_info__opensl(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_share_mode shareMode, ma_device_info* pDeviceInfo)
static void ma_context_add_data_format_ex__opensl(ma_context* pContext, ma_format format, ma_uint32 channels, ma_uint32 sampleRate, ma_device_info* pDeviceInfo)
{
MA_ASSERT(pContext != NULL);
MA_ASSERT(pDeviceInfo != NULL);
pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].format = format;
pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].channels = channels;
pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].sampleRate = sampleRate;
pDeviceInfo->nativeDataFormats[pDeviceInfo->nativeDataFormatCount].flags = 0;
pDeviceInfo->nativeDataFormatCount += 1;
}
static void ma_context_add_data_format__opensl(ma_context* pContext, ma_format format, ma_device_info* pDeviceInfo)
{
ma_uint32 minChannels = 1;
ma_uint32 maxChannels = 2;
ma_uint32 minSampleRate = (ma_uint32)ma_standard_sample_rate_8000;
ma_uint32 maxSampleRate = (ma_uint32)ma_standard_sample_rate_48000;
ma_uint32 iChannel;
ma_uint32 iSampleRate;
MA_ASSERT(pContext != NULL);
MA_ASSERT(pDeviceInfo != NULL);
/*
Each sample format can support mono and stereo, and we'll support a small subset of standard
rates (up to 48000). A better solution would be to somehow find a native sample rate.
*/
for (iChannel = minChannels; iChannel < maxChannels; iChannel += 1) {
for (iSampleRate = 0; iSampleRate < ma_countof(g_maStandardSampleRatePriorities); iSampleRate += 1) {
ma_uint32 standardSampleRate = g_maStandardSampleRatePriorities[iSampleRate];
if (standardSampleRate >= minSampleRate && standardSampleRate <= maxSampleRate) {
ma_context_add_data_format_ex__opensl(pContext, format, iChannel, standardSampleRate, pDeviceInfo);
}
}
}
}
static ma_result ma_context_get_device_info__opensl(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_device_info* pDeviceInfo)
{
MA_ASSERT(pContext != NULL);
......@@ -30431,11 +30468,6 @@ static ma_result ma_context_get_device_info__opensl(ma_context* pContext, ma_dev
return MA_INVALID_OPERATION;
}
/* No exclusive mode with OpenSL|ES. */
if (shareMode == ma_share_mode_exclusive) {
return MA_SHARE_MODE_NOT_SUPPORTED;
}
/*
TODO: Test Me.
......@@ -30487,6 +30519,8 @@ return_default_device:
ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
}
pDeviceInfo->isDefault = MA_TRUE;
goto return_detailed_info;
......@@ -30497,17 +30531,12 @@ return_detailed_info:
by the device natively. Later on we should work on this so that it more closely reflects the device's
actual native format.
*/
pDeviceInfo->minChannels = 1;
pDeviceInfo->maxChannels = 2;
pDeviceInfo->minSampleRate = 8000;
pDeviceInfo->maxSampleRate = 48000;
pDeviceInfo->formatCount = 2;
pDeviceInfo->formats[0] = ma_format_u8;
pDeviceInfo->formats[1] = ma_format_s16;
pDeviceInfo->nativeDataFormatCount = 0;
#if defined(MA_ANDROID) && __ANDROID_API__ >= 21
pDeviceInfo->formats[pDeviceInfo->formatCount] = ma_format_f32;
pDeviceInfo->formatCount += 1;
ma_context_add_data_format__opensl(pContext, ma_format_f32, pDeviceInfo);
#endif
ma_context_add_data_format__opensl(pContext, ma_format_s16, pDeviceInfo);
ma_context_add_data_format__opensl(pContext, ma_format_u8, pDeviceInfo);
return MA_SUCCESS;
}
......@@ -30545,11 +30574,7 @@ static void ma_buffer_queue_callback_capture__opensl_android(SLAndroidSimpleBuff
periodSizeInBytes = pDevice->capture.internalPeriodSizeInFrames * ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
pBuffer = pDevice->opensl.pBufferCapture + (pDevice->opensl.currentBufferIndexCapture * periodSizeInBytes);
if (pDevice->type == ma_device_type_duplex) {
ma_device__handle_duplex_callback_capture(pDevice, pDevice->capture.internalPeriodSizeInFrames, pBuffer, &pDevice->opensl.duplexRB);
} else {
ma_device__send_frames_to_client(pDevice, pDevice->capture.internalPeriodSizeInFrames, pBuffer);
}
ma_device_handle_backend_data_callback(pDevice, NULL, pBuffer, pDevice->capture.internalPeriodSizeInFrames);
resultSL = MA_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueueCapture)->Enqueue((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueueCapture, pBuffer, periodSizeInBytes);
if (resultSL != SL_RESULT_SUCCESS) {
......@@ -30583,11 +30608,7 @@ static void ma_buffer_queue_callback_playback__opensl_android(SLAndroidSimpleBuf
periodSizeInBytes = pDevice->playback.internalPeriodSizeInFrames * ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
pBuffer = pDevice->opensl.pBufferPlayback + (pDevice->opensl.currentBufferIndexPlayback * periodSizeInBytes);
if (pDevice->type == ma_device_type_duplex) {
ma_device__handle_duplex_callback_playback(pDevice, pDevice->playback.internalPeriodSizeInFrames, pBuffer, &pDevice->opensl.duplexRB);
} else {
ma_device__read_frames_from_client(pDevice, pDevice->playback.internalPeriodSizeInFrames, pBuffer);
}
ma_device_handle_backend_data_callback(pDevice, pBuffer, NULL, pDevice->playback.internalPeriodSizeInFrames);
resultSL = MA_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueuePlayback)->Enqueue((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueuePlayback, pBuffer, periodSizeInBytes);
if (resultSL != SL_RESULT_SUCCESS) {
......@@ -30598,13 +30619,13 @@ static void ma_buffer_queue_callback_playback__opensl_android(SLAndroidSimpleBuf
}
#endif
static void ma_device_uninit__opensl(ma_device* pDevice)
static ma_result ma_device_uninit__opensl(ma_device* pDevice)
{
MA_ASSERT(pDevice != NULL);
MA_ASSERT(g_maOpenSLInitCounter > 0); /* <-- If you trigger this it means you've either not initialized the context, or you've uninitialized it before uninitializing the device. */
if (g_maOpenSLInitCounter == 0) {
return;
return MA_INVALID_OPERATION;
}
if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
......@@ -30626,9 +30647,7 @@ static void ma_device_uninit__opensl(ma_device* pDevice)
ma__free_from_callbacks(pDevice->opensl.pBufferPlayback, &pDevice->pContext->allocationCallbacks);
}
if (pDevice->type == ma_device_type_duplex) {
ma_pcm_rb_uninit(&pDevice->opensl.duplexRB);
}
return MA_SUCCESS;
}
#if defined(MA_ANDROID) && __ANDROID_API__ >= 21
......@@ -30639,6 +30658,17 @@ typedef SLDataFormat_PCM ma_SLDataFormat_PCM;
static ma_result ma_SLDataFormat_PCM_init__opensl(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, const ma_channel* channelMap, ma_SLDataFormat_PCM* pDataFormat)
{
/* We need to convert our format/channels/rate so that they aren't set to default. */
if (format == ma_format_unknown) {
format = MA_DEFAULT_FORMAT;
}
if (channels == 0) {
channels = MA_DEFAULT_CHANNELS;
}
if (sampleRate == 0) {
sampleRate = MA_DEFAULT_SAMPLE_RATE;
}
#if defined(MA_ANDROID) && __ANDROID_API__ >= 21
if (format == ma_format_f32) {
pDataFormat->formatType = SL_ANDROID_DATAFORMAT_PCM_EX;
......@@ -30651,7 +30681,7 @@ static ma_result ma_SLDataFormat_PCM_init__opensl(ma_format format, ma_uint32 ch
#endif
pDataFormat->numChannels = channels;
((SLDataFormat_PCM*)pDataFormat)->samplesPerSec = ma_round_to_standard_sample_rate__opensl(sampleRate * 1000); /* In millihertz. Annoyingly, the sample rate variable is named differently between SLAndroidDataFormat_PCM_EX and SLDataFormat_PCM */
((SLDataFormat_PCM*)pDataFormat)->samplesPerSec = ma_round_to_standard_sample_rate__opensl(sampleRate) * 1000; /* In millihertz. Annoyingly, the sample rate variable is named differently between SLAndroidDataFormat_PCM_EX and SLDataFormat_PCM */
pDataFormat->bitsPerSample = ma_get_bytes_per_sample(format)*8;
pDataFormat->channelMask = ma_channel_map_to_channel_mask__opensl(channelMap, channels);
pDataFormat->endianness = (ma_is_little_endian()) ? SL_BYTEORDER_LITTLEENDIAN : SL_BYTEORDER_BIGENDIAN;
......@@ -30725,7 +30755,7 @@ static ma_result ma_deconstruct_SLDataFormat_PCM__opensl(ma_SLDataFormat_PCM* pD
return MA_SUCCESS;
}
static ma_result ma_device_init__opensl(ma_context* pContext, const ma_device_config* pConfig, ma_device* pDevice)
static ma_result ma_device_init__opensl(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
{
#ifdef MA_ANDROID
SLDataLocator_AndroidSimpleBufferQueue queue;
......@@ -30736,8 +30766,6 @@ static ma_result ma_device_init__opensl(ma_context* pContext, const ma_device_co
const SLboolean itfIDsRequired1[] = {SL_BOOLEAN_TRUE};
#endif
(void)pContext;
MA_ASSERT(g_maOpenSLInitCounter > 0); /* <-- If you trigger this it means you've either not initialized the context, or you've uninitialized it and then attempted to initialize a new device. */
if (g_maOpenSLInitCounter == 0) {
return MA_INVALID_OPERATION;
......@@ -30753,11 +30781,11 @@ static ma_result ma_device_init__opensl(ma_context* pContext, const ma_device_co
queues).
*/
#ifdef MA_ANDROID
itfIDs1[0] = (SLInterfaceID)pContext->opensl.SL_IID_ANDROIDSIMPLEBUFFERQUEUE;
itfIDs1[0] = (SLInterfaceID)pDevice->pContext->opensl.SL_IID_ANDROIDSIMPLEBUFFERQUEUE;
/* No exclusive mode with OpenSL|ES. */
if (((pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) && pConfig->playback.shareMode == ma_share_mode_exclusive) ||
((pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) && pConfig->capture.shareMode == ma_share_mode_exclusive)) {
if (((pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) && pDescriptorPlayback->shareMode == ma_share_mode_exclusive) ||
((pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) && pDescriptorCapture->shareMode == ma_share_mode_exclusive)) {
return MA_SHARE_MODE_NOT_SUPPORTED;
}
......@@ -30766,8 +30794,6 @@ static ma_result ma_device_init__opensl(ma_context* pContext, const ma_device_co
MA_ZERO_OBJECT(&pDevice->opensl);
queue.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
queue.numBuffers = pConfig->periods;
if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
ma_SLDataFormat_PCM pcm;
......@@ -30776,16 +30802,18 @@ static ma_result ma_device_init__opensl(ma_context* pContext, const ma_device_co
SLDataSink sink;
SLAndroidConfigurationItf pRecorderConfig;
ma_SLDataFormat_PCM_init__opensl(pConfig->capture.format, pConfig->capture.channels, pConfig->sampleRate, pConfig->capture.channelMap, &pcm);
ma_SLDataFormat_PCM_init__opensl(pDescriptorCapture->format, pDescriptorCapture->channels, pDescriptorCapture->sampleRate, pDescriptorCapture->channelMap, &pcm);
locatorDevice.locatorType = SL_DATALOCATOR_IODEVICE;
locatorDevice.deviceType = SL_IODEVICE_AUDIOINPUT;
locatorDevice.deviceID = (pConfig->capture.pDeviceID == NULL) ? SL_DEFAULTDEVICEID_AUDIOINPUT : pConfig->capture.pDeviceID->opensl;
locatorDevice.deviceID = (pDescriptorCapture->pDeviceID == NULL) ? SL_DEFAULTDEVICEID_AUDIOINPUT : pDescriptorCapture->pDeviceID->opensl;
locatorDevice.device = NULL;
source.pLocator = &locatorDevice;
source.pFormat = NULL;
queue.numBuffers = pDescriptorCapture->periodCount;
sink.pLocator = &queue;
sink.pFormat = (SLDataFormat_PCM*)&pcm;
......@@ -30809,7 +30837,7 @@ static ma_result ma_device_init__opensl(ma_context* pContext, const ma_device_co
/* Set the recording preset before realizing the player. */
if (pConfig->opensl.recordingPreset != ma_opensl_recording_preset_default) {
resultSL = MA_OPENSL_OBJ(pDevice->opensl.pAudioPlayerObj)->GetInterface((SLObjectItf)pDevice->opensl.pAudioPlayerObj, (SLInterfaceID)pContext->opensl.SL_IID_ANDROIDCONFIGURATION, &pRecorderConfig);
resultSL = MA_OPENSL_OBJ(pDevice->opensl.pAudioPlayerObj)->GetInterface((SLObjectItf)pDevice->opensl.pAudioPlayerObj, (SLInterfaceID)pDevice->pContext->opensl.SL_IID_ANDROIDCONFIGURATION, &pRecorderConfig);
if (resultSL == SL_RESULT_SUCCESS) {
SLint32 recordingPreset = ma_to_recording_preset__opensl(pConfig->opensl.recordingPreset);
resultSL = (*pRecorderConfig)->SetConfiguration(pRecorderConfig, SL_ANDROID_KEY_RECORDING_PRESET, &recordingPreset, sizeof(SLint32));
......@@ -30825,13 +30853,13 @@ static ma_result ma_device_init__opensl(ma_context* pContext, const ma_device_co
return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to realize audio recorder.", ma_result_from_OpenSL(resultSL));
}
resultSL = MA_OPENSL_OBJ(pDevice->opensl.pAudioRecorderObj)->GetInterface((SLObjectItf)pDevice->opensl.pAudioRecorderObj, (SLInterfaceID)pContext->opensl.SL_IID_RECORD, &pDevice->opensl.pAudioRecorder);
resultSL = MA_OPENSL_OBJ(pDevice->opensl.pAudioRecorderObj)->GetInterface((SLObjectItf)pDevice->opensl.pAudioRecorderObj, (SLInterfaceID)pDevice->pContext->opensl.SL_IID_RECORD, &pDevice->opensl.pAudioRecorder);
if (resultSL != SL_RESULT_SUCCESS) {
ma_device_uninit__opensl(pDevice);
return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to retrieve SL_IID_RECORD interface.", ma_result_from_OpenSL(resultSL));
}
resultSL = MA_OPENSL_OBJ(pDevice->opensl.pAudioRecorderObj)->GetInterface((SLObjectItf)pDevice->opensl.pAudioRecorderObj, (SLInterfaceID)pContext->opensl.SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &pDevice->opensl.pBufferQueueCapture);
resultSL = MA_OPENSL_OBJ(pDevice->opensl.pAudioRecorderObj)->GetInterface((SLObjectItf)pDevice->opensl.pAudioRecorderObj, (SLInterfaceID)pDevice->pContext->opensl.SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &pDevice->opensl.pBufferQueueCapture);
if (resultSL != SL_RESULT_SUCCESS) {
ma_device_uninit__opensl(pDevice);
return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to retrieve SL_IID_ANDROIDSIMPLEBUFFERQUEUE interface.", ma_result_from_OpenSL(resultSL));
......@@ -30844,19 +30872,28 @@ static ma_result ma_device_init__opensl(ma_context* pContext, const ma_device_co
}
/* The internal format is determined by the "pcm" object. */
ma_deconstruct_SLDataFormat_PCM__opensl(&pcm, &pDevice->capture.internalFormat, &pDevice->capture.internalChannels, &pDevice->capture.internalSampleRate, pDevice->capture.internalChannelMap, ma_countof(pDevice->capture.internalChannelMap));
ma_deconstruct_SLDataFormat_PCM__opensl(&pcm, &pDescriptorCapture->format, &pDescriptorCapture->channels, &pDescriptorCapture->sampleRate, pDescriptorCapture->channelMap, ma_countof(pDescriptorCapture->channelMap));
/* Buffer. */
periodSizeInFrames = pConfig->periodSizeInFrames;
if (periodSizeInFrames == 0) {
periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_milliseconds(pConfig->periodSizeInMilliseconds, pDevice->capture.internalSampleRate);
if (pDescriptorCapture->periodSizeInFrames == 0) {
if (pDescriptorCapture->periodSizeInMilliseconds == 0) {
if (pConfig->performanceProfile == ma_performance_profile_low_latency) {
periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_milliseconds(MA_DEFAULT_PERIOD_SIZE_IN_MILLISECONDS_LOW_LATENCY, pDescriptorCapture->sampleRate);
} else {
periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_milliseconds(MA_DEFAULT_PERIOD_SIZE_IN_MILLISECONDS_CONSERVATIVE, pDescriptorCapture->sampleRate);
}
} else {
periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_milliseconds(pDescriptorCapture->periodSizeInMilliseconds, pDescriptorCapture->sampleRate);
}
} else {
periodSizeInFrames = pDescriptorCapture->periodSizeInFrames;
}
pDevice->capture.internalPeriods = pConfig->periods;
pDevice->capture.internalPeriodSizeInFrames = periodSizeInFrames;
pDescriptorCapture->periodSizeInFrames = periodSizeInFrames;
pDevice->opensl.currentBufferIndexCapture = 0;
bufferSizeInBytes = pDevice->capture.internalPeriodSizeInFrames * ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels) * pDevice->capture.internalPeriods;
pDevice->opensl.pBufferCapture = (ma_uint8*)ma__calloc_from_callbacks(bufferSizeInBytes, &pContext->allocationCallbacks);
bufferSizeInBytes = pDescriptorCapture->periodSizeInFrames * ma_get_bytes_per_frame(pDescriptorCapture->format, pDescriptorCapture->channels) * pDescriptorCapture->periodCount;
pDevice->opensl.pBufferCapture = (ma_uint8*)ma__calloc_from_callbacks(bufferSizeInBytes, &pDevice->pContext->allocationCallbacks);
if (pDevice->opensl.pBufferCapture == NULL) {
ma_device_uninit__opensl(pDevice);
return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to allocate memory for data buffer.", MA_OUT_OF_MEMORY);
......@@ -30871,7 +30908,7 @@ static ma_result ma_device_init__opensl(ma_context* pContext, const ma_device_co
SLDataSink sink;
SLAndroidConfigurationItf pPlayerConfig;
ma_SLDataFormat_PCM_init__opensl(pConfig->playback.format, pConfig->playback.channels, pConfig->sampleRate, pConfig->playback.channelMap, &pcm);
ma_SLDataFormat_PCM_init__opensl(pDescriptorPlayback->format, pDescriptorPlayback->channels, pDescriptorPlayback->sampleRate, pDescriptorPlayback->channelMap, &pcm);
resultSL = (*g_maEngineSL)->CreateOutputMix(g_maEngineSL, (SLObjectItf*)&pDevice->opensl.pOutputMixObj, 0, NULL, NULL);
if (resultSL != SL_RESULT_SUCCESS) {
......@@ -30885,18 +30922,20 @@ static ma_result ma_device_init__opensl(ma_context* pContext, const ma_device_co
return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to realize output mix object.", ma_result_from_OpenSL(resultSL));
}
resultSL = MA_OPENSL_OBJ(pDevice->opensl.pOutputMixObj)->GetInterface((SLObjectItf)pDevice->opensl.pOutputMixObj, (SLInterfaceID)pContext->opensl.SL_IID_OUTPUTMIX, &pDevice->opensl.pOutputMix);
resultSL = MA_OPENSL_OBJ(pDevice->opensl.pOutputMixObj)->GetInterface((SLObjectItf)pDevice->opensl.pOutputMixObj, (SLInterfaceID)pDevice->pContext->opensl.SL_IID_OUTPUTMIX, &pDevice->opensl.pOutputMix);
if (resultSL != SL_RESULT_SUCCESS) {
ma_device_uninit__opensl(pDevice);
return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to retrieve SL_IID_OUTPUTMIX interface.", ma_result_from_OpenSL(resultSL));
}
/* Set the output device. */
if (pConfig->playback.pDeviceID != NULL) {
SLuint32 deviceID_OpenSL = pConfig->playback.pDeviceID->opensl;
if (pDescriptorPlayback->pDeviceID != NULL) {
SLuint32 deviceID_OpenSL = pDescriptorPlayback->pDeviceID->opensl;
MA_OPENSL_OUTPUTMIX(pDevice->opensl.pOutputMix)->ReRoute((SLOutputMixItf)pDevice->opensl.pOutputMix, 1, &deviceID_OpenSL);
}
queue.numBuffers = pDescriptorPlayback->periodCount;
source.pLocator = &queue;
source.pFormat = (SLDataFormat_PCM*)&pcm;
......@@ -30926,7 +30965,7 @@ static ma_result ma_device_init__opensl(ma_context* pContext, const ma_device_co
/* Set the stream type before realizing the player. */
if (pConfig->opensl.streamType != ma_opensl_stream_type_default) {
resultSL = MA_OPENSL_OBJ(pDevice->opensl.pAudioPlayerObj)->GetInterface((SLObjectItf)pDevice->opensl.pAudioPlayerObj, (SLInterfaceID)pContext->opensl.SL_IID_ANDROIDCONFIGURATION, &pPlayerConfig);
resultSL = MA_OPENSL_OBJ(pDevice->opensl.pAudioPlayerObj)->GetInterface((SLObjectItf)pDevice->opensl.pAudioPlayerObj, (SLInterfaceID)pDevice->pContext->opensl.SL_IID_ANDROIDCONFIGURATION, &pPlayerConfig);
if (resultSL == SL_RESULT_SUCCESS) {
SLint32 streamType = ma_to_stream_type__opensl(pConfig->opensl.streamType);
resultSL = (*pPlayerConfig)->SetConfiguration(pPlayerConfig, SL_ANDROID_KEY_STREAM_TYPE, &streamType, sizeof(SLint32));
......@@ -30942,13 +30981,13 @@ static ma_result ma_device_init__opensl(ma_context* pContext, const ma_device_co
return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to realize audio player.", ma_result_from_OpenSL(resultSL));
}
resultSL = MA_OPENSL_OBJ(pDevice->opensl.pAudioPlayerObj)->GetInterface((SLObjectItf)pDevice->opensl.pAudioPlayerObj, (SLInterfaceID)pContext->opensl.SL_IID_PLAY, &pDevice->opensl.pAudioPlayer);
resultSL = MA_OPENSL_OBJ(pDevice->opensl.pAudioPlayerObj)->GetInterface((SLObjectItf)pDevice->opensl.pAudioPlayerObj, (SLInterfaceID)pDevice->pContext->opensl.SL_IID_PLAY, &pDevice->opensl.pAudioPlayer);
if (resultSL != SL_RESULT_SUCCESS) {
ma_device_uninit__opensl(pDevice);
return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to retrieve SL_IID_PLAY interface.", ma_result_from_OpenSL(resultSL));
}
resultSL = MA_OPENSL_OBJ(pDevice->opensl.pAudioPlayerObj)->GetInterface((SLObjectItf)pDevice->opensl.pAudioPlayerObj, (SLInterfaceID)pContext->opensl.SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &pDevice->opensl.pBufferQueuePlayback);
resultSL = MA_OPENSL_OBJ(pDevice->opensl.pAudioPlayerObj)->GetInterface((SLObjectItf)pDevice->opensl.pAudioPlayerObj, (SLInterfaceID)pDevice->pContext->opensl.SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &pDevice->opensl.pBufferQueuePlayback);
if (resultSL != SL_RESULT_SUCCESS) {
ma_device_uninit__opensl(pDevice);
return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to retrieve SL_IID_ANDROIDSIMPLEBUFFERQUEUE interface.", ma_result_from_OpenSL(resultSL));
......@@ -30961,19 +31000,28 @@ static ma_result ma_device_init__opensl(ma_context* pContext, const ma_device_co
}
/* The internal format is determined by the "pcm" object. */
ma_deconstruct_SLDataFormat_PCM__opensl(&pcm, &pDevice->playback.internalFormat, &pDevice->playback.internalChannels, &pDevice->playback.internalSampleRate, pDevice->playback.internalChannelMap, ma_countof(pDevice->playback.internalChannelMap));
ma_deconstruct_SLDataFormat_PCM__opensl(&pcm, &pDescriptorPlayback->format, &pDescriptorPlayback->channels, &pDescriptorPlayback->sampleRate, pDescriptorPlayback->channelMap, ma_countof(pDescriptorPlayback->channelMap));
/* Buffer. */
periodSizeInFrames = pConfig->periodSizeInFrames;
if (periodSizeInFrames == 0) {
periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_milliseconds(pConfig->periodSizeInMilliseconds, pDevice->playback.internalSampleRate);
if (pDescriptorPlayback->periodSizeInFrames == 0) {
if (pDescriptorPlayback->periodSizeInMilliseconds == 0) {
if (pConfig->performanceProfile == ma_performance_profile_low_latency) {
periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_milliseconds(MA_DEFAULT_PERIOD_SIZE_IN_MILLISECONDS_LOW_LATENCY, pDescriptorPlayback->sampleRate);
} else {
periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_milliseconds(MA_DEFAULT_PERIOD_SIZE_IN_MILLISECONDS_CONSERVATIVE, pDescriptorPlayback->sampleRate);
}
} else {
periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_milliseconds(pDescriptorPlayback->periodSizeInMilliseconds, pDescriptorPlayback->sampleRate);
}
pDevice->playback.internalPeriods = pConfig->periods;
pDevice->playback.internalPeriodSizeInFrames = periodSizeInFrames;
} else {
periodSizeInFrames = pDescriptorPlayback->periodSizeInFrames;
}
pDescriptorPlayback->periodSizeInFrames = periodSizeInFrames;
pDevice->opensl.currentBufferIndexPlayback = 0;
bufferSizeInBytes = pDevice->playback.internalPeriodSizeInFrames * ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels) * pDevice->playback.internalPeriods;
pDevice->opensl.pBufferPlayback = (ma_uint8*)ma__calloc_from_callbacks(bufferSizeInBytes, &pContext->allocationCallbacks);
bufferSizeInBytes = pDescriptorPlayback->periodSizeInFrames * ma_get_bytes_per_frame(pDescriptorPlayback->format, pDescriptorPlayback->channels) * pDescriptorPlayback->periodCount;
pDevice->opensl.pBufferPlayback = (ma_uint8*)ma__calloc_from_callbacks(bufferSizeInBytes, &pDevice->pContext->allocationCallbacks);
if (pDevice->opensl.pBufferPlayback == NULL) {
ma_device_uninit__opensl(pDevice);
return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to allocate memory for data buffer.", MA_OUT_OF_MEMORY);
......@@ -30981,26 +31029,6 @@ static ma_result ma_device_init__opensl(ma_context* pContext, const ma_device_co
MA_ZERO_MEMORY(pDevice->opensl.pBufferPlayback, bufferSizeInBytes);
}
if (pConfig->deviceType == ma_device_type_duplex) {
ma_uint32 rbSizeInFrames = (ma_uint32)ma_calculate_frame_count_after_resampling(pDevice->sampleRate, pDevice->capture.internalSampleRate, pDevice->capture.internalPeriodSizeInFrames) * pDevice->capture.internalPeriods;
ma_result result = ma_pcm_rb_init(pDevice->capture.format, pDevice->capture.channels, rbSizeInFrames, NULL, &pDevice->pContext->allocationCallbacks, &pDevice->opensl.duplexRB);
if (result != MA_SUCCESS) {
ma_device_uninit__opensl(pDevice);
return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[OpenSL] Failed to initialize ring buffer.", result);
}
/* We need a period to act as a buffer for cases where the playback and capture device's end up desyncing. */
{
ma_uint32 marginSizeInFrames = rbSizeInFrames / pDevice->capture.internalPeriods;
void* pMarginData;
ma_pcm_rb_acquire_write(&pDevice->opensl.duplexRB, &marginSizeInFrames, &pMarginData);
{
MA_ZERO_MEMORY(pMarginData, marginSizeInFrames * ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels));
}
ma_pcm_rb_commit_write(&pDevice->opensl.duplexRB, marginSizeInFrames, pMarginData);
}
}
return MA_SUCCESS;
#else
return MA_NO_BACKEND; /* Non-Android implementations are not supported. */
......@@ -31199,7 +31227,7 @@ static ma_result ma_context_init_engine_nolock__opensl(ma_context* pContext)
return MA_SUCCESS;
}
static ma_result ma_context_init__opensl(const ma_context_config* pConfig, ma_context* pContext)
static ma_result ma_context_init__opensl(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
{
ma_result result;
......@@ -31306,16 +31334,17 @@ static ma_result ma_context_init__opensl(const ma_context_config* pConfig, ma_co
return result;
}
pContext->isBackendAsynchronous = MA_TRUE;
pContext->onUninit = ma_context_uninit__opensl;
pContext->onEnumDevices = ma_context_enumerate_devices__opensl;
pContext->onGetDeviceInfo = ma_context_get_device_info__opensl;
pContext->onDeviceInit = ma_device_init__opensl;
pContext->onDeviceUninit = ma_device_uninit__opensl;
pContext->onDeviceStart = ma_device_start__opensl;
pContext->onDeviceStop = ma_device_stop__opensl;
pCallbacks->onContextInit = ma_context_init__opensl;
pCallbacks->onContextUninit = ma_context_uninit__opensl;
pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__opensl;
pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__opensl;
pCallbacks->onDeviceInit = ma_device_init__opensl;
pCallbacks->onDeviceUninit = ma_device_uninit__opensl;
pCallbacks->onDeviceStart = ma_device_start__opensl;
pCallbacks->onDeviceStop = ma_device_stop__opensl;
pCallbacks->onDeviceRead = NULL; /* Not needed because OpenSL|ES is asynchronous. */
pCallbacks->onDeviceWrite = NULL; /* Not needed because OpenSL|ES is asynchronous. */
pCallbacks->onDeviceAudioThread = NULL; /* Not needed because OpenSL|ES is asynchronous. */
return MA_SUCCESS;
}
......@@ -32452,6 +32481,12 @@ MA_API ma_result ma_context_init(const ma_backend backends[], ma_uint32 backendC
pContext->callbacks.onContextInit = ma_context_init__jack;
} break;
#endif
#ifdef MA_HAS_OPENSL
case ma_backend_opensl:
{
pContext->callbacks.onContextInit = ma_context_init__opensl;
} break;
#endif
#ifdef MA_HAS_WEBAUDIO
case ma_backend_webaudio:
{
......@@ -32556,8 +32591,7 @@ MA_API ma_result ma_context_init(const ma_backend backends[], ma_uint32 backendC
#ifdef MA_HAS_OPENSL
case ma_backend_opensl:
{
ma_post_log_message(pContext, NULL, MA_LOG_LEVEL_VERBOSE, "Attempting to initialize OpenSL backend...");
result = ma_context_init__opensl(pConfig, pContext);
/*result = ma_context_init__opensl(pConfig, pContext);*/
} break;
#endif
#ifdef MA_HAS_WEBAUDIO
......@@ -64633,8 +64667,11 @@ REVISION HISTORY
v0.10.32 - TBD
- WASAPI: Fix a deadlock in exclusive mode.
- PulseAudio: Yet another refactor, this time to remove the dependency on `pa_threaded_mainloop`.
- ALSA: Internal refactoring to migrate to the new backend callback system.
- Core Audio: Internal refactoring to migrate to the new backend callback system.
- Internal refactoring to migrate to the new backend callback system for the following backends:
- PulseAudio
- ALSA
- Core Audio
- OpenSL|ES
- Update to latest version of c89atomic.
- Fix a bug where thread handles are not being freed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment