Commit 7a2bd78f authored by David Reid's avatar David Reid

Add support for the f32 format for OpenSL|ES.

parent 830d9e6c
...@@ -1518,7 +1518,16 @@ static void mal_samples_to_f32(float* pSamplesOut, const void* pSamplesIn, mal_u ...@@ -1518,7 +1518,16 @@ static void mal_samples_to_f32(float* pSamplesOut, const void* pSamplesIn, mal_u
mal_int16* pSamplesInS16 = (mal_int16*)pSamplesIn; mal_int16* pSamplesInS16 = (mal_int16*)pSamplesIn;
for (mal_uint32 i = 0; i < sampleCount; ++i) { for (mal_uint32 i = 0; i < sampleCount; ++i) {
mal_uint32 sign = (pSamplesInS16[i] & 0x8000) >> 15; mal_uint32 sign = (pSamplesInS16[i] & 0x8000) >> 15;
pSamplesOut[i] = (pSamplesInS16[i] / (float)(32767 + sign)); pSamplesOut[i] = (pSamplesInS16[i] / (float)(0x7FFF + sign));
}
} break;
case mal_format_s32:
{
mal_int32* pSamplesInS32 = (mal_int32*)pSamplesIn;
for (mal_uint32 i = 0; i < sampleCount; ++i) {
mal_uint32 sign = (pSamplesInS32[i] & 0x80000000) >> 31;
pSamplesOut[i] = (pSamplesInS32[i] / (float)(0x7FFFFFFF + sign));
} }
} break; } break;
...@@ -1570,9 +1579,19 @@ static void mal_samples_from_f32(void* pSamplesOut, const float* pSamplesIn, mal ...@@ -1570,9 +1579,19 @@ static void mal_samples_from_f32(void* pSamplesOut, const float* pSamplesIn, mal
float sampleIn = mal_clip_f32(pSamplesIn[i]); float sampleIn = mal_clip_f32(pSamplesIn[i]);
mal_uint32 sign = ((*((mal_uint32*)&pSamplesIn[i])) & 0x80000000) >> 31; mal_uint32 sign = ((*((mal_uint32*)&pSamplesIn[i])) & 0x80000000) >> 31;
pSamplesOutS16[i] = (mal_int16)(sampleIn * (32767 + sign)); pSamplesOutS16[i] = (mal_int16)(sampleIn * (0x7FFF + sign));
} }
} break;
case mal_format_s32:
{
mal_int32* pSamplesOutS32 = (mal_int32*)pSamplesOut;
for (mal_uint32 i = 0; i < sampleCount; ++i) {
float sampleIn = mal_clip_f32(pSamplesIn[i]);
mal_uint32 sign = ((*((mal_uint32*)&pSamplesIn[i])) & 0x80000000) >> 31;
pSamplesOutS32[i] = (mal_int32)(sampleIn * (0x7FFFFFFF + sign));
}
} break; } break;
default: break; default: break;
...@@ -3900,7 +3919,7 @@ static void mal_buffer_queue_callback__opensl_android(SLAndroidSimpleBufferQueue ...@@ -3900,7 +3919,7 @@ static void mal_buffer_queue_callback__opensl_android(SLAndroidSimpleBufferQueue
return; return;
} }
size_t periodSizeInBytes = pDevice->opensl.periodSizeInFrames * pDevice->channels * mal_get_sample_size_in_bytes(pDevice->format); size_t periodSizeInBytes = pDevice->opensl.periodSizeInFrames * pDevice->internalChannels * mal_get_sample_size_in_bytes(pDevice->internalFormat);
mal_uint8* pBuffer = pDevice->opensl.pBuffer + (pDevice->opensl.currentBufferIndex * periodSizeInBytes); mal_uint8* pBuffer = pDevice->opensl.pBuffer + (pDevice->opensl.currentBufferIndex * periodSizeInBytes);
if (pDevice->type == mal_device_type_playback) { if (pDevice->type == mal_device_type_playback) {
...@@ -3961,10 +3980,9 @@ static mal_result mal_device_init__opensl(mal_context* pContext, mal_device_type ...@@ -3961,10 +3980,9 @@ static mal_result mal_device_init__opensl(mal_context* pContext, mal_device_type
return MAL_NO_BACKEND; return MAL_NO_BACKEND;
#endif #endif
// Currently only supporting simple PCM formats. 32-bit floating point is not currently supported, // Use s32 as the internal format for when floating point is specified.
// but may be emulated later on.
if (pConfig->format == mal_format_f32) { if (pConfig->format == mal_format_f32) {
return MAL_FORMAT_NOT_SUPPORTED; pDevice->internalFormat = mal_format_s32;
} }
// Initialize global data first if applicable. // Initialize global data first if applicable.
...@@ -4000,11 +4018,11 @@ static mal_result mal_device_init__opensl(mal_context* pContext, mal_device_type ...@@ -4000,11 +4018,11 @@ static mal_result mal_device_init__opensl(mal_context* pContext, mal_device_type
SLDataFormat_PCM pcm; SLDataFormat_PCM pcm;
pcm.formatType = SL_DATAFORMAT_PCM; pcm.formatType = SL_DATAFORMAT_PCM;
pcm.numChannels = pConfig->channels; pcm.numChannels = pDevice->internalChannels;
pcm.samplesPerSec = pConfig->sampleRate * 1000; // In millihertz because, you know, the people who wrote the OpenSL|ES spec thought it would be funny to be the _only_ API to do this... pcm.samplesPerSec = pDevice->internalSampleRate * 1000; // In millihertz because, you know, the people who wrote the OpenSL|ES spec thought it would be funny to be the _only_ API to do this...
pcm.bitsPerSample = mal_get_sample_size_in_bytes(pConfig->format) * 8; pcm.bitsPerSample = mal_get_sample_size_in_bytes(pDevice->internalFormat)*8;
pcm.containerSize = pcm.bitsPerSample; // Always tightly packed for now. pcm.containerSize = pcm.bitsPerSample; // Always tightly packed for now.
pcm.channelMask = ~((~0UL) << pConfig->channels); pcm.channelMask = ~((~0UL) << pDevice->internalChannels);
pcm.endianness = SL_BYTEORDER_LITTLEENDIAN; pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
if (type == mal_device_type_playback) { if (type == mal_device_type_playback) {
...@@ -4109,7 +4127,7 @@ static mal_result mal_device_init__opensl(mal_context* pContext, mal_device_type ...@@ -4109,7 +4127,7 @@ static mal_result mal_device_init__opensl(mal_context* pContext, mal_device_type
} }
} }
size_t bufferSizeInBytes = pDevice->bufferSizeInFrames * pDevice->channels * mal_get_sample_size_in_bytes(pDevice->format); size_t bufferSizeInBytes = pDevice->bufferSizeInFrames * pDevice->internalChannels * mal_get_sample_size_in_bytes(pDevice->internalFormat);
pDevice->opensl.pBuffer = (mal_uint8*)mal_malloc(bufferSizeInBytes); pDevice->opensl.pBuffer = (mal_uint8*)mal_malloc(bufferSizeInBytes);
if (pDevice->opensl.pBuffer == NULL) { if (pDevice->opensl.pBuffer == NULL) {
mal_device_uninit__opensl(pDevice); mal_device_uninit__opensl(pDevice);
...@@ -4134,7 +4152,7 @@ static mal_result mal_device__start_backend__opensl(mal_device* pDevice) ...@@ -4134,7 +4152,7 @@ static mal_result mal_device__start_backend__opensl(mal_device* pDevice)
// We need to enqueue a buffer for each period. // We need to enqueue a buffer for each period.
mal_device__read_frames_from_client(pDevice, pDevice->bufferSizeInFrames, pDevice->opensl.pBuffer); mal_device__read_frames_from_client(pDevice, pDevice->bufferSizeInFrames, pDevice->opensl.pBuffer);
size_t periodSizeInBytes = pDevice->opensl.periodSizeInFrames * pDevice->channels * mal_get_sample_size_in_bytes(pDevice->format); size_t periodSizeInBytes = pDevice->opensl.periodSizeInFrames * pDevice->internalChannels * mal_get_sample_size_in_bytes(pDevice->internalFormat);
for (mal_uint32 iPeriod = 0; iPeriod < pDevice->periods; ++iPeriod) { for (mal_uint32 iPeriod = 0; iPeriod < pDevice->periods; ++iPeriod) {
resultSL = MAL_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueue)->Enqueue((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueue, pDevice->opensl.pBuffer + (periodSizeInBytes * iPeriod), periodSizeInBytes); resultSL = MAL_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueue)->Enqueue((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueue, pDevice->opensl.pBuffer + (periodSizeInBytes * iPeriod), periodSizeInBytes);
if (resultSL != SL_RESULT_SUCCESS) { if (resultSL != SL_RESULT_SUCCESS) {
...@@ -4148,7 +4166,7 @@ static mal_result mal_device__start_backend__opensl(mal_device* pDevice) ...@@ -4148,7 +4166,7 @@ static mal_result mal_device__start_backend__opensl(mal_device* pDevice)
return MAL_FAILED_TO_START_BACKEND_DEVICE; return MAL_FAILED_TO_START_BACKEND_DEVICE;
} }
size_t periodSizeInBytes = pDevice->opensl.periodSizeInFrames * pDevice->channels * mal_get_sample_size_in_bytes(pDevice->format); size_t periodSizeInBytes = pDevice->opensl.periodSizeInFrames * pDevice->internalChannels * mal_get_sample_size_in_bytes(pDevice->internalFormat);
for (mal_uint32 iPeriod = 0; iPeriod < pDevice->periods; ++iPeriod) { for (mal_uint32 iPeriod = 0; iPeriod < pDevice->periods; ++iPeriod) {
resultSL = MAL_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueue)->Enqueue((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueue, pDevice->opensl.pBuffer + (periodSizeInBytes * iPeriod), periodSizeInBytes); resultSL = MAL_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueue)->Enqueue((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueue, pDevice->opensl.pBuffer + (periodSizeInBytes * iPeriod), periodSizeInBytes);
if (resultSL != SL_RESULT_SUCCESS) { if (resultSL != SL_RESULT_SUCCESS) {
...@@ -5563,6 +5581,7 @@ mal_uint32 mal_get_sample_size_in_bytes(mal_format format) ...@@ -5563,6 +5581,7 @@ mal_uint32 mal_get_sample_size_in_bytes(mal_format format)
// to test and maintain, and just generally unreliable. // to test and maintain, and just generally unreliable.
// - Null Backend: Fixed a crash when recording. // - Null Backend: Fixed a crash when recording.
// - Fixed build for UWP. // - Fixed build for UWP.
// - Added support for f32 formats to the OpenSL|ES backend.
// - Added initial implementation of the WASAPI backend. // - Added initial implementation of the WASAPI backend.
// - Added initial implementation of the OpenAL backend. // - Added initial implementation of the OpenAL backend.
// //
...@@ -5609,8 +5628,6 @@ mal_uint32 mal_get_sample_size_in_bytes(mal_format format) ...@@ -5609,8 +5628,6 @@ mal_uint32 mal_get_sample_size_in_bytes(mal_format format)
// OpenSL|ES / Android // OpenSL|ES / Android
// ------------------- // -------------------
// - Test! // - Test!
// - Add software f32 conversion
// - 32-bit floating point is only supported from Android API Level 21.
/* /*
......
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