Modified: trunk/Source/WebCore/ChangeLog (212724 => 212725)
--- trunk/Source/WebCore/ChangeLog 2017-02-21 18:24:51 UTC (rev 212724)
+++ trunk/Source/WebCore/ChangeLog 2017-02-21 18:28:47 UTC (rev 212725)
@@ -1,5 +1,28 @@
2017-02-21 Jer Noble <jer.no...@apple.com>
+ Give the Mock audio input a "hum" to make drop-outs more detectable
+ https://bugs.webkit.org/show_bug.cgi?id=168641
+
+ Reviewed by Eric Carlson.
+
+ Add two helper functions to generate waveforms: addHum() and writeHum(). Use these methods
+ to create a bip-bop audio buffer which can be used to "blit" a portion the waveform into the
+ destination buffer during rendering. The background hum must be seamless across multiple
+ pull operations, so add the hum sound during rendering.
+
+ To ensure the waveform buffer is created, initialize the sampleRate to zero, then call
+ applySampleRate() with the desired default rate, 44.1kHz.
+
+ * platform/mediastream/mac/MockRealtimeAudioSourceMac.h:
+ * platform/mediastream/mac/MockRealtimeAudioSourceMac.mm:
+ (WebCore::writeHum):
+ (WebCore::addHum):
+ (WebCore::MockRealtimeAudioSource::create):
+ (WebCore::MockRealtimeAudioSourceMac::render):
+ (WebCore::MockRealtimeAudioSourceMac::applySampleRate):
+
+2017-02-21 Jer Noble <jer.no...@apple.com>
+
Make TrackPrivateBase ThreadSafeRefCounted, so that it can be retained in non-main threads
https://bugs.webkit.org/show_bug.cgi?id=168642
Modified: trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeAudioSourceMac.h (212724 => 212725)
--- trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeAudioSourceMac.h 2017-02-21 18:24:51 UTC (rev 212724)
+++ trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeAudioSourceMac.h 2017-02-21 18:28:47 UTC (rev 212725)
@@ -35,6 +35,7 @@
#include "FontCascade.h"
#include "MockRealtimeAudioSource.h"
#include <CoreAudio/CoreAudioTypes.h>
+#include <wtf/Vector.h>
OBJC_CLASS AVAudioPCMBuffer;
typedef struct OpaqueCMClock* CMClockRef;
@@ -64,12 +65,15 @@
std::unique_ptr<WebAudioBufferList> m_audioBufferList;
uint32_t m_maximiumFrameCount;
- uint32_t m_sampleRate { 44100 };
- uint64_t m_bytesEmitted { 0 };
+ uint32_t m_sampleRate { 0 };
+ uint64_t m_samplesEmitted { 0 };
+ uint64_t m_samplesRendered { 0 };
RetainPtr<CMFormatDescriptionRef> m_formatDescription;
AudioStreamBasicDescription m_streamFormat;
RefPtr<WebAudioSourceProviderAVFObjC> m_audioSourceProvider;
+
+ Vector<float> m_bipBopBuffer;
};
} // namespace WebCore
Modified: trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeAudioSourceMac.mm (212724 => 212725)
--- trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeAudioSourceMac.mm 2017-02-21 18:24:51 UTC (rev 212724)
+++ trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeAudioSourceMac.mm 2017-02-21 18:28:47 UTC (rev 212725)
@@ -57,6 +57,33 @@
return (size + 15) & ~15;
}
+static const double Tau = 2 * M_PI;
+static const double BipBopDuration = 0.07;
+static const double BipBopVolume = 0.5;
+static const double BipFrequency = 1500;
+static const double BopFrequency = 500;
+static const double HumFrequency = 150;
+static const double HumVolume = 0.1;
+
+template <typename AudioSampleType>
+static void writeHum(float amplitude, float frequency, float sampleRate, AudioSampleType *p, uint64_t count)
+{
+ float humPeriod = sampleRate / frequency;
+ for (uint64_t i = 0; i < count; ++i)
+ *p++ = amplitude * sin(i * Tau / humPeriod);
+}
+
+template <typename AudioSampleType>
+static void addHum(float amplitude, float frequency, float sampleRate, uint64_t start, AudioSampleType *p, uint64_t count)
+{
+ float humPeriod = sampleRate / frequency;
+ for (uint64_t i = start, end = start + count; i < end; ++i) {
+ AudioSampleType a = amplitude * sin(i * Tau / humPeriod);
+ a += *p;
+ *p++ = a;
+ }
+}
+
RefPtr<MockRealtimeAudioSource> MockRealtimeAudioSource::create(const String& name, const MediaConstraints* constraints)
{
auto source = adoptRef(new MockRealtimeAudioSourceMac(name));
@@ -63,6 +90,8 @@
if (constraints && source->applyConstraints(*constraints))
source = nullptr;
+ source->applySampleRate(44100);
+
return source;
}
@@ -90,8 +119,8 @@
{
ASSERT(m_formatDescription);
- CMTime startTime = CMTimeMake(m_bytesEmitted, m_sampleRate);
- m_bytesEmitted += frameCount;
+ CMTime startTime = CMTimeMake(m_samplesEmitted, m_sampleRate);
+ m_samplesEmitted += frameCount;
audioSamplesAvailable(toMediaTime(startTime), *m_audioBufferList, CAAudioStreamDescription(m_streamFormat), frameCount);
}
@@ -121,54 +150,24 @@
if (m_muted || !m_enabled)
return;
- static double theta;
- static const double frequencies[] = { 1500., 500. };
- static const double tau = 2 * M_PI;
-
if (!m_audioBufferList)
reconfigure();
uint32_t totalFrameCount = alignTo16Bytes(delta * m_sampleRate);
uint32_t frameCount = std::min(totalFrameCount, m_maximiumFrameCount);
- double elapsed = elapsedTime();
while (frameCount) {
+ uint32_t bipBopStart = m_samplesRendered % m_bipBopBuffer.size();
+ uint32_t bipBopRemain = m_bipBopBuffer.size() - bipBopStart;
+ uint32_t bipBopCount = std::min(frameCount, bipBopRemain);
for (auto& audioBuffer : m_audioBufferList->buffers()) {
audioBuffer.mDataByteSize = frameCount * m_streamFormat.mBytesPerFrame;
- float *buffer = static_cast<float *>(audioBuffer.mData);
- for (uint32_t frame = 0; frame < frameCount; ++frame) {
- int phase = fmod(elapsed, 2) * 15;
- double increment = 0;
- bool silent = true;
-
- switch (phase) {
- case 0:
- case 14: {
- int index = fmod(elapsed, 1) * 2;
- increment = tau * frequencies[index] / m_sampleRate;
- silent = false;
- break;
- }
- default:
- break;
- }
-
- if (silent) {
- buffer[frame] = 0;
- continue;
- }
-
- float tone = sin(theta) * 0.25;
- buffer[frame] = tone;
-
- theta += increment;
- if (theta > tau)
- theta -= tau;
- elapsed += 1 / m_sampleRate;
- }
+ memcpy(audioBuffer.mData, &m_bipBopBuffer[bipBopStart], sizeof(Float32) * bipBopCount);
+ addHum(HumVolume, HumFrequency, m_sampleRate, m_samplesRendered, static_cast<float*>(audioBuffer.mData), bipBopCount);
}
- emitSampleBuffers(frameCount);
- totalFrameCount -= frameCount;
+ emitSampleBuffers(bipBopCount);
+ m_samplesRendered += bipBopCount;
+ totalFrameCount -= bipBopCount;
frameCount = std::min(totalFrameCount, m_maximiumFrameCount);
}
}
@@ -186,6 +185,18 @@
m_audioBufferList = nullptr;
m_audioBufferListBufferSize = 0;
+ size_t sampleCount = 2 * m_sampleRate;
+
+ m_bipBopBuffer.grow(sampleCount);
+ m_bipBopBuffer.fill(0);
+
+ size_t bipBopSampleCount = ceil(BipBopDuration * m_sampleRate);
+ size_t bipStart = 0;
+ size_t bopStart = m_sampleRate;
+
+ addHum(BipBopVolume, BipFrequency, m_sampleRate, 0, m_bipBopBuffer.data() + bipStart, bipBopSampleCount);
+ addHum(BipBopVolume, BopFrequency, m_sampleRate, 0, m_bipBopBuffer.data() + bopStart, bipBopSampleCount);
+
return true;
}