michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef MOZILLA_AUDIOMIXER_H_ michael@0: #define MOZILLA_AUDIOMIXER_H_ michael@0: michael@0: #include "AudioSampleFormat.h" michael@0: #include "nsTArray.h" michael@0: #include "mozilla/PodOperations.h" michael@0: michael@0: namespace mozilla { michael@0: typedef void(*MixerFunc)(AudioDataValue* aMixedBuffer, michael@0: AudioSampleFormat aFormat, michael@0: uint32_t aChannels, michael@0: uint32_t aFrames, michael@0: uint32_t aSampleRate); michael@0: michael@0: /** michael@0: * This class mixes multiple streams of audio together to output a single audio michael@0: * stream. michael@0: * michael@0: * AudioMixer::Mix is to be called repeatedly with buffers that have the same michael@0: * length, sample rate, sample format and channel count. michael@0: * michael@0: * When all the tracks have been mixed, calling FinishMixing will call back with michael@0: * a buffer containing the mixed audio data. michael@0: * michael@0: * This class is not thread safe. michael@0: */ michael@0: class AudioMixer michael@0: { michael@0: public: michael@0: AudioMixer(MixerFunc aCallback) michael@0: : mCallback(aCallback), michael@0: mFrames(0), michael@0: mChannels(0), michael@0: mSampleRate(0) michael@0: { } michael@0: michael@0: /* Get the data from the mixer. This is supposed to be called when all the michael@0: * tracks have been mixed in. The caller should not hold onto the data. */ michael@0: void FinishMixing() { michael@0: mCallback(mMixedAudio.Elements(), michael@0: AudioSampleTypeToFormat::Format, michael@0: mChannels, michael@0: mFrames, michael@0: mSampleRate); michael@0: PodZero(mMixedAudio.Elements(), mMixedAudio.Length()); michael@0: mSampleRate = mChannels = mFrames = 0; michael@0: } michael@0: michael@0: /* Add a buffer to the mix. aSamples is interleaved. */ michael@0: void Mix(AudioDataValue* aSamples, michael@0: uint32_t aChannels, michael@0: uint32_t aFrames, michael@0: uint32_t aSampleRate) { michael@0: if (!mFrames && !mChannels) { michael@0: mFrames = aFrames; michael@0: mChannels = aChannels; michael@0: mSampleRate = aSampleRate; michael@0: EnsureCapacityAndSilence(); michael@0: } michael@0: michael@0: MOZ_ASSERT(aFrames == mFrames); michael@0: MOZ_ASSERT(aChannels == mChannels); michael@0: MOZ_ASSERT(aSampleRate == mSampleRate); michael@0: michael@0: for (uint32_t i = 0; i < aFrames * aChannels; i++) { michael@0: mMixedAudio[i] += aSamples[i]; michael@0: } michael@0: } michael@0: private: michael@0: void EnsureCapacityAndSilence() { michael@0: if (mFrames * mChannels > mMixedAudio.Length()) { michael@0: mMixedAudio.SetLength(mFrames* mChannels); michael@0: } michael@0: PodZero(mMixedAudio.Elements(), mMixedAudio.Length()); michael@0: } michael@0: michael@0: /* Function that is called when the mixing is done. */ michael@0: MixerFunc mCallback; michael@0: /* Number of frames for this mixing block. */ michael@0: uint32_t mFrames; michael@0: /* Number of channels for this mixing block. */ michael@0: uint32_t mChannels; michael@0: /* Sample rate the of the mixed data. */ michael@0: uint32_t mSampleRate; michael@0: /* Buffer containing the mixed audio data. */ michael@0: nsTArray mMixedAudio; michael@0: }; michael@0: } michael@0: michael@0: #endif // MOZILLA_AUDIOMIXER_H_