Title: [267014] trunk/Source/WebCore
Revision
267014
Author
[email protected]
Date
2020-09-14 08:47:53 -0700 (Mon, 14 Sep 2020)

Log Message

Add proper support for AudioContextOptions.sampleRate
https://bugs.webkit.org/show_bug.cgi?id=216425

Reviewed by Eric Carlson.

Add proper support for AudioContextOptions.sampleRate. Previously, our AudioContext always ran
at the hardware's sampleRate, no matter what value was set for AudioContextOptions.sampleRate.

This patch is based on the following Chromium changes:
- https://chromium-review.googlesource.com/c/chromium/src/+/1482957
- https://codereview.chromium.org/2549093009
- https://codereview.chromium.org/14189035

* Modules/webaudio/DefaultAudioDestinationNode.cpp:
(WebCore::DefaultAudioDestinationNode::createDestination):
When creating an AudioDestination, pass the requested AudioContext sample rate
instead of the hardware sample rate.

* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:

* platform/audio/AudioFIFO.cpp: Removed.
* platform/audio/AudioFIFO.h: Removed.
* platform/audio/AudioPullFIFO.cpp: Removed.
* platform/audio/AudioPullFIFO.h: Removed.
* platform/audio/PushPullFIFO.cpp: Added.
* platform/audio/PushPullFIFO.h: Added.
Replace AudioFIFO and AudioPullFIFO with a new PushPullFIFO replacement, similarly
to what was done in Chromium in:
- https://codereview.chromium.org/2549093009

* platform/audio/MultiChannelResampler.cpp:
(WebCore::MultiChannelResampler::MultiChannelResampler):
* platform/audio/MultiChannelResampler.h:
* platform/audio/SincResampler.cpp:
(WebCore::SincResampler::SincResampler):
(WebCore::SincResampler::updateRegions):
(WebCore::SincResampler::initializeKernel):
(WebCore::SincResampler::process):
* platform/audio/SincResampler.h:
Add parameter to MultiChannelResampler & SincResampler to allow the client to specify
the size of the buffer in frames when the resampler calls AudioSourceProvider::provideInput()
to get input data. This is necessary because our WebAudio implementation uses a static
buffer size of 128 frames. This is similar to what was done in Chromium in:
- https://codereview.chromium.org/14189035

* platform/audio/cocoa/AudioDestinationCocoa.cpp:
(WebCore::AudioDestinationCocoa::AudioDestinationCocoa):
(WebCore::AudioDestinationCocoa::setAudioStreamBasicDescription):
(WebCore::AudioDestinationCocoa::render):
(WebCore::AudioDestinationCocoa::provideInput):
* platform/audio/cocoa/AudioDestinationCocoa.h:
- Adopt PushPullFIFO to resolve the buffer size mismatch between the WebAudio engine and
  the callback function from the actual audio device, similarly to what was done in Chromium.
- When the context's sample rate differs from the hardware sample rate, instantiate a
  MultiChannelResampler and use it in render() to do the resampling.

* platform/audio/ios/AudioDestinationIOS.cpp:
(WebCore::AudioDestinationCocoa::configure):
* platform/audio/mac/AudioDestinationMac.cpp:
(WebCore::AudioDestinationCocoa::configure):
Drop sampleRate parameter as it is no longer needed.

* platform/mock/MockAudioDestinationCocoa.cpp:
(WebCore::MockAudioDestinationCocoa::tick):

Modified Paths

Added Paths

Removed Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (267013 => 267014)


--- trunk/Source/WebCore/ChangeLog	2020-09-14 15:44:59 UTC (rev 267013)
+++ trunk/Source/WebCore/ChangeLog	2020-09-14 15:47:53 UTC (rev 267014)
@@ -1,3 +1,71 @@
+2020-09-14  Chris Dumez  <[email protected]>
+
+        Add proper support for AudioContextOptions.sampleRate
+        https://bugs.webkit.org/show_bug.cgi?id=216425
+
+        Reviewed by Eric Carlson.
+
+        Add proper support for AudioContextOptions.sampleRate. Previously, our AudioContext always ran
+        at the hardware's sampleRate, no matter what value was set for AudioContextOptions.sampleRate.
+
+        This patch is based on the following Chromium changes:
+        - https://chromium-review.googlesource.com/c/chromium/src/+/1482957
+        - https://codereview.chromium.org/2549093009
+        - https://codereview.chromium.org/14189035
+
+        * Modules/webaudio/DefaultAudioDestinationNode.cpp:
+        (WebCore::DefaultAudioDestinationNode::createDestination):
+        When creating an AudioDestination, pass the requested AudioContext sample rate
+        instead of the hardware sample rate.
+
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+
+        * platform/audio/AudioFIFO.cpp: Removed.
+        * platform/audio/AudioFIFO.h: Removed.
+        * platform/audio/AudioPullFIFO.cpp: Removed.
+        * platform/audio/AudioPullFIFO.h: Removed.
+        * platform/audio/PushPullFIFO.cpp: Added.
+        * platform/audio/PushPullFIFO.h: Added.
+        Replace AudioFIFO and AudioPullFIFO with a new PushPullFIFO replacement, similarly
+        to what was done in Chromium in:
+        - https://codereview.chromium.org/2549093009
+
+        * platform/audio/MultiChannelResampler.cpp:
+        (WebCore::MultiChannelResampler::MultiChannelResampler):
+        * platform/audio/MultiChannelResampler.h:
+        * platform/audio/SincResampler.cpp:
+        (WebCore::SincResampler::SincResampler):
+        (WebCore::SincResampler::updateRegions):
+        (WebCore::SincResampler::initializeKernel):
+        (WebCore::SincResampler::process):
+        * platform/audio/SincResampler.h:
+        Add parameter to MultiChannelResampler & SincResampler to allow the client to specify
+        the size of the buffer in frames when the resampler calls AudioSourceProvider::provideInput()
+        to get input data. This is necessary because our WebAudio implementation uses a static
+        buffer size of 128 frames. This is similar to what was done in Chromium in:
+        - https://codereview.chromium.org/14189035
+
+        * platform/audio/cocoa/AudioDestinationCocoa.cpp:
+        (WebCore::AudioDestinationCocoa::AudioDestinationCocoa):
+        (WebCore::AudioDestinationCocoa::setAudioStreamBasicDescription):
+        (WebCore::AudioDestinationCocoa::render):
+        (WebCore::AudioDestinationCocoa::provideInput):
+        * platform/audio/cocoa/AudioDestinationCocoa.h:
+        - Adopt PushPullFIFO to resolve the buffer size mismatch between the WebAudio engine and
+          the callback function from the actual audio device, similarly to what was done in Chromium.
+        - When the context's sample rate differs from the hardware sample rate, instantiate a
+          MultiChannelResampler and use it in render() to do the resampling.
+
+        * platform/audio/ios/AudioDestinationIOS.cpp:
+        (WebCore::AudioDestinationCocoa::configure):
+        * platform/audio/mac/AudioDestinationMac.cpp:
+        (WebCore::AudioDestinationCocoa::configure):
+        Drop sampleRate parameter as it is no longer needed.
+
+        * platform/mock/MockAudioDestinationCocoa.cpp:
+        (WebCore::MockAudioDestinationCocoa::tick):
+
 2020-09-14  Sam Weinig  <[email protected]>
 
         [WebIDL] Split DOM Parsing related functions out of Element and ShadowRoot and into their own IDL files to match specs

Modified: trunk/Source/WebCore/Modules/webaudio/DefaultAudioDestinationNode.cpp (267013 => 267014)


--- trunk/Source/WebCore/Modules/webaudio/DefaultAudioDestinationNode.cpp	2020-09-14 15:44:59 UTC (rev 267013)
+++ trunk/Source/WebCore/Modules/webaudio/DefaultAudioDestinationNode.cpp	2020-09-14 15:47:53 UTC (rev 267014)
@@ -82,10 +82,8 @@
 
 void DefaultAudioDestinationNode::createDestination()
 {
-    float hardwareSampleRate = AudioDestination::hardwareSampleRate();
-    LOG(WebAudio, ">>>> hardwareSampleRate = %f\n", hardwareSampleRate);
-
-    m_destination = platformStrategies()->mediaStrategy().createAudioDestination(*this, m_inputDeviceId, m_numberOfInputChannels, channelCount(), hardwareSampleRate);
+    ALWAYS_LOG(LOGIDENTIFIER, "contextSampleRate = ", m_sampleRate, ", hardwareSampleRate = ", AudioDestination::hardwareSampleRate());
+    m_destination = platformStrategies()->mediaStrategy().createAudioDestination(*this, m_inputDeviceId, m_numberOfInputChannels, channelCount(), m_sampleRate);
 }
 
 void DefaultAudioDestinationNode::enableInput(const String& inputDeviceId)

