mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-19 16:25:38 +00:00
Bug 1656438 - Generalize AudioGenerator and SineWaveGenerator to support AudioToneGenerator's use cases. r=padenot
Depends on D85552 Differential Revision: https://phabricator.services.mozilla.com/D89738
This commit is contained in:
parent
bd90aec1ed
commit
4da0ed94ab
@ -1,28 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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 https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "AudioGenerator.h"
|
||||
|
||||
#include "AudioSegment.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
AudioGenerator::AudioGenerator(int32_t aChannels, int32_t aSampleRate)
|
||||
: mGenerator(aSampleRate, 1000), mChannels(aChannels) {}
|
||||
|
||||
void AudioGenerator::Generate(AudioSegment& aSegment, const int32_t& aSamples) {
|
||||
CheckedInt<size_t> bufferSize(sizeof(int16_t));
|
||||
bufferSize *= aSamples;
|
||||
RefPtr<SharedBuffer> buffer = SharedBuffer::Create(bufferSize);
|
||||
int16_t* dest = static_cast<int16_t*>(buffer->Data());
|
||||
mGenerator.generate(dest, aSamples);
|
||||
AutoTArray<const int16_t*, 1> channels;
|
||||
for (int32_t i = 0; i < mChannels; i++) {
|
||||
channels.AppendElement(dest);
|
||||
}
|
||||
aSegment.AppendFrames(buffer.forget(), channels, aSamples,
|
||||
PRINCIPAL_HANDLE_NONE);
|
||||
}
|
@ -7,21 +7,50 @@
|
||||
#ifndef DOM_MEDIA_GTEST_AUDIO_GENERATOR_H_
|
||||
#define DOM_MEDIA_GTEST_AUDIO_GENERATOR_H_
|
||||
|
||||
#include "AudioSegment.h"
|
||||
#include "prtime.h"
|
||||
#include "SineWaveGenerator.h"
|
||||
|
||||
namespace mozilla {
|
||||
class AudioSegment;
|
||||
}
|
||||
|
||||
template <typename Sample>
|
||||
class AudioGenerator {
|
||||
public:
|
||||
AudioGenerator(int32_t aChannels, int32_t aSampleRate);
|
||||
void Generate(mozilla::AudioSegment& aSegment, const int32_t& aSamples);
|
||||
AudioGenerator(uint32_t aChannels, uint32_t aSampleRate,
|
||||
uint32_t aFrequency = 1000)
|
||||
: mChannels(aChannels),
|
||||
mSampleRate(aSampleRate),
|
||||
mFrequency(aFrequency),
|
||||
mGenerator(aSampleRate, aFrequency) {}
|
||||
|
||||
void Generate(mozilla::AudioSegment& aSegment, const uint32_t& aSamples) {
|
||||
CheckedInt<size_t> bufferSize(sizeof(Sample));
|
||||
bufferSize *= aSamples;
|
||||
RefPtr<SharedBuffer> buffer = SharedBuffer::Create(bufferSize);
|
||||
Sample* dest = static_cast<Sample*>(buffer->Data());
|
||||
mGenerator.generate(dest, aSamples);
|
||||
AutoTArray<const Sample*, 1> channels;
|
||||
for (uint32_t i = 0; i < mChannels; ++i) {
|
||||
channels.AppendElement(dest);
|
||||
}
|
||||
aSegment.AppendFrames(buffer.forget(), channels, aSamples,
|
||||
PRINCIPAL_HANDLE_NONE);
|
||||
}
|
||||
|
||||
void SetOffset(TrackTicks aFrames) { mGenerator.SetOffset(aFrames); }
|
||||
|
||||
TrackTicks Offset() const { return mGenerator.Offset(); }
|
||||
|
||||
static float Amplitude() { return SineWaveGenerator<Sample>::Amplitude(); }
|
||||
|
||||
const uint32_t mChannels;
|
||||
const uint32_t mSampleRate;
|
||||
const uint32_t mFrequency;
|
||||
|
||||
private:
|
||||
mozilla::SineWaveGenerator mGenerator;
|
||||
const int32_t mChannels;
|
||||
mozilla::SineWaveGenerator<Sample> mGenerator;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // DOM_MEDIA_GTEST_AUDIO_GENERATOR_H_
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "OpusTrackEncoder.h"
|
||||
|
||||
#include "AudioGenerator.h"
|
||||
#include "AudioSampleFormat.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
@ -102,7 +103,7 @@ TEST(OpusAudioTrackEncoder, Init)
|
||||
// For non-null segments we should init immediately
|
||||
OpusTrackEncoder encoder(48000);
|
||||
AudioSegment segment;
|
||||
AudioGenerator generator(2, 48000);
|
||||
AudioGenerator<AudioDataValue> generator(2, 48000);
|
||||
generator.Generate(segment, 1);
|
||||
encoder.TryInit(segment, segment.GetDuration());
|
||||
EXPECT_TRUE(encoder.IsInitialized());
|
||||
@ -112,7 +113,7 @@ TEST(OpusAudioTrackEncoder, Init)
|
||||
// Test low sample rate bound
|
||||
OpusTrackEncoder encoder(7999);
|
||||
AudioSegment segment;
|
||||
AudioGenerator generator(2, 7999);
|
||||
AudioGenerator<AudioDataValue> generator(2, 7999);
|
||||
generator.Generate(segment, 1);
|
||||
encoder.TryInit(segment, segment.GetDuration());
|
||||
EXPECT_FALSE(encoder.IsInitialized());
|
||||
@ -122,7 +123,7 @@ TEST(OpusAudioTrackEncoder, Init)
|
||||
// Test low sample rate bound
|
||||
OpusTrackEncoder encoder(8000);
|
||||
AudioSegment segment;
|
||||
AudioGenerator generator(2, 8000);
|
||||
AudioGenerator<AudioDataValue> generator(2, 8000);
|
||||
generator.Generate(segment, 1);
|
||||
encoder.TryInit(segment, segment.GetDuration());
|
||||
EXPECT_TRUE(encoder.IsInitialized());
|
||||
@ -132,7 +133,7 @@ TEST(OpusAudioTrackEncoder, Init)
|
||||
// Test high sample rate bound
|
||||
OpusTrackEncoder encoder(192001);
|
||||
AudioSegment segment;
|
||||
AudioGenerator generator(2, 192001);
|
||||
AudioGenerator<AudioDataValue> generator(2, 192001);
|
||||
generator.Generate(segment, 1);
|
||||
encoder.TryInit(segment, segment.GetDuration());
|
||||
EXPECT_FALSE(encoder.IsInitialized());
|
||||
@ -142,7 +143,7 @@ TEST(OpusAudioTrackEncoder, Init)
|
||||
// Test high sample rate bound
|
||||
OpusTrackEncoder encoder(192000);
|
||||
AudioSegment segment;
|
||||
AudioGenerator generator(2, 192000);
|
||||
AudioGenerator<AudioDataValue> generator(2, 192000);
|
||||
generator.Generate(segment, 1);
|
||||
encoder.TryInit(segment, segment.GetDuration());
|
||||
EXPECT_TRUE(encoder.IsInitialized());
|
||||
@ -194,7 +195,7 @@ TEST(OpusAudioTrackEncoder, FrameEncode)
|
||||
EXPECT_TRUE(encoder.TestOpusRawCreation(channels, sampleRate));
|
||||
|
||||
// Generate five seconds of raw audio data.
|
||||
AudioGenerator generator(channels, sampleRate);
|
||||
AudioGenerator<AudioDataValue> generator(channels, sampleRate);
|
||||
AudioSegment segment;
|
||||
const int32_t samples = sampleRate * 5;
|
||||
generator.Generate(segment, samples);
|
||||
|
@ -15,7 +15,6 @@ LOCAL_INCLUDES += [
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'AudioGenerator.cpp',
|
||||
'MockMediaResource.cpp',
|
||||
'TestAudioBuffers.cpp',
|
||||
'TestAudioCallbackDriver.cpp',
|
||||
|
@ -358,8 +358,8 @@ class AudioSourcePullListener : public MediaTrackListener {
|
||||
uint32_t aFrequency)
|
||||
: mTrack(std::move(aTrack)),
|
||||
mPrincipalHandle(aPrincipalHandle),
|
||||
mSineGenerator(
|
||||
MakeUnique<SineWaveGenerator>(mTrack->mSampleRate, aFrequency)) {
|
||||
mSineGenerator(MakeUnique<SineWaveGenerator<int16_t>>(
|
||||
mTrack->mSampleRate, aFrequency)) {
|
||||
MOZ_COUNT_CTOR(AudioSourcePullListener);
|
||||
}
|
||||
|
||||
@ -370,7 +370,7 @@ class AudioSourcePullListener : public MediaTrackListener {
|
||||
|
||||
const RefPtr<SourceMediaTrack> mTrack;
|
||||
const PrincipalHandle mPrincipalHandle;
|
||||
const UniquePtr<SineWaveGenerator> mSineGenerator;
|
||||
const UniquePtr<SineWaveGenerator<int16_t>> mSineGenerator;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -10,9 +10,13 @@
|
||||
namespace mozilla {
|
||||
|
||||
// generate 1k sine wave per second
|
||||
template <typename Sample>
|
||||
class SineWaveGenerator {
|
||||
static_assert(std::is_same<Sample, int16_t>::value ||
|
||||
std::is_same<Sample, float>::value);
|
||||
|
||||
public:
|
||||
static const int bytesPerSample = 2;
|
||||
static const int bytesPerSample = sizeof(Sample);
|
||||
static const int millisecondsPerSecond = PR_MSEC_PER_SEC;
|
||||
|
||||
explicit SineWaveGenerator(uint32_t aSampleRate, uint32_t aFrequency)
|
||||
@ -21,15 +25,14 @@ class SineWaveGenerator {
|
||||
// rounded here We could include an error term and adjust for it in
|
||||
// generation; not worth the trouble
|
||||
// MOZ_ASSERT(mTotalLength * aFrequency == aSampleRate);
|
||||
mAudioBuffer = MakeUnique<int16_t[]>(mTotalLength);
|
||||
for (int i = 0; i < mTotalLength; i++) {
|
||||
// Set volume to -20db. It's from 32768.0 * 10^(-20/20) = 3276.8
|
||||
mAudioBuffer[i] = (3276.8f * sin(2 * M_PI * i / mTotalLength));
|
||||
mAudioBuffer = MakeUnique<Sample[]>(mTotalLength);
|
||||
for (uint32_t i = 0; i < mTotalLength; ++i) {
|
||||
mAudioBuffer[i] = Amplitude() * sin(2 * M_PI * i / mTotalLength);
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: only safely called from a single thread (MTG callback)
|
||||
void generate(int16_t* aBuffer, TrackTicks aLengthInSamples) {
|
||||
void generate(Sample* aBuffer, TrackTicks aLengthInSamples) {
|
||||
TrackTicks remaining = aLengthInSamples;
|
||||
|
||||
while (remaining) {
|
||||
@ -51,8 +54,20 @@ class SineWaveGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
void SetOffset(TrackTicks aFrames) { mReadLength = aFrames % mTotalLength; }
|
||||
|
||||
TrackTicks Offset() const { return mReadLength; }
|
||||
|
||||
static float Amplitude() {
|
||||
// Set volume to -20db.
|
||||
if (std::is_same<Sample, int16_t>::value) {
|
||||
return 3276.8; // 32768.0 * 10^(-20/20) = 3276.8
|
||||
}
|
||||
return 0.1f; // 1.0 * 10^(-20/20) = 0.1
|
||||
}
|
||||
|
||||
private:
|
||||
UniquePtr<int16_t[]> mAudioBuffer;
|
||||
UniquePtr<Sample[]> mAudioBuffer;
|
||||
TrackTicks mTotalLength;
|
||||
TrackTicks mReadLength;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user