2 * Copyright (C) 2011-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
21 #include "CoreAudioChannelLayout.h"
23 #include <AudioToolbox/AudioToolbox.h>
25 #define MAX_CHANNEL_LABEL 15
27 const char* g_ChannelLabels[] =
29 "Unused", // kAudioChannelLabel_Unused
30 "Left", // kAudioChannelLabel_Left
31 "Right", // kAudioChannelLabel_Right
32 "Center", // kAudioChannelLabel_Center
33 "LFE", // kAudioChannelLabel_LFEScreen
34 "Side Left", // kAudioChannelLabel_LeftSurround
35 "Side Right", // kAudioChannelLabel_RightSurround
36 "Left Center", // kAudioChannelLabel_LeftCenter
37 "Right Center", // kAudioChannelLabel_RightCenter
38 "Back Center", // kAudioChannelLabel_CenterSurround
39 "Back Left", // kAudioChannelLabel_LeftSurroundDirect
40 "Back Right", // kAudioChannelLabel_RightSurroundDirect
41 "Top Center", // kAudioChannelLabel_TopCenterSurround
42 "Top Back Left", // kAudioChannelLabel_VerticalHeightLeft
43 "Top Back Center", // kAudioChannelLabel_VerticalHeightCenter
44 "Top Back Right", // kAudioChannelLabel_VerticalHeightRight
47 CCoreAudioChannelLayout::CCoreAudioChannelLayout() :
52 CCoreAudioChannelLayout::CCoreAudioChannelLayout(AudioChannelLayout& layout) :
58 CCoreAudioChannelLayout::~CCoreAudioChannelLayout()
63 bool CCoreAudioChannelLayout::CopyLayout(AudioChannelLayout& layout)
66 kVariableLengthArray_deprecated = 1
72 // This method always produces a layout with a ChannelDescriptions structure
75 UInt32 channels = GetChannelCountForLayout(layout);
76 UInt32 size = sizeof(AudioChannelLayout) + (channels - kVariableLengthArray_deprecated) * sizeof(AudioChannelDescription);
78 if (layout.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions)
80 // We can copy the whole layout
81 m_pLayout = (AudioChannelLayout*)malloc(size);
82 memcpy(m_pLayout, &layout, size);
84 else if (layout.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap)
86 // Deconstruct the bitmap to get the layout
88 AudioFormatGetPropertyInfo(kAudioFormatProperty_ChannelLayoutForBitmap, sizeof(layout.mChannelBitmap), &layout.mChannelBitmap, &propSize);
89 m_pLayout = (AudioChannelLayout*)malloc(propSize);
90 ret = AudioFormatGetProperty(kAudioFormatProperty_ChannelLayoutForBitmap, sizeof(layout.mChannelBitmap), &layout.mChannelBitmap, &propSize, m_pLayout);
91 m_pLayout->mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions;
95 // Convert the known layout to a custom layout
97 AudioFormatGetPropertyInfo(kAudioFormatProperty_ChannelLayoutForTag,
98 sizeof(layout.mChannelLayoutTag), &layout.mChannelLayoutTag, &propSize);
99 m_pLayout = (AudioChannelLayout*)malloc(propSize);
100 ret = AudioFormatGetProperty(kAudioFormatProperty_ChannelLayoutForTag,
101 sizeof(layout.mChannelLayoutTag), &layout.mChannelLayoutTag, &propSize, m_pLayout);
102 m_pLayout->mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions;
105 return (ret == noErr);
108 UInt32 CCoreAudioChannelLayout::GetChannelCountForLayout(AudioChannelLayout& layout)
111 if (layout.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap)
113 // Channels are in fixed-order('USB Order'), any combination
114 UInt32 bitmap = layout.mChannelBitmap;
115 for (UInt32 c = 0; c < (sizeof(layout.mChannelBitmap) << 3); c++)
122 else if (layout.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions)
124 // Channels are in any order, any combination
125 channels = layout.mNumberChannelDescriptions;
129 // Channels are in a predefined order and combination
130 channels = AudioChannelLayoutTag_GetNumberOfChannels(layout.mChannelLayoutTag);
136 const char* CCoreAudioChannelLayout::ChannelLabelToString(UInt32 label)
138 if (label > MAX_CHANNEL_LABEL)
140 return g_ChannelLabels[label];
143 const char* CCoreAudioChannelLayout::ChannelLayoutToString(AudioChannelLayout& layout, std::string& str)
145 AudioChannelLayout* pLayout = NULL;
147 if (layout.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions)
151 else if (layout.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap)
153 // Deconstruct the bitmap to get the layout
155 AudioFormatGetPropertyInfo(kAudioFormatProperty_ChannelLayoutForBitmap,
156 sizeof(layout.mChannelBitmap), &layout.mChannelBitmap, &propSize);
157 pLayout = (AudioChannelLayout*)calloc(propSize, 1);
158 AudioFormatGetProperty(kAudioFormatProperty_ChannelLayoutForBitmap,
159 sizeof(layout.mChannelBitmap), &layout.mChannelBitmap, &propSize, pLayout);
163 // Predefinied layout 'tag'
165 AudioFormatGetPropertyInfo(kAudioFormatProperty_ChannelLayoutForTag,
166 sizeof(layout.mChannelLayoutTag), &layout.mChannelLayoutTag, &propSize);
167 pLayout = (AudioChannelLayout*)calloc(propSize, 1);
168 AudioFormatGetProperty(kAudioFormatProperty_ChannelLayoutForTag,
169 sizeof(layout.mChannelLayoutTag), &layout.mChannelLayoutTag, &propSize, pLayout);
172 for (UInt32 c = 0; c < pLayout->mNumberChannelDescriptions; c++)
175 str += ChannelLabelToString(pLayout->mChannelDescriptions[c].mChannelLabel);
179 if (layout.mChannelLayoutTag != kAudioChannelLayoutTag_UseChannelDescriptions)
185 bool CCoreAudioChannelLayout::AllChannelUnknown()
187 AudioChannelLayout* pLayout = NULL;
192 if (m_pLayout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions)
196 else if (m_pLayout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap)
198 // Deconstruct the bitmap to get the layout
200 AudioFormatGetPropertyInfo(kAudioFormatProperty_ChannelLayoutForBitmap,
201 sizeof(m_pLayout->mChannelBitmap), &m_pLayout->mChannelBitmap, &propSize);
202 pLayout = (AudioChannelLayout*)calloc(propSize, 1);
203 AudioFormatGetProperty(kAudioFormatProperty_ChannelLayoutForBitmap,
204 sizeof(m_pLayout->mChannelBitmap), &m_pLayout->mChannelBitmap, &propSize, pLayout);
208 // Predefinied layout 'tag'
210 AudioFormatGetPropertyInfo(kAudioFormatProperty_ChannelLayoutForTag,
211 sizeof(m_pLayout->mChannelLayoutTag), &m_pLayout->mChannelLayoutTag, &propSize);
212 pLayout = (AudioChannelLayout*)calloc(propSize, 1);
213 AudioFormatGetProperty(kAudioFormatProperty_ChannelLayoutForTag,
214 sizeof(m_pLayout->mChannelLayoutTag), &m_pLayout->mChannelLayoutTag, &propSize, pLayout);
217 for (UInt32 c = 0; c < pLayout->mNumberChannelDescriptions; c++)
219 if (pLayout->mChannelDescriptions[c].mChannelLabel != kAudioChannelLabel_Unknown)
225 if (m_pLayout->mChannelLayoutTag != kAudioChannelLayoutTag_UseChannelDescriptions)