Bug 1265405 - Use a dictionary to specify how PeriodicWave should be normalized (or not); r?padenot
MozReview-Commit-ID: IH7no48COML
--- a/dom/media/webaudio/AudioContext.cpp
+++ b/dom/media/webaudio/AudioContext.cpp
@@ -537,17 +537,18 @@ AudioContext::CreatePeriodicWave(const F
if (aRealData.Length() != aImagData.Length() ||
aRealData.Length() == 0) {
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return nullptr;
}
RefPtr<PeriodicWave> periodicWave =
new PeriodicWave(this, aRealData.Data(), aImagData.Data(),
- aImagData.Length(), aRv);
+ aImagData.Length(), aConstraints.mDisableNormalization,
+ aRv);
if (aRv.Failed()) {
return nullptr;
}
return periodicWave.forget();
}
AudioListener*
AudioContext::Listener()
--- a/dom/media/webaudio/OscillatorNode.cpp
+++ b/dom/media/webaudio/OscillatorNode.cpp
@@ -37,31 +37,33 @@ public:
, 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,
+ PERIODICWAVE_LENGTH,
+ DISABLE_NORMALIZATION,
START,
STOP,
};
void RecvTimelineEvent(uint32_t aIndex,
AudioTimelineEvent& aEvent) override
{
mRecomputeParameters = true;
@@ -99,16 +101,17 @@ public:
{
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;
mCustom = nullptr;
mPeriodicWave = nullptr;
mRecomputeParameters = true;
}
switch (mType) {
case OscillatorType::Sine:
mPhase = 0.0;
break;
@@ -119,34 +122,41 @@ public:
break;
case OscillatorType::Custom:
break;
default:
NS_ERROR("Bad OscillatorNodeEngine type parameter.");
}
// End type switch.
break;
- case PERIODICWAVE:
+ 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
{
MOZ_ASSERT(mCustomLength, "Custom buffer sent before length");
mCustom = aBuffer;
MOZ_ASSERT(mCustom->GetChannels() == 2,
"PeriodicWave should have sent two channels");
mPeriodicWave = WebCore::PeriodicWave::create(mSource->SampleRate(),
- mCustom->GetData(0), mCustom->GetData(1), mCustomLength);
+ mCustom->GetData(0),
+ mCustom->GetData(1),
+ mCustomLength,
+ mCustomDisableNormalization);
}
void IncrementPhase()
{
const float twoPiFloat = float(2 * M_PI);
mPhase += mPhaseIncrement;
if (mPhase > twoPiFloat) {
mPhase -= twoPiFloat;
@@ -388,16 +398,17 @@ public:
OscillatorType mType;
float mPhase;
float mFinalFrequency;
float mPhaseIncrement;
bool mRecomputeParameters;
RefPtr<ThreadSharedFloatArrayBufferList> mCustom;
RefPtr<BasicWaveFormCache> mBasicWaveFormCache;
uint32_t mCustomLength;
+ bool mCustomDisableNormalization;
RefPtr<WebCore::PeriodicWave> mPeriodicWave;
};
OscillatorNode::OscillatorNode(AudioContext* aContext)
: AudioNode(aContext,
2,
ChannelCountMode::Max,
ChannelInterpretation::Speakers)
@@ -467,18 +478,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,
+ SendInt32ParameterToStream(OscillatorNodeEngine::PERIODICWAVE_LENGTH,
mPeriodicWave->DataLength());
+ SendInt32ParameterToStream(OscillatorNodeEngine::DISABLE_NORMALIZATION,
+ mPeriodicWave->DisableNormalization());
RefPtr<ThreadSharedFloatArrayBufferList> data =
mPeriodicWave->GetThreadSharedBuffer();
mStream->SetBuffer(data.forget());
}
void
OscillatorNode::Start(double aWhen, ErrorResult& aRv)
{
--- a/dom/media/webaudio/PeriodicWave.cpp
+++ b/dom/media/webaudio/PeriodicWave.cpp
@@ -15,18 +15,20 @@ NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Pe
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(PeriodicWave, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(PeriodicWave, Release)
PeriodicWave::PeriodicWave(AudioContext* aContext,
const float* aRealData,
const float* aImagData,
const uint32_t aLength,
+ const bool aDisableNormalization,
ErrorResult& aRv)
: mContext(aContext)
+ , mDisableNormalization(aDisableNormalization)
{
MOZ_ASSERT(aContext);
// Caller should have checked this and thrown.
MOZ_ASSERT(aLength > 0);
mLength = aLength;
// Copy coefficient data. The two arrays share an allocation.
--- a/dom/media/webaudio/PeriodicWave.h
+++ b/dom/media/webaudio/PeriodicWave.h
@@ -19,16 +19,17 @@ namespace dom {
class PeriodicWave final : public nsWrapperCache
{
public:
PeriodicWave(AudioContext* aContext,
const float* aRealData,
const float* aImagData,
const uint32_t aLength,
+ const bool aDisableNormalization,
ErrorResult& aRv);
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(PeriodicWave)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(PeriodicWave)
AudioContext* GetParentObject() const
{
return mContext;
@@ -36,28 +37,34 @@ public:
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
uint32_t DataLength() const
{
return mLength;
}
+ bool DisableNormalization() const
+ {
+ return mDisableNormalization;
+ }
+
ThreadSharedFloatArrayBufferList* GetThreadSharedBuffer() const
{
return mCoefficients;
}
size_t SizeOfExcludingThisIfNotShared(MallocSizeOf aMallocSizeOf) const;
size_t SizeOfIncludingThisIfNotShared(MallocSizeOf aMallocSizeOf) const;
private:
~PeriodicWave() {}
RefPtr<AudioContext> mContext;
RefPtr<ThreadSharedFloatArrayBufferList> mCoefficients;
uint32_t mLength;
+ bool mDisableNormalization;
};
} // namespace dom
} // namespace mozilla
#endif
--- a/dom/media/webaudio/blink/PeriodicWave.cpp
+++ b/dom/media/webaudio/blink/PeriodicWave.cpp
@@ -40,23 +40,25 @@ using namespace mozilla;
using mozilla::dom::OscillatorType;
namespace WebCore {
already_AddRefed<PeriodicWave>
PeriodicWave::create(float sampleRate,
const float* real,
const float* imag,
- size_t numberOfComponents)
+ size_t numberOfComponents,
+ bool disableNormalization)
{
bool isGood = real && imag && numberOfComponents > 0;
MOZ_ASSERT(isGood);
if (isGood) {
RefPtr<PeriodicWave> periodicWave =
- new PeriodicWave(sampleRate, numberOfComponents);
+ new PeriodicWave(sampleRate, numberOfComponents,
+ disableNormalization);
// Limit the number of components used to those for frequencies below the
// Nyquist of the fixed length inverse FFT.
size_t halfSize = periodicWave->m_periodicWaveSize / 2;
numberOfComponents = std::min(numberOfComponents, halfSize);
periodicWave->m_numberOfComponents = numberOfComponents;
periodicWave->m_realComponents = new AudioFloatArray(numberOfComponents);
periodicWave->m_imagComponents = new AudioFloatArray(numberOfComponents);
@@ -69,51 +71,52 @@ PeriodicWave::create(float sampleRate,
}
return nullptr;
}
already_AddRefed<PeriodicWave>
PeriodicWave::createSine(float sampleRate)
{
RefPtr<PeriodicWave> periodicWave =
- new PeriodicWave(sampleRate, MinPeriodicWaveSize);
+ new PeriodicWave(sampleRate, MinPeriodicWaveSize, false);
periodicWave->generateBasicWaveform(OscillatorType::Sine);
return periodicWave.forget();
}
already_AddRefed<PeriodicWave>
PeriodicWave::createSquare(float sampleRate)
{
RefPtr<PeriodicWave> periodicWave =
- new PeriodicWave(sampleRate, MinPeriodicWaveSize);
+ new PeriodicWave(sampleRate, MinPeriodicWaveSize, false);
periodicWave->generateBasicWaveform(OscillatorType::Square);
return periodicWave.forget();
}
already_AddRefed<PeriodicWave>
PeriodicWave::createSawtooth(float sampleRate)
{
RefPtr<PeriodicWave> periodicWave =
- new PeriodicWave(sampleRate, MinPeriodicWaveSize);
+ new PeriodicWave(sampleRate, MinPeriodicWaveSize, false);
periodicWave->generateBasicWaveform(OscillatorType::Sawtooth);
return periodicWave.forget();
}
already_AddRefed<PeriodicWave>
PeriodicWave::createTriangle(float sampleRate)
{
RefPtr<PeriodicWave> periodicWave =
- new PeriodicWave(sampleRate, MinPeriodicWaveSize);
+ new PeriodicWave(sampleRate, MinPeriodicWaveSize, false);
periodicWave->generateBasicWaveform(OscillatorType::Triangle);
return periodicWave.forget();
}
-PeriodicWave::PeriodicWave(float sampleRate, size_t numberOfComponents)
+PeriodicWave::PeriodicWave(float sampleRate, size_t numberOfComponents, bool disableNormalization)
: m_sampleRate(sampleRate)
, m_centsPerRange(CentsPerRange)
+ , m_disableNormalization(disableNormalization)
, m_maxPartialsInBandLimitedTable(0)
, m_normalizationScale(1.0f)
{
float nyquist = 0.5 * m_sampleRate;
if (numberOfComponents <= MinPeriodicWaveSize) {
m_periodicWaveSize = MinPeriodicWaveSize;
} else {
@@ -262,26 +265,28 @@ void PeriodicWave::createBandLimitedTabl
m_bandLimitedTables[rangeIndex] = table;
// Apply an inverse FFT to generate the time-domain table data.
float* data = m_bandLimitedTables[rangeIndex]->Elements();
frame.GetInverseWithoutScaling(data);
// For the first range (which has the highest power), calculate
// its peak value then compute normalization scale.
- if (!rangeIndex) {
+ if (!m_disableNormalization && !rangeIndex) {
float maxValue;
maxValue = AudioBufferPeakValue(data, m_periodicWaveSize);
if (maxValue)
m_normalizationScale = 1.0f / maxValue;
}
// Apply normalization scale.
- AudioBufferInPlaceScale(data, m_normalizationScale, m_periodicWaveSize);
+ if (!m_disableNormalization) {
+ AudioBufferInPlaceScale(data, m_normalizationScale, m_periodicWaveSize);
+ }
}
void PeriodicWave::generateBasicWaveform(OscillatorType shape)
{
const float piFloat = float(M_PI);
unsigned fftSize = periodicWaveSize();
unsigned halfSize = fftSize / 2;
--- a/dom/media/webaudio/blink/PeriodicWave.h
+++ b/dom/media/webaudio/blink/PeriodicWave.h
@@ -49,17 +49,18 @@ public:
static already_AddRefed<PeriodicWave> createSawtooth(float sampleRate);
static already_AddRefed<PeriodicWave> createTriangle(float sampleRate);
// Creates an arbitrary periodic wave given the frequency components
// (Fourier coefficients).
static already_AddRefed<PeriodicWave> create(float sampleRate,
const float* real,
const float* imag,
- size_t numberOfComponents);
+ size_t numberOfComponents,
+ bool disableNormalization);
// Returns pointers to the lower and higher wave data for the pitch range
// containing the given fundamental frequency. These two tables are in
// adjacent "pitch" ranges where the higher table will have the maximum
// number of partials which won't alias when played back at this
// fundamental frequency. The lower wave is the next range containing fewer
// partials than the higher wave. Interpolation between these two tables
// can be made according to tableInterpolationFactor. Where values
@@ -71,17 +72,17 @@ public:
float rateScale() const { return m_rateScale; }
unsigned periodicWaveSize() const { return m_periodicWaveSize; }
float sampleRate() const { return m_sampleRate; }
size_t sizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
private:
- explicit PeriodicWave(float sampleRate, size_t numberOfComponents);
+ explicit PeriodicWave(float sampleRate, size_t numberOfComponents, bool disableNormalization);
~PeriodicWave() {}
void generateBasicWaveform(mozilla::dom::OscillatorType);
float m_sampleRate;
unsigned m_periodicWaveSize;
unsigned m_numberOfRanges;
float m_centsPerRange;
@@ -103,14 +104,15 @@ private:
unsigned maxNumberOfPartials() const;
unsigned numberOfPartialsForRange(unsigned rangeIndex) const;
// Creates table for specified index based on fundamental frequency.
void createBandLimitedTables(float fundamentalFrequency, unsigned rangeIndex);
unsigned m_maxPartialsInBandLimitedTable;
float m_normalizationScale;
+ bool m_disableNormalization;
nsTArray<nsAutoPtr<AlignedAudioFloatArray> > m_bandLimitedTables;
};
} // namespace WebCore
#endif // PeriodicWave_h