<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[211539] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/211539">211539</a></dd>
<dt>Author</dt> <dd>eric.carlson@apple.com</dd>
<dt>Date</dt> <dd>2017-02-01 15:38:04 -0800 (Wed, 01 Feb 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>[Mac] Update CARingBuffer class
https://bugs.webkit.org/show_bug.cgi?id=167656

Reviewed by NOBODY (OOPS!).

Source/WebCore:

API test CARingBufferTest added.

* WebCore.xcodeproj/project.pbxproj: Add headers to framework so they can be used from the API test.

* platform/audio/AudioStreamDescription.h: Add Int32.

* platform/audio/mac/CAAudioStreamDescription.cpp:
(WebCore::CAAudioStreamDescription::CAAudioStreamDescription):
(WebCore::CAAudioStreamDescription::~CAAudioStreamDescription):
(WebCore::CAAudioStreamDescription::format): Support Int32.
(WebCore::CAAudioStreamDescription::operator==): Make inline.
* platform/audio/mac/CAAudioStreamDescription.h:

* platform/audio/mac/CARingBuffer.cpp:
(WebCore::CARingBuffer::CARingBuffer): Move initializers into class declaration.
(WebCore::CARingBuffer::allocate): Use flush method, get allocation info from a CAAudioStreamDescription.
(WebCore::FetchABL): Add a mode parameter to allow samples to replace or mix into destination.
(WebCore::CARingBuffer::flush): New.
(WebCore::CARingBuffer::fetch): Add mode parameter.
(WebCore::CARingBuffer::~CARingBuffer): Deleted.
* platform/audio/mac/CARingBuffer.h:
(WebCore::CARingBuffer::~CARingBuffer):

* platform/graphics/avfoundation/AudioSourceProviderAVFObjC.mm:
(WebCore::AudioSourceProviderAVFObjC::prepare): Use new CARingBuffer constructor.
(WebCore::operator==): Deleted.
(WebCore::operator!=): Deleted.

* platform/mediastream/mac/WebAudioSourceProviderAVFObjC.mm:
(WebCore::WebAudioSourceProviderAVFObjC::prepare): Use new CARingBuffer constructor
(WebCore::operator==): Deleted.
(WebCore::operator!=): Deleted.

Tools:

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebCore/CARingBuffer.cpp: Added.
(TestWebKitAPI::CARingBufferTest::SetUp):
(TestWebKitAPI::CARingBufferTest::setup):
(TestWebKitAPI::CARingBufferTest::setListDataBuffer):
(TestWebKitAPI::CARingBufferTest::description):
(TestWebKitAPI::CARingBufferTest::bufferList):
(TestWebKitAPI::CARingBufferTest::ringBuffer):
(TestWebKitAPI::CARingBufferTest::capacity):
(TestWebKitAPI::CARingBufferTest::audioBufferListSizeForStream):
(TestWebKitAPI::CARingBufferTest::configureBufferListForStream):
(TestWebKitAPI::TEST_F):
(TestWebKitAPI::MixingTest::run):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebCoreplatformaudioAudioStreamDescriptionh">trunk/Source/WebCore/platform/audio/AudioStreamDescription.h</a></li>
<li><a href="#trunkSourceWebCoreplatformaudiomacCAAudioStreamDescriptioncpp">trunk/Source/WebCore/platform/audio/mac/CAAudioStreamDescription.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformaudiomacCAAudioStreamDescriptionh">trunk/Source/WebCore/platform/audio/mac/CAAudioStreamDescription.h</a></li>
<li><a href="#trunkSourceWebCoreplatformaudiomacCARingBuffercpp">trunk/Source/WebCore/platform/audio/mac/CARingBuffer.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformaudiomacCARingBufferh">trunk/Source/WebCore/platform/audio/mac/CARingBuffer.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsavfoundationAudioSourceProviderAVFObjCmm">trunk/Source/WebCore/platform/graphics/avfoundation/AudioSourceProviderAVFObjC.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreammacWebAudioSourceProviderAVFObjCmm">trunk/Source/WebCore/platform/mediastream/mac/WebAudioSourceProviderAVFObjC.mm</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsTestWebKitAPITestWebKitAPIxcodeprojprojectpbxproj">trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkToolsTestWebKitAPITestsWebCoreCARingBuffercpp">trunk/Tools/TestWebKitAPI/Tests/WebCore/CARingBuffer.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (211538 => 211539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2017-02-01 23:25:15 UTC (rev 211538)
+++ trunk/Source/WebCore/ChangeLog        2017-02-01 23:38:04 UTC (rev 211539)
</span><span class="lines">@@ -1,3 +1,43 @@
</span><ins>+2017-02-01  Eric Carlson  &lt;eric.carlson@apple.com&gt;
+
+        [Mac] Update CARingBuffer class
+        https://bugs.webkit.org/show_bug.cgi?id=167656
+
+        Reviewed by Jer Noble.
+
+        API test CARingBufferTest added.
+
+        * WebCore.xcodeproj/project.pbxproj: Add headers to framework so they can be used from the API test.
+
+        * platform/audio/AudioStreamDescription.h: Add Int32.
+
+        * platform/audio/mac/CAAudioStreamDescription.cpp:
+        (WebCore::CAAudioStreamDescription::CAAudioStreamDescription):
+        (WebCore::CAAudioStreamDescription::~CAAudioStreamDescription):
+        (WebCore::CAAudioStreamDescription::format): Support Int32.
+        (WebCore::CAAudioStreamDescription::operator==): Make inline.
+        * platform/audio/mac/CAAudioStreamDescription.h:
+
+        * platform/audio/mac/CARingBuffer.cpp:
+        (WebCore::CARingBuffer::CARingBuffer): Move initializers into class declaration.
+        (WebCore::CARingBuffer::allocate): Use flush method, get allocation info from a CAAudioStreamDescription.
+        (WebCore::FetchABL): Add a mode parameter to allow samples to replace or mix into destination.
+        (WebCore::CARingBuffer::flush): New.
+        (WebCore::CARingBuffer::fetch): Add mode parameter.
+        (WebCore::CARingBuffer::~CARingBuffer): Deleted.
+        * platform/audio/mac/CARingBuffer.h:
+        (WebCore::CARingBuffer::~CARingBuffer):
+
+        * platform/graphics/avfoundation/AudioSourceProviderAVFObjC.mm:
+        (WebCore::AudioSourceProviderAVFObjC::prepare): Use new CARingBuffer constructor.
+        (WebCore::operator==): Deleted.
+        (WebCore::operator!=): Deleted.
+
+        * platform/mediastream/mac/WebAudioSourceProviderAVFObjC.mm:
+        (WebCore::WebAudioSourceProviderAVFObjC::prepare): Use new CARingBuffer constructor
+        (WebCore::operator==): Deleted.
+        (WebCore::operator!=): Deleted.
+
</ins><span class="cx"> 2017-02-01  Zalan Bujtas  &lt;zalan@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Simple line layout: Move TextFragmentIterator::runWidth to ::textWidth.
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (211538 => 211539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2017-02-01 23:25:15 UTC (rev 211538)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2017-02-01 23:38:04 UTC (rev 211539)
</span><span class="lines">@@ -278,6 +278,11 @@
</span><span class="cx">                 07B7116D1D899E63009F0FFB /* CaptureDevice.h in Headers */ = {isa = PBXBuildFile; fileRef = 07B7116A1D899E63009F0FFB /* CaptureDevice.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 07B7116E1D899E63009F0FFB /* CaptureDeviceManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07B7116B1D899E63009F0FFB /* CaptureDeviceManager.cpp */; };
</span><span class="cx">                 07B7116F1D899E63009F0FFB /* CaptureDeviceManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 07B7116C1D899E63009F0FFB /* CaptureDeviceManager.h */; };
</span><ins>+                07C046C31E42508B007201E7 /* CAAudioStreamDescription.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 073B87571E40DCFD0071C0EC /* CAAudioStreamDescription.cpp */; };
+                07C046C41E42508B007201E7 /* CAAudioStreamDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = 073B87581E40DCFD0071C0EC /* CAAudioStreamDescription.h */; settings = {ATTRIBUTES = (Private, ); }; };
+                07C046C71E425155007201E7 /* AudioTrackPrivateMediaStreamCocoa.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07C046C51E42512F007201E7 /* AudioTrackPrivateMediaStreamCocoa.cpp */; };
+                07C046C81E425155007201E7 /* AudioTrackPrivateMediaStreamCocoa.h in Headers */ = {isa = PBXBuildFile; fileRef = 07C046C61E42512F007201E7 /* AudioTrackPrivateMediaStreamCocoa.h */; };
+                07C046CB1E426413007201E7 /* AudioStreamDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = 073B87561E40DCE50071C0EC /* AudioStreamDescription.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 07C1C0E21BFB600100BD2256 /* MediaTrackSupportedConstraints.h in Headers */ = {isa = PBXBuildFile; fileRef = 07C1C0E01BFB600100BD2256 /* MediaTrackSupportedConstraints.h */; };
</span><span class="cx">                 07C1C0E51BFB60ED00BD2256 /* RealtimeMediaSourceSupportedConstraints.h in Headers */ = {isa = PBXBuildFile; fileRef = 07C1C0E41BFB60ED00BD2256 /* RealtimeMediaSourceSupportedConstraints.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 07CE77D516712A6A00C55A47 /* InbandTextTrackPrivateClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 07CE77D416712A6A00C55A47 /* InbandTextTrackPrivateClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -5897,7 +5902,7 @@
</span><span class="cx">                 CDC69DDA16371FD4007C38DF /* WebCoreFullScreenPlaceholderView.h in Headers */ = {isa = PBXBuildFile; fileRef = CDC69DD816371FD3007C38DF /* WebCoreFullScreenPlaceholderView.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 CDC69DDB16371FD4007C38DF /* WebCoreFullScreenPlaceholderView.mm in Sources */ = {isa = PBXBuildFile; fileRef = CDC69DD916371FD3007C38DF /* WebCoreFullScreenPlaceholderView.mm */; };
</span><span class="cx">                 CDC734141977896C0046BFC5 /* CARingBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDC734121977896C0046BFC5 /* CARingBuffer.cpp */; };
</span><del>-                CDC734151977896D0046BFC5 /* CARingBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = CDC734131977896C0046BFC5 /* CARingBuffer.h */; };
</del><ins>+                CDC734151977896D0046BFC5 /* CARingBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = CDC734131977896C0046BFC5 /* CARingBuffer.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 CDC8B5A2180463470016E685 /* MediaPlayerPrivateMediaSourceAVFObjC.mm in Sources */ = {isa = PBXBuildFile; fileRef = CDC8B5A0180463470016E685 /* MediaPlayerPrivateMediaSourceAVFObjC.mm */; };
</span><span class="cx">                 CDC8B5A3180463470016E685 /* MediaPlayerPrivateMediaSourceAVFObjC.h in Headers */ = {isa = PBXBuildFile; fileRef = CDC8B5A1180463470016E685 /* MediaPlayerPrivateMediaSourceAVFObjC.h */; };
</span><span class="cx">                 CDC8B5A6180474F70016E685 /* MediaSourcePrivateAVFObjC.mm in Sources */ = {isa = PBXBuildFile; fileRef = CDC8B5A4180474F70016E685 /* MediaSourcePrivateAVFObjC.mm */; };
</span><span class="lines">@@ -15351,6 +15356,8 @@
</span><span class="cx">                         children = (
</span><span class="cx">                                 07707CB11E20649C00005BF7 /* AudioCaptureSourceProviderObjC.h */,
</span><span class="cx">                                 07707CAF1E205EC400005BF7 /* AudioSourceObserverObjC.h */,
</span><ins>+                                07C046C51E42512F007201E7 /* AudioTrackPrivateMediaStreamCocoa.cpp */,
+                                07C046C61E42512F007201E7 /* AudioTrackPrivateMediaStreamCocoa.h */,
</ins><span class="cx">                                 070363D8181A1CDC00C074A5 /* AVAudioCaptureSource.h */,
</span><span class="cx">                                 070363D9181A1CDC00C074A5 /* AVAudioCaptureSource.mm */,
</span><span class="cx">                                 070363DA181A1CDC00C074A5 /* AVCaptureDeviceManager.h */,
</span><span class="lines">@@ -24889,8 +24896,6 @@
</span><span class="cx">                 FD3160B012B0270700C1A359 /* mac */ = {
</span><span class="cx">                         isa = PBXGroup;
</span><span class="cx">                         children = (
</span><del>-                                073B87571E40DCFD0071C0EC /* CAAudioStreamDescription.cpp */,
-                                073B87581E40DCFD0071C0EC /* CAAudioStreamDescription.h */,
</del><span class="cx">                                 FD3160B512B0272A00C1A359 /* AudioBusMac.mm */,
</span><span class="cx">                                 FD3160B612B0272A00C1A359 /* AudioDestinationMac.cpp */,
</span><span class="cx">                                 FD3160B712B0272A00C1A359 /* AudioDestinationMac.h */,
</span><span class="lines">@@ -24901,6 +24906,8 @@
</span><span class="cx">                                 CD54DE4917469C6D005E5B36 /* AudioSessionMac.cpp */,
</span><span class="cx">                                 CDC734121977896C0046BFC5 /* CARingBuffer.cpp */,
</span><span class="cx">                                 CDC734131977896C0046BFC5 /* CARingBuffer.h */,
</span><ins>+                                073B87571E40DCFD0071C0EC /* CAAudioStreamDescription.cpp */,
+                                073B87581E40DCFD0071C0EC /* CAAudioStreamDescription.h */,
</ins><span class="cx">                                 FD3160BA12B0272A00C1A359 /* FFTFrameMac.cpp */,
</span><span class="cx">                                 CD669D671D232E10004D1866 /* MediaSessionManagerMac.h */,
</span><span class="cx">                                 07EDC3ED1AACB75D00983EB5 /* MediaSessionManagerMac.mm */,
</span><span class="lines">@@ -26571,6 +26578,7 @@
</span><span class="cx">                                 E107400E0E77BDC00033AF24 /* JSMessageChannel.h in Headers */,
</span><span class="cx">                                 75793EC90D0CE72D007FC0AC /* JSMessageEvent.h in Headers */,
</span><span class="cx">                                 E1ADEDDA0E76BD93004A1A5E /* JSMessagePort.h in Headers */,
</span><ins>+                                07C046CB1E426413007201E7 /* AudioStreamDescription.h in Headers */,
</ins><span class="cx">                                 CDF4B7301E03CA4A00E235A2 /* JSMockCDMFactory.h in Headers */,
</span><span class="cx">                                 2D6F3E951C1F85550061DBD4 /* JSMockPageOverlay.h in Headers */,
</span><span class="cx">                                 A86629D109DA2B48009633A5 /* JSMouseEvent.h in Headers */,
</span><span class="lines">@@ -27695,6 +27703,7 @@
</span><span class="cx">                                 A79BADA4161E7F3F00C2E652 /* RuleSet.h in Headers */,
</span><span class="cx">                                 2D76BB821945632400CFD29A /* RunLoopObserver.h in Headers */,
</span><span class="cx">                                 1A569D1F0D7E2B82007C3983 /* runtime_array.h in Headers */,
</span><ins>+                                07C046C41E42508B007201E7 /* CAAudioStreamDescription.h in Headers */,
</ins><span class="cx">                                 1A569D210D7E2B82007C3983 /* runtime_method.h in Headers */,
</span><span class="cx">                                 1A569D230D7E2B82007C3983 /* runtime_object.h in Headers */,
</span><span class="cx">                                 1A569D250D7E2B82007C3983 /* runtime_root.h in Headers */,
</span><span class="lines">@@ -27760,6 +27769,7 @@
</span><span class="cx">                                 1AAADDE414DC8C8F00AF64B3 /* ScrollingTreeNode.h in Headers */,
</span><span class="cx">                                 0FEA3E80191B3169000F1B55 /* ScrollingTreeOverflowScrollingNode.h in Headers */,
</span><span class="cx">                                 9391A99D1629D70000297330 /* ScrollingTreeScrollingNode.h in Headers */,
</span><ins>+                                07C046C81E425155007201E7 /* AudioTrackPrivateMediaStreamCocoa.h in Headers */,
</ins><span class="cx">                                 0FB8890A167D2FA10010CDA5 /* ScrollingTreeStickyNode.h in Headers */,
</span><span class="cx">                                 7AAFE8D019CB8672000F56D8 /* ScrollLatchingState.h in Headers */,
</span><span class="cx">                                 F478755419983AFF0024A287 /* ScrollSnapAnimatorState.h in Headers */,
</span><span class="lines">@@ -28315,6 +28325,7 @@
</span><span class="cx">                                 BE913D80181EF92400DCB09E /* TrackPrivateBase.h in Headers */,
</span><span class="cx">                                 FFAC30FE184FB145008C4F1E /* TrailingObjects.h in Headers */,
</span><span class="cx">                                 516071321BD8308B00DBC4F2 /* TransactionOperation.h in Headers */,
</span><ins>+                                07C046C21E425022007201E7 /* AudioSampleDataSource.h in Headers */,
</ins><span class="cx">                                 49E911C40EF86D47009D0CAF /* TransformationMatrix.h in Headers */,
</span><span class="cx">                                 FB484F4D171F821E00040755 /* TransformFunctions.h in Headers */,
</span><span class="cx">                                 49E911CE0EF86D47009D0CAF /* TransformOperation.h in Headers */,
</span><span class="lines">@@ -30422,6 +30433,7 @@
</span><span class="cx">                                 E1284BB210449FFA00EAEB52 /* JSPageTransitionEvent.cpp in Sources */,
</span><span class="cx">                                 FDA15EB112B03EE1003A583A /* JSPannerNode.cpp in Sources */,
</span><span class="cx">                                 E51A81DF17298D7700BFCA61 /* JSPerformance.cpp in Sources */,
</span><ins>+                                07C046C11E425022007201E7 /* AudioSampleDataSource.cpp in Sources */,
</ins><span class="cx">                                 CB38FD511CCF938900592A3F /* JSPerformanceEntry.cpp in Sources */,
</span><span class="cx">                                 CB38FD571CD21E2A00592A3F /* JSPerformanceEntryCustom.cpp in Sources */,
</span><span class="cx">                                 A58C59D01E382EAC0047859C /* JSPerformanceMark.cpp in Sources */,
</span><span class="lines">@@ -30767,6 +30779,7 @@
</span><span class="cx">                                 517A63C41B74318B00E7DCDC /* KeyedEncoderCF.cpp in Sources */,
</span><span class="cx">                                 A513B3D8114B166A001C429B /* KeyEventCocoa.mm in Sources */,
</span><span class="cx">                                 2655413A1489811C000DFC5D /* KeyEventIOS.mm in Sources */,
</span><ins>+                                07C046C31E42508B007201E7 /* CAAudioStreamDescription.cpp in Sources */,
</ins><span class="cx">                                 935C477009AC4D7300A6AAB4 /* KeyEventMac.mm in Sources */,
</span><span class="cx">                                 316FE1190E6E1DA700BF6088 /* KeyframeAnimation.cpp in Sources */,
</span><span class="cx">                                 12A253DB1C8FF7DC00C22295 /* KeyframeEffect.cpp in Sources */,
</span><span class="lines">@@ -32013,6 +32026,7 @@
</span><span class="cx">                                 49C7B9E51042D32F0009D447 /* WebGLTexture.cpp in Sources */,
</span><span class="cx">                                 6F995A231A7078B100A735F4 /* WebGLTransformFeedback.cpp in Sources */,
</span><span class="cx">                                 0C3F1F5A10C8871200D72CE1 /* WebGLUniformLocation.cpp in Sources */,
</span><ins>+                                07C046C71E425155007201E7 /* AudioTrackPrivateMediaStreamCocoa.cpp in Sources */,
</ins><span class="cx">                                 6F995A251A7078B100A735F4 /* WebGLVertexArrayObject.cpp in Sources */,
</span><span class="cx">                                 6F222B761AB52D8A0094651A /* WebGLVertexArrayObjectBase.cpp in Sources */,
</span><span class="cx">                                 77A17A7712F28642004E02F6 /* WebGLVertexArrayObjectOES.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformaudioAudioStreamDescriptionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/audio/AudioStreamDescription.h (211538 => 211539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/audio/AudioStreamDescription.h        2017-02-01 23:25:15 UTC (rev 211538)
+++ trunk/Source/WebCore/platform/audio/AudioStreamDescription.h        2017-02-01 23:38:04 UTC (rev 211539)
</span><span class="lines">@@ -48,6 +48,7 @@
</span><span class="cx">     enum PCMFormat {
</span><span class="cx">         None,
</span><span class="cx">         Int16,
</span><ins>+        Int32,
</ins><span class="cx">         Float32,
</span><span class="cx">         Float64
</span><span class="cx">     };
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformaudiomacCAAudioStreamDescriptioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/audio/mac/CAAudioStreamDescription.cpp (211538 => 211539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/audio/mac/CAAudioStreamDescription.cpp        2017-02-01 23:25:15 UTC (rev 211538)
+++ trunk/Source/WebCore/platform/audio/mac/CAAudioStreamDescription.cpp        2017-02-01 23:38:04 UTC (rev 211539)
</span><span class="lines">@@ -28,6 +28,15 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><ins>+CAAudioStreamDescription::CAAudioStreamDescription()
+    : m_streamDescription({ })
+{
+}
+    
+CAAudioStreamDescription::~CAAudioStreamDescription()
+{
+}
+
</ins><span class="cx"> CAAudioStreamDescription::CAAudioStreamDescription(const AudioStreamBasicDescription &amp;desc)
</span><span class="cx">     : m_streamDescription(desc)
</span><span class="cx"> {
</span><span class="lines">@@ -46,6 +55,14 @@
</span><span class="cx"> 
</span><span class="cx">     int wordsize;
</span><span class="cx">     switch (format) {
</span><ins>+    case Int16:
+        wordsize = 2;
+        m_streamDescription.mFormatFlags |= kAudioFormatFlagIsSignedInteger;
+        break;
+    case Int32:
+        wordsize = 4;
+        m_streamDescription.mFormatFlags |= kAudioFormatFlagIsSignedInteger;
+        break;
</ins><span class="cx">     case Float32:
</span><span class="cx">         wordsize = 4;
</span><span class="cx">         m_streamDescription.mFormatFlags |= kAudioFormatFlagIsFloat;
</span><span class="lines">@@ -54,10 +71,6 @@
</span><span class="cx">         wordsize = 8;
</span><span class="cx">         m_streamDescription.mFormatFlags |= kAudioFormatFlagIsFloat;
</span><span class="cx">         break;
</span><del>-    case Int16:
-        wordsize = 2;
-        m_streamDescription.mFormatFlags |= kAudioFormatFlagIsSignedInteger;
-        break;
</del><span class="cx">     case None:
</span><span class="cx">         ASSERT_NOT_REACHED();
</span><span class="cx">     }
</span><span class="lines">@@ -109,7 +122,7 @@
</span><span class="cx"> 
</span><span class="cx">             if (wordsize == sizeof(float))
</span><span class="cx">                 return m_format = Float32;
</span><del>-            else if (wordsize == sizeof(double))
</del><ins>+            if (wordsize == sizeof(double))
</ins><span class="cx">                 return m_format = Float64;
</span><span class="cx"> 
</span><span class="cx">             return None;
</span><span class="lines">@@ -117,8 +130,12 @@
</span><span class="cx"> 
</span><span class="cx">         if (m_streamDescription.mFormatFlags &amp; kLinearPCMFormatFlagIsSignedInteger) {
</span><span class="cx">             unsigned fractionBits = (m_streamDescription.mFormatFlags &amp; kLinearPCMFormatFlagsSampleFractionMask) &gt;&gt; kLinearPCMFormatFlagsSampleFractionShift;
</span><del>-            if (wordsize == 2 &amp;&amp; !fractionBits)
-                return m_format = Int16;
</del><ins>+            if (!fractionBits) {
+                if (wordsize == sizeof(int16_t))
+                    return m_format = Int16;
+                if (wordsize == sizeof(int32_t))
+                    return m_format = Int32;
+            }
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -125,14 +142,6 @@
</span><span class="cx">     return None;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool CAAudioStreamDescription::operator==(const AudioStreamDescription&amp; other)
-{
-    if (other.platformDescription().type != PlatformDescription::CAAudioStreamBasicType)
-        return false;
-
-    return operator==(*WTF::get&lt;const AudioStreamBasicDescription*&gt;(other.platformDescription().description));
-}
-
</del><span class="cx"> bool operator==(const AudioStreamBasicDescription&amp; a, const AudioStreamBasicDescription&amp; b)
</span><span class="cx"> {
</span><span class="cx">     return a.mSampleRate == b.mSampleRate
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformaudiomacCAAudioStreamDescriptionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/audio/mac/CAAudioStreamDescription.h (211538 => 211539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/audio/mac/CAAudioStreamDescription.h        2017-02-01 23:25:15 UTC (rev 211538)
+++ trunk/Source/WebCore/platform/audio/mac/CAAudioStreamDescription.h        2017-02-01 23:38:04 UTC (rev 211539)
</span><span class="lines">@@ -35,15 +35,18 @@
</span><span class="cx"> 
</span><span class="cx"> class CAAudioStreamDescription final : public AudioStreamDescription {
</span><span class="cx"> public:
</span><del>-    CAAudioStreamDescription(const AudioStreamBasicDescription&amp;);
-    CAAudioStreamDescription(double, uint32_t, PCMFormat, bool);
</del><span class="cx"> 
</span><ins>+    WEBCORE_EXPORT CAAudioStreamDescription();
+    WEBCORE_EXPORT CAAudioStreamDescription(const AudioStreamBasicDescription&amp;);
+    WEBCORE_EXPORT CAAudioStreamDescription(double, uint32_t, PCMFormat, bool);
+    WEBCORE_EXPORT ~CAAudioStreamDescription();
+
</ins><span class="cx">     const PlatformDescription&amp; platformDescription() const final;
</span><span class="cx"> 
</span><span class="cx">     PCMFormat format() const final;
</span><span class="cx"> 
</span><span class="cx">     double sampleRate() const final { return m_streamDescription.mSampleRate; }
</span><del>-
</del><ins>+    bool isPCM() const final { return m_streamDescription.mFormatID == kAudioFormatLinearPCM; }
</ins><span class="cx">     bool isInterleaved() const final { return !(m_streamDescription.mFormatFlags &amp; kAudioFormatFlagIsNonInterleaved); }
</span><span class="cx">     bool isSignedInteger() const final { return isPCM() &amp;&amp; (m_streamDescription.mFormatFlags &amp; kAudioFormatFlagIsSignedInteger); }
</span><span class="cx">     bool isFloat() const final { return isPCM() &amp;&amp; (m_streamDescription.mFormatFlags &amp; kAudioFormatFlagIsFloat); }
</span><span class="lines">@@ -61,7 +64,13 @@
</span><span class="cx"> 
</span><span class="cx">     bool operator==(const AudioStreamBasicDescription&amp; other) { return m_streamDescription == other; }
</span><span class="cx">     bool operator!=(const AudioStreamBasicDescription&amp; other) { return !operator == (other); }
</span><del>-    bool operator==(const AudioStreamDescription&amp;);
</del><ins>+    bool operator==(const AudioStreamDescription&amp; other)
+    {
+        if (other.platformDescription().type != PlatformDescription::CAAudioStreamBasicType)
+            return false;
+
+        return operator==(*WTF::get&lt;const AudioStreamBasicDescription*&gt;(other.platformDescription().description));
+    }
</ins><span class="cx">     bool operator!=(const AudioStreamDescription&amp; other) { return !operator == (other); }
</span><span class="cx"> 
</span><span class="cx">     const AudioStreamBasicDescription&amp; streamDescription() { return m_streamDescription; }
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformaudiomacCARingBuffercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/audio/mac/CARingBuffer.cpp (211538 => 211539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/audio/mac/CARingBuffer.cpp        2017-02-01 23:25:15 UTC (rev 211538)
+++ trunk/Source/WebCore/platform/audio/mac/CARingBuffer.cpp        2017-02-01 23:38:04 UTC (rev 211539)
</span><span class="lines">@@ -28,6 +28,8 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(WEB_AUDIO) &amp;&amp; USE(MEDIATOOLBOX)
</span><span class="cx"> 
</span><ins>+#include &quot;CAAudioStreamDescription.h&quot;
+#include &lt;Accelerate/Accelerate.h&gt;
</ins><span class="cx"> #include &lt;CoreAudio/CoreAudioTypes.h&gt;
</span><span class="cx"> #include &lt;wtf/MathExtras.h&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -37,17 +39,14 @@
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="cx"> CARingBuffer::CARingBuffer()
</span><del>-    : m_channelCount(0)
-    , m_frameCount(0)
-    , m_capacityBytes(0)
-    , m_timeBoundsQueue(kGeneralRingTimeBoundsQueueSize)
-    , m_timeBoundsQueuePtr(0)
</del><ins>+    : m_timeBoundsQueue(kGeneralRingTimeBoundsQueueSize)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-CARingBuffer::~CARingBuffer()
</del><ins>+void CARingBuffer::allocate(const CAAudioStreamDescription&amp; format, size_t frameCount)
</ins><span class="cx"> {
</span><del>-    deallocate();
</del><ins>+    m_description = format;
+    allocate(format.numberOfChannelStreams(), format.bytesPerFrame(), frameCount);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void CARingBuffer::allocate(uint32_t channelCount, size_t bytesPerFrame, size_t frameCount)
</span><span class="lines">@@ -74,12 +73,7 @@
</span><span class="cx">         channelData += m_capacityBytes;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    for (auto timeBounds : m_timeBoundsQueue) {
-        timeBounds.m_startFrame = 0;
-        timeBounds.m_endFrame = 0;
-        timeBounds.m_updateCounter = 0;
-    }
-    m_timeBoundsQueuePtr = 0;
</del><ins>+    flush();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void CARingBuffer::deallocate()
</span><span class="lines">@@ -113,7 +107,7 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static void FetchABL(AudioBufferList* list, size_t destOffset, Byte** buffers, size_t srcOffset, size_t nbytes)
</del><ins>+static void FetchABL(AudioBufferList* list, size_t destOffset, Byte** buffers, size_t srcOffset, size_t nbytes, AudioStreamDescription::PCMFormat format, CARingBuffer::FetchMode mode)
</ins><span class="cx"> {
</span><span class="cx">     int channelCount = list-&gt;mNumberBuffers;
</span><span class="cx">     AudioBuffer* dest = list-&gt;mBuffers;
</span><span class="lines">@@ -120,7 +114,39 @@
</span><span class="cx">     while (--channelCount &gt;= 0) {
</span><span class="cx">         if (destOffset &gt; dest-&gt;mDataByteSize)
</span><span class="cx">             continue;
</span><del>-        memcpy(static_cast&lt;Byte*&gt;(dest-&gt;mData) + destOffset, *buffers + srcOffset, std::min&lt;size_t&gt;(nbytes, dest-&gt;mDataByteSize - destOffset));
</del><ins>+
+        nbytes = std::min&lt;size_t&gt;(nbytes, dest-&gt;mDataByteSize - destOffset);
+        if (mode == CARingBuffer::Copy)
+            memcpy(static_cast&lt;Byte*&gt;(dest-&gt;mData) + destOffset, *buffers + srcOffset, nbytes);
+        else {
+            switch (format) {
+            case AudioStreamDescription::Int16: {
+                int16_t* destination = static_cast&lt;int16_t*&gt;(dest-&gt;mData);
+                int16_t* source = reinterpret_cast&lt;int16_t*&gt;(*buffers + srcOffset);
+                for (size_t i = 0; i &lt; nbytes / sizeof(int16_t); i++)
+                    destination[i] += source[i];
+                break;
+            }
+            case AudioStreamDescription::Int32: {
+                int32_t* destination = static_cast&lt;int32_t*&gt;(dest-&gt;mData);
+                vDSP_vaddi(destination, 1, reinterpret_cast&lt;int32_t*&gt;(*buffers + srcOffset), 1, destination, 1, nbytes / sizeof(int32_t));
+                break;
+            }
+            case AudioStreamDescription::Float32: {
+                float* destination = static_cast&lt;float*&gt;(dest-&gt;mData);
+                vDSP_vadd(destination, 1, reinterpret_cast&lt;float*&gt;(*buffers + srcOffset), 1, destination, 1, nbytes / sizeof(float));
+                break;
+            }
+            case AudioStreamDescription::Float64: {
+                double* destination = static_cast&lt;double*&gt;(dest-&gt;mData);
+                vDSP_vaddD(destination, 1, reinterpret_cast&lt;double*&gt;(*buffers + srcOffset), 1, destination, 1, nbytes / sizeof(double));
+                break;
+            }
+            case AudioStreamDescription::None:
+                ASSERT_NOT_REACHED();
+                break;
+            }
+        }
</ins><span class="cx">         ++buffers;
</span><span class="cx">         ++dest;
</span><span class="cx">     }
</span><span class="lines">@@ -138,6 +164,17 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void CARingBuffer::flush()
+{
+    LockHolder locker(m_currentFrameBoundsLock);
+    for (auto&amp; timeBounds : m_timeBoundsQueue) {
+        timeBounds.m_startFrame = 0;
+        timeBounds.m_endFrame = 0;
+        timeBounds.m_updateCounter = 0;
+    }
+    m_timeBoundsQueuePtr = 0;
+}
+
</ins><span class="cx"> CARingBuffer::Error CARingBuffer::store(const AudioBufferList* list, size_t framesToWrite, uint64_t startFrame)
</span><span class="cx"> {
</span><span class="cx">     if (!framesToWrite)
</span><span class="lines">@@ -249,7 +286,7 @@
</span><span class="cx">     return m_timeBoundsQueue[index].m_endFrame;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-CARingBuffer::Error CARingBuffer::fetch(AudioBufferList* list, size_t nFrames, uint64_t startRead)
</del><ins>+CARingBuffer::Error CARingBuffer::fetch(AudioBufferList* list, size_t nFrames, uint64_t startRead, FetchMode mode)
</ins><span class="cx"> {
</span><span class="cx">     if (!nFrames)
</span><span class="cx">         return Ok;
</span><span class="lines">@@ -286,11 +323,12 @@
</span><span class="cx">     
</span><span class="cx">     if (offset0 &lt; offset1) {
</span><span class="cx">         nbytes = offset1 - offset0;
</span><del>-        FetchABL(list, destStartByteOffset, buffers, offset0, nbytes);
</del><ins>+        FetchABL(list, destStartByteOffset, buffers, offset0, nbytes, m_description.format(), mode);
</ins><span class="cx">     } else {
</span><span class="cx">         nbytes = m_capacityBytes - offset0;
</span><del>-        FetchABL(list, destStartByteOffset, buffers, offset0, nbytes);
-        FetchABL(list, destStartByteOffset + nbytes, buffers, 0, offset1);
</del><ins>+        FetchABL(list, destStartByteOffset, buffers, offset0, nbytes, m_description.format(), mode);
+        if (offset1)
+            FetchABL(list, destStartByteOffset + nbytes, buffers, 0, offset1, m_description.format(), mode);
</ins><span class="cx">         nbytes += offset1;
</span><span class="cx">     }
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformaudiomacCARingBufferh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/audio/mac/CARingBuffer.h (211538 => 211539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/audio/mac/CARingBuffer.h        2017-02-01 23:25:15 UTC (rev 211538)
+++ trunk/Source/WebCore/platform/audio/mac/CARingBuffer.h        2017-02-01 23:38:04 UTC (rev 211539)
</span><span class="lines">@@ -23,11 +23,12 @@
</span><span class="cx">  * THE POSSIBILITY OF SUCH DAMAGE.
</span><span class="cx">  */
</span><span class="cx"> 
</span><del>-#ifndef CARingBuffer_h
-#define CARingBuffer_h
</del><ins>+#pragma once
</ins><span class="cx"> 
</span><span class="cx"> #if ENABLE(WEB_AUDIO) &amp;&amp; USE(MEDIATOOLBOX)
</span><span class="cx"> 
</span><ins>+#include &quot;AudioStreamDescription.h&quot;
+#include &quot;CAAudioStreamDescription.h&quot;
</ins><span class="cx"> #include &lt;runtime/ArrayBuffer.h&gt;
</span><span class="cx"> #include &lt;wtf/Lock.h&gt;
</span><span class="cx"> #include &lt;wtf/Vector.h&gt;
</span><span class="lines">@@ -38,24 +39,33 @@
</span><span class="cx"> 
</span><span class="cx"> class CARingBuffer {
</span><span class="cx"> public:
</span><del>-    CARingBuffer();
-    ~CARingBuffer();
</del><ins>+    WEBCORE_EXPORT CARingBuffer();
+    WEBCORE_EXPORT ~CARingBuffer()
+    {
+        deallocate();
+    }
</ins><span class="cx"> 
</span><span class="cx">     enum Error {
</span><span class="cx">         Ok,
</span><span class="cx">         TooMuch, // fetch start time is earlier than buffer start time and fetch end time is later than buffer end time
</span><del>-        CPUOverload, // the reader is unable to get enough CPU cycles to capture a consistent snapshot of the time bounds
</del><span class="cx">     };
</span><span class="cx"> 
</span><del>-    void allocate(uint32_t m_channelCount, size_t bytesPerFrame, size_t frameCount);
-    void deallocate();
-    Error store(const AudioBufferList*, size_t frameCount, uint64_t startFrame);
-    Error fetch(AudioBufferList*, size_t frameCount, uint64_t startFrame);
-    void getCurrentFrameBounds(uint64_t &amp;startTime, uint64_t &amp;endTime);
</del><ins>+    WEBCORE_EXPORT void allocate(const CAAudioStreamDescription&amp;, size_t);
+    WEBCORE_EXPORT void deallocate();
</ins><span class="cx"> 
</span><ins>+    WEBCORE_EXPORT Error store(const AudioBufferList*, size_t frameCount, uint64_t startFrame);
+
+    enum FetchMode { Copy, Mix };
+    WEBCORE_EXPORT Error fetch(AudioBufferList*, size_t frameCount, uint64_t startFrame, FetchMode mode = Copy);
+
+    WEBCORE_EXPORT void flush();
+
+    WEBCORE_EXPORT void getCurrentFrameBounds(uint64_t &amp;startTime, uint64_t &amp;endTime);
+
</ins><span class="cx">     uint32_t channelCount() const { return m_channelCount; }
</span><span class="cx"> 
</span><span class="cx"> private:
</span><ins>+    void allocate(uint32_t m_channelCount, size_t bytesPerFrame, size_t frameCount);
</ins><span class="cx">     size_t frameOffset(uint64_t frameNumber) { return (frameNumber &amp; m_frameCountMask) * m_bytesPerFrame; }
</span><span class="cx"> 
</span><span class="cx">     void clipTimeBounds(uint64_t&amp; startRead, uint64_t&amp; endRead);
</span><span class="lines">@@ -65,11 +75,11 @@
</span><span class="cx">     void setCurrentFrameBounds(uint64_t startFrame, uint64_t endFrame);
</span><span class="cx"> 
</span><span class="cx">     RefPtr&lt;ArrayBuffer&gt; m_buffers;
</span><del>-    uint32_t m_channelCount;
-    size_t m_bytesPerFrame;
-    uint32_t m_frameCount;
-    uint32_t m_frameCountMask;
-    size_t m_capacityBytes;
</del><ins>+    uint32_t m_channelCount { 0 };
+    size_t m_bytesPerFrame { 0 };
+    uint32_t m_frameCount { 0 };
+    uint32_t m_frameCountMask { 0 };
+    size_t m_capacityBytes { 0 };
</ins><span class="cx"> 
</span><span class="cx">     struct TimeBounds {
</span><span class="cx">         TimeBounds()
</span><span class="lines">@@ -82,14 +92,13 @@
</span><span class="cx">         volatile uint64_t m_endFrame;
</span><span class="cx">         volatile uint32_t m_updateCounter;
</span><span class="cx">     };
</span><del>-    
</del><ins>+
+    CAAudioStreamDescription m_description;
</ins><span class="cx">     Vector&lt;TimeBounds&gt; m_timeBoundsQueue;
</span><span class="cx">     Lock m_currentFrameBoundsLock;
</span><del>-    std::atomic&lt;int32_t&gt; m_timeBoundsQueuePtr;
</del><ins>+    std::atomic&lt;int32_t&gt; m_timeBoundsQueuePtr { 0 };
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(WEB_AUDIO) &amp;&amp; USE(MEDIATOOLBOX)
</span><del>-
-#endif // CARingBuffer_h
</del></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationAudioSourceProviderAVFObjCmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/avfoundation/AudioSourceProviderAVFObjC.mm (211538 => 211539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/AudioSourceProviderAVFObjC.mm        2017-02-01 23:25:15 UTC (rev 211538)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/AudioSourceProviderAVFObjC.mm        2017-02-01 23:38:04 UTC (rev 211539)
</span><span class="lines">@@ -264,23 +264,6 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static bool operator==(const AudioStreamBasicDescription&amp; a, const AudioStreamBasicDescription&amp; b)
-{
-    return a.mSampleRate == b.mSampleRate
-        &amp;&amp; a.mFormatID == b.mFormatID
-        &amp;&amp; a.mFormatFlags == b.mFormatFlags
-        &amp;&amp; a.mBytesPerPacket == b.mBytesPerPacket
-        &amp;&amp; a.mFramesPerPacket == b.mFramesPerPacket
-        &amp;&amp; a.mBytesPerFrame == b.mBytesPerFrame
-        &amp;&amp; a.mChannelsPerFrame == b.mChannelsPerFrame
-        &amp;&amp; a.mBitsPerChannel == b.mBitsPerChannel;
-}
-
-static bool operator!=(const AudioStreamBasicDescription&amp; a, const AudioStreamBasicDescription&amp; b)
-{
-    return !(a == b);
-}
-
</del><span class="cx"> void AudioSourceProviderAVFObjC::prepare(CMItemCount maxFrames, const AudioStreamBasicDescription *processingFormat)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(maxFrames &gt;= 0);
</span><span class="lines">@@ -289,7 +272,6 @@
</span><span class="cx"> 
</span><span class="cx">     m_tapDescription = std::make_unique&lt;AudioStreamBasicDescription&gt;(*processingFormat);
</span><span class="cx">     int numberOfChannels = processingFormat-&gt;mChannelsPerFrame;
</span><del>-    size_t bytesPerFrame = processingFormat-&gt;mBytesPerFrame;
</del><span class="cx">     double sampleRate = processingFormat-&gt;mSampleRate;
</span><span class="cx">     ASSERT(sampleRate &gt;= 0);
</span><span class="cx"> 
</span><span class="lines">@@ -314,7 +296,7 @@
</span><span class="cx">     size_t capacity = std::max(static_cast&lt;size_t&gt;(2 * maxFrames), static_cast&lt;size_t&gt;(kRingBufferDuration * sampleRate));
</span><span class="cx"> 
</span><span class="cx">     m_ringBuffer = std::make_unique&lt;CARingBuffer&gt;();
</span><del>-    m_ringBuffer-&gt;allocate(numberOfChannels, bytesPerFrame, capacity);
</del><ins>+    m_ringBuffer-&gt;allocate(CAAudioStreamDescription(*processingFormat), capacity);
</ins><span class="cx"> 
</span><span class="cx">     // AudioBufferList is a variable-length struct, so create on the heap with a generic new() operator
</span><span class="cx">     // with a custom size, and initialize the struct manually.
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreammacWebAudioSourceProviderAVFObjCmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/mac/WebAudioSourceProviderAVFObjC.mm (211538 => 211539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/mac/WebAudioSourceProviderAVFObjC.mm        2017-02-01 23:25:15 UTC (rev 211538)
+++ trunk/Source/WebCore/platform/mediastream/mac/WebAudioSourceProviderAVFObjC.mm        2017-02-01 23:38:04 UTC (rev 211539)
</span><span class="lines">@@ -134,23 +134,6 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static bool operator==(const AudioStreamBasicDescription&amp; a, const AudioStreamBasicDescription&amp; b)
-{
-    return a.mSampleRate == b.mSampleRate
-        &amp;&amp; a.mFormatID == b.mFormatID
-        &amp;&amp; a.mFormatFlags == b.mFormatFlags
-        &amp;&amp; a.mBytesPerPacket == b.mBytesPerPacket
-        &amp;&amp; a.mFramesPerPacket == b.mFramesPerPacket
-        &amp;&amp; a.mBytesPerFrame == b.mBytesPerFrame
-        &amp;&amp; a.mChannelsPerFrame == b.mChannelsPerFrame
-        &amp;&amp; a.mBitsPerChannel == b.mBitsPerChannel;
-}
-
-static bool operator!=(const AudioStreamBasicDescription&amp; a, const AudioStreamBasicDescription&amp; b)
-{
-    return !(a == b);
-}
-
</del><span class="cx"> void WebAudioSourceProviderAVFObjC::prepare(const AudioStreamBasicDescription* format)
</span><span class="cx"> {
</span><span class="cx">     LOG(Media, &quot;WebAudioSourceProviderAVFObjC::prepare(%p)&quot;, this);
</span><span class="lines">@@ -201,7 +184,7 @@
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     m_ringBuffer = std::make_unique&lt;CARingBuffer&gt;();
</span><del>-    m_ringBuffer-&gt;allocate(numberOfChannels, format-&gt;mBytesPerFrame, static_cast&lt;size_t&gt;(capacity));
</del><ins>+    m_ringBuffer-&gt;allocate(CAAudioStreamDescription(*format), static_cast&lt;size_t&gt;(capacity));
</ins><span class="cx"> 
</span><span class="cx">     m_listBufferSize = static_cast&lt;size_t&gt;(bufferListSize);
</span><span class="cx">     m_list = std::unique_ptr&lt;AudioBufferList&gt;(static_cast&lt;AudioBufferList*&gt;(::operator new (m_listBufferSize)));
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (211538 => 211539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2017-02-01 23:25:15 UTC (rev 211538)
+++ trunk/Tools/ChangeLog        2017-02-01 23:38:04 UTC (rev 211539)
</span><span class="lines">@@ -1,3 +1,24 @@
</span><ins>+2017-02-01  Eric Carlson  &lt;eric.carlson@apple.com&gt;
+
+        [Mac] Update CARingBuffer class
+        https://bugs.webkit.org/show_bug.cgi?id=167656
+
+        Reviewed by Jer Noble.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebCore/CARingBuffer.cpp: Added.
+        (TestWebKitAPI::CARingBufferTest::SetUp):
+        (TestWebKitAPI::CARingBufferTest::setup):
+        (TestWebKitAPI::CARingBufferTest::setListDataBuffer):
+        (TestWebKitAPI::CARingBufferTest::description):
+        (TestWebKitAPI::CARingBufferTest::bufferList):
+        (TestWebKitAPI::CARingBufferTest::ringBuffer):
+        (TestWebKitAPI::CARingBufferTest::capacity):
+        (TestWebKitAPI::CARingBufferTest::audioBufferListSizeForStream):
+        (TestWebKitAPI::CARingBufferTest::configureBufferListForStream):
+        (TestWebKitAPI::TEST_F):
+        (TestWebKitAPI::MixingTest::run):
+
</ins><span class="cx"> 2017-02-01  Alexey Proskuryakov  &lt;ap@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [Mac] TestWebKitAPI includes system frameworks incorrectly
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestWebKitAPIxcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (211538 => 211539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj        2017-02-01 23:25:15 UTC (rev 211538)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj        2017-02-01 23:38:04 UTC (rev 211539)
</span><span class="lines">@@ -24,6 +24,7 @@
</span><span class="cx"> /* Begin PBXBuildFile section */
</span><span class="cx">                 07492B3B1DF8B14C00633DE1 /* EnumerateMediaDevices.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07492B3A1DF8AE2D00633DE1 /* EnumerateMediaDevices.cpp */; };
</span><span class="cx">                 07492B3C1DF8B86600633DE1 /* enumerateMediaDevices.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 07492B391DF8ADA400633DE1 /* enumerateMediaDevices.html */; };
</span><ins>+                07C046CA1E4262A8007201E7 /* CARingBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07C046C91E42573E007201E7 /* CARingBuffer.cpp */; };
</ins><span class="cx">                 0F139E771A423A5B00F590F5 /* WeakObjCPtr.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0F139E751A423A5300F590F5 /* WeakObjCPtr.mm */; };
</span><span class="cx">                 0F139E781A423A6B00F590F5 /* PlatformUtilitiesCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0F139E721A423A2B00F590F5 /* PlatformUtilitiesCocoa.mm */; };
</span><span class="cx">                 0F139E791A42457000F590F5 /* PlatformUtilitiesCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0F139E721A423A2B00F590F5 /* PlatformUtilitiesCocoa.mm */; };
</span><span class="lines">@@ -785,6 +786,7 @@
</span><span class="cx">                 07492B391DF8ADA400633DE1 /* enumerateMediaDevices.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = enumerateMediaDevices.html; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 07492B3A1DF8AE2D00633DE1 /* EnumerateMediaDevices.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EnumerateMediaDevices.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0766DD1F1A5AD5200023E3BB /* PendingAPIRequestURL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PendingAPIRequestURL.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                07C046C91E42573E007201E7 /* CARingBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CARingBuffer.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0BCD833414857CE400EA2003 /* HashMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HashMap.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0BCD85691485C98B00EA2003 /* SetForScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SetForScope.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F139E721A423A2B00F590F5 /* PlatformUtilitiesCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = PlatformUtilitiesCocoa.mm; path = cocoa/PlatformUtilitiesCocoa.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -1590,6 +1592,7 @@
</span><span class="cx">                                 8E4A85361E1D1AA100F53B0F /* GridPosition.cpp */,
</span><span class="cx">                                 CD89D0371C4EDB1300040A04 /* cocoa */,
</span><span class="cx">                                 7A909A6F1D877475007E10F8 /* AffineTransform.cpp */,
</span><ins>+                                07C046C91E42573E007201E7 /* CARingBuffer.cpp */,
</ins><span class="cx">                                 7A909A701D877475007E10F8 /* FloatPoint.cpp */,
</span><span class="cx">                                 7A909A711D877475007E10F8 /* FloatRect.cpp */,
</span><span class="cx">                                 7A909A721D877475007E10F8 /* FloatSize.cpp */,
</span><span class="lines">@@ -2671,6 +2674,7 @@
</span><span class="cx">                                 7CCE7F0D1A411AE600447C4C /* ReloadPageAfterCrash.cpp in Sources */,
</span><span class="cx">                                 7C83E0C31D0A653A00FEBCF3 /* RemoteObjectRegistry.mm in Sources */,
</span><span class="cx">                                 7CCE7EC91A411A7E00447C4C /* RenderedImageFromDOMNode.mm in Sources */,
</span><ins>+                                07C046CA1E4262A8007201E7 /* CARingBuffer.cpp in Sources */,
</ins><span class="cx">                                 7A909A7D1D877480007E10F8 /* AffineTransform.cpp in Sources */,
</span><span class="cx">                                 7CCE7ECA1A411A7E00447C4C /* RenderedImageFromDOMRange.mm in Sources */,
</span><span class="cx">                                 7C83E0C41D0A654200FEBCF3 /* RequiresUserActionForPlayback.mm in Sources */,
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebCoreCARingBuffercpp"></a>
<div class="addfile"><h4>Added: trunk/Tools/TestWebKitAPI/Tests/WebCore/CARingBuffer.cpp (0 => 211539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WebCore/CARingBuffer.cpp                                (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebCore/CARingBuffer.cpp        2017-02-01 23:38:04 UTC (rev 211539)
</span><span class="lines">@@ -0,0 +1,251 @@
</span><ins>+/*
+ * Copyright (C) 2017 Apple 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.
+ *
+ * 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 &quot;config.h&quot;
+
+#if PLATFORM(MAC)
+
+#include &quot;Test.h&quot;
+#include &lt;WebCore/CARingBuffer.h&gt;
+#include &lt;wtf/MainThread.h&gt;
+
+using namespace WebCore;
+
+namespace TestWebKitAPI {
+
+class CARingBufferTest : public testing::Test {
+public:
+
+    virtual void SetUp()
+    {
+        WTF::initializeMainThread();
+        m_ringBuffer = std::make_unique&lt;CARingBuffer&gt;();
+    }
+
+    // CAAudioStreamDescription(double sampleRate, UInt32 numChannels, PCMFormat format, bool isInterleaved, size_t capacity)
+    void setup(double sampleRate, UInt32 numChannels, CAAudioStreamDescription::PCMFormat format, bool isInterleaved, size_t capacity)
+    {
+        m_description = CAAudioStreamDescription(sampleRate, numChannels, format, isInterleaved);
+        m_capacity = capacity;
+        size_t listSize = offsetof(AudioBufferList, mBuffers) + (sizeof(AudioBuffer) * std::max&lt;uint32_t&gt;(1, m_description.numberOfChannelStreams()));
+        m_bufferList = std::unique_ptr&lt;AudioBufferList&gt;(static_cast&lt;AudioBufferList*&gt;(::operator new (listSize)));
+        m_ringBuffer-&gt;allocate(m_description, capacity);
+    }
+
+    void setListDataBuffer(uint8_t* bufferData, size_t sampleCount)
+    {
+        size_t bufferCount = m_description.numberOfChannelStreams();
+        size_t channelCount = m_description.numberOfInterleavedChannels();
+        size_t bytesPerChannel = sampleCount * m_description.bytesPerFrame();
+
+        m_bufferList-&gt;mNumberBuffers = bufferCount;
+        for (unsigned i = 0; i &lt; bufferCount; ++i) {
+            m_bufferList-&gt;mBuffers[i].mNumberChannels = channelCount;
+            m_bufferList-&gt;mBuffers[i].mDataByteSize = bytesPerChannel;
+            m_bufferList-&gt;mBuffers[i].mData = bufferData;
+            if (bufferData)
+                bufferData = bufferData + bytesPerChannel;
+        }
+    }
+
+    const CAAudioStreamDescription&amp; description() const { return m_description; }
+    AudioBufferList&amp; bufferList() const { return *m_bufferList.get(); }
+    CARingBuffer&amp; ringBuffer() const { return *m_ringBuffer.get(); }
+    size_t capacity() const { return m_capacity; }
+
+private:
+    size_t audioBufferListSizeForStream(const CAAudioStreamDescription&amp; format)
+    {
+        return offsetof(AudioBufferList, mBuffers) + (sizeof(AudioBuffer) * std::max&lt;uint32_t&gt;(1, format.numberOfChannelStreams()));
+    }
+
+    void configureBufferListForStream(AudioBufferList&amp; bufferList, const CAAudioStreamDescription&amp; format, uint8_t* bufferData, size_t sampleCount)
+    {
+        size_t bufferCount = format.numberOfChannelStreams();
+        size_t channelCount = format.numberOfInterleavedChannels();
+        size_t bytesPerChannel = sampleCount * format.bytesPerFrame();
+
+        bufferList.mNumberBuffers = bufferCount;
+        for (unsigned i = 0; i &lt; bufferCount; ++i) {
+            bufferList.mBuffers[i].mNumberChannels = channelCount;
+            bufferList.mBuffers[i].mDataByteSize = bytesPerChannel;
+            bufferList.mBuffers[i].mData = bufferData;
+            if (bufferData)
+                bufferData = bufferData + bytesPerChannel;
+        }
+    }
+
+    std::unique_ptr&lt;AudioBufferList&gt; m_bufferList;
+    std::unique_ptr&lt;CARingBuffer&gt; m_ringBuffer;
+    CAAudioStreamDescription m_description = { };
+    size_t m_capacity = { 0 };
+};
+
+TEST_F(CARingBufferTest, Basics)
+{
+    const int capacity = 32;
+
+    setup(44100, 1, CAAudioStreamDescription::PCMFormat::Float32, true, capacity);
+
+    float sourceBuffer[capacity];
+    for (int i = 0; i &lt; capacity; i++)
+        sourceBuffer[i] = i + 0.5;
+
+    setListDataBuffer(reinterpret_cast&lt;uint8_t*&gt;(sourceBuffer), capacity);
+
+    // Fill the first half of the buffer ...
+    int sampleCount = capacity / 2;
+    CARingBuffer::Error err = ringBuffer().store(&amp;bufferList(), sampleCount, 0);
+    EXPECT_EQ(err, CARingBuffer::Error::Ok);
+
+    uint64_t startTime;
+    uint64_t endTime;
+    ringBuffer().getCurrentFrameBounds(startTime, endTime);
+    EXPECT_EQ(0, (int)startTime);
+    EXPECT_EQ((int)sampleCount, (int)endTime);
+
+    float scratchBuffer[capacity];
+    setListDataBuffer(reinterpret_cast&lt;uint8_t*&gt;(scratchBuffer), capacity);
+
+    err = ringBuffer().fetch(&amp;bufferList(), sampleCount, 0);
+    EXPECT_EQ(err, CARingBuffer::Error::Ok);
+    EXPECT_TRUE(!memcmp(sourceBuffer, scratchBuffer, sampleCount * description().sampleWordSize()));
+
+    // ... and the second half.
+    err = ringBuffer().store(&amp;bufferList(), capacity / 2, capacity / 2);
+    EXPECT_EQ(err, CARingBuffer::Error::Ok);
+
+    ringBuffer().getCurrentFrameBounds(startTime, endTime);
+    EXPECT_EQ(0, (int)startTime);
+    EXPECT_EQ(capacity, (int)endTime);
+
+    memset(scratchBuffer, 0, sampleCount * description().sampleWordSize());
+    err = ringBuffer().fetch(&amp;bufferList(), sampleCount, 0);
+    EXPECT_EQ(err, CARingBuffer::Error::Ok);
+    EXPECT_TRUE(!memcmp(sourceBuffer, scratchBuffer, sampleCount * description().sampleWordSize()));
+
+    // Force the buffer to wrap around
+    err = ringBuffer().store(&amp;bufferList(), capacity, capacity - 1);
+    EXPECT_EQ(err, CARingBuffer::Error::Ok);
+
+    ringBuffer().getCurrentFrameBounds(startTime, endTime);
+    EXPECT_EQ((int)capacity - 1, (int)startTime);
+    EXPECT_EQ(capacity - 1 + capacity, (int)endTime);
+
+    // Make sure it returns an error when asked to store too much ...
+    err = ringBuffer().store(&amp;bufferList(), capacity * 3, capacity / 2);
+    EXPECT_EQ(err, CARingBuffer::Error::TooMuch);
+
+    // ... and doesn't modify the buffer
+    ringBuffer().getCurrentFrameBounds(startTime, endTime);
+    EXPECT_EQ((int)capacity - 1, (int)startTime);
+    EXPECT_EQ(capacity - 1 + capacity, (int)endTime);
+
+    ringBuffer().flush();
+    ringBuffer().getCurrentFrameBounds(startTime, endTime);
+    EXPECT_EQ(0, (int)startTime);
+    EXPECT_EQ(0, (int)endTime);
+}
+
+template &lt;typename type&gt;
+class MixingTest {
+public:
+    static void run(CARingBufferTest&amp; test)
+    {
+        const int sampleCount = 64;
+
+        CAAudioStreamDescription::PCMFormat format;
+        if (std::is_same&lt;type, float&gt;::value)
+            format = CAAudioStreamDescription::PCMFormat::Float32;
+        else if (std::is_same&lt;type, double&gt;::value)
+            format = CAAudioStreamDescription::PCMFormat::Float64;
+        else if (std::is_same&lt;type, int32_t&gt;::value)
+            format = CAAudioStreamDescription::PCMFormat::Int32;
+        else if (std::is_same&lt;type, int16_t&gt;::value)
+            format = CAAudioStreamDescription::PCMFormat::Int16;
+        else
+            ASSERT_NOT_REACHED();
+
+        test.setup(44100, 1, format, true, sampleCount);
+
+        type referenceBuffer[sampleCount];
+        type sourceBuffer[sampleCount];
+        type readBuffer[sampleCount];
+
+        for (int i = 0; i &lt; sampleCount; i++) {
+            sourceBuffer[i] = i * 0.5;
+            referenceBuffer[i] = sourceBuffer[i];
+        }
+
+        test.setListDataBuffer(reinterpret_cast&lt;uint8_t*&gt;(sourceBuffer), sampleCount);
+        CARingBuffer::Error err = test.ringBuffer().store(&amp;test.bufferList(), sampleCount, 0);
+        EXPECT_EQ(err, CARingBuffer::Error::Ok);
+
+        memset(readBuffer, 0, sampleCount * test.description().sampleWordSize());
+        test.setListDataBuffer(reinterpret_cast&lt;uint8_t*&gt;(readBuffer), sampleCount);
+        err = test.ringBuffer().fetch(&amp;test.bufferList(), sampleCount, 0, CARingBuffer::FetchMode::Mix);
+        EXPECT_EQ(err, CARingBuffer::Error::Ok);
+
+        for (int i = 0; i &lt; sampleCount; i++)
+            EXPECT_EQ(readBuffer[i], referenceBuffer[i]) &lt;&lt; &quot;Ring buffer value differs at index &quot; &lt;&lt; i;
+
+        err = test.ringBuffer().fetch(&amp;test.bufferList(), sampleCount, 0, CARingBuffer::FetchMode::Mix);
+        EXPECT_EQ(err, CARingBuffer::Error::Ok);
+        err = test.ringBuffer().fetch(&amp;test.bufferList(), sampleCount, 0, CARingBuffer::FetchMode::Mix);
+        EXPECT_EQ(err, CARingBuffer::Error::Ok);
+        err = test.ringBuffer().fetch(&amp;test.bufferList(), sampleCount, 0, CARingBuffer::FetchMode::Mix);
+        EXPECT_EQ(err, CARingBuffer::Error::Ok);
+
+        for (int i = 0; i &lt; sampleCount; i++)
+            referenceBuffer[i] += sourceBuffer[i] * 3;
+        
+        for (int i = 0; i &lt; sampleCount; i++)
+            EXPECT_EQ(readBuffer[i], referenceBuffer[i]) &lt;&lt; &quot;Ring buffer value differs at index &quot; &lt;&lt; i;
+    }
+};
+
+TEST_F(CARingBufferTest, FloatMixing)
+{
+    MixingTest&lt;float&gt;::run(*this);
+}
+
+TEST_F(CARingBufferTest, DoubleMixing)
+{
+    MixingTest&lt;double&gt;::run(*this);
+}
+
+TEST_F(CARingBufferTest, Int32Mixing)
+{
+    MixingTest&lt;int32_t&gt;::run(*this);
+}
+
+TEST_F(CARingBufferTest, Int16Mixing)
+{
+    MixingTest&lt;int16_t&gt;::run(*this);
+}
+
+}
+
+#endif
</ins></span></pre>
</div>
</div>

</body>
</html>