PageRenderTime 48ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioChannelLayout.cpp

http://github.com/xbmc/xbmc
C++ | 226 lines | 169 code | 27 blank | 30 comment | 33 complexity | f01d45e735f9a6a6cb7e9169301847a1 MD5 | raw file
Possible License(s): GPL-3.0, CC-BY-SA-3.0, LGPL-2.0, 0BSD, Unlicense, GPL-2.0, AGPL-1.0, BSD-3-Clause, LGPL-2.1, LGPL-3.0
  1. /*
  2. * Copyright (C) 2011-2013 Team XBMC
  3. * http://xbmc.org
  4. *
  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)
  8. * any later version.
  9. *
  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.
  14. *
  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/>.
  18. *
  19. */
  20. #include "CoreAudioChannelLayout.h"
  21. #include <AudioToolbox/AudioToolbox.h>
  22. #define MAX_CHANNEL_LABEL 15
  23. const char* g_ChannelLabels[] =
  24. {
  25. "Unused", // kAudioChannelLabel_Unused
  26. "Left", // kAudioChannelLabel_Left
  27. "Right", // kAudioChannelLabel_Right
  28. "Center", // kAudioChannelLabel_Center
  29. "LFE", // kAudioChannelLabel_LFEScreen
  30. "Side Left", // kAudioChannelLabel_LeftSurround
  31. "Side Right", // kAudioChannelLabel_RightSurround
  32. "Left Center", // kAudioChannelLabel_LeftCenter
  33. "Right Center", // kAudioChannelLabel_RightCenter
  34. "Back Center", // kAudioChannelLabel_CenterSurround
  35. "Back Left", // kAudioChannelLabel_LeftSurroundDirect
  36. "Back Right", // kAudioChannelLabel_RightSurroundDirect
  37. "Top Center", // kAudioChannelLabel_TopCenterSurround
  38. "Top Back Left", // kAudioChannelLabel_VerticalHeightLeft
  39. "Top Back Center", // kAudioChannelLabel_VerticalHeightCenter
  40. "Top Back Right", // kAudioChannelLabel_VerticalHeightRight
  41. };
  42. CCoreAudioChannelLayout::CCoreAudioChannelLayout() :
  43. m_pLayout(NULL)
  44. {
  45. }
  46. CCoreAudioChannelLayout::CCoreAudioChannelLayout(AudioChannelLayout& layout) :
  47. m_pLayout(NULL)
  48. {
  49. CopyLayout(layout);
  50. }
  51. CCoreAudioChannelLayout::~CCoreAudioChannelLayout()
  52. {
  53. free(m_pLayout);
  54. }
  55. bool CCoreAudioChannelLayout::CopyLayout(AudioChannelLayout& layout)
  56. {
  57. free(m_pLayout);
  58. m_pLayout = NULL;
  59. // This method always produces a layout with a ChannelDescriptions structure
  60. OSStatus ret = 0;
  61. UInt32 channels = GetChannelCountForLayout(layout);
  62. UInt32 size = sizeof(AudioChannelLayout) + (channels - kVariableLengthArray) * sizeof(AudioChannelDescription);
  63. if (layout.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions)
  64. {
  65. // We can copy the whole layout
  66. m_pLayout = (AudioChannelLayout*)malloc(size);
  67. memcpy(m_pLayout, &layout, size);
  68. }
  69. else if (layout.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap)
  70. {
  71. // Deconstruct the bitmap to get the layout
  72. UInt32 propSize = 0;
  73. AudioFormatGetPropertyInfo(kAudioFormatProperty_ChannelLayoutForBitmap, sizeof(layout.mChannelBitmap), &layout.mChannelBitmap, &propSize);
  74. m_pLayout = (AudioChannelLayout*)malloc(propSize);
  75. ret = AudioFormatGetProperty(kAudioFormatProperty_ChannelLayoutForBitmap, sizeof(layout.mChannelBitmap), &layout.mChannelBitmap, &propSize, m_pLayout);
  76. m_pLayout->mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions;
  77. }
  78. else
  79. {
  80. // Convert the known layout to a custom layout
  81. UInt32 propSize = 0;
  82. AudioFormatGetPropertyInfo(kAudioFormatProperty_ChannelLayoutForTag,
  83. sizeof(layout.mChannelLayoutTag), &layout.mChannelLayoutTag, &propSize);
  84. m_pLayout = (AudioChannelLayout*)malloc(propSize);
  85. ret = AudioFormatGetProperty(kAudioFormatProperty_ChannelLayoutForTag,
  86. sizeof(layout.mChannelLayoutTag), &layout.mChannelLayoutTag, &propSize, m_pLayout);
  87. m_pLayout->mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions;
  88. }
  89. return (ret == noErr);
  90. }
  91. UInt32 CCoreAudioChannelLayout::GetChannelCountForLayout(AudioChannelLayout& layout)
  92. {
  93. UInt32 channels = 0;
  94. if (layout.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap)
  95. {
  96. // Channels are in fixed-order('USB Order'), any combination
  97. UInt32 bitmap = layout.mChannelBitmap;
  98. for (UInt32 c = 0; c < (sizeof(layout.mChannelBitmap) << 3); c++)
  99. {
  100. if (bitmap & 0x1)
  101. channels++;
  102. bitmap >>= 1;
  103. }
  104. }
  105. else if (layout.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions)
  106. {
  107. // Channels are in any order, any combination
  108. channels = layout.mNumberChannelDescriptions;
  109. }
  110. else
  111. {
  112. // Channels are in a predefined order and combination
  113. channels = AudioChannelLayoutTag_GetNumberOfChannels(layout.mChannelLayoutTag);
  114. }
  115. return channels;
  116. }
  117. const char* CCoreAudioChannelLayout::ChannelLabelToString(UInt32 label)
  118. {
  119. if (label > MAX_CHANNEL_LABEL)
  120. return "Unknown";
  121. return g_ChannelLabels[label];
  122. }
  123. const char* CCoreAudioChannelLayout::ChannelLayoutToString(AudioChannelLayout& layout, std::string& str)
  124. {
  125. AudioChannelLayout* pLayout = NULL;
  126. if (layout.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions)
  127. {
  128. pLayout = &layout;
  129. }
  130. else if (layout.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap)
  131. {
  132. // Deconstruct the bitmap to get the layout
  133. UInt32 propSize = 0;
  134. AudioFormatGetPropertyInfo(kAudioFormatProperty_ChannelLayoutForBitmap,
  135. sizeof(layout.mChannelBitmap), &layout.mChannelBitmap, &propSize);
  136. pLayout = (AudioChannelLayout*)calloc(propSize, 1);
  137. AudioFormatGetProperty(kAudioFormatProperty_ChannelLayoutForBitmap,
  138. sizeof(layout.mChannelBitmap), &layout.mChannelBitmap, &propSize, pLayout);
  139. }
  140. else
  141. {
  142. // Predefinied layout 'tag'
  143. UInt32 propSize = 0;
  144. AudioFormatGetPropertyInfo(kAudioFormatProperty_ChannelLayoutForTag,
  145. sizeof(layout.mChannelLayoutTag), &layout.mChannelLayoutTag, &propSize);
  146. pLayout = (AudioChannelLayout*)calloc(propSize, 1);
  147. AudioFormatGetProperty(kAudioFormatProperty_ChannelLayoutForTag,
  148. sizeof(layout.mChannelLayoutTag), &layout.mChannelLayoutTag, &propSize, pLayout);
  149. }
  150. for (UInt32 c = 0; c < pLayout->mNumberChannelDescriptions; c++)
  151. {
  152. str += "[";
  153. str += ChannelLabelToString(pLayout->mChannelDescriptions[c].mChannelLabel);
  154. str += "] ";
  155. }
  156. if (layout.mChannelLayoutTag != kAudioChannelLayoutTag_UseChannelDescriptions)
  157. free(pLayout);
  158. return str.c_str();
  159. }
  160. bool CCoreAudioChannelLayout::AllChannelUnknown()
  161. {
  162. AudioChannelLayout* pLayout = NULL;
  163. if (!m_pLayout)
  164. return false;
  165. if (m_pLayout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions)
  166. {
  167. pLayout = m_pLayout;
  168. }
  169. else if (m_pLayout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap)
  170. {
  171. // Deconstruct the bitmap to get the layout
  172. UInt32 propSize = 0;
  173. AudioFormatGetPropertyInfo(kAudioFormatProperty_ChannelLayoutForBitmap,
  174. sizeof(m_pLayout->mChannelBitmap), &m_pLayout->mChannelBitmap, &propSize);
  175. pLayout = (AudioChannelLayout*)calloc(propSize, 1);
  176. AudioFormatGetProperty(kAudioFormatProperty_ChannelLayoutForBitmap,
  177. sizeof(m_pLayout->mChannelBitmap), &m_pLayout->mChannelBitmap, &propSize, pLayout);
  178. }
  179. else
  180. {
  181. // Predefinied layout 'tag'
  182. UInt32 propSize = 0;
  183. AudioFormatGetPropertyInfo(kAudioFormatProperty_ChannelLayoutForTag,
  184. sizeof(m_pLayout->mChannelLayoutTag), &m_pLayout->mChannelLayoutTag, &propSize);
  185. pLayout = (AudioChannelLayout*)calloc(propSize, 1);
  186. AudioFormatGetProperty(kAudioFormatProperty_ChannelLayoutForTag,
  187. sizeof(m_pLayout->mChannelLayoutTag), &m_pLayout->mChannelLayoutTag, &propSize, pLayout);
  188. }
  189. for (UInt32 c = 0; c < pLayout->mNumberChannelDescriptions; c++)
  190. {
  191. if (pLayout->mChannelDescriptions[c].mChannelLabel != kAudioChannelLabel_Unknown)
  192. {
  193. return false;
  194. }
  195. }
  196. if (m_pLayout->mChannelLayoutTag != kAudioChannelLayoutTag_UseChannelDescriptions)
  197. free(pLayout);
  198. return true;
  199. }