Bug 1941046 - Part 4: Send a callback request for impression and clicks of MARS Top...
[gecko.git] / dom / media / AudioMixer.h
blobbd8c02a8282e8c8e5fc450bb1fc4483688c9442a
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/. */
6 #ifndef MOZILLA_AUDIOMIXER_H_
7 #define MOZILLA_AUDIOMIXER_H_
9 #include "AudioSampleFormat.h"
10 #include "AudioSegment.h"
11 #include "AudioStream.h"
12 #include "nsTArray.h"
13 #include "mozilla/NotNull.h"
14 #include "mozilla/PodOperations.h"
16 namespace mozilla {
18 struct MixerCallbackReceiver {
19 // MixerCallback MAY modify aMixedBuffer but MUST clear
20 // aMixedBuffer->mBuffer if its data is to live longer than the duration of
21 // the callback.
22 virtual void MixerCallback(AudioChunk* aMixedBuffer,
23 uint32_t aSampleRate) = 0;
25 /**
26 * This class mixes multiple streams of audio together to output a single audio
27 * stream.
29 * AudioMixer::Mix is to be called repeatedly with buffers that have the same
30 * length, sample rate, sample format and channel count. This class works with
31 * planar buffers.
33 * When all the tracks have been mixed, calling MixedChunk() will provide
34 * a buffer containing the mixed audio data.
36 * This class is not thread safe.
38 class AudioMixer {
39 public:
40 AudioMixer() { mChunk.mBufferFormat = AUDIO_OUTPUT_FORMAT; }
42 ~AudioMixer() = default;
44 void StartMixing() {
45 mChunk.mDuration = 0;
46 mSampleRate = 0;
49 /* Get the data from the mixer. This is supposed to be called when all the
50 * tracks have been mixed in. The caller MAY modify the chunk but MUST clear
51 * mBuffer if its data needs to survive the next call to Mix(). */
52 AudioChunk* MixedChunk() {
53 MOZ_ASSERT(mSampleRate, "Mix not called for this cycle?");
54 mSampleRate = 0;
55 return &mChunk;
58 /* Add a buffer to the mix. The buffer can be null if there's nothing to mix
59 * but the callback is still needed. */
60 void Mix(AudioDataValue* aSamples, uint32_t aChannels, uint32_t aFrames,
61 uint32_t aSampleRate) {
62 if (!mChunk.mDuration) {
63 mChunk.mDuration = aFrames;
64 MOZ_ASSERT(aChannels > 0);
65 mChunk.mChannelData.SetLength(aChannels);
66 mSampleRate = aSampleRate;
67 EnsureCapacityAndSilence();
70 MOZ_ASSERT(aFrames == mChunk.mDuration);
71 MOZ_ASSERT(aChannels == mChunk.ChannelCount());
72 MOZ_ASSERT(aSampleRate == mSampleRate);
74 if (!aSamples) {
75 return;
78 for (uint32_t i = 0; i < aFrames * aChannels; i++) {
79 mChunk.ChannelDataForWrite<AudioDataValue>(0)[i] += aSamples[i];
83 private:
84 void EnsureCapacityAndSilence() {
85 uint32_t sampleCount = mChunk.mDuration * mChunk.ChannelCount();
86 if (!mChunk.mBuffer || sampleCount > mSampleCapacity) {
87 CheckedInt<size_t> bufferSize(sizeof(AudioDataValue));
88 bufferSize *= sampleCount;
89 mChunk.mBuffer = SharedBuffer::Create(bufferSize);
90 mSampleCapacity = sampleCount;
92 MOZ_ASSERT(!mChunk.mBuffer->IsShared());
93 mChunk.mChannelData[0] =
94 static_cast<SharedBuffer*>(mChunk.mBuffer.get())->Data();
95 for (size_t i = 1; i < mChunk.ChannelCount(); ++i) {
96 mChunk.mChannelData[i] =
97 mChunk.ChannelData<AudioDataValue>()[0] + i * mChunk.mDuration;
99 PodZero(mChunk.ChannelDataForWrite<AudioDataValue>(0), sampleCount);
102 /* Buffer containing the mixed audio data. */
103 AudioChunk mChunk;
104 /* Size allocated for mChunk.mBuffer. */
105 uint32_t mSampleCapacity = 0;
106 /* Sample rate the of the mixed data. */
107 uint32_t mSampleRate = 0;
110 } // namespace mozilla
112 #endif // MOZILLA_AUDIOMIXER_H_