Modified: trunk/Source/WebCore/Sources.txt (267013 => 267014)


--- trunk/Source/WebCore/Sources.txt	2020-09-14 15:44:59 UTC (rev 267013)
+++ trunk/Source/WebCore/Sources.txt	2020-09-14 15:47:53 UTC (rev 267014)
@@ -1788,9 +1788,7 @@
 platform/audio/AudioBus.cpp
 platform/audio/AudioChannel.cpp
 platform/audio/AudioDSPKernelProcessor.cpp
-platform/audio/AudioFIFO.cpp
 platform/audio/AudioHardwareListener.cpp
-platform/audio/AudioPullFIFO.cpp
 platform/audio/AudioResampler.cpp
 platform/audio/AudioResamplerKernel.cpp
 platform/audio/AudioUtilities.cpp
@@ -1814,6 +1812,7 @@
 platform/audio/Panner.cpp
 platform/audio/PlatformMediaSession.cpp
 platform/audio/PlatformMediaSessionManager.cpp
+platform/audio/PushPullFIFO.cpp
 platform/audio/Reverb.cpp
 platform/audio/ReverbAccumulationBuffer.cpp
 platform/audio/ReverbConvolver.cpp

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (267013 => 267014)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2020-09-14 15:44:59 UTC (rev 267013)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2020-09-14 15:47:53 UTC (rev 267014)
@@ -2526,6 +2526,7 @@
 		83C5795D1DA5C301006FACA8 /* ScrollToOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 8350C3E71DA59B6200356446 /* ScrollToOptions.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		83D35AEC1C7187FA00F70D5A /* XMLHttpRequestEventTarget.h in Headers */ = {isa = PBXBuildFile; fileRef = 83D35AEA1C7187ED00F70D5A /* XMLHttpRequestEventTarget.h */; };
 		83D35AF21C718D9000F70D5A /* JSXMLHttpRequestEventTarget.h in Headers */ = {isa = PBXBuildFile; fileRef = 83D35AF01C718D8400F70D5A /* JSXMLHttpRequestEventTarget.h */; };
+		83D511F6250C1CBF002EDC51 /* PushPullFIFO.h in Headers */ = {isa = PBXBuildFile; fileRef = 83D511F5250C1CA8002EDC51 /* PushPullFIFO.h */; };
 		83DB9E0F24DA19490037B468 /* BiquadFilterType.h in Headers */ = {isa = PBXBuildFile; fileRef = 83DB9E0C24DA18B50037B468 /* BiquadFilterType.h */; };
 		83DB9E1024DA19570037B468 /* BiquadFilterOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 83DB9E0E24DA18B60037B468 /* BiquadFilterOptions.h */; };
 		83E359A21BB1031D002CEB98 /* JSHTMLTimeElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 83E359A01BB1031D002CEB98 /* JSHTMLTimeElement.h */; };
@@ -10710,6 +10711,8 @@
 		83D35AEB1C7187ED00F70D5A /* XMLHttpRequestEventTarget.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = XMLHttpRequestEventTarget.idl; sourceTree = "<group>"; };
 		83D35AEF1C718D8400F70D5A /* JSXMLHttpRequestEventTarget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSXMLHttpRequestEventTarget.cpp; sourceTree = "<group>"; };
 		83D35AF01C718D8400F70D5A /* JSXMLHttpRequestEventTarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSXMLHttpRequestEventTarget.h; sourceTree = "<group>"; };
+		83D511F3250C1CA8002EDC51 /* PushPullFIFO.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PushPullFIFO.cpp; sourceTree = "<group>"; };
+		83D511F5250C1CA8002EDC51 /* PushPullFIFO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PushPullFIFO.h; sourceTree = "<group>"; };
 		83DB9E0A24DA18B40037B468 /* BiquadFilterType.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = BiquadFilterType.idl; sourceTree = "<group>"; };
 		83DB9E0C24DA18B50037B468 /* BiquadFilterType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BiquadFilterType.h; sourceTree = "<group>"; };
 		83DB9E0D24DA18B50037B468 /* BiquadFilterOptions.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = BiquadFilterOptions.idl; sourceTree = "<group>"; };
@@ -30036,6 +30039,8 @@
 				070E09181875ED93003A1D3C /* PlatformMediaSession.h */,
 				CDAE8C071746B95700532D78 /* PlatformMediaSessionManager.cpp */,
 				CDAE8C081746B95700532D78 /* PlatformMediaSessionManager.h */,
+				83D511F3250C1CA8002EDC51 /* PushPullFIFO.cpp */,
+				83D511F5250C1CA8002EDC51 /* PushPullFIFO.h */,
 				FD31606E12B026F700C1A359 /* Reverb.cpp */,
 				FD31606F12B026F700C1A359 /* Reverb.h */,
 				FD31607012B026F700C1A359 /* ReverbAccumulationBuffer.cpp */,
@@ -33267,6 +33272,7 @@
 				57303BEB20097F4000355965 /* PublicKeyCredentialType.h in Headers */,
 				0081FF0016B0A2D3008AAA7A /* PublicSuffix.h in Headers */,
 				10FB084B14E15C7E00A3DB98 /* PublicURLManager.h in Headers */,
+				83D511F6250C1CBF002EDC51 /* PushPullFIFO.h in Headers */,
 				550A0BCA085F6039007353D6 /* QualifiedName.h in Headers */,
 				83C1F5941EDF69D300410D27 /* QualifiedNameCache.h in Headers */,
 				A15E31F41E0CB0B5004B371C /* QuickLook.h in Headers */,

Deleted: trunk/Source/WebCore/platform/audio/AudioFIFO.cpp (267013 => 267014)


