MockRealtimeAudioSourceGStreamer.cpp [plain text]
#include "config.h"
#if ENABLE(MEDIA_STREAM) && USE(LIBWEBRTC) && USE(GSTREAMER)
#include "MockRealtimeAudioSourceGStreamer.h"
#include "MockRealtimeMediaSourceCenter.h"
namespace WebCore {
static const double s_Tau = 2 * M_PI;
static const double s_BipBopDuration = 0.07;
static const double s_BipBopVolume = 0.5;
static const double s_BipFrequency = 1500;
static const double s_BopFrequency = 500;
static const double s_HumFrequency = 150;
static const double s_HumVolume = 0.1;
static const double s_NoiseFrequency = 3000;
static const double s_NoiseVolume = 0.05;
CaptureSourceOrError MockRealtimeAudioSource::create(String&& deviceID, String&& name, String&& hashSalt, const MediaConstraints* constraints)
{
#ifndef NDEBUG
auto device = MockRealtimeMediaSourceCenter::mockDeviceWithPersistentID(deviceID);
ASSERT(device);
if (!device)
return { "No mock microphone device"_s };
#endif
auto source = adoptRef(*new MockRealtimeAudioSourceGStreamer(WTFMove(deviceID), WTFMove(name), WTFMove(hashSalt)));
if (constraints) {
if (auto error = source->applyConstraints(*constraints))
return WTFMove(error->message);
}
return CaptureSourceOrError(WTFMove(source));
}
Ref<MockRealtimeAudioSource> MockRealtimeAudioSourceGStreamer::createForMockAudioCapturer(String&& deviceID, String&& name, String&& hashSalt)
{
return adoptRef(*new MockRealtimeAudioSourceGStreamer(WTFMove(deviceID), WTFMove(name), WTFMove(hashSalt)));
}
MockRealtimeAudioSourceGStreamer::MockRealtimeAudioSourceGStreamer(String&& deviceID, String&& name, String&& hashSalt)
: MockRealtimeAudioSource(WTFMove(deviceID), WTFMove(name), WTFMove(hashSalt))
{
}
void MockRealtimeAudioSourceGStreamer::render(Seconds delta)
{
if (!m_bipBopBuffer.size())
reconfigure();
uint32_t totalFrameCount = GST_ROUND_UP_16(static_cast<size_t>(delta.seconds() * sampleRate()));
uint32_t frameCount = std::min(totalFrameCount, m_maximiumFrameCount);
while (frameCount) {
uint32_t bipBopStart = m_samplesRendered % m_bipBopBuffer.size();
uint32_t bipBopRemain = m_bipBopBuffer.size() - bipBopStart;
uint32_t bipBopCount = std::min(frameCount, bipBopRemain);
ASSERT(m_streamFormat);
GstAudioInfo* info = m_streamFormat->getInfo();
GRefPtr<GstBuffer> buffer = adoptGRef(gst_buffer_new_allocate(nullptr, bipBopCount * m_streamFormat->bytesPerFrame(), nullptr));
{
GstMappedBuffer map(buffer.get(), GST_MAP_WRITE);
if (muted())
gst_audio_format_fill_silence(info->finfo, map.data(), map.size());
else {
memcpy(map.data(), &m_bipBopBuffer[bipBopStart], sizeof(float) * bipBopCount);
addHum(s_HumVolume, s_HumFrequency, sampleRate(), m_samplesRendered, reinterpret_cast<float*>(map.data()), bipBopCount);
}
}
m_samplesRendered += bipBopCount;
totalFrameCount -= bipBopCount;
frameCount = std::min(totalFrameCount, m_maximiumFrameCount);
GRefPtr<GstCaps> caps = adoptGRef(gst_audio_info_to_caps(info));
auto sample = adoptGRef(gst_sample_new(buffer.get(), caps.get(), nullptr, nullptr));
auto data(std::unique_ptr<GStreamerAudioData>(new GStreamerAudioData(WTFMove(sample), *info)));
auto mediaTime = MediaTime((m_samplesRendered * G_USEC_PER_SEC) / sampleRate(), G_USEC_PER_SEC);
audioSamplesAvailable(mediaTime, *data.get(), *m_streamFormat, bipBopCount);
}
}
void MockRealtimeAudioSourceGStreamer::addHum(float amplitude, float frequency, float sampleRate, uint64_t start, float *p, uint64_t count)
{
float humPeriod = sampleRate / frequency;
for (uint64_t i = start, end = start + count; i < end; ++i) {
float a = amplitude * sin(i * s_Tau / humPeriod);
a += *p;
*p++ = a;
}
}
void MockRealtimeAudioSourceGStreamer::reconfigure()
{
GstAudioInfo info;
auto rate = sampleRate();
size_t sampleCount = 2 * rate;
m_maximiumFrameCount = WTF::roundUpToPowerOfTwo(renderInterval().seconds() * sampleRate());
gst_audio_info_set_format(&info, GST_AUDIO_FORMAT_F32LE, rate, 1, nullptr);
m_streamFormat = GStreamerAudioStreamDescription(info);
m_bipBopBuffer.resize(sampleCount);
m_bipBopBuffer.fill(0);
size_t bipBopSampleCount = ceil(s_BipBopDuration * rate);
size_t bipStart = 0;
size_t bopStart = rate;
addHum(s_BipBopVolume, s_BipFrequency, rate, 0, m_bipBopBuffer.data() + bipStart, bipBopSampleCount);
addHum(s_BipBopVolume, s_BopFrequency, rate, 0, m_bipBopBuffer.data() + bopStart, bipBopSampleCount);
if (!echoCancellation())
addHum(s_NoiseVolume, s_NoiseFrequency, rate, 0, m_bipBopBuffer.data(), sampleCount);
}
}
#endif // ENABLE(MEDIA_STREAM) && USE(LIBWEBRTC) && USE(GSTREAMER)