bug 1391482 use AudioChunk to store and pass PeriodicWave data to engine r?padenot
This is mostly to be consistent with other nodes so that only a single
SetBuffer method is required to pass buffers from nodes to engines.
AudioChunk also has the advantage of ThreadSharedFloatArrayBufferList that it
keeps a record of the length of the buffer in the same struct, and so this is
passed to the engine with the buffer.
SharedBuffer needs one fewer allocation than ThreadSharedFloatArrayBufferList,
but this is not a hot path.
MozReview-Commit-ID: JsLcuFdFvRO
--- a/dom/media/webaudio/OscillatorNode.cpp
+++ b/dom/media/webaudio/OscillatorNode.cpp
@@ -36,33 +36,31 @@ public:
// Keep the default values in sync with OscillatorNode::OscillatorNode.
, mFrequency(440.f)
, mDetune(0.f)
, mType(OscillatorType::Sine)
, mPhase(0.)
, mFinalFrequency(0.)
, mPhaseIncrement(0.)
, mRecomputeParameters(true)
- , mCustomLength(0)
, mCustomDisableNormalization(false)
{
MOZ_ASSERT(NS_IsMainThread());
mBasicWaveFormCache = aDestination->Context()->GetBasicWaveFormCache();
}
void SetSourceStream(AudioNodeStream* aSource)
{
mSource = aSource;
}
enum Parameters {
FREQUENCY,
DETUNE,
TYPE,
- PERIODICWAVE_LENGTH,
DISABLE_NORMALIZATION,
START,
STOP,
};
void RecvTimelineEvent(uint32_t aIndex,
AudioTimelineEvent& aEvent) override
{
mRecomputeParameters = true;
@@ -100,17 +98,16 @@ public:
void SetInt32Parameter(uint32_t aIndex, int32_t aParam) override
{
switch (aIndex) {
case TYPE:
// Set the new type.
mType = static_cast<OscillatorType>(aParam);
if (mType == OscillatorType::Sine) {
// Forget any previous custom data.
- mCustomLength = 0;
mCustomDisableNormalization = false;
mPeriodicWave = nullptr;
mRecomputeParameters = true;
}
switch (mType) {
case OscillatorType::Sine:
mPhase = 0.0;
break;
@@ -121,41 +118,37 @@ public:
break;
case OscillatorType::Custom:
break;
default:
NS_ERROR("Bad OscillatorNodeEngine type parameter.");
}
// End type switch.
break;
- case PERIODICWAVE_LENGTH:
- MOZ_ASSERT(aParam >= 0, "negative custom array length");
- mCustomLength = static_cast<uint32_t>(aParam);
- break;
case DISABLE_NORMALIZATION:
MOZ_ASSERT(aParam >= 0, "negative custom array length");
mCustomDisableNormalization = static_cast<uint32_t>(aParam);
break;
default:
NS_ERROR("Bad OscillatorNodeEngine Int32Parameter.");
}
// End index switch.
}
- void SetBuffer(already_AddRefed<ThreadSharedFloatArrayBufferList> aBuffer) override
+ void SetBuffer(AudioChunk&& aBuffer) override
{
- MOZ_ASSERT(mCustomLength, "Custom buffer sent before length");
- RefPtr<ThreadSharedFloatArrayBufferList> custom = aBuffer;
- MOZ_ASSERT(custom->GetChannels() == 2,
+ MOZ_ASSERT(aBuffer.ChannelCount() == 2,
"PeriodicWave should have sent two channels");
- mPeriodicWave = WebCore::PeriodicWave::create(mSource->SampleRate(),
- custom->GetData(0),
- custom->GetData(1),
- mCustomLength,
- mCustomDisableNormalization);
+ MOZ_ASSERT(aBuffer.mVolume == 1.0f);
+ mPeriodicWave =
+ WebCore::PeriodicWave::create(mSource->SampleRate(),
+ aBuffer.ChannelData<float>()[0],
+ aBuffer.ChannelData<float>()[1],
+ aBuffer.mDuration,
+ mCustomDisableNormalization);
}
void IncrementPhase()
{
const float twoPiFloat = float(2 * M_PI);
mPhase += mPhaseIncrement;
if (mPhase > twoPiFloat) {
mPhase -= twoPiFloat;
@@ -392,17 +385,16 @@ public:
AudioParamTimeline mFrequency;
AudioParamTimeline mDetune;
OscillatorType mType;
float mPhase;
float mFinalFrequency;
float mPhaseIncrement;
bool mRecomputeParameters;
RefPtr<BasicWaveFormCache> mBasicWaveFormCache;
- uint32_t mCustomLength;
bool mCustomDisableNormalization;
RefPtr<WebCore::PeriodicWave> mPeriodicWave;
};
OscillatorNode::OscillatorNode(AudioContext* aContext)
: AudioScheduledSourceNode(aContext,
2,
ChannelCountMode::Max,
@@ -503,23 +495,20 @@ OscillatorNode::SendTypeToStream()
}
void OscillatorNode::SendPeriodicWaveToStream()
{
NS_ASSERTION(mType == OscillatorType::Custom,
"Sending custom waveform to engine thread with non-custom type");
MOZ_ASSERT(mStream, "Missing node stream.");
MOZ_ASSERT(mPeriodicWave, "Send called without PeriodicWave object.");
- SendInt32ParameterToStream(OscillatorNodeEngine::PERIODICWAVE_LENGTH,
- mPeriodicWave->DataLength());
SendInt32ParameterToStream(OscillatorNodeEngine::DISABLE_NORMALIZATION,
mPeriodicWave->DisableNormalization());
- RefPtr<ThreadSharedFloatArrayBufferList> data =
- mPeriodicWave->GetThreadSharedBuffer();
- mStream->SetBuffer(data.forget());
+ AudioChunk data = mPeriodicWave->GetThreadSharedBuffer();
+ mStream->SetBuffer(Move(data));
}
void
OscillatorNode::Start(double aWhen, ErrorResult& aRv)
{
if (!WebAudioUtils::IsTimeValid(aWhen)) {
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return;
--- a/dom/media/webaudio/PeriodicWave.cpp
+++ b/dom/media/webaudio/PeriodicWave.cpp
@@ -25,41 +25,47 @@ PeriodicWave::PeriodicWave(AudioContext*
: mContext(aContext)
, mDisableNormalization(aDisableNormalization)
{
MOZ_ASSERT(aContext);
MOZ_ASSERT(aRealData || aImagData);
// Caller should have checked this and thrown.
MOZ_ASSERT(aLength > 0);
- mLength = aLength;
+ mCoefficients.mDuration = aLength;
- // Copy coefficient data. The two arrays share an allocation.
- mCoefficients = new ThreadSharedFloatArrayBufferList(2);
- float* buffer = static_cast<float*>(malloc(aLength*sizeof(float)*2));
- if (buffer == nullptr) {
+ // Copy coefficient data.
+ // The SharedBuffer and two arrays share a single allocation.
+ RefPtr<SharedBuffer> buffer =
+ SharedBuffer::Create(sizeof(float) * aLength * 2, fallible);
+ if (!buffer) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return;
}
+ auto data = static_cast<float*>(buffer->Data());
+ mCoefficients.mBuffer = Move(buffer);
+
if (aRealData) {
- PodCopy(buffer, aRealData, aLength);
+ PodCopy(data, aRealData, aLength);
} else {
- PodZero(buffer, aLength);
+ PodZero(data, aLength);
}
-
- mCoefficients->SetData(0, buffer, free, buffer);
+ mCoefficients.mChannelData.AppendElement(data);
+ data += aLength;
if (aImagData) {
- PodCopy(buffer+aLength, aImagData, aLength);
+ PodCopy(data, aImagData, aLength);
} else {
- PodZero(buffer+aLength, aLength);
+ PodZero(data, aLength);
}
+ mCoefficients.mChannelData.AppendElement(data);
- mCoefficients->SetData(1, nullptr, free, buffer+aLength);
+ mCoefficients.mVolume = 1.0f;
+ mCoefficients.mBufferFormat = AUDIO_FORMAT_FLOAT32;
}
/* static */ already_AddRefed<PeriodicWave>
PeriodicWave::Constructor(const GlobalObject& aGlobal,
AudioContext& aAudioContext,
const PeriodicWaveOptions& aOptions,
ErrorResult& aRv)
{
@@ -97,19 +103,17 @@ PeriodicWave::Constructor(const GlobalOb
}
size_t
PeriodicWave::SizeOfExcludingThisIfNotShared(MallocSizeOf aMallocSizeOf) const
{
// Not owned:
// - mContext
size_t amount = 0;
- if (!mCoefficients->IsShared()) {
- amount += mCoefficients->SizeOfIncludingThis(aMallocSizeOf);
- }
+ amount += mCoefficients.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
return amount;
}
size_t
PeriodicWave::SizeOfIncludingThisIfNotShared(MallocSizeOf aMallocSizeOf) const
{
return aMallocSizeOf(this) + SizeOfExcludingThisIfNotShared(aMallocSizeOf);
--- a/dom/media/webaudio/PeriodicWave.h
+++ b/dom/media/webaudio/PeriodicWave.h
@@ -41,37 +41,36 @@ public:
{
return mContext;
}
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
uint32_t DataLength() const
{
- return mLength;
+ return mCoefficients.mDuration;
}
bool DisableNormalization() const
{
return mDisableNormalization;
}
- ThreadSharedFloatArrayBufferList* GetThreadSharedBuffer() const
+ const AudioChunk& GetThreadSharedBuffer() const
{
return mCoefficients;
}
size_t SizeOfExcludingThisIfNotShared(MallocSizeOf aMallocSizeOf) const;
size_t SizeOfIncludingThisIfNotShared(MallocSizeOf aMallocSizeOf) const;
private:
~PeriodicWave() = default;
+ AudioChunk mCoefficients;
RefPtr<AudioContext> mContext;
- RefPtr<ThreadSharedFloatArrayBufferList> mCoefficients;
- uint32_t mLength;
bool mDisableNormalization;
};
} // namespace dom
} // namespace mozilla
#endif