--- trunk/Source/WebCore/platform/audio/AudioFIFO.cpp	2020-09-14 15:44:59 UTC (rev 267013)
+++ trunk/Source/WebCore/platform/audio/AudioFIFO.cpp	2020-09-14 15:47:53 UTC (rev 267014)
@@ -1,144 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
- *     its contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(WEB_AUDIO)
-
-#include "AudioFIFO.h"
-
-namespace WebCore {
-
-AudioFIFO::AudioFIFO(unsigned numberOfChannels, size_t fifoLength)
-    : m_fifoAudioBus(AudioBus::create(numberOfChannels, fifoLength))
-    , m_fifoLength(fifoLength)
-    , m_framesInFifo(0)
-    , m_readIndex(0)
-    , m_writeIndex(0)
-{
-}
-
-void AudioFIFO::consume(AudioBus* destination, size_t framesToConsume)
-{
-    bool isGood = destination && (framesToConsume <= m_fifoLength) && (framesToConsume <= m_framesInFifo) && (destination->length() >= framesToConsume);
-    ASSERT(isGood);
-    if (!isGood)
-        return;
-
-    // Copy the requested number of samples to the destination.
-
-    size_t part1Length;
-    size_t part2Length;
-    findWrapLengths(m_readIndex, framesToConsume, part1Length, part2Length);
-
-    size_t numberOfChannels = m_fifoAudioBus->numberOfChannels();
-
-    for (size_t channelIndex = 0; channelIndex < numberOfChannels; ++channelIndex) {
-        float* destinationData = destination->channel(channelIndex)->mutableData();
-        const float* sourceData = m_fifoAudioBus->channel(channelIndex)->data();
-
-        bool isCopyGood = ((m_readIndex < m_fifoLength)
-                           && (m_readIndex + part1Length) <= m_fifoLength
-                           && (part1Length <= destination->length())
-                           && (part1Length + part2Length) <= destination->length());
-        ASSERT(isCopyGood);
-        if (!isCopyGood)
-            return;
-
-        memcpy(destinationData, sourceData + m_readIndex, part1Length * sizeof(*sourceData));
-        // Handle wrap around of the FIFO, if needed.
-        if (part2Length)
-            memcpy(destinationData + part1Length, sourceData, part2Length * sizeof(*sourceData));
-    }
-    m_readIndex = updateIndex(m_readIndex, framesToConsume);
-    ASSERT(m_framesInFifo >= framesToConsume);
-    m_framesInFifo -= framesToConsume;
-}
-
-void AudioFIFO::push(const AudioBus* sourceBus)
-{
-    // Copy the sourceBus into the FIFO buffer.
-
-    bool isGood = sourceBus && (m_framesInFifo + sourceBus->length() <= m_fifoLength);
-    if (!isGood)
-        return;
-
-    size_t sourceLength = sourceBus->length();
-    size_t part1Length;
-    size_t part2Length;
-    findWrapLengths(m_writeIndex, sourceLength, part1Length, part2Length);
-
-    size_t numberOfChannels = m_fifoAudioBus->numberOfChannels();
-
-    for (size_t channelIndex = 0; channelIndex < numberOfChannels; ++channelIndex) {
-        float* destination = m_fifoAudioBus->channel(channelIndex)->mutableData();
-        const float* source = sourceBus->channel(channelIndex)->data();
-
-        bool isCopyGood = ((m_writeIndex < m_fifoLength)
-                           && (m_writeIndex + part1Length) <= m_fifoLength
-                           && part2Length < m_fifoLength
-                           && part1Length + part2Length <= sourceLength);
-        ASSERT(isCopyGood);
-        if (!isCopyGood)
-            return;
-
-        memcpy(destination + m_writeIndex, source, part1Length * sizeof(*destination));
-
-        // Handle wrap around of the FIFO, if needed.
-        if (part2Length)
-            memcpy(destination, source + part1Length, part2Length * sizeof(*destination));
-    }
-        
-    m_framesInFifo += sourceLength;
-    ASSERT(m_framesInFifo <= m_fifoLength);
-    m_writeIndex = updateIndex(m_writeIndex, sourceLength);
-}
-
-void AudioFIFO::findWrapLengths(size_t index, size_t size, size_t& part1Length, size_t& part2Length)
-{
-    ASSERT_WITH_SECURITY_IMPLICATION(index < m_fifoLength && size <= m_fifoLength);
-    if (index < m_fifoLength && size <= m_fifoLength) {
-        if (index + size > m_fifoLength) {
-            // Need to wrap. Figure out the length of each piece.
-            part1Length = m_fifoLength - index;
-            part2Length = size - part1Length;
-        } else {
-            // No wrap needed.
-            part1Length = size;
-            part2Length = 0;
-        }
-    } else {
-        // Invalid values for index or size. Set the part lengths to zero so nothing is copied.
-        part1Length = 0;
-        part2Length = 0;
-    }
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(WEB_AUDIO)

Deleted: trunk/Source/WebCore/platform/audio/AudioFIFO.h (267013 => 267014)


--- trunk/Source/WebCore/platform/audio/AudioFIFO.h	2020-09-14 15:44:59 UTC (rev 267013)
+++ trunk/Source/WebCore/platform/audio/AudioFIFO.h	2020-09-14 15:47:53 UTC (rev 267014)
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
- *     its contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef AudioFIFO_h
-#define AudioFIFO_h
-
-#include "AudioBus.h"
-
-namespace WebCore {
-
-class AudioFIFO final {
-    WTF_MAKE_FAST_ALLOCATED;
-public:
-    // Create a FIFO large enough to hold |fifoLength| frames of data of |numberOfChannels| channels.
-    AudioFIFO(unsigned numberOfChannels, size_t fifoLength);
-
-    // Push the data from the bus into the FIFO.
-    void push(const AudioBus*);
-
-    // Consume |framesToConsume| frames of data from the FIFO and put them in |destination|. The
-    // corresponding frames are removed from the FIFO.
-    void consume(AudioBus* destination, size_t framesToConsume);
-
-    // Number of frames of data that are currently in the FIFO.
-    size_t framesInFifo() const { return m_framesInFifo; }
-
-private:
-    // Update the FIFO index by the step, with appropriate wrapping around the endpoint.
-    int updateIndex(int index, int step) { return (index + step) % m_fifoLength; }
-
-    void findWrapLengths(size_t index, size_t providerSize, size_t& part1Length, size_t& part2Length);
-    
-    // The FIFO itself. In reality, the FIFO is a circular buffer.
-    RefPtr<AudioBus> m_fifoAudioBus;
-
-    // The total available space in the FIFO.
-    size_t m_fifoLength;
-
-    // The number of actual elements in the FIFO
-    size_t m_framesInFifo;
-
-    // Where to start reading from the FIFO.
-    size_t m_readIndex;
-
-    // Where to start writing to the FIFO.
-    size_t m_writeIndex;
-};
-
-} // namespace WebCore
-
-#endif // AudioFIFO.h

Deleted: trunk/Source/WebCore/platform/audio/AudioPullFIFO.cpp (267013 => 267014)


--- trunk/Source/WebCore/platform/audio/AudioPullFIFO.cpp	2020-09-14 15:44:59 UTC (rev 267013)
+++ trunk/Source/WebCore/platform/audio/AudioPullFIFO.cpp	2020-09-14 15:47:53 UTC (rev 267014)
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
- *     its contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(WEB_AUDIO)
-
-#include "AudioPullFIFO.h"
-
-namespace WebCore {
-
-AudioPullFIFO::AudioPullFIFO(AudioSourceProvider& audioProvider, unsigned numberOfChannels, size_t fifoLength, size_t providerSize)
-    : m_provider(audioProvider)
-    , m_fifo(numberOfChannels, fifoLength)
-    , m_providerSize(providerSize)
-    , m_tempBus(AudioBus::create(numberOfChannels, providerSize))
-{
-}
-
-void AudioPullFIFO::consume(AudioBus* destination, size_t framesToConsume)
-{
-    if (!destination)
-        return;
-
-    if (framesToConsume > m_fifo.framesInFifo()) {
-        // We don't have enough data in the FIFO to fulfill the request. Ask for more data.
-        fillBuffer(framesToConsume - m_fifo.framesInFifo());
-    }
-
-    m_fifo.consume(destination, framesToConsume);
-}
-
-void AudioPullFIFO::fillBuffer(size_t numberOfFrames)
-{
-    // Keep asking the provider to give us data until we have received at least |numberOfFrames| of
-    // data. Stuff the data into the FIFO.
-    size_t framesProvided = 0;
-
-    while (framesProvided < numberOfFrames) {
-        m_provider.provideInput(m_tempBus.get(), m_providerSize);
-
-        m_fifo.push(m_tempBus.get());
-
-        framesProvided += m_providerSize;
-    }
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(WEB_AUDIO)

Deleted: trunk/Source/WebCore/platform/audio/AudioPullFIFO.h (267013 => 267014)


--- trunk/Source/WebCore/platform/audio/AudioPullFIFO.h	2020-09-14 15:44:59 UTC (rev 267013)
+++ trunk/Source/WebCore/platform/audio/AudioPullFIFO.h	2020-09-14 15:47:53 UTC (rev 267014)
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
- *     its contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef AudioPullFIFO_h
-#define AudioPullFIFO_h
-
-#include "AudioBus.h"
-#include "AudioFIFO.h"
-#include "AudioSourceProvider.h"
-
-namespace WebCore {
-
-// A FIFO (First In First Out) buffer to handle mismatches in buffer sizes between a provider and
-// receiver. The receiver will "pull" data from this FIFO. If data is already available in the
-// FIFO, it is provided to the receiver. If insufficient data is available to satisfy the request,
-// the FIFO will ask the provider for more data when necessary to fulfill a request. Contrast this
-// with a "push" FIFO, where the sender pushes data to the FIFO which will itself push the data to
-// the receiver when the FIFO is full.
-class AudioPullFIFO final {
-    WTF_MAKE_FAST_ALLOCATED;
-public:
-    // Create a FIFO that gets data from |provider|. The FIFO will be large enough to hold
-    // |fifoLength| frames of data of |numberOfChannels| channels. The AudioSourceProvider will be
-    // asked to produce |providerSize| frames when the FIFO needs more data.
-    AudioPullFIFO(AudioSourceProvider& audioProvider, unsigned numberOfChannels, size_t fifoLength, size_t providerSize);
-
-    // Read |framesToConsume| frames from the FIFO into the destination. If the FIFO does not have
-    // enough data, we ask the |provider| to get more data to fulfill the request.
-    void consume(AudioBus* destination, size_t framesToConsume);
-
-private:
-    // Fill the FIFO buffer with at least |numberOfFrames| more data.
-    void fillBuffer(size_t numberOfFrames);
-
-    // The provider of the data in our FIFO.
-    AudioSourceProvider& m_provider;
-
-    // The actual FIFO
-    AudioFIFO m_fifo;
-
-    // Number of frames of data that the provider will produce per call.
-    unsigned int m_providerSize;
-
-    // Temporary workspace to hold the data from the provider.
-    RefPtr<AudioBus> m_tempBus;
-};
-
-} // namespace WebCore
-
-#endif // AudioPullFIFO.h

Modified: trunk/Source/WebCore/platform/audio/MultiChannelResampler.cpp (267013 => 267014)


--- trunk/Source/WebCore/platform/audio/MultiChannelResampler.cpp	2020-09-14 15:44:59 UTC (rev 267013)
+++ trunk/Source/WebCore/platform/audio/MultiChannelResampler.cpp	2020-09-14 15:47:53 UTC (rev 267014)
@@ -92,13 +92,13 @@
     size_t m_framesToProcess { 0 }; // Used to verify that all channels ask for the same amount.
 };
 
-MultiChannelResampler::MultiChannelResampler(double scaleFactor, unsigned numberOfChannels)
+MultiChannelResampler::MultiChannelResampler(double scaleFactor, unsigned numberOfChannels, Optional<unsigned> requestFrames)
     : m_numberOfChannels(numberOfChannels)
     , m_channelProvider(makeUnique<ChannelProvider>(m_numberOfChannels))
 {
     // Create each channel's resampler.
     for (unsigned channelIndex = 0; channelIndex < numberOfChannels; ++channelIndex)
-        m_kernels.append(makeUnique<SincResampler>(scaleFactor));
+        m_kernels.append(makeUnique<SincResampler>(scaleFactor, requestFrames));
 }
 
 MultiChannelResampler::~MultiChannelResampler() = default;

Modified: trunk/Source/WebCore/platform/audio/MultiChannelResampler.h (267013 => 267014)


--- trunk/Source/WebCore/platform/audio/MultiChannelResampler.h	2020-09-14 15:44:59 UTC (rev 267013)
+++ trunk/Source/WebCore/platform/audio/MultiChannelResampler.h	2020-09-14 15:47:53 UTC (rev 267014)
@@ -40,7 +40,8 @@
 class MultiChannelResampler final {
     WTF_MAKE_FAST_ALLOCATED;
 public:   
-    explicit MultiChannelResampler(double scaleFactor, unsigned numberOfChannels);
+    // requestFrames constrols the size of the buffer in frames when AudioSourceProvider::provideInput() is called.
+    explicit MultiChannelResampler(double scaleFactor, unsigned numberOfChannels, Optional<unsigned> requestFrames = WTF::nullopt);
     ~MultiChannelResampler();
 
     // Process given AudioSourceProvider for streaming applications.

Added: trunk/Source/WebCore/platform/audio/PushPullFIFO.cpp (0 => 267014)


--- trunk/Source/WebCore/platform/audio/PushPullFIFO.cpp	                        (rev 0)
+++ trunk/Source/WebCore/platform/audio/PushPullFIFO.cpp	2020-09-14 15:47:53 UTC (rev 267014)
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2017 The Chromium Authors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1.  Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(WEB_AUDIO)
+#include "PushPullFIFO.h"
+
+#include "AudioBus.h"
+
+namespace WebCore {
+
+const size_t PushPullFIFO::kMaxFIFOLength = 65536;
+
+PushPullFIFO::PushPullFIFO(unsigned numberOfChannels, size_t fifoLength)
+    : m_fifoLength(fifoLength)
+{
+    ASSERT(m_fifoLength <= kMaxFIFOLength);
+    m_fifoBus = AudioBus::create(numberOfChannels, m_fifoLength);
+}
+
+PushPullFIFO::~PushPullFIFO() = default;
+
+// Push the data from |inputBus| to FIFO. The size of push is determined by
+// the length of |inputBus|.
+void PushPullFIFO::push(const AudioBus* inputBus)
+{
+    ASSERT(inputBus);
+    ASSERT(inputBus->length() <= m_fifoLength);
+    ASSERT(m_indexWrite < m_fifoLength);
+
+    const size_t inputBusLength = inputBus->length();
+    const size_t remainder = m_fifoLength - m_indexWrite;
+
+    for (unsigned i = 0; i < m_fifoBus->numberOfChannels(); ++i) {
+        float* fifoBusChannel = m_fifoBus->channel(i)->mutableData();
+        const float* inputBusChannel = inputBus->channel(i)->data();
+        if (remainder >= inputBusLength) {
+            // The remainder is big enough for the input data.
+            memcpy(fifoBusChannel + m_indexWrite, inputBusChannel, inputBusLength * sizeof(*fifoBusChannel));
+        } else {
+            // The input data overflows the remainder size. Wrap around the index.
+            memcpy(fifoBusChannel + m_indexWrite, inputBusChannel, remainder * sizeof(*fifoBusChannel));
+            memcpy(fifoBusChannel, inputBusChannel + remainder, (inputBusLength - remainder) * sizeof(*fifoBusChannel));
+        }
+    }
+
+    // Update the write index; wrap it around if necessary.
+    m_indexWrite = (m_indexWrite + inputBusLength) % m_fifoLength;
+
+    // In case of overflow, move the |indexRead| to the updated |indexWrite| to
+    // avoid reading overwritten frames by the next pull.
+    if (inputBusLength > m_fifoLength - m_framesAvailable)
+        m_indexRead = m_indexWrite;
+
+    // Update the number of frames available in FIFO.
+    m_framesAvailable = std::min(m_framesAvailable + inputBusLength, m_fifoLength);
+    ASSERT(((m_indexRead + m_framesAvailable) % m_fifoLength) == m_indexWrite);
+}
+
+// Pull the data out of FIFO to |outputBus|. If remaining frame in the FIFO
+// is less than the frames to pull, provides remaining frame plus the silence.
+size_t PushPullFIFO::pull(AudioBus* outputBus, size_t framesRequested)
+{
+    ASSERT(outputBus);
+    ASSERT(framesRequested <= outputBus->length());
+    ASSERT(framesRequested <= m_fifoLength);
+    ASSERT(m_indexRead < m_fifoLength);
+
+    const size_t remainder = m_fifoLength - m_indexRead;
+    const size_t framesToFill = std::min(m_framesAvailable, framesRequested);
+
+    for (unsigned i = 0; i < m_fifoBus->numberOfChannels(); ++i) {
+        const float* fifoBusChannel = m_fifoBus->channel(i)->data();
+        float* outputBusChannel = outputBus->channel(i)->mutableData();
+
+        // Fill up the output bus with the available frames first.
+        if (remainder >= framesToFill) {
+            // The remainder is big enough for the frames to pull.
+            memcpy(outputBusChannel, fifoBusChannel + m_indexRead, framesToFill * sizeof(*fifoBusChannel));
+        } else {
+            // The frames to pull is bigger than the remainder size.
+            // Wrap around the index.
+            memcpy(outputBusChannel, fifoBusChannel + m_indexRead, remainder * sizeof(*fifoBusChannel));
+            memcpy(outputBusChannel + remainder, fifoBusChannel, (framesToFill - remainder) * sizeof(*fifoBusChannel));
+        }
+
+        // The frames available was not enough to fulfill the requested frames. Fill
+        // the rest of the channel with silence.
+        if (framesRequested > framesToFill)
+            memset(outputBusChannel + framesToFill, 0, (framesRequested - framesToFill) * sizeof(*outputBusChannel));
+    }
+
+    // Update the read index; wrap it around if necessary.
+    m_indexRead = (m_indexRead + framesToFill) % m_fifoLength;
+
+    // In case of underflow, move the |indexWrite| to the updated |indexRead|.
+    if (framesRequested > framesToFill)
+        m_indexWrite = m_indexRead;
+
+    // Update the number of frames in FIFO.
+    m_framesAvailable -= framesToFill;
+    ASSERT(((m_indexRead + m_framesAvailable) % m_fifoLength) == m_indexWrite);
+
+    // |framesRequested > m_framesAvailable| means the frames in FIFO is not
+    // enough to fulfill the requested frames from the audio device.
+    return framesRequested > m_framesAvailable ? framesRequested - m_framesAvailable : 0;
+}
+
+unsigned PushPullFIFO::numberOfChannels() const
+{
+    return m_fifoBus->numberOfChannels();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_AUDIO)

Added: trunk/Source/WebCore/platform/audio/PushPullFIFO.h (0 => 267014)


--- trunk/Source/WebCore/platform/audio/PushPullFIFO.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/audio/PushPullFIFO.h	2020-09-14 15:47:53 UTC (rev 267014)
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2017 The Chromium Authors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1.  Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <wtf/Forward.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class AudioBus;
+
+// PushPullFIFO class is an intermediate audio sample storage between
+// WebKit-WebAudio and the renderer. The renderer's hardware callback buffer size
+// varies on the platform, but the WebAudio always renders 128 frames (render
+// quantum, RQ) thus FIFO is needed to handle the general case.
+class PushPullFIFO {
+    WTF_MAKE_FAST_ALLOCATED;
+    WTF_MAKE_NONCOPYABLE(PushPullFIFO);
+
+public:
+    // Maximum FIFO length. (512 render quanta)
+    static const size_t kMaxFIFOLength;
+
+    // |fifoLength| cannot exceed |kMaxFIFOLength|. Otherwise it crashes.
+    PushPullFIFO(unsigned numberOfChannels, size_t fifoLength);
+    ~PushPullFIFO();
+
+    // Pushes the rendered frames by WebAudio engine.
+    //  - The |inputBus| length is 128 frames (1 render quantum), fixed.
+    //  - In case of overflow (FIFO full while push), the existing frames in FIFO
+    //    will be overwritten and |indexRead| will be forcibly moved to
+    //    |indexWrite| to avoid reading overwritten frames.
+    void push(const AudioBus* inputBus);
+
+    // Pulls |framesRequested| by the audio device thread and returns the actual
+    // number of frames to be rendered by the source. (i.e. WebAudio graph)
+    size_t pull(AudioBus* outputBus, size_t framesRequested);
+
+    size_t framesAvailable() const { return m_framesAvailable; }
+    size_t length() const { return m_fifoLength; }
+    unsigned numberOfChannels() const;
+    AudioBus* bus() const { return m_fifoBus.get(); }
+
+private:
+    // The size of the FIFO.
+    const size_t m_fifoLength = 0;
+
+    RefPtr<AudioBus> m_fifoBus;
+
+    // The number of frames in the FIFO actually available for pulling.
+    size_t m_framesAvailable { 0 };
+
+    size_t m_indexRead { 0 };
+    size_t m_indexWrite { 0 };
+};
+
+} // namespace WebCore
+
+

Modified: trunk/Source/WebCore/platform/audio/SincResampler.cpp (267013 => 267014)


--- trunk/Source/WebCore/platform/audio/SincResampler.cpp	2020-09-14 15:44:59 UTC (rev 267013)
+++ trunk/Source/WebCore/platform/audio/SincResampler.cpp	2020-09-14 15:47:53 UTC (rev 267014)
@@ -39,51 +39,113 @@
 #include <emmintrin.h>
 #endif
 
-// Input buffer layout, dividing the total buffer into regions (r0 - r5):
+// Initial input buffer layout, dividing into regions r0 to r4 (note: r0, r3
+// and r4 will move after the first load):
 //
 // |----------------|----------------------------------------------------------------|----------------|
 //
-//                                              blockSize + kernelSize / 2                           
+//                                              m_requestFrames
 //                   <-------------------------------------------------------------------------------->
-//                                                  r0
+//                                           r0 (during first load)
 //
 //   kernelSize / 2   kernelSize / 2                                 kernelSize / 2     kernelSize / 2 
 // <---------------> <--------------->                              <---------------> <--------------->
 //         r1                r2                                             r3                r4
 // 
-//                                              blockSize                           
-//                                     <-------------------------------------------------------------->
-//                                                  r5
+//                             m_blockSize == r4 - r2
+//                   <--------------------------------------->
+//
+//                                                  m_requestFrames
+//                                    <------------------ ... ----------------->
+//                                               r0 (during second load)
+//
+// On the second request r0 slides to the right by kernelSize / 2 and r3, r4
+// and m_blockSize are reinitialized via step (3) in the algorithm below.
+//
+// These new regions remain constant until a Flush() occurs. While complicated,
+// this allows us to reduce jitter by always requesting the same amount from the
+// provided callback.
 
 // The Algorithm:
 //
-// 1) Consume input frames into r0 (r1 is zero-initialized).
-// 2) Position kernel centered at start of r0 (r2) and generate output frames until kernel is centered at start of r4.
-//    or we've finished generating all the output frames.
-// 3) Copy r3 to r1 and r4 to r2.
-// 4) Consume input frames into r5 (zero-pad if we run out of input).
-// 5) Goto (2) until all of input is consumed.
+// 1) Allocate input_buffer of size: m_requestFrames + kernelSize; this ensures
+//    there's enough room to read m_requestFrames from the callback into region
+//    r0 (which will move between the first and subsequent passes).
 //
+// 2) Let r1, r2 each represent half the kernel centered around r0:
+//
+//        r0 = m_inputBuffer + kernelSize / 2
+//        r1 = m_inputBuffer
+//        r2 = r0
+//
+//    r0 is always m_requestFrames in size. r1, r2 are kernelSize / 2 in
+//    size. r1 must be zero initialized to avoid convolution with garbage (see
+//    step (5) for why).
+//
+// 3) Let r3, r4 each represent half the kernel right aligned with the end of
+//    r0 and choose m_blockSize as the distance in frames between r4 and r2:
+//
+//        r3 = r0 + m_requestFrames - kernelSize
+//        r4 = r0 + m_requestFrames - kernelSize / 2
+//        m_blockSize = r4 - r2 = m_requestFrames - kernelSize / 2
+//
+// 4) Consume m_requestFrames frames into r0.
+//
+// 5) Position kernel centered at start of r2 and generate output frames until
+//    the kernel is centered at the start of r4 or we've finished generating
+//    all the output frames.
+//
+// 6) Wrap left over data from the r3 to r1 and r4 to r2.
+//
+// 7) If we're on the second load, in order to avoid overwriting the frames we
+//    just wrapped from r4 we need to slide r0 to the right by the size of
+//    r4, which is kernelSize / 2:
+//
+//        r0 = r0 + kernelSize / 2 = m_inputBuffer + kernelSize
+//
+//    r3, r4, and m_blockSize then need to be reinitialized, so goto (3).
+//
+// 8) Else, if we're not on the second load, goto (4).
+//
 // note: we're glossing over how the sub-sample handling works with m_virtualSourceIndex, etc.
 
 namespace WebCore {
 
-SincResampler::SincResampler(double scaleFactor, unsigned kernelSize, unsigned numberOfKernelOffsets)
+constexpr unsigned defaultRequestFrames { 512 };
+constexpr unsigned kernelSize { 32 };
+constexpr unsigned numberOfKernelOffsets { 32 };
+
+SincResampler::SincResampler(double scaleFactor, Optional<unsigned> requestFrames)
     : m_scaleFactor(scaleFactor)
-    , m_kernelSize(kernelSize)
-    , m_numberOfKernelOffsets(numberOfKernelOffsets)
-    , m_kernelStorage(m_kernelSize * (m_numberOfKernelOffsets + 1))
-    , m_virtualSourceIndex(0)
-    , m_blockSize(512)
-    , m_inputBuffer(m_blockSize + m_kernelSize) // See input buffer layout above.
-    , m_source(0)
-    , m_sourceFramesAvailable(0)
-    , m_sourceProvider(0)
-    , m_isBufferPrimed(false)
+    , m_kernelStorage(kernelSize * (numberOfKernelOffsets + 1))
+    , m_requestFrames(requestFrames.valueOr(defaultRequestFrames))
+    , m_inputBuffer(m_requestFrames + kernelSize) // See input buffer layout above.
+    , m_r1(m_inputBuffer.data())
+    , m_r2(m_inputBuffer.data() + kernelSize / 2)
 {
+    ASSERT(m_requestFrames > 0);
+    updateRegions(false);
+    ASSERT(m_blockSize > kernelSize);
     initializeKernel();
 }
 
+void SincResampler::updateRegions(bool isSecondLoad)
+{
+    // Setup various region pointers in the buffer (see diagram above). If we're
+    // on the second load we need to slide m_r0 to the right by kernelSize / 2.
+    m_r0 = m_inputBuffer.data() + (isSecondLoad ? kernelSize : kernelSize / 2);
+    m_r3 = m_r0 + m_requestFrames - kernelSize;
+    m_r4 = m_r0 + m_requestFrames - kernelSize / 2;
+    m_blockSize = m_r4 - m_r2;
+
+    // m_r1 at the beginning of the buffer.
+    ASSERT(m_r1 == m_inputBuffer.data());
+    // m_r1 left of m_r2, m_r4 left of m_r3 and size correct.
+    ASSERT((m_r2 - m_r1) == (m_r4 - m_r3));
+    // m_r2 left of r3.
+    ASSERT(m_r2 <= m_r3);
+}
+
 void SincResampler::initializeKernel()
 {
     // Blackman window parameters.
@@ -98,16 +160,16 @@
     // The sinc function is an idealized brick-wall filter, but since we're windowing it the
     // transition from pass to stop does not happen right away. So we should adjust the
     // lowpass filter cutoff slightly downward to avoid some aliasing at the very high-end.
-    // FIXME: this value is empirical and to be more exact should vary depending on m_kernelSize.
+    // FIXME: this value is empirical and to be more exact should vary depending on kernelSize.
     sincScaleFactor *= 0.9;
 
-    int n = m_kernelSize;
+    int n = kernelSize;
     int halfSize = n / 2;
 
     // Generates a set of windowed sinc() kernels.
     // We generate a range of sub-sample offsets from 0.0 to 1.0.
-    for (unsigned offsetIndex = 0; offsetIndex <= m_numberOfKernelOffsets; ++offsetIndex) {
-        double subsampleOffset = static_cast<double>(offsetIndex) / m_numberOfKernelOffsets;
+    for (unsigned offsetIndex = 0; offsetIndex <= numberOfKernelOffsets; ++offsetIndex) {
+        double subsampleOffset = static_cast<double>(offsetIndex) / numberOfKernelOffsets;
 
         for (int i = 0; i < n; ++i) {
             // Compute the sinc() with offset.
@@ -120,7 +182,7 @@
             double window = a0 - a1 * cos(2.0 * piDouble * x) + a2 * cos(4.0 * piDouble * x);
 
             // Window the sinc() function and store at the correct offset.
-            m_kernelStorage[i + offsetIndex * m_kernelSize] = sinc * window;
+            m_kernelStorage[i + offsetIndex * kernelSize] = sinc * window;
         }
     }
 }
@@ -190,7 +252,7 @@
     unsigned remaining = numberOfDestinationFrames;
     
     while (remaining) {
-        unsigned framesThisTime = std::min(remaining, m_blockSize);
+        unsigned framesThisTime = std::min(remaining, m_requestFrames);
         process(&sourceProvider, destination, framesThisTime);
         
         destination += framesThisTime;
@@ -200,27 +262,18 @@
 
 void SincResampler::process(AudioSourceProvider* sourceProvider, float* destination, size_t framesToProcess)
 {
-    bool isGood = sourceProvider && m_blockSize > m_kernelSize && m_inputBuffer.size() >= m_blockSize + m_kernelSize && !(m_kernelSize % 2);
-    ASSERT(isGood);
-    if (!isGood)
+    ASSERT(sourceProvider);
+    if (!sourceProvider)
         return;
     
     m_sourceProvider = sourceProvider;
 
     unsigned numberOfDestinationFrames = framesToProcess;
-    
-    // Setup various region pointers in the buffer (see diagram above).
-    float* r0 = m_inputBuffer.data() + m_kernelSize / 2;
-    float* r1 = m_inputBuffer.data();
-    float* r2 = r0;
-    float* r3 = r0 + m_blockSize - m_kernelSize / 2;
-    float* r4 = r0 + m_blockSize;
-    float* r5 = r0 + m_kernelSize / 2;
 
     // Step (1)
     // Prime the input buffer at the start of the input stream.
     if (!m_isBufferPrimed) {
-        consumeSource(r0, m_blockSize + m_kernelSize / 2);
+        consumeSource(m_r0, m_requestFrames);
         m_isBufferPrimed = true;
     }
     
@@ -232,14 +285,14 @@
             int sourceIndexI = static_cast<int>(m_virtualSourceIndex);
             double subsampleRemainder = m_virtualSourceIndex - sourceIndexI;
 
-            double virtualOffsetIndex = subsampleRemainder * m_numberOfKernelOffsets;
+            double virtualOffsetIndex = subsampleRemainder * numberOfKernelOffsets;
             int offsetIndex = static_cast<int>(virtualOffsetIndex);
             
-            float* k1 = m_kernelStorage.data() + offsetIndex * m_kernelSize;
-            float* k2 = k1 + m_kernelSize;
+            float* k1 = m_kernelStorage.data() + offsetIndex * kernelSize;
+            float* k2 = k1 + kernelSize;
 
             // Initialize input pointer based on quantized m_virtualSourceIndex.
-            float* inputP = r1 + sourceIndexI;
+            float* inputP = m_r1 + sourceIndexI;
 
             // We'll compute "convolutions" for the two kernels which straddle m_virtualSourceIndex
             float sum1 = 0;
@@ -249,7 +302,7 @@
             double kernelInterpolationFactor = virtualOffsetIndex - offsetIndex;
 
             // Generate a single output sample. 
-            int n = m_kernelSize;
+            int n = kernelSize;
 
 #define CONVOLVE_ONE_SAMPLE      \
             input = *inputP++;   \
@@ -455,16 +508,20 @@
         }
 
         // Wrap back around to the start.
+        ASSERT(m_virtualSourceIndex >= m_blockSize);
         m_virtualSourceIndex -= m_blockSize;
 
-        // Step (3) Copy r3 to r1 and r4 to r2.
+        // Step (3) Copy r3 to r1.
         // This wraps the last input frames back to the start of the buffer.
-        memcpy(r1, r3, sizeof(float) * (m_kernelSize / 2));
-        memcpy(r2, r4, sizeof(float) * (m_kernelSize / 2));
+        memcpy(m_r1, m_r3, sizeof(float) * kernelSize);
 
-        // Step (4)
+        // Step (4) -- Reinitialize regions if necessary.
+        if (m_r0 == m_r2)
+            updateRegions(true);
+
+        // Step (5)
         // Refresh the buffer with more input.
-        consumeSource(r5, m_blockSize);
+        consumeSource(m_r0, m_requestFrames);
     }
 }
 

Modified: trunk/Source/WebCore/platform/audio/SincResampler.h (267013 => 267014)


--- trunk/Source/WebCore/platform/audio/SincResampler.h	2020-09-14 15:44:59 UTC (rev 267013)
+++ trunk/Source/WebCore/platform/audio/SincResampler.h	2020-09-14 15:47:53 UTC (rev 267014)
@@ -39,11 +39,10 @@
 
 class SincResampler final {
     WTF_MAKE_FAST_ALLOCATED;
-public:   
+public:
     // scaleFactor == sourceSampleRate / destinationSampleRate
-    // kernelSize can be adjusted for quality (higher is better)
-    // numberOfKernelOffsets is used for interpolation and is the number of sub-sample kernel shifts.
-    SincResampler(double scaleFactor, unsigned kernelSize = 32, unsigned numberOfKernelOffsets = 32);
+    // requestFrames controls the size in frames of the buffer requested by each provideInput() call.
+    SincResampler(double scaleFactor, Optional<unsigned> requestFrames = WTF::nullopt);
     
     // Processes numberOfSourceFrames from source to produce numberOfSourceFrames / scaleFactor frames in destination.
     void process(const float* source, float* destination, unsigned numberOfSourceFrames);
@@ -54,10 +53,9 @@
 protected:
     void initializeKernel();
     void consumeSource(float* buffer, unsigned numberOfSourceFrames);
+    void updateRegions(bool isSecondLoad);
     
     double m_scaleFactor;
-    unsigned m_kernelSize;
-    unsigned m_numberOfKernelOffsets;
 
     // m_kernelStorage has m_numberOfKernelOffsets kernels back-to-back, each of size m_kernelSize.
     // The kernel offsets are sub-sample shifts of a windowed sinc() shifted from 0.0 to 1.0 sample.
@@ -65,22 +63,33 @@
     
     // m_virtualSourceIndex is an index on the source input buffer with sub-sample precision.
     // It must be double precision to avoid drift.
-    double m_virtualSourceIndex;
+    double m_virtualSourceIndex { 0 };
     
     // This is the number of destination frames we generate per processing pass on the buffer.
-    unsigned m_blockSize;
+    unsigned m_requestFrames;
 
+    // The number of source frames processed per pass.
+    unsigned m_blockSize { 0 };
+
     // Source is copied into this buffer for each processing pass.
     AudioFloatArray m_inputBuffer;
 
-    const float* m_source;
-    unsigned m_sourceFramesAvailable;
+    // Pointers to the various regions inside |m_inputBuffer|. See the diagram at
+    // the top of the .cpp file for more information.
+    float* m_r0 { nullptr };
+    float* const m_r1 { nullptr };
+    float* const m_r2 { nullptr };
+    float* m_r3 { nullptr };
+    float* m_r4 { nullptr };
+
+    const float* m_source { nullptr };
+    unsigned m_sourceFramesAvailable { 0 };
     
     // m_sourceProvider is used to provide the audio input stream to the resampler.
-    AudioSourceProvider* m_sourceProvider;    
+    AudioSourceProvider* m_sourceProvider { nullptr };
 
     // The buffer is primed once at the very beginning of processing.
-    bool m_isBufferPrimed;
+    bool m_isBufferPrimed { false };
 
     RefPtr<AudioBus> m_internalBus;
 };

Modified: trunk/Source/WebCore/platform/audio/cocoa/AudioDestinationCocoa.cpp (267013 => 267014)


--- trunk/Source/WebCore/platform/audio/cocoa/AudioDestinationCocoa.cpp	2020-09-14 15:44:59 UTC (rev 267013)
+++ trunk/Source/WebCore/platform/audio/cocoa/AudioDestinationCocoa.cpp	2020-09-14 15:47:53 UTC (rev 267014)
@@ -29,14 +29,17 @@
 #if ENABLE(WEB_AUDIO)
 
 #include "AudioBus.h"
-#include "AudioIOCallback.h"
 #include "AudioSession.h"
 #include "Logging.h"
+#include "MultiChannelResampler.h"
+#include "PushPullFIFO.h"
 
 namespace WebCore {
 
-const int kRenderBufferSize = 128;
+constexpr size_t kRenderBufferSize = 128;
 
+constexpr size_t fifoSize = 96 * kRenderBufferSize;
+
 CreateAudioDestinationCocoaOverride AudioDestinationCocoa::createOverride = nullptr;
 
 std::unique_ptr<AudioDestination> AudioDestination::create(AudioIOCallback& callback, const String&, unsigned numberOfInputChannels, unsigned numberOfOutputChannels, float sampleRate)
@@ -68,14 +71,24 @@
     return AudioSession::sharedSession().maximumNumberOfOutputChannels();
 }
 
+// FIXME: We should not be hardcoding the number of input channels.
+constexpr unsigned legacyNumberOfOutputChannels { 2 };
+
 AudioDestinationCocoa::AudioDestinationCocoa(AudioIOCallback& callback, float sampleRate)
     : m_outputUnit(0)
     , m_callback(callback)
-    , m_renderBus(AudioBus::create(2, kRenderBufferSize, false).releaseNonNull())
-    , m_spareBus(AudioBus::create(2, kRenderBufferSize, true).releaseNonNull())
-    , m_sampleRate(sampleRate)
+    , m_outputBus(AudioBus::create(legacyNumberOfOutputChannels, kRenderBufferSize, false).releaseNonNull())
+    , m_renderBus(AudioBus::create(legacyNumberOfOutputChannels, kRenderBufferSize).releaseNonNull())
+    , m_fifo(makeUniqueRef<PushPullFIFO>(legacyNumberOfOutputChannels, fifoSize))
+    , m_contextSampleRate(sampleRate)
 {
     configure();
+
+    auto hardwareSampleRate = this->hardwareSampleRate();
+    if (sampleRate != hardwareSampleRate) {
+        double scaleFactor = static_cast<double>(sampleRate) / hardwareSampleRate;
+        m_resampler = makeUnique<MultiChannelResampler>(scaleFactor, legacyNumberOfOutputChannels, kRenderBufferSize);
+    }
 }
 
 AudioDestinationCocoa::~AudioDestinationCocoa()
@@ -116,11 +129,11 @@
     m_callback.isPlayingDidChange();
 }
 
-void AudioDestinationCocoa::setAudioStreamBasicDescription(AudioStreamBasicDescription& streamFormat, float sampleRate)
+void AudioDestinationCocoa::setAudioStreamBasicDescription(AudioStreamBasicDescription& streamFormat)
 {
     const int bytesPerFloat = sizeof(Float32);
     const int bitsPerByte = 8;
-    streamFormat.mSampleRate = sampleRate;
+    streamFormat.mSampleRate = hardwareSampleRate();
     streamFormat.mFormatID = kAudioFormatLinearPCM;
     streamFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kAudioFormatFlagIsNonInterleaved;
     streamFormat.mBytesPerPacket = bytesPerFloat;
@@ -143,44 +156,31 @@
 // Pulls on our provider to get rendered audio stream.
 OSStatus AudioDestinationCocoa::render(const AudioTimeStamp* timestamp, UInt32 numberOfFrames, AudioBufferList* ioData)
 {
-    AudioIOPosition outputTimestamp;
+    if (m_fifo->length() < numberOfFrames)
+        return noErr;
+
     if (timestamp) {
-        outputTimestamp = {
-            Seconds { timestamp->mSampleTime / m_sampleRate },
+        m_outputTimestamp = {
+            Seconds { timestamp->mSampleTime / sampleRate() },
             MonotonicTime::fromMachAbsoluteTime(timestamp->mHostTime)
         };
-    }
+    } else
+        m_outputTimestamp = AudioIOPosition { };
+
     auto* buffers = ioData->mBuffers;
     UInt32 numberOfBuffers = ioData->mNumberBuffers;
-    UInt32 framesRemaining = numberOfFrames;
-    UInt32 frameOffset = 0;
-    while (framesRemaining > 0) {
-        if (m_startSpareFrame < m_endSpareFrame) {
-            ASSERT(m_startSpareFrame < m_endSpareFrame);
-            UInt32 framesThisTime = std::min<UInt32>(m_endSpareFrame - m_startSpareFrame, numberOfFrames);
-            assignAudioBuffersToBus(buffers, m_renderBus.get(), numberOfBuffers, numberOfFrames, frameOffset, framesThisTime);
-            m_renderBus->copyFromRange(m_spareBus.get(), m_startSpareFrame, m_endSpareFrame);
-            processBusAfterRender(m_renderBus.get(), framesThisTime);
-            frameOffset += framesThisTime;
-            framesRemaining -= framesThisTime;
-            m_startSpareFrame += framesThisTime;
-        }
 
-        UInt32 framesThisTime = std::min<UInt32>(kRenderBufferSize, framesRemaining);
-        assignAudioBuffersToBus(buffers, m_renderBus.get(), numberOfBuffers, numberOfFrames, frameOffset, framesThisTime);
+    // Associate the destination data array with the output bus then fill the FIFO.
+    assignAudioBuffersToBus(buffers, m_outputBus.get(), numberOfBuffers, numberOfFrames, 0, numberOfFrames);
+    size_t framesToRender = m_fifo->pull(m_outputBus.ptr(), numberOfFrames);
 
-        if (!framesThisTime)
-            break;
-        if (framesThisTime < kRenderBufferSize) {
-            m_callback.render(0, m_spareBus.ptr(), kRenderBufferSize, outputTimestamp);
-            m_renderBus->copyFromRange(m_spareBus.get(), 0, framesThisTime);
-            m_startSpareFrame = framesThisTime;
-            m_endSpareFrame = kRenderBufferSize;
-        } else
-            m_callback.render(0, m_renderBus.ptr(), framesThisTime, outputTimestamp);
-        processBusAfterRender(m_renderBus.get(), framesThisTime);
-        frameOffset += framesThisTime;
-        framesRemaining -= framesThisTime;
+    for (size_t pushedFrames = 0; pushedFrames < framesToRender; pushedFrames += kRenderBufferSize) {
+        if (m_resampler)
+            m_resampler->process(this, m_renderBus.ptr(), kRenderBufferSize);
+        else
+            m_callback.render(0, m_renderBus.ptr(), kRenderBufferSize, m_outputTimestamp);
+
+        m_fifo->push(m_renderBus.ptr());
     }
 
     return noErr;
@@ -193,6 +193,12 @@
     return audioOutput->render(timestamp, numberOfFrames, ioData);
 }
 
+void AudioDestinationCocoa::provideInput(AudioBus* bus, size_t framesToProcess)
+{
+    ASSERT_UNUSED(framesToProcess, framesToProcess == kRenderBufferSize);
+    m_callback.render(0, bus, kRenderBufferSize, m_outputTimestamp);
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(WEB_AUDIO)

Modified: trunk/Source/WebCore/platform/audio/cocoa/AudioDestinationCocoa.h (267013 => 267014)


--- trunk/Source/WebCore/platform/audio/cocoa/AudioDestinationCocoa.h	2020-09-14 15:44:59 UTC (rev 267013)
+++ trunk/Source/WebCore/platform/audio/cocoa/AudioDestinationCocoa.h	2020-09-14 15:47:53 UTC (rev 267014)
@@ -28,17 +28,22 @@
 #if ENABLE(WEB_AUDIO)
 
 #include "AudioDestination.h"
+#include "AudioIOCallback.h"
+#include "AudioSourceProvider.h"
 #include <AudioUnit/AudioUnit.h>
 #include <wtf/RefPtr.h>
+#include <wtf/UniqueRef.h>
 
 namespace WebCore {
 
 class AudioBus;
+class MultiChannelResampler;
+class PushPullFIFO;
 
 using CreateAudioDestinationCocoaOverride = std::unique_ptr<AudioDestination>(*)(AudioIOCallback&, float sampleRate);
 
 // An AudioDestination using CoreAudio's default output AudioUnit
-class AudioDestinationCocoa : public AudioDestination {
+class AudioDestinationCocoa : public AudioDestination, public AudioSourceProvider {
 public:
     AudioDestinationCocoa(AudioIOCallback&, float sampleRate);
     virtual ~AudioDestinationCocoa();
@@ -49,7 +54,7 @@
     void setIsPlaying(bool);
 
     bool isPlaying() final { return m_isPlaying; }
-    float sampleRate() const final { return m_sampleRate; }
+    float sampleRate() const final { return m_contextSampleRate; }
     unsigned framesPerBuffer() const final;
     AudioUnit& outputUnit() { return m_outputUnit; }
     
@@ -56,7 +61,7 @@
     // DefaultOutputUnit callback
     static OSStatus inputProc(void* userData, AudioUnitRenderActionFlags*, const AudioTimeStamp*, UInt32 busNumber, UInt32 numberOfFrames, AudioBufferList* ioData);
 
-    void setAudioStreamBasicDescription(AudioStreamBasicDescription&, float sampleRate);
+    void setAudioStreamBasicDescription(AudioStreamBasicDescription&);
 
 private:
     void start() override;
@@ -64,6 +69,9 @@
 
     friend std::unique_ptr<AudioDestination> AudioDestination::create(AudioIOCallback&, const String&, unsigned, unsigned, float);
     
+    // AudioSourceProvider.
+    void provideInput(AudioBus*, size_t framesToProcess) final;
+
     void configure();
     void processBusAfterRender(AudioBus&, UInt32 numberOfFrames);
 
@@ -71,14 +79,22 @@
 
     AudioUnit m_outputUnit;
     AudioIOCallback& m_callback;
+
+    // To pass the data from FIFO to the audio device callback.
+    Ref<AudioBus> m_outputBus;
+
+    // To push the rendered result from WebAudio graph into the FIFO.
     Ref<AudioBus> m_renderBus;
-    Ref<AudioBus> m_spareBus;
 
-    float m_sampleRate;
+    // Resolves the buffer size mismatch between the WebAudio engine and
+    // the callback function from the actual audio device.
+    UniqueRef<PushPullFIFO> m_fifo;
+
+    std::unique_ptr<MultiChannelResampler> m_resampler;
+    AudioIOPosition m_outputTimestamp;
+
+    float m_contextSampleRate;
     bool m_isPlaying { false };
-
-    unsigned m_startSpareFrame { 0 };
-    unsigned m_endSpareFrame { 0 };
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/platform/audio/ios/AudioDestinationIOS.cpp (267013 => 267014)


--- trunk/Source/WebCore/platform/audio/ios/AudioDestinationIOS.cpp	2020-09-14 15:44:59 UTC (rev 267013)
+++ trunk/Source/WebCore/platform/audio/ios/AudioDestinationIOS.cpp	2020-09-14 15:47:53 UTC (rev 267014)
@@ -91,7 +91,7 @@
     result = AudioUnitGetProperty(outputUnit(), kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, (void*)&streamFormat, &size);
     ASSERT(!result);
 
-    setAudioStreamBasicDescription(streamFormat, sampleRate());
+    setAudioStreamBasicDescription(streamFormat);
 
     result = AudioUnitSetProperty(outputUnit(), kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, (void*)&streamFormat, sizeof(AudioStreamBasicDescription));
     ASSERT(!result);

Modified: trunk/Source/WebCore/platform/audio/mac/AudioDestinationMac.cpp (267013 => 267014)


--- trunk/Source/WebCore/platform/audio/mac/AudioDestinationMac.cpp	2020-09-14 15:44:59 UTC (rev 267013)
+++ trunk/Source/WebCore/platform/audio/mac/AudioDestinationMac.cpp	2020-09-14 15:47:53 UTC (rev 267014)
@@ -67,7 +67,7 @@
 
     // Set stream format
     AudioStreamBasicDescription streamFormat;
-    setAudioStreamBasicDescription(streamFormat, sampleRate());
+    setAudioStreamBasicDescription(streamFormat);
 
     result = AudioUnitSetProperty(outputUnit(), kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, (void*)&streamFormat, sizeof(AudioStreamBasicDescription));
     ASSERT(!result);

Modified: trunk/Source/WebCore/platform/graphics/cocoa/SourceBufferParserWebM.cpp (267013 => 267014)


--- trunk/Source/WebCore/platform/graphics/cocoa/SourceBufferParserWebM.cpp	2020-09-14 15:44:59 UTC (rev 267013)
+++ trunk/Source/WebCore/platform/graphics/cocoa/SourceBufferParserWebM.cpp	2020-09-14 15:47:53 UTC (rev 267014)
@@ -55,6 +55,9 @@
 
 using namespace PAL;
 
+// FIXME: Remove this once kCMVideoCodecType_VP9 is added to CMFormatDescription.h
+constexpr CMVideoCodecType kCMVideoCodecType_VP9 { 'vp09' };
+
 static bool isWebmParserAvailable()
 {
     return !!webm::swap && RuntimeEnabledFeatures::sharedFeatures().webMParserEnabled();

Modified: trunk/Source/WebCore/platform/mediastream/mac/CoreAudioCaptureDevice.h (267013 => 267014)


--- trunk/Source/WebCore/platform/mediastream/mac/CoreAudioCaptureDevice.h	2020-09-14 15:44:59 UTC (rev 267013)
+++ trunk/Source/WebCore/platform/mediastream/mac/CoreAudioCaptureDevice.h	2020-09-14 15:47:53 UTC (rev 267014)
@@ -28,6 +28,7 @@
 #if ENABLE(MEDIA_STREAM) && PLATFORM(MAC)
 
 #include "CaptureDevice.h"
+#include <pal/spi/cf/CoreAudioSPI.h>
 #include <wtf/RefPtr.h>
 #include <wtf/text/WTFString.h>
 

Modified: trunk/Source/WebCore/platform/mock/MockAudioDestinationCocoa.cpp (267013 => 267014)


--- trunk/Source/WebCore/platform/mock/MockAudioDestinationCocoa.cpp	2020-09-14 15:44:59 UTC (rev 267013)
+++ trunk/Source/WebCore/platform/mock/MockAudioDestinationCocoa.cpp	2020-09-14 15:47:53 UTC (rev 267014)
@@ -67,7 +67,7 @@
 {
     m_workQueue->dispatch([this, sampleRate = sampleRate(), numberOfFramesToProcess = m_numberOfFramesToProcess] {
         AudioStreamBasicDescription streamFormat;
-        setAudioStreamBasicDescription(streamFormat, sampleRate);
+        setAudioStreamBasicDescription(streamFormat);
 
         WebAudioBufferList webAudioBufferList { streamFormat, numberOfFramesToProcess };
         AudioDestinationCocoa::inputProc(this, 0, 0, 0, numberOfFramesToProcess, webAudioBufferList.list());
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to