1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 #if !defined(AudioLayout_h) 7 # define AudioLayout_h 8 9 # include <cstdint> 10 # include <initializer_list> 11 # include "mozilla/MathAlgorithms.h" 12 # include "nsTArray.h" 13 14 namespace mozilla { 15 16 class AudioConfig { 17 public: 18 // Channel definition is conveniently defined to be in the same order as 19 // WAVEFORMAT && SMPTE, even though this is unused for now. 20 enum Channel { 21 CHANNEL_INVALID = -1, 22 CHANNEL_FRONT_LEFT = 0, 23 CHANNEL_FRONT_RIGHT, 24 CHANNEL_FRONT_CENTER, 25 CHANNEL_LFE, 26 CHANNEL_BACK_LEFT, 27 CHANNEL_BACK_RIGHT, 28 CHANNEL_FRONT_LEFT_OF_CENTER, 29 CHANNEL_FRONT_RIGHT_OF_CENTER, 30 CHANNEL_BACK_CENTER, 31 CHANNEL_SIDE_LEFT, 32 CHANNEL_SIDE_RIGHT, 33 // From WAVEFORMAT definition. 34 CHANNEL_TOP_CENTER, 35 CHANNEL_TOP_FRONT_LEFT, 36 CHANNEL_TOP_FRONT_CENTER, 37 CHANNEL_TOP_FRONT_RIGHT, 38 CHANNEL_TOP_BACK_LEFT, 39 CHANNEL_TOP_BACK_CENTER, 40 CHANNEL_TOP_BACK_RIGHT 41 }; 42 43 class ChannelLayout { 44 public: 45 // The maximum number of channels a channel map can represent. 46 static constexpr uint32_t MAX_CHANNELS = 32; 47 48 typedef uint32_t ChannelMap; 49 ChannelLayout()50 ChannelLayout() : mChannelMap(UNKNOWN_MAP), mValid(false) {} ChannelLayout(uint32_t aChannels)51 explicit ChannelLayout(uint32_t aChannels) 52 : ChannelLayout(aChannels, DefaultLayoutForChannels(aChannels)) {} ChannelLayout(uint32_t aChannels,const Channel * aConfig)53 ChannelLayout(uint32_t aChannels, const Channel* aConfig) 54 : ChannelLayout() { 55 if (aChannels == 0 || !aConfig) { 56 return; 57 } 58 mChannels.AppendElements(aConfig, aChannels); 59 UpdateChannelMap(); 60 } ChannelLayout(std::initializer_list<Channel> aChannelList)61 explicit ChannelLayout(std::initializer_list<Channel> aChannelList) 62 : ChannelLayout(aChannelList.size(), aChannelList.begin()) {} 63 bool operator==(const ChannelLayout& aOther) const { 64 return mChannels == aOther.mChannels; 65 } 66 bool operator!=(const ChannelLayout& aOther) const { 67 return mChannels != aOther.mChannels; 68 } 69 const Channel& operator[](uint32_t aIndex) const { 70 MOZ_ASSERT(mChannels.Length() > aIndex); 71 return mChannels[aIndex]; 72 } Count()73 uint32_t Count() const { return mChannels.Length(); } 74 ChannelMap Map() const; 75 76 // Calculate the mapping table from the current layout to aOther such that 77 // one can easily go from one layout to the other by doing: 78 // out[channel] = in[map[channel]]. 79 // Returns true if the reordering is possible or false otherwise. 80 // If true, then aMap, if set, will be updated to contain the mapping table 81 // allowing conversion from the current layout to aOther. 82 // If aMap is empty, then MappingTable can be used to simply determine if 83 // the current layout can be easily reordered to aOther. 84 bool MappingTable(const ChannelLayout& aOther, 85 nsTArray<uint8_t>* aMap = nullptr) const; IsValid()86 bool IsValid() const { return mValid; } HasChannel(Channel aChannel)87 bool HasChannel(Channel aChannel) const { 88 return mChannelMap & (1 << aChannel); 89 } 90 // Return the number of channels found in this ChannelMap. Channels(ChannelMap aMap)91 static uint32_t Channels(ChannelMap aMap) { 92 static_assert(sizeof(ChannelMap) == sizeof(uint32_t), 93 "Must adjust ChannelMap type"); 94 return CountPopulation32(aMap); 95 } 96 97 static ChannelLayout SMPTEDefault(const ChannelLayout& aChannelLayout); 98 static ChannelLayout SMPTEDefault(ChannelMap aMap); 99 100 static constexpr ChannelMap UNKNOWN_MAP = 0; 101 102 // Common channel layout definitions. 103 static constexpr ChannelMap LMONO_MAP = 1 << CHANNEL_FRONT_CENTER; 104 static constexpr ChannelMap LMONO_LFE_MAP = 105 1 << CHANNEL_FRONT_CENTER | 1 << CHANNEL_LFE; 106 static constexpr ChannelMap LSTEREO_MAP = 107 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT; 108 static constexpr ChannelMap LSTEREO_LFE_MAP = 109 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT | 1 << CHANNEL_LFE; 110 static constexpr ChannelMap L3F_MAP = 1 << CHANNEL_FRONT_LEFT | 111 1 << CHANNEL_FRONT_RIGHT | 112 1 << CHANNEL_FRONT_CENTER; 113 static constexpr ChannelMap L3F_LFE_MAP = 114 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT | 115 1 << CHANNEL_FRONT_CENTER | 1 << CHANNEL_LFE; 116 static constexpr ChannelMap L2F1_MAP = 1 << CHANNEL_FRONT_LEFT | 117 1 << CHANNEL_FRONT_RIGHT | 118 1 << CHANNEL_BACK_CENTER; 119 static constexpr ChannelMap L2F1_LFE_MAP = 120 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT | 1 << CHANNEL_LFE | 121 1 << CHANNEL_BACK_CENTER; 122 static constexpr ChannelMap L3F1_MAP = 123 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT | 124 1 << CHANNEL_FRONT_CENTER | 1 << CHANNEL_BACK_CENTER; 125 static constexpr ChannelMap LSURROUND_MAP = L3F1_MAP; 126 static constexpr ChannelMap L3F1_LFE_MAP = 127 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT | 128 1 << CHANNEL_FRONT_CENTER | 1 << CHANNEL_LFE | 1 << CHANNEL_BACK_CENTER; 129 static constexpr ChannelMap L2F2_MAP = 130 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT | 131 1 << CHANNEL_SIDE_LEFT | 1 << CHANNEL_SIDE_RIGHT; 132 static constexpr ChannelMap L2F2_LFE_MAP = 133 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT | 1 << CHANNEL_LFE | 134 1 << CHANNEL_SIDE_LEFT | 1 << CHANNEL_SIDE_RIGHT; 135 static constexpr ChannelMap LQUAD_MAP = 136 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT | 137 1 << CHANNEL_BACK_LEFT | 1 << CHANNEL_BACK_RIGHT; 138 static constexpr ChannelMap LQUAD_LFE_MAP = 139 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT | 1 << CHANNEL_LFE | 140 1 << CHANNEL_BACK_LEFT | 1 << CHANNEL_BACK_RIGHT; 141 static constexpr ChannelMap L3F2_MAP = 142 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT | 143 1 << CHANNEL_FRONT_CENTER | 1 << CHANNEL_SIDE_LEFT | 144 1 << CHANNEL_SIDE_RIGHT; 145 static constexpr ChannelMap L3F2_LFE_MAP = 146 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT | 147 1 << CHANNEL_FRONT_CENTER | 1 << CHANNEL_LFE | 1 << CHANNEL_SIDE_LEFT | 148 1 << CHANNEL_SIDE_RIGHT; 149 // 3F2_LFE Alias 150 static constexpr ChannelMap L5POINT1_SURROUND_MAP = L3F2_LFE_MAP; 151 static constexpr ChannelMap L3F2_BACK_MAP = 152 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT | 153 1 << CHANNEL_FRONT_CENTER | 1 << CHANNEL_BACK_LEFT | 154 1 << CHANNEL_BACK_RIGHT; 155 static constexpr ChannelMap L3F2_BACK_LFE_MAP = 156 L3F2_BACK_MAP | 1 << CHANNEL_LFE; 157 static constexpr ChannelMap L3F3R_LFE_MAP = 158 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT | 159 1 << CHANNEL_FRONT_CENTER | 1 << CHANNEL_LFE | 160 1 << CHANNEL_BACK_CENTER | 1 << CHANNEL_SIDE_LEFT | 161 1 << CHANNEL_SIDE_RIGHT; 162 static ChannelLayout L3F4_LFE; 163 static constexpr ChannelMap L3F4_LFE_MAP = 164 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT | 165 1 << CHANNEL_FRONT_CENTER | 1 << CHANNEL_LFE | 1 << CHANNEL_BACK_LEFT | 166 1 << CHANNEL_BACK_RIGHT | 1 << CHANNEL_SIDE_LEFT | 167 1 << CHANNEL_SIDE_RIGHT; 168 // 3F4_LFE Alias 169 static ChannelLayout L7POINT1_SURROUND; 170 static constexpr ChannelMap L7POINT1_SURROUND_MAP = L3F4_LFE_MAP; 171 172 private: 173 void UpdateChannelMap(); 174 const Channel* DefaultLayoutForChannels(uint32_t aChannels) const; 175 CopyableAutoTArray<Channel, MAX_CHANNELS> mChannels; 176 ChannelMap mChannelMap; 177 bool mValid; 178 }; 179 180 enum SampleFormat { 181 FORMAT_NONE = 0, 182 FORMAT_U8, 183 FORMAT_S16, 184 FORMAT_S24LSB, 185 FORMAT_S24, 186 FORMAT_S32, 187 FORMAT_FLT, 188 # if defined(MOZ_SAMPLE_TYPE_FLOAT32) 189 FORMAT_DEFAULT = FORMAT_FLT 190 # elif defined(MOZ_SAMPLE_TYPE_S16) 191 FORMAT_DEFAULT = FORMAT_S16 192 # else 193 # error "Not supported audio type" 194 # endif 195 }; 196 197 AudioConfig(const ChannelLayout& aChannelLayout, uint32_t aRate, 198 AudioConfig::SampleFormat aFormat = FORMAT_DEFAULT, 199 bool aInterleaved = true); 200 AudioConfig(const ChannelLayout& aChannelLayout, uint32_t aChannels, 201 uint32_t aRate, 202 AudioConfig::SampleFormat aFormat = FORMAT_DEFAULT, 203 bool aInterleaved = true); 204 // Will create a channel configuration from default SMPTE ordering. 205 AudioConfig(uint32_t aChannels, uint32_t aRate, 206 AudioConfig::SampleFormat aFormat = FORMAT_DEFAULT, 207 bool aInterleaved = true); 208 Layout()209 const ChannelLayout& Layout() const { return mChannelLayout; } Channels()210 uint32_t Channels() const { 211 if (!mChannelLayout.IsValid()) { 212 return mChannels; 213 } 214 return mChannelLayout.Count(); 215 } Rate()216 uint32_t Rate() const { return mRate; } Format()217 SampleFormat Format() const { return mFormat; } Interleaved()218 bool Interleaved() const { return mInterleaved; } 219 bool operator==(const AudioConfig& aOther) const { 220 return mChannelLayout == aOther.mChannelLayout && mRate == aOther.mRate && 221 mFormat == aOther.mFormat && mInterleaved == aOther.mInterleaved; 222 } 223 bool operator!=(const AudioConfig& aOther) const { 224 return !(*this == aOther); 225 } 226 IsValid()227 bool IsValid() const { 228 return mChannelLayout.IsValid() && Format() != FORMAT_NONE && Rate() > 0; 229 } 230 231 static const char* FormatToString(SampleFormat aFormat); 232 static uint32_t SampleSize(SampleFormat aFormat); 233 static uint32_t FormatToBits(SampleFormat aFormat); 234 235 private: 236 // Channels configuration. 237 ChannelLayout mChannelLayout; 238 239 // Channel count. 240 uint32_t mChannels; 241 242 // Sample rate. 243 uint32_t mRate; 244 245 // Sample format. 246 SampleFormat mFormat; 247 248 bool mInterleaved; 249 }; 250 251 } // namespace mozilla 252 253 #endif // AudioLayout_h 254