Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
M
miniaudio
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
MyCard
miniaudio
Commits
c3fcb643
Commit
c3fcb643
authored
Nov 29, 2018
by
David Reid
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Core Audio: Fix some issues with channel maps.
parent
20820048
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
128 additions
and
106 deletions
+128
-106
mini_al.h
mini_al.h
+128
-106
No files found.
mini_al.h
View file @
c3fcb643
...
...
@@ -13939,6 +13939,80 @@ mal_result mal_format_from_AudioStreamBasicDescription(const AudioStreamBasicDes
return MAL_FORMAT_NOT_SUPPORTED;
}
mal_result mal_get_channel_map_from_AudioChannelLayout(AudioChannelLayout* pChannelLayout, mal_channel channelMap[MAL_MAX_CHANNELS])
{
mal_assert(pChannelLayout != NULL);
if (pChannelLayout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions) {
for (UInt32 iChannel = 0; iChannel < pChannelLayout->mNumberChannelDescriptions; ++iChannel) {
channelMap[iChannel] = mal_channel_from_AudioChannelLabel(pChannelLayout->mChannelDescriptions[iChannel].mChannelLabel);
}
} else
#if 0
if (pChannelLayout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap) {
// This is the same kind of system that's used by Windows audio APIs.
UInt32 iChannel = 0;
AudioChannelBitmap bitmap = pChannelLayout->mChannelBitmap;
for (UInt32 iBit = 0; iBit < 32; ++iBit) {
AudioChannelBitmap bit = bitmap & (1 << iBit);
if (bit != 0) {
channelMap[iChannel++] = mal_channel_from_AudioChannelBit(bit);
}
}
} else
#endif
{
// Need to use the tag to determine the channel map. For now I'm just assuming a default channel map, but later on this should
// be updated to determine the mapping based on the tag.
UInt32 channelCount = AudioChannelLayoutTag_GetNumberOfChannels(pChannelLayout->mChannelLayoutTag);
switch (pChannelLayout->mChannelLayoutTag)
{
case kAudioChannelLayoutTag_Mono:
case kAudioChannelLayoutTag_Stereo:
case kAudioChannelLayoutTag_StereoHeadphones:
case kAudioChannelLayoutTag_MatrixStereo:
case kAudioChannelLayoutTag_MidSide:
case kAudioChannelLayoutTag_XY:
case kAudioChannelLayoutTag_Binaural:
case kAudioChannelLayoutTag_Ambisonic_B_Format:
{
mal_get_standard_channel_map(mal_standard_channel_map_default, channelCount, channelMap);
} break;
case kAudioChannelLayoutTag_Octagonal:
{
channelMap[7] = MAL_CHANNEL_SIDE_RIGHT;
channelMap[6] = MAL_CHANNEL_SIDE_LEFT;
} // Intentional fallthrough.
case kAudioChannelLayoutTag_Hexagonal:
{
channelMap[5] = MAL_CHANNEL_BACK_CENTER;
} // Intentional fallthrough.
case kAudioChannelLayoutTag_Pentagonal:
{
channelMap[4] = MAL_CHANNEL_FRONT_CENTER;
} // Intentional fallghrough.
case kAudioChannelLayoutTag_Quadraphonic:
{
channelMap[3] = MAL_CHANNEL_BACK_RIGHT;
channelMap[2] = MAL_CHANNEL_BACK_LEFT;
channelMap[1] = MAL_CHANNEL_RIGHT;
channelMap[0] = MAL_CHANNEL_LEFT;
} break;
// TODO: Add support for more tags here.
default:
{
mal_get_standard_channel_map(mal_standard_channel_map_default, channelCount, channelMap);
} break;
}
}
return MAL_SUCCESS;
}
#if defined(MAL_APPLE_DESKTOP)
mal_result mal_get_device_object_ids__coreaudio(mal_context* pContext, UInt32* pDeviceCount, AudioObjectID** ppDeviceObjectIDs) // NOTE: Free the returned buffer with mal_free().
{
...
...
@@ -14178,79 +14252,6 @@ mal_result mal_get_AudioObject_channel_count(mal_context* pContext, AudioObjectI
return MAL_SUCCESS;
}
mal_result mal_get_channel_map_from_AudioChannelLayout(AudioChannelLayout* pChannelLayout, mal_channel channelMap[MAL_MAX_CHANNELS])
{
mal_assert(pChannelLayout != NULL);
if (pChannelLayout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions) {
for (UInt32 iChannel = 0; iChannel < pChannelLayout->mNumberChannelDescriptions; ++iChannel) {
channelMap[iChannel] = mal_channel_from_AudioChannelLabel(pChannelLayout->mChannelDescriptions[iChannel].mChannelLabel);
}
} else
#if 0
if (pChannelLayout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap) {
// This is the same kind of system that's used by Windows audio APIs.
UInt32 iChannel = 0;
AudioChannelBitmap bitmap = pChannelLayout->mChannelBitmap;
for (UInt32 iBit = 0; iBit < 32; ++iBit) {
AudioChannelBitmap bit = bitmap & (1 << iBit);
if (bit != 0) {
channelMap[iChannel++] = mal_channel_from_AudioChannelBit(bit);
}
}
} else
#endif
{
// Need to use the tag to determine the channel map. For now I'm just assuming a default channel map, but later on this should
// be updated to determine the mapping based on the tag.
UInt32 channelCount = AudioChannelLayoutTag_GetNumberOfChannels(pChannelLayout->mChannelLayoutTag);
switch (pChannelLayout->mChannelLayoutTag)
{
case kAudioChannelLayoutTag_Mono:
case kAudioChannelLayoutTag_Stereo:
case kAudioChannelLayoutTag_StereoHeadphones:
case kAudioChannelLayoutTag_MatrixStereo:
case kAudioChannelLayoutTag_MidSide:
case kAudioChannelLayoutTag_XY:
case kAudioChannelLayoutTag_Binaural:
case kAudioChannelLayoutTag_Ambisonic_B_Format:
{
mal_get_standard_channel_map(mal_standard_channel_map_default, channelCount, channelMap);
} break;
case kAudioChannelLayoutTag_Octagonal:
{
channelMap[7] = MAL_CHANNEL_SIDE_RIGHT;
channelMap[6] = MAL_CHANNEL_SIDE_LEFT;
} // Intentional fallthrough.
case kAudioChannelLayoutTag_Hexagonal:
{
channelMap[5] = MAL_CHANNEL_BACK_CENTER;
} // Intentional fallthrough.
case kAudioChannelLayoutTag_Pentagonal:
{
channelMap[4] = MAL_CHANNEL_FRONT_CENTER;
} // Intentional fallghrough.
case kAudioChannelLayoutTag_Quadraphonic:
{
channelMap[3] = MAL_CHANNEL_BACK_RIGHT;
channelMap[2] = MAL_CHANNEL_BACK_LEFT;
channelMap[1] = MAL_CHANNEL_RIGHT;
channelMap[0] = MAL_CHANNEL_LEFT;
} break;
// TODO: Add support for more tags here.
default:
{
mal_get_standard_channel_map(mal_standard_channel_map_default, channelCount, channelMap);
} break;
}
}
return MAL_SUCCESS;
}
mal_result mal_get_AudioObject_channel_map(mal_context* pContext, AudioObjectID deviceObjectID, mal_device_type deviceType, mal_channel channelMap[MAL_MAX_CHANNELS])
{
mal_assert(pContext != NULL);
...
...
@@ -14271,37 +14272,6 @@ mal_result mal_get_AudioObject_channel_map(mal_context* pContext, AudioObjectID
return result;
}
mal_result mal_get_AudioUnit_channel_map(mal_context* pContext, AudioUnit audioUnit, mal_device_type deviceType, mal_channel channelMap[MAL_MAX_CHANNELS])
{
mal_assert(pContext != NULL);
UInt32 channelLayoutSize;
OSStatus status = ((mal_AudioUnitGetPropertyInfo_proc)pContext->coreaudio.AudioUnitGetPropertyInfo)(audioUnit, kAudioUnitProperty_AudioChannelLayout, kAudioUnitScope_Output, MAL_COREAUDIO_OUTPUT_BUS, &channelLayoutSize, NULL);
if (status != noErr) {
return mal_result_from_OSStatus(status);
}
AudioChannelLayout* pChannelLayout = (AudioChannelLayout*)mal_malloc(channelLayoutSize);
if (pChannelLayout == NULL) {
return MAL_OUT_OF_MEMORY;
}
status = ((mal_AudioUnitGetProperty_proc)pContext->coreaudio.AudioUnitGetProperty)(audioUnit, kAudioUnitProperty_AudioChannelLayout, kAudioUnitScope_Output, MAL_COREAUDIO_OUTPUT_BUS, pChannelLayout, &channelLayoutSize);
if (status != noErr) {
mal_free(pChannelLayout);
return mal_result_from_OSStatus(status);
}
mal_result result = mal_get_channel_map_from_AudioChannelLayout(pChannelLayout, channelMap);
if (result != MAL_SUCCESS) {
mal_free(pChannelLayout);
return result;
}
mal_free(pChannelLayout);
return MAL_SUCCESS;
}
mal_result mal_get_AudioObject_sample_rates(mal_context* pContext, AudioObjectID deviceObjectID, mal_device_type deviceType, UInt32* pSampleRateRangesCount, AudioValueRange** ppSampleRateRanges) // NOTE: Free the returned pointer with mal_free().
{
mal_assert(pContext != NULL);
...
...
@@ -14716,7 +14686,46 @@ mal_result mal_find_best_format__coreaudio(mal_context* pContext, AudioObjectID
}
#endif
mal_result mal_get_AudioUnit_channel_map(mal_context* pContext, AudioUnit audioUnit, mal_device_type deviceType, mal_channel channelMap[MAL_MAX_CHANNELS])
{
mal_assert(pContext != NULL);
AudioUnitScope deviceScope;
AudioUnitElement deviceBus;
if (deviceType == mal_device_type_playback) {
deviceScope = kAudioUnitScope_Output;
deviceBus = MAL_COREAUDIO_OUTPUT_BUS;
} else {
deviceScope = kAudioUnitScope_Input;
deviceBus = MAL_COREAUDIO_INPUT_BUS;
}
UInt32 channelLayoutSize;
OSStatus status = ((mal_AudioUnitGetPropertyInfo_proc)pContext->coreaudio.AudioUnitGetPropertyInfo)(audioUnit, kAudioUnitProperty_AudioChannelLayout, deviceScope, deviceBus, &channelLayoutSize, NULL);
if (status != noErr) {
return mal_result_from_OSStatus(status);
}
AudioChannelLayout* pChannelLayout = (AudioChannelLayout*)mal_malloc(channelLayoutSize);
if (pChannelLayout == NULL) {
return MAL_OUT_OF_MEMORY;
}
status = ((mal_AudioUnitGetProperty_proc)pContext->coreaudio.AudioUnitGetProperty)(audioUnit, kAudioUnitProperty_AudioChannelLayout, deviceScope, deviceBus, pChannelLayout, &channelLayoutSize);
if (status != noErr) {
mal_free(pChannelLayout);
return mal_result_from_OSStatus(status);
}
mal_result result = mal_get_channel_map_from_AudioChannelLayout(pChannelLayout, channelMap);
if (result != MAL_SUCCESS) {
mal_free(pChannelLayout);
return result;
}
mal_free(pChannelLayout);
return MAL_SUCCESS;
}
mal_bool32 mal_context_is_device_id_equal__coreaudio(mal_context* pContext, const mal_device_id* pID0, const mal_device_id* pID1)
{
...
...
@@ -15425,12 +15434,25 @@ mal_result mal_device_init_internal__coreaudio(mal_context* pContext, mal_device
}
// Internal channel map.
// Internal channel map. This is weird in my testing. If I use the AudioObject to get the
// channel map, the channel descriptions are set to "Unknown" for some reason. To work around
// this it looks like retrieving it from the AudioUnit will work. However, and this is where
// it gets weird, it doesn't seem to work with capture devices, nor at all on iOS... Therefore
// I'm going to fall back to a default assumption in these cases.
#if defined(MAL_APPLE_DESKTOP)
result = mal_get_AudioUnit_channel_map(pContext, pData->audioUnit, deviceType, pData->channelMapOut);
if (result != MAL_SUCCESS) {
#if 0
// Try falling back to the channel map from the AudioObject.
result = mal_get_AudioObject_channel_map(pContext, deviceObjectID, deviceType, pData->channelMapOut);
if (result != MAL_SUCCESS) {
return result;
}
#else
// Fall back to default assumptions.
mal_get_standard_channel_map(mal_standard_channel_map_default, pData->channelsOut, pData->channelMapOut);
#endif
}
#else
// TODO: Figure out how to get the channel map using AVAudioSession.
mal_get_standard_channel_map(mal_standard_channel_map_default, pData->channelsOut, pData->channelMapOut);
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment