Title: [198903] branches/safari-601.1.46-branch/Source/WebCore

Diff

Modified: branches/safari-601.1.46-branch/Source/WebCore/ChangeLog (198902 => 198903)


--- branches/safari-601.1.46-branch/Source/WebCore/ChangeLog	2016-03-31 18:28:48 UTC (rev 198902)
+++ branches/safari-601.1.46-branch/Source/WebCore/ChangeLog	2016-03-31 18:45:26 UTC (rev 198903)
@@ -1,3 +1,31 @@
+2016-03-31  Matthew Hanson  <matthew_han...@apple.com>
+
+        Merge r198035. rdar://problem/25467558
+
+    2016-03-10  Jer Noble  <jer.no...@apple.com>
+
+            Web Audio becomes distorted after sample rate changes
+            https://bugs.webkit.org/show_bug.cgi?id=154538
+            <rdar://problem/24771292>
+
+            Reviewed by Darin Adler.
+
+            When the underlying audio hardware sample rate changes, the AudioUnit render callback will begin asking
+            for fewer or more frames. For example, when the sample rate goes from 44.1kHz to 48kHz, it will ask for
+            118 samples instead of 128. (And vice-versa, 140 samples instead of 128.) But the Web Audio engine can only
+            really handle requests in multiples of 128 samples. In the case where there are requests for < 128 samples,
+            actually render 128, but save off the unrequested samples in a separate bus. Then fill that bus during the
+            next request.
+
+            * platform/audio/AudioBus.cpp:
+            (WebCore::AudioBus::copyFromRange): Added utility method.
+            * platform/audio/AudioBus.h:
+            * platform/audio/ios/AudioDestinationIOS.cpp:
+            (WebCore::AudioDestinationIOS::AudioDestinationIOS): Create a "spare" bus.
+            (WebCore::assignAudioBuffersToBus): Moved from inside render.
+            (WebCore::AudioDestinationIOS::render): Save off extra samples to the "spare" bus.
+            * platform/audio/ios/AudioDestinationIOS.h:
+
 2016-03-25  Matthew Hanson  <matthew_han...@apple.com>
 
         Merge r197856. rdar://problem/25152411

Modified: branches/safari-601.1.46-branch/Source/WebCore/platform/audio/AudioBus.cpp (198902 => 198903)


--- branches/safari-601.1.46-branch/Source/WebCore/platform/audio/AudioBus.cpp	2016-03-31 18:28:48 UTC (rev 198902)
+++ branches/safari-601.1.46-branch/Source/WebCore/platform/audio/AudioBus.cpp	2016-03-31 18:45:26 UTC (rev 198903)
@@ -213,6 +213,33 @@
         channel(i)->scale(scale);
 }
 
+void AudioBus::copyFromRange(const AudioBus& sourceBus, unsigned startFrame, unsigned endFrame)
+{
+    if (!topologyMatches(sourceBus)) {
+        ASSERT_NOT_REACHED();
+        zero();
+        return;
+    }
+
+    size_t numberOfSourceFrames = sourceBus.length();
+    bool isRangeSafe = startFrame < endFrame && endFrame <= numberOfSourceFrames;
+    ASSERT(isRangeSafe);
+    if (!isRangeSafe) {
+        zero();
+        return;
+    }
+
+    unsigned numberOfChannels = this->numberOfChannels();
+    ASSERT(numberOfChannels <= MaxBusChannels);
+    if (numberOfChannels > MaxBusChannels) {
+        zero();
+        return;
+    }
+
+    for (unsigned i = 0; i < numberOfChannels; ++i)
+        channel(i)->copyFromRange(sourceBus.channel(i), startFrame, endFrame);
+}
+
 void AudioBus::copyFrom(const AudioBus& sourceBus, ChannelInterpretation channelInterpretation)
 {
     if (&sourceBus == this)

Modified: branches/safari-601.1.46-branch/Source/WebCore/platform/audio/AudioBus.h (198902 => 198903)


--- branches/safari-601.1.46-branch/Source/WebCore/platform/audio/AudioBus.h	2016-03-31 18:28:48 UTC (rev 198902)
+++ branches/safari-601.1.46-branch/Source/WebCore/platform/audio/AudioBus.h	2016-03-31 18:45:26 UTC (rev 198903)
@@ -122,6 +122,9 @@
     void reset() { m_isFirstTime = true; } // for de-zippering
 
     // Copies the samples from the source bus to this one.
+    void copyFromRange(const AudioBus& sourceBus, unsigned startFrame, unsigned endFrame);
+
+    // Copies the samples from the source bus to this one.
     // This is just a simple per-channel copy if the number of channels match, otherwise an up-mix or down-mix is done.
     void copyFrom(const AudioBus& sourceBus, ChannelInterpretation = Speakers);
 

Modified: branches/safari-601.1.46-branch/Source/WebCore/platform/audio/ios/AudioDestinationIOS.cpp (198902 => 198903)


--- branches/safari-601.1.46-branch/Source/WebCore/platform/audio/ios/AudioDestinationIOS.cpp	2016-03-31 18:28:48 UTC (rev 198902)
+++ branches/safari-601.1.46-branch/Source/WebCore/platform/audio/ios/AudioDestinationIOS.cpp	2016-03-31 18:45:26 UTC (rev 198903)
@@ -100,6 +100,7 @@
     : m_outputUnit(0)
     , m_callback(callback)
     , m_renderBus(AudioBus::create(2, kRenderBufferSize, false))
+    , m_spareBus(AudioBus::create(2, kRenderBufferSize, true))
     , m_sampleRate(sampleRate)
     , m_isPlaying(false)
 {
@@ -198,19 +199,47 @@
         setIsPlaying(false);
 }
 
+static void assignAudioBuffersToBus(AudioBuffer* buffers, AudioBus& bus, UInt32 numberOfBuffers, UInt32 numberOfFrames, UInt32 frameOffset, UInt32 framesThisTime)
+{
+    for (UInt32 i = 0; i < numberOfBuffers; ++i) {
+        UInt32 bytesPerFrame = buffers[i].mDataByteSize / numberOfFrames;
+        UInt32 byteOffset = frameOffset * bytesPerFrame;
+        float* memory = reinterpret_cast<float*>(reinterpret_cast<char*>(buffers[i].mData) + byteOffset);
+        bus.setChannelMemory(i, memory, framesThisTime);
+    }
+}
+
 // Pulls on our provider to get rendered audio stream.
 OSStatus AudioDestinationIOS::render(UInt32 numberOfFrames, AudioBufferList* ioData)
 {
     AudioBuffer* buffers = ioData->mBuffers;
-    for (UInt32 frameOffset = 0; frameOffset + kRenderBufferSize <= numberOfFrames; frameOffset += kRenderBufferSize) {
-        UInt32 remainingFrames = std::min<UInt32>(kRenderBufferSize, numberOfFrames - frameOffset);
-        for (UInt32 i = 0; i < ioData->mNumberBuffers; ++i) {
-            UInt32 bytesPerFrame = buffers[i].mDataByteSize / numberOfFrames;
-            UInt32 byteOffset = frameOffset * bytesPerFrame;
-            float* memory = (float*)((char*)buffers[i].mData + byteOffset);
-            m_renderBus->setChannelMemory(i, memory, remainingFrames);
+    UInt32 numberOfBuffers = ioData->mNumberBuffers;
+    UInt32 framesRemaining = numberOfFrames;
+    UInt32 frameOffset = 0;
+    while (framesRemaining > 0) {
+        if (m_firstSpareFrame && m_lastSpareFrame) {
+            ASSERT(m_firstSpareFrame < m_lastSpareFrame);
+            UInt32 framesThisTime = m_lastSpareFrame - m_firstSpareFrame;
+            assignAudioBuffersToBus(buffers, *m_renderBus, numberOfBuffers, numberOfFrames, frameOffset, framesThisTime);
+            m_renderBus->copyFromRange(*m_spareBus, m_firstSpareFrame, m_lastSpareFrame);
+            frameOffset += framesThisTime;
+            framesRemaining -= framesThisTime;
+            m_firstSpareFrame = 0;
+            m_lastSpareFrame = 0;
         }
-        m_callback.render(0, m_renderBus.get(), remainingFrames);
+
+        UInt32 framesThisTime = std::min<UInt32>(kRenderBufferSize, framesRemaining);
+        assignAudioBuffersToBus(buffers, *m_renderBus, numberOfBuffers, numberOfFrames, frameOffset, framesThisTime);
+
+        if (framesThisTime < kRenderBufferSize) {
+            m_callback.render(0, m_spareBus.get(), kRenderBufferSize);
+            m_renderBus->copyFromRange(*m_spareBus, 0, framesThisTime);
+            m_firstSpareFrame = framesThisTime;
+            m_lastSpareFrame = kRenderBufferSize - 1;
+        } else
+            m_callback.render(0, m_renderBus.get(), framesThisTime);
+        frameOffset += framesThisTime;
+        framesRemaining -= framesThisTime;
     }
 
     return noErr;

Modified: branches/safari-601.1.46-branch/Source/WebCore/platform/audio/ios/AudioDestinationIOS.h (198902 => 198903)


--- branches/safari-601.1.46-branch/Source/WebCore/platform/audio/ios/AudioDestinationIOS.h	2016-03-31 18:28:48 UTC (rev 198902)
+++ branches/safari-601.1.46-branch/Source/WebCore/platform/audio/ios/AudioDestinationIOS.h	2016-03-31 18:45:26 UTC (rev 198903)
@@ -65,6 +65,9 @@
     AudioUnit m_outputUnit;
     AudioIOCallback& m_callback;
     RefPtr<AudioBus> m_renderBus;
+    RefPtr<AudioBus> m_spareBus;
+    unsigned m_firstSpareFrame { 0 };
+    unsigned m_lastSpareFrame { 0 };
 
     double m_sampleRate;
     bool m_isPlaying;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to