tor-browser

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

AudioChunkList.h (5194B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      4 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 #ifndef DOM_MEDIA_DRIFTCONTROL_AUDIOCHUNKLIST_H_
      7 #define DOM_MEDIA_DRIFTCONTROL_AUDIOCHUNKLIST_H_
      8 
      9 #include "AudioSegment.h"
     10 #include "TimeUnits.h"
     11 
     12 namespace mozilla {
     13 
     14 /**
     15 * AudioChunkList provides a way to have preallocated audio buffers in
     16 * AudioSegment. The idea is that the amount of  AudioChunks is created in
     17 * advance. Each AudioChunk is able to hold a specific amount of audio
     18 * (capacity). The total capacity of AudioChunkList is specified by the number
     19 * of AudioChunks. The important aspect of the AudioChunkList is that
     20 * preallocates everything and reuse the same chunks similar to a ring buffer.
     21 *
     22 * Why the whole AudioChunk is preallocated and not some raw memory buffer? This
     23 * is due to the limitations of MediaTrackGraph. The way that MTG works depends
     24 * on `AudioSegment`s to convey the actual audio data. An AudioSegment consists
     25 * of AudioChunks. The AudioChunk is built in a way, that owns and allocates the
     26 * audio buffers. Thus, since the use of AudioSegment is mandatory if the audio
     27 * data was in a different form, the only way to use it from the audio thread
     28 * would be to create the AudioChunk there. That would result in a copy
     29 * operation (not very important) and most of all an allocation of the audio
     30 * buffer in the audio thread. This happens in many places inside MTG it's a bad
     31 * practice, though, and it has been avoided due to the AudioChunkList.
     32 *
     33 * After construction the sample format must be set, when it is available. It
     34 * can be set in the audio thread. Before setting the sample format is not
     35 * possible to use any method of AudioChunkList.
     36 *
     37 * Every AudioChunk in the AudioChunkList is preallocated with a capacity of 128
     38 * frames of float audio. Nevertheless, the sample format is not available at
     39 * that point. Thus if the sample format is set to short, the capacity of each
     40 * chunk changes to 256 number of frames, and the total duration becomes twice
     41 * big. There are methods to get the chunk capacity and total capacity in frames
     42 * and must always be used.
     43 *
     44 * Two things to note. First, when the channel count changes everything is
     45 * recreated which means reallocations. Second, the total capacity might differs
     46 * from the requested total capacity for two reasons. First, if the sample
     47 * format is set to short and second because the number of chunks in the list
     48 * divides exactly the final total capacity. The corresponding method must
     49 * always be used to query the total capacity.
     50 */
     51 class AudioChunkList {
     52 public:
     53  /**
     54   * Constructor, the final total duration might be different from the requested
     55   * `aTotalDuration`. Memory allocation takes place.
     56   */
     57  AudioChunkList(uint32_t aTotalDuration, uint32_t aChannels,
     58                 const PrincipalHandle& aPrincipalHandle);
     59  AudioChunkList(const AudioChunkList&) = delete;
     60  AudioChunkList(AudioChunkList&&) = delete;
     61  ~AudioChunkList() = default;
     62 
     63  /**
     64   * Set sample format. It must be done before any other method being used.
     65   */
     66  void SetSampleFormat(AudioSampleFormat aFormat);
     67  /**
     68   * Get the next available AudioChunk. The duration of the chunk will be zero
     69   * and the volume 1.0. However, the buffers will be there ready to be written.
     70   * Please note, that a reference of the preallocated chunk is returned. Thus
     71   * it _must not be consumed_ directly. If the chunk needs to be consumed it
     72   * must be copied to a temporary chunk first. For example:
     73   * ```
     74   *   AudioChunk& chunk = audioChunklist.GetNext();
     75   *   // Set up the chunk
     76   *   AudioChunk tmp = chunk;
     77   *   audioSegment.AppendAndConsumeChunk(std::move(tmp));
     78   * ```
     79   * This way no memory allocation or copy, takes place.
     80   */
     81  AudioChunk& GetNext();
     82 
     83  /**
     84   * Get the capacity of each individual AudioChunk in the list.
     85   */
     86  uint32_t ChunkCapacity() const {
     87    MOZ_ASSERT(mSampleFormat == AUDIO_FORMAT_S16 ||
     88               mSampleFormat == AUDIO_FORMAT_FLOAT32);
     89    return mChunkCapacity;
     90  }
     91  /**
     92   * Get the total capacity of AudioChunkList.
     93   */
     94  uint32_t TotalCapacity() const {
     95    MOZ_ASSERT(mSampleFormat == AUDIO_FORMAT_S16 ||
     96               mSampleFormat == AUDIO_FORMAT_FLOAT32);
     97    return CheckedInt<uint32_t>(mChunkCapacity * mChunks.Length()).value();
     98  }
     99 
    100  /**
    101   * Update the channel count of the AudioChunkList. Memory allocation is
    102   * taking place.
    103   */
    104  void Update(uint32_t aChannels);
    105 
    106 private:
    107  void IncrementIndex() {
    108    ++mIndex;
    109    mIndex = CheckedInt<uint32_t>(mIndex % mChunks.Length()).value();
    110  }
    111  void CreateChunks(uint32_t aNumOfChunks, uint32_t aChannels);
    112  void UpdateToMonoOrStereo(uint32_t aChannels);
    113 
    114 private:
    115  const PrincipalHandle mPrincipalHandle;
    116  nsTArray<AudioChunk> mChunks;
    117  uint32_t mIndex = 0;
    118  uint32_t mChunkCapacity = WEBAUDIO_BLOCK_SIZE;
    119  AudioSampleFormat mSampleFormat = AUDIO_FORMAT_SILENCE;
    120 };
    121 
    122 }  // namespace mozilla
    123 
    124 #endif  // DOM_MEDIA_DRIFTCONTROL_AUDIOCHUNKLIST_H_