tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

AudioConfig.h (11118B)


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