Bug 1872003 uninline AudioSegment::Resample() to remove MediaTrackGraph.h include r=padenot

Depends on D197876

Differential Revision: https://phabricator.services.mozilla.com/D197877
This commit is contained in:
Karl Tomlinson 2024-01-09 00:11:22 +00:00
Родитель 6fb77931ec
Коммит 0263de1ada
4 изменённых файлов: 67 добавлений и 60 удалений

Просмотреть файл

@ -6,6 +6,7 @@
#include "AudioSegment.h"
#include "AudioMixer.h"
#include "AudioChannelFormat.h"
#include "MediaTrackGraph.h" // for nsAutoRefTraits<SpeexResamplerState>
#include <speex/speex_resampler.h>
namespace mozilla {
@ -30,6 +31,64 @@ void AudioSegment::ApplyVolume(float aVolume) {
}
}
template <typename T>
void AudioSegment::Resample(nsAutoRef<SpeexResamplerState>& aResampler,
uint32_t* aResamplerChannelCount, uint32_t aInRate,
uint32_t aOutRate) {
mDuration = 0;
for (ChunkIterator ci(*this); !ci.IsEnded(); ci.Next()) {
AutoTArray<nsTArray<T>, GUESS_AUDIO_CHANNELS> output;
AutoTArray<const T*, GUESS_AUDIO_CHANNELS> bufferPtrs;
AudioChunk& c = *ci;
// If this chunk is null, don't bother resampling, just alter its duration
if (c.IsNull()) {
c.mDuration = (c.mDuration * aOutRate) / aInRate;
mDuration += c.mDuration;
continue;
}
uint32_t channels = c.mChannelData.Length();
// This might introduce a discontinuity, but a channel count change in the
// middle of a stream is not that common. This also initializes the
// resampler as late as possible.
if (channels != *aResamplerChannelCount) {
SpeexResamplerState* state =
speex_resampler_init(channels, aInRate, aOutRate,
SPEEX_RESAMPLER_QUALITY_DEFAULT, nullptr);
MOZ_ASSERT(state);
aResampler.own(state);
*aResamplerChannelCount = channels;
}
output.SetLength(channels);
bufferPtrs.SetLength(channels);
uint32_t inFrames = c.mDuration;
// Round up to allocate; the last frame may not be used.
NS_ASSERTION((UINT64_MAX - aInRate + 1) / c.mDuration >= aOutRate,
"Dropping samples");
uint32_t outSize =
(static_cast<uint64_t>(c.mDuration) * aOutRate + aInRate - 1) / aInRate;
for (uint32_t i = 0; i < channels; i++) {
T* out = output[i].AppendElements(outSize);
uint32_t outFrames = outSize;
const T* in = static_cast<const T*>(c.mChannelData[i]);
dom::WebAudioUtils::SpeexResamplerProcess(aResampler.get(), i, in,
&inFrames, out, &outFrames);
MOZ_ASSERT(inFrames == c.mDuration);
bufferPtrs[i] = out;
output[i].SetLength(outFrames);
}
MOZ_ASSERT(channels > 0);
c.mDuration = output[0].Length();
c.mBuffer = new mozilla::SharedChannelArrayBuffer<T>(std::move(output));
for (uint32_t i = 0; i < channels; i++) {
c.mChannelData[i] = bufferPtrs[i];
}
mDuration += c.mDuration;
}
}
void AudioSegment::ResampleChunks(nsAutoRef<SpeexResamplerState>& aResampler,
uint32_t* aResamplerChannelCount,
uint32_t aInRate, uint32_t aOutRate) {

Просмотреть файл

@ -7,7 +7,6 @@
#define MOZILLA_AUDIOSEGMENT_H_
#include <speex/speex_resampler.h>
#include "MediaTrackGraph.h"
#include "MediaSegment.h"
#include "AudioSampleFormat.h"
#include "AudioChannelFormat.h"
@ -337,65 +336,6 @@ class AudioSegment : public MediaSegmentBase<AudioSegment, AudioChunk> {
// function finds a chunk with more channels, `aResampler` is destroyed and a
// new resampler is created, and `aResamplerChannelCount` is updated with the
// new channel count value.
template <typename T>
void Resample(nsAutoRef<SpeexResamplerState>& aResampler,
uint32_t* aResamplerChannelCount, uint32_t aInRate,
uint32_t aOutRate) {
mDuration = 0;
for (ChunkIterator ci(*this); !ci.IsEnded(); ci.Next()) {
AutoTArray<nsTArray<T>, GUESS_AUDIO_CHANNELS> output;
AutoTArray<const T*, GUESS_AUDIO_CHANNELS> bufferPtrs;
AudioChunk& c = *ci;
// If this chunk is null, don't bother resampling, just alter its duration
if (c.IsNull()) {
c.mDuration = (c.mDuration * aOutRate) / aInRate;
mDuration += c.mDuration;
continue;
}
uint32_t channels = c.mChannelData.Length();
// This might introduce a discontinuity, but a channel count change in the
// middle of a stream is not that common. This also initializes the
// resampler as late as possible.
if (channels != *aResamplerChannelCount) {
SpeexResamplerState* state =
speex_resampler_init(channels, aInRate, aOutRate,
SPEEX_RESAMPLER_QUALITY_DEFAULT, nullptr);
MOZ_ASSERT(state);
aResampler.own(state);
*aResamplerChannelCount = channels;
}
output.SetLength(channels);
bufferPtrs.SetLength(channels);
uint32_t inFrames = c.mDuration;
// Round up to allocate; the last frame may not be used.
NS_ASSERTION((UINT64_MAX - aInRate + 1) / c.mDuration >= aOutRate,
"Dropping samples");
uint32_t outSize =
(static_cast<uint64_t>(c.mDuration) * aOutRate + aInRate - 1) /
aInRate;
for (uint32_t i = 0; i < channels; i++) {
T* out = output[i].AppendElements(outSize);
uint32_t outFrames = outSize;
const T* in = static_cast<const T*>(c.mChannelData[i]);
dom::WebAudioUtils::SpeexResamplerProcess(aResampler.get(), i, in,
&inFrames, out, &outFrames);
MOZ_ASSERT(inFrames == c.mDuration);
bufferPtrs[i] = out;
output[i].SetLength(outFrames);
}
MOZ_ASSERT(channels > 0);
c.mDuration = output[0].Length();
c.mBuffer = new mozilla::SharedChannelArrayBuffer<T>(std::move(output));
for (uint32_t i = 0; i < channels; i++) {
c.mChannelData[i] = bufferPtrs[i];
}
mDuration += c.mDuration;
}
}
void ResampleChunks(nsAutoRef<SpeexResamplerState>& aResampler,
uint32_t* aResamplerChannelCount, uint32_t aInRate,
uint32_t aOutRate);
@ -509,6 +449,12 @@ class AudioSegment : public MediaSegmentBase<AudioSegment, AudioChunk> {
}
}
}
private:
template <typename T>
void Resample(nsAutoRef<SpeexResamplerState>& aResampler,
uint32_t* aResamplerChannelCount, uint32_t aInRate,
uint32_t aOutRate);
};
template <typename SrcT>

Просмотреть файл

@ -10,6 +10,7 @@
#include "AudioVerifier.h"
#include "MediaEventSource.h"
#include "mozilla/DataMutex.h"
#include "mozilla/MozPromise.h"
#include "mozilla/ThreadSafeWeakPtr.h"
#include "nsTArray.h"

Просмотреть файл

@ -28,6 +28,7 @@ class AudioData;
class VideoData;
struct PlaybackInfoInit;
class ProcessedMediaTrack;
struct SharedDummyTrack;
class TimeStamp;
template <class T>