bug use AudioChunk to store and pass PeriodicWave data to engine r?padenot draft
authorKarl Tomlinson <karlt+@karlt.net>
Thu, 10 Aug 2017 20:26:20 +1200
changeset 645171 cd129d831847644e6ca3dc66f590af66aa540207
parent 645170 91d362093d8ee98543b047059154194600882890
child 645172 772d179c310594a283ccd8943eb8f5555bfaf535
push id73684
push userktomlinson@mozilla.com
push dateFri, 11 Aug 2017 22:29:12 +0000
reviewerspadenot
milestone57.0a1
bug use AudioChunk to store and pass PeriodicWave data to engine r?padenot
dom/media/webaudio/OscillatorNode.cpp
dom/media/webaudio/PeriodicWave.cpp
dom/media/webaudio/PeriodicWave.h
--- 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,48 @@ 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);
+  mCoefficients.mChannelData.SetCapacity(2);
+
   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(buffer);
 
+  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 +104,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