tor-browser

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

AudioConfig.cpp (12386B)


      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 
      7 #include "AudioConfig.h"
      8 
      9 #include <array>
     10 
     11 #include "nsString.h"
     12 
     13 namespace mozilla {
     14 
     15 using ChannelLayout = AudioConfig::ChannelLayout;
     16 
     17 /**
     18 * AudioConfig::ChannelLayout
     19 */
     20 
     21 /*
     22 SMPTE channel layout (also known as wave order)
     23 DUAL-MONO      L   R
     24 DUAL-MONO-LFE  L   R   LFE
     25 MONO           M
     26 MONO-LFE       M   LFE
     27 STEREO         L   R
     28 STEREO-LFE     L   R   LFE
     29 3F             L   R   C
     30 3F-LFE         L   R   C    LFE
     31 2F1            L   R   S
     32 2F1-LFE        L   R   LFE  S
     33 3F1            L   R   C    S
     34 3F1-LFE        L   R   C    LFE S
     35 2F2            L   R   LS   RS
     36 2F2-LFE        L   R   LFE  LS   RS
     37 3F2            L   R   C    LS   RS
     38 3F2-LFE        L   R   C    LFE  LS   RS
     39 3F3R-LFE       L   R   C    LFE  BC   LS   RS
     40 3F4-LFE        L   R   C    LFE  Rls  Rrs  LS   RS
     41 */
     42 
     43 void AudioConfig::ChannelLayout::UpdateChannelMap() {
     44  mValid = mChannels.Length() <= MAX_CHANNELS;
     45  mChannelMap = UNKNOWN_MAP;
     46  if (mValid) {
     47    mChannelMap = Map();
     48    mValid = mChannelMap > 0;
     49  }
     50 }
     51 
     52 auto AudioConfig::ChannelLayout::Map() const -> ChannelMap {
     53  if (mChannelMap != UNKNOWN_MAP) {
     54    return mChannelMap;
     55  }
     56  if (mChannels.Length() > MAX_CHANNELS) {
     57    return UNKNOWN_MAP;
     58  }
     59  ChannelMap map = UNKNOWN_MAP;
     60  for (size_t i = 0; i < mChannels.Length(); i++) {
     61    if (uint32_t(mChannels[i]) > sizeof(ChannelMap) * 8) {
     62      return UNKNOWN_MAP;
     63    }
     64    ChannelMap mask = 1 << mChannels[i];
     65    if (mChannels[i] == CHANNEL_INVALID || (mChannelMap & mask)) {
     66      // Invalid configuration.
     67      return UNKNOWN_MAP;
     68    }
     69    map |= mask;
     70  }
     71  return map;
     72 }
     73 
     74 const AudioConfig::Channel*
     75 AudioConfig::ChannelLayout::DefaultLayoutForChannels(uint32_t aChannels) const {
     76  switch (aChannels) {
     77    case 1:  // MONO
     78    {
     79      static const Channel config[] = {CHANNEL_FRONT_CENTER};
     80      return config;
     81    }
     82    case 2:  // STEREO
     83    {
     84      static const Channel config[] = {CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT};
     85      return config;
     86    }
     87    case 3:  // 3F
     88    {
     89      static const Channel config[] = {CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT,
     90                                       CHANNEL_FRONT_CENTER};
     91      return config;
     92    }
     93    case 4:  // QUAD
     94    {
     95      static const Channel config[] = {CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT,
     96                                       CHANNEL_BACK_LEFT, CHANNEL_BACK_RIGHT};
     97      return config;
     98    }
     99    case 5:  // 3F2
    100    {
    101      static const Channel config[] = {CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT,
    102                                       CHANNEL_FRONT_CENTER, CHANNEL_SIDE_LEFT,
    103                                       CHANNEL_SIDE_RIGHT};
    104      return config;
    105    }
    106    case 6:  // 3F2-LFE
    107    {
    108      static const Channel config[] = {
    109          CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_FRONT_CENTER,
    110          CHANNEL_LFE,        CHANNEL_SIDE_LEFT,   CHANNEL_SIDE_RIGHT};
    111      return config;
    112    }
    113    case 7:  // 3F3R-LFE
    114    {
    115      static const Channel config[] = {
    116          CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_FRONT_CENTER,
    117          CHANNEL_LFE,        CHANNEL_BACK_CENTER, CHANNEL_SIDE_LEFT,
    118          CHANNEL_SIDE_RIGHT};
    119      return config;
    120    }
    121    case 8:  // 3F4-LFE
    122    {
    123      static const Channel config[] = {
    124          CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_FRONT_CENTER,
    125          CHANNEL_LFE,        CHANNEL_BACK_LEFT,   CHANNEL_BACK_RIGHT,
    126          CHANNEL_SIDE_LEFT,  CHANNEL_SIDE_RIGHT};
    127      return config;
    128    }
    129    default:
    130      return nullptr;
    131  }
    132 }
    133 
    134 /* static */ AudioConfig::ChannelLayout
    135 AudioConfig::ChannelLayout::SMPTEDefault(const ChannelLayout& aChannelLayout) {
    136  if (!aChannelLayout.IsValid()) {
    137    return aChannelLayout;
    138  }
    139  return SMPTEDefault(aChannelLayout.Map());
    140 }
    141 
    142 /* static */
    143 ChannelLayout AudioConfig::ChannelLayout::SMPTEDefault(ChannelMap aMap) {
    144  // First handle the most common cases.
    145  switch (aMap) {
    146    case LMONO_MAP:
    147      return ChannelLayout{CHANNEL_FRONT_CENTER};
    148    case LSTEREO_MAP:
    149      return ChannelLayout{CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT};
    150    case L3F_MAP:
    151      return ChannelLayout{CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT,
    152                           CHANNEL_FRONT_CENTER};
    153    case L3F_LFE_MAP:
    154      return ChannelLayout{CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT,
    155                           CHANNEL_FRONT_CENTER, CHANNEL_LFE};
    156    case L2F1_MAP:
    157      return ChannelLayout{CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT,
    158                           CHANNEL_BACK_CENTER};
    159    case L2F1_LFE_MAP:
    160      return ChannelLayout{CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_LFE,
    161                           CHANNEL_BACK_CENTER};
    162    case L3F1_MAP:
    163      return ChannelLayout{CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT,
    164                           CHANNEL_FRONT_CENTER, CHANNEL_BACK_CENTER};
    165    case L3F1_LFE_MAP:
    166      return ChannelLayout{CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT,
    167                           CHANNEL_FRONT_CENTER, CHANNEL_LFE,
    168                           CHANNEL_BACK_CENTER};
    169    case L2F2_MAP:
    170      return ChannelLayout{CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT,
    171                           CHANNEL_SIDE_LEFT, CHANNEL_SIDE_RIGHT};
    172    case L2F2_LFE_MAP:
    173      return ChannelLayout{CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_LFE,
    174                           CHANNEL_SIDE_LEFT, CHANNEL_SIDE_RIGHT};
    175    case LQUAD_MAP:
    176      return ChannelLayout{CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT,
    177                           CHANNEL_BACK_LEFT, CHANNEL_BACK_RIGHT};
    178    case LQUAD_LFE_MAP:
    179      return ChannelLayout{CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_LFE,
    180                           CHANNEL_BACK_LEFT, CHANNEL_BACK_RIGHT};
    181    case L3F2_MAP:
    182      return ChannelLayout{CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT,
    183                           CHANNEL_FRONT_CENTER, CHANNEL_SIDE_LEFT,
    184                           CHANNEL_SIDE_RIGHT};
    185    case L3F2_LFE_MAP:
    186      return ChannelLayout{CHANNEL_FRONT_LEFT,   CHANNEL_FRONT_RIGHT,
    187                           CHANNEL_FRONT_CENTER, CHANNEL_LFE,
    188                           CHANNEL_SIDE_LEFT,    CHANNEL_SIDE_RIGHT};
    189    case L3F2_BACK_MAP:
    190      return ChannelLayout{CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT,
    191                           CHANNEL_FRONT_CENTER, CHANNEL_BACK_LEFT,
    192                           CHANNEL_BACK_RIGHT};
    193    case L3F2_BACK_LFE_MAP:
    194      return ChannelLayout{CHANNEL_FRONT_LEFT,   CHANNEL_FRONT_RIGHT,
    195                           CHANNEL_FRONT_CENTER, CHANNEL_LFE,
    196                           CHANNEL_BACK_LEFT,    CHANNEL_BACK_RIGHT};
    197    case L3F3R_LFE_MAP:
    198      return ChannelLayout{CHANNEL_FRONT_LEFT,   CHANNEL_FRONT_RIGHT,
    199                           CHANNEL_FRONT_CENTER, CHANNEL_LFE,
    200                           CHANNEL_BACK_CENTER,  CHANNEL_SIDE_LEFT,
    201                           CHANNEL_SIDE_RIGHT};
    202    case L3F4_LFE_MAP:
    203      return ChannelLayout{CHANNEL_FRONT_LEFT,   CHANNEL_FRONT_RIGHT,
    204                           CHANNEL_FRONT_CENTER, CHANNEL_LFE,
    205                           CHANNEL_BACK_LEFT,    CHANNEL_BACK_RIGHT,
    206                           CHANNEL_SIDE_LEFT,    CHANNEL_SIDE_RIGHT};
    207    default:
    208      break;
    209  }
    210 
    211  static_assert(MAX_CHANNELS <= sizeof(ChannelMap) * 8,
    212                "Must be able to fit channels on bit mask");
    213  AutoTArray<Channel, MAX_CHANNELS> layout;
    214  uint32_t channels = 0;
    215 
    216  uint32_t i = 0;
    217  while (aMap) {
    218    if (aMap & 1) {
    219      channels++;
    220      if (channels > MAX_CHANNELS) {
    221        return ChannelLayout();
    222      }
    223      layout.AppendElement(static_cast<Channel>(i));
    224    }
    225    aMap >>= 1;
    226    i++;
    227  }
    228  return ChannelLayout(channels, layout.Elements());
    229 }
    230 
    231 nsCString AudioConfig::ChannelLayout::ChannelMapToString(
    232    const ChannelMap aChannelMap) {
    233  nsCString rv;
    234 
    235  constexpr const std::array CHANNEL_NAME = {"Front left",
    236                                             "Front right",
    237                                             "Front center",
    238                                             "Low frequency",
    239                                             "Back left",
    240                                             "Back right",
    241                                             "Front left of center",
    242                                             "Front right of center",
    243                                             "Back center",
    244                                             "Side left",
    245                                             "Side right",
    246                                             "Top center",
    247                                             "Top front left",
    248                                             "Top front center",
    249                                             "Top front right",
    250                                             "Top back left",
    251                                             "Top back center",
    252                                             "Top back right"};
    253 
    254  rv.AppendPrintf("0x%08x", aChannelMap);
    255  rv.Append("[");
    256  bool empty = true;
    257  for (size_t i = 0; i < CHANNEL_NAME.size(); i++) {
    258    if (aChannelMap & (1 << i)) {
    259      if (!empty) {
    260        rv.Append("|");
    261      }
    262      empty = false;
    263      rv.Append(CHANNEL_NAME[i]);
    264    }
    265  }
    266  rv.Append("]");
    267 
    268  return rv;
    269 }
    270 
    271 bool AudioConfig::ChannelLayout::MappingTable(const ChannelLayout& aOther,
    272                                              nsTArray<uint8_t>* aMap) const {
    273  if (!IsValid() || !aOther.IsValid() || Map() != aOther.Map()) {
    274    if (aMap) {
    275      aMap->SetLength(0);
    276    }
    277    return false;
    278  }
    279  if (!aMap) {
    280    return true;
    281  }
    282  aMap->SetLength(Count());
    283  for (uint32_t i = 0; i < Count(); i++) {
    284    for (uint32_t j = 0; j < Count(); j++) {
    285      if (aOther[j] == mChannels[i]) {
    286        (*aMap)[j] = i;
    287        break;
    288      }
    289    }
    290  }
    291  return true;
    292 }
    293 
    294 /**
    295 * AudioConfig::ChannelConfig
    296 */
    297 
    298 /* static */ const char* AudioConfig::FormatToString(
    299    AudioConfig::SampleFormat aFormat) {
    300  switch (aFormat) {
    301    case FORMAT_U8:
    302      return "unsigned 8 bit";
    303    case FORMAT_S16:
    304      return "signed 16 bit";
    305    case FORMAT_S24:
    306      return "signed 24 bit MSB";
    307    case FORMAT_S24LSB:
    308      return "signed 24 bit LSB";
    309    case FORMAT_S32:
    310      return "signed 32 bit";
    311    case FORMAT_FLT:
    312      return "32 bit floating point";
    313    case FORMAT_NONE:
    314      return "none";
    315    default:
    316      return "unknown";
    317  }
    318 }
    319 /* static */
    320 uint32_t AudioConfig::SampleSize(AudioConfig::SampleFormat aFormat) {
    321  switch (aFormat) {
    322    case FORMAT_U8:
    323      return 1;
    324    case FORMAT_S16:
    325      return 2;
    326    case FORMAT_S24:
    327      [[fallthrough]];
    328    case FORMAT_S24LSB:
    329      [[fallthrough]];
    330    case FORMAT_S32:
    331      [[fallthrough]];
    332    case FORMAT_FLT:
    333      return 4;
    334    case FORMAT_NONE:
    335    default:
    336      return 0;
    337  }
    338 }
    339 
    340 /* static */
    341 uint32_t AudioConfig::FormatToBits(AudioConfig::SampleFormat aFormat) {
    342  switch (aFormat) {
    343    case FORMAT_U8:
    344      return 8;
    345    case FORMAT_S16:
    346      return 16;
    347    case FORMAT_S24LSB:
    348      [[fallthrough]];
    349    case FORMAT_S24:
    350      return 24;
    351    case FORMAT_S32:
    352      [[fallthrough]];
    353    case FORMAT_FLT:
    354      return 32;
    355    case FORMAT_NONE:
    356      [[fallthrough]];
    357    default:
    358      return 0;
    359  }
    360 }
    361 
    362 AudioConfig::AudioConfig(const ChannelLayout& aChannelLayout, uint32_t aRate,
    363                         AudioConfig::SampleFormat aFormat, bool aInterleaved)
    364    : mChannelLayout(aChannelLayout),
    365      mChannels(aChannelLayout.Count()),
    366      mRate(aRate),
    367      mFormat(aFormat),
    368      mInterleaved(aInterleaved) {}
    369 
    370 AudioConfig::AudioConfig(const ChannelLayout& aChannelLayout,
    371                         uint32_t aChannels, uint32_t aRate,
    372                         AudioConfig::SampleFormat aFormat, bool aInterleaved)
    373    : mChannelLayout(aChannelLayout),
    374      mChannels(aChannels),
    375      mRate(aRate),
    376      mFormat(aFormat),
    377      mInterleaved(aInterleaved) {}
    378 
    379 AudioConfig::AudioConfig(uint32_t aChannels, uint32_t aRate,
    380                         AudioConfig::SampleFormat aFormat, bool aInterleaved)
    381    : mChannelLayout(aChannels),
    382      mChannels(aChannels),
    383      mRate(aRate),
    384      mFormat(aFormat),
    385      mInterleaved(aInterleaved) {}
    386 
    387 }  // namespace mozilla