/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "AudioMixer.h" #include "gtest/gtest.h" using mozilla::AudioDataValue; using mozilla::AudioSampleFormat; namespace audio_mixer { struct MixerConsumer : public mozilla::MixerCallbackReceiver { /* In this test, the different audio stream and channels are always created to * cancel each other. */ void MixerCallback(AudioDataValue* aData, AudioSampleFormat aFormat, uint32_t aChannels, uint32_t aFrames, uint32_t aSampleRate) { bool silent = true; for (uint32_t i = 0; i < aChannels * aFrames; i++) { if (aData[i] != 0.0) { if (aFormat == mozilla::AUDIO_FORMAT_S16) { fprintf(stderr, "Sample at %d is not silent: %d\n", i, (short)aData[i]); } else { fprintf(stderr, "Sample at %d is not silent: %f\n", i, (float)aData[i]); } silent = false; } } ASSERT_TRUE(silent); } }; /* Helper function to give us the maximum and minimum value that don't clip, * for a given sample format (integer or floating-point). */ template T GetLowValue(); template T GetHighValue(); template <> float GetLowValue() { return -1.0; } template <> short GetLowValue() { return -INT16_MAX; } template <> float GetHighValue() { return 1.0; } template <> short GetHighValue() { return INT16_MAX; } void FillBuffer(AudioDataValue* aBuffer, uint32_t aLength, AudioDataValue aValue) { AudioDataValue* end = aBuffer + aLength; while (aBuffer != end) { *aBuffer++ = aValue; } } TEST(AudioMixer, Test) { const uint32_t CHANNEL_LENGTH = 256; const uint32_t AUDIO_RATE = 44100; MixerConsumer consumer; AudioDataValue a[CHANNEL_LENGTH * 2]; AudioDataValue b[CHANNEL_LENGTH * 2]; FillBuffer(a, CHANNEL_LENGTH, GetLowValue()); FillBuffer(a + CHANNEL_LENGTH, CHANNEL_LENGTH, GetHighValue()); FillBuffer(b, CHANNEL_LENGTH, GetHighValue()); FillBuffer(b + CHANNEL_LENGTH, CHANNEL_LENGTH, GetLowValue()); { int iterations = 2; mozilla::AudioMixer mixer; mixer.AddCallback(WrapNotNull(&consumer)); fprintf(stderr, "Test AudioMixer constant buffer length.\n"); while (iterations--) { mixer.Mix(a, 2, CHANNEL_LENGTH, AUDIO_RATE); mixer.Mix(b, 2, CHANNEL_LENGTH, AUDIO_RATE); mixer.FinishMixing(); } } { mozilla::AudioMixer mixer; mixer.AddCallback(WrapNotNull(&consumer)); fprintf(stderr, "Test AudioMixer variable buffer length.\n"); FillBuffer(a, CHANNEL_LENGTH / 2, GetLowValue()); FillBuffer(a + CHANNEL_LENGTH / 2, CHANNEL_LENGTH / 2, GetLowValue()); FillBuffer(b, CHANNEL_LENGTH / 2, GetHighValue()); FillBuffer(b + CHANNEL_LENGTH / 2, CHANNEL_LENGTH / 2, GetHighValue()); mixer.Mix(a, 2, CHANNEL_LENGTH / 2, AUDIO_RATE); mixer.Mix(b, 2, CHANNEL_LENGTH / 2, AUDIO_RATE); mixer.FinishMixing(); FillBuffer(a, CHANNEL_LENGTH, GetLowValue()); FillBuffer(a + CHANNEL_LENGTH, CHANNEL_LENGTH, GetHighValue()); FillBuffer(b, CHANNEL_LENGTH, GetHighValue()); FillBuffer(b + CHANNEL_LENGTH, CHANNEL_LENGTH, GetLowValue()); mixer.Mix(a, 2, CHANNEL_LENGTH, AUDIO_RATE); mixer.Mix(b, 2, CHANNEL_LENGTH, AUDIO_RATE); mixer.FinishMixing(); FillBuffer(a, CHANNEL_LENGTH / 2, GetLowValue()); FillBuffer(a + CHANNEL_LENGTH / 2, CHANNEL_LENGTH / 2, GetLowValue()); FillBuffer(b, CHANNEL_LENGTH / 2, GetHighValue()); FillBuffer(b + CHANNEL_LENGTH / 2, CHANNEL_LENGTH / 2, GetHighValue()); mixer.Mix(a, 2, CHANNEL_LENGTH / 2, AUDIO_RATE); mixer.Mix(b, 2, CHANNEL_LENGTH / 2, AUDIO_RATE); mixer.FinishMixing(); } FillBuffer(a, CHANNEL_LENGTH, GetLowValue()); FillBuffer(b, CHANNEL_LENGTH, GetHighValue()); { mozilla::AudioMixer mixer; mixer.AddCallback(WrapNotNull(&consumer)); fprintf(stderr, "Test AudioMixer variable channel count.\n"); mixer.Mix(a, 1, CHANNEL_LENGTH, AUDIO_RATE); mixer.Mix(b, 1, CHANNEL_LENGTH, AUDIO_RATE); mixer.FinishMixing(); mixer.Mix(a, 1, CHANNEL_LENGTH, AUDIO_RATE); mixer.Mix(b, 1, CHANNEL_LENGTH, AUDIO_RATE); mixer.FinishMixing(); mixer.Mix(a, 1, CHANNEL_LENGTH, AUDIO_RATE); mixer.Mix(b, 1, CHANNEL_LENGTH, AUDIO_RATE); mixer.FinishMixing(); } { mozilla::AudioMixer mixer; mixer.AddCallback(WrapNotNull(&consumer)); fprintf(stderr, "Test AudioMixer variable stream count.\n"); mixer.Mix(a, 2, CHANNEL_LENGTH, AUDIO_RATE); mixer.Mix(b, 2, CHANNEL_LENGTH, AUDIO_RATE); mixer.FinishMixing(); mixer.Mix(a, 2, CHANNEL_LENGTH, AUDIO_RATE); mixer.Mix(b, 2, CHANNEL_LENGTH, AUDIO_RATE); mixer.Mix(a, 2, CHANNEL_LENGTH, AUDIO_RATE); mixer.Mix(b, 2, CHANNEL_LENGTH, AUDIO_RATE); mixer.FinishMixing(); mixer.Mix(a, 2, CHANNEL_LENGTH, AUDIO_RATE); mixer.Mix(b, 2, CHANNEL_LENGTH, AUDIO_RATE); mixer.FinishMixing(); } } } // namespace audio_mixer