summaryrefslogtreecommitdiff
path: root/Source/WebCore/Modules/webaudio/MediaStreamAudioSourceNode.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/Modules/webaudio/MediaStreamAudioSourceNode.cpp')
-rw-r--r--Source/WebCore/Modules/webaudio/MediaStreamAudioSourceNode.cpp95
1 files changed, 56 insertions, 39 deletions
diff --git a/Source/WebCore/Modules/webaudio/MediaStreamAudioSourceNode.cpp b/Source/WebCore/Modules/webaudio/MediaStreamAudioSourceNode.cpp
index 867212e51..f640a6826 100644
--- a/Source/WebCore/Modules/webaudio/MediaStreamAudioSourceNode.cpp
+++ b/Source/WebCore/Modules/webaudio/MediaStreamAudioSourceNode.cpp
@@ -35,18 +35,21 @@
namespace WebCore {
-PassRefPtr<MediaStreamAudioSourceNode> MediaStreamAudioSourceNode::create(AudioContext* context, MediaStream* mediaStream, MediaStreamTrack* audioTrack, AudioSourceProvider* audioSourceProvider)
+Ref<MediaStreamAudioSourceNode> MediaStreamAudioSourceNode::create(AudioContext& context, MediaStream& mediaStream, MediaStreamTrack& audioTrack)
{
- return adoptRef(new MediaStreamAudioSourceNode(context, mediaStream, audioTrack, audioSourceProvider));
+ return adoptRef(*new MediaStreamAudioSourceNode(context, mediaStream, audioTrack));
}
-MediaStreamAudioSourceNode::MediaStreamAudioSourceNode(AudioContext* context, MediaStream* mediaStream, MediaStreamTrack* audioTrack, AudioSourceProvider* audioSourceProvider)
- : AudioNode(context, context->sampleRate())
+MediaStreamAudioSourceNode::MediaStreamAudioSourceNode(AudioContext& context, MediaStream& mediaStream, MediaStreamTrack& audioTrack)
+ : AudioNode(context, context.sampleRate())
, m_mediaStream(mediaStream)
, m_audioTrack(audioTrack)
- , m_audioSourceProvider(audioSourceProvider)
- , m_sourceNumberOfChannels(0)
{
+ AudioSourceProvider* audioSourceProvider = m_audioTrack->audioSourceProvider();
+ ASSERT(audioSourceProvider);
+
+ audioSourceProvider->setClient(this);
+
// Default to stereo. This could change depending on the format of the MediaStream's audio track.
addOutput(std::make_unique<AudioNodeOutput>(this, 2));
@@ -57,45 +60,56 @@ MediaStreamAudioSourceNode::MediaStreamAudioSourceNode(AudioContext* context, Me
MediaStreamAudioSourceNode::~MediaStreamAudioSourceNode()
{
+ AudioSourceProvider* audioSourceProvider = m_audioTrack->audioSourceProvider();
+ ASSERT(audioSourceProvider);
+ audioSourceProvider->setClient(nullptr);
uninitialize();
}
void MediaStreamAudioSourceNode::setFormat(size_t numberOfChannels, float sourceSampleRate)
{
- if (numberOfChannels != m_sourceNumberOfChannels || sourceSampleRate != sampleRate()) {
- // The sample-rate must be equal to the context's sample-rate.
- if (!numberOfChannels || numberOfChannels > AudioContext::maxNumberOfChannels() || sourceSampleRate != sampleRate()) {
- // process() will generate silence for these uninitialized values.
- LOG(Media, "MediaStreamAudioSourceNode::setFormat(%u, %f) - unhandled format change", static_cast<unsigned>(numberOfChannels), sourceSampleRate);
- m_sourceNumberOfChannels = 0;
- return;
- }
-
- // Synchronize with process().
- std::lock_guard<std::mutex> lock(m_processMutex);
-
- m_sourceNumberOfChannels = numberOfChannels;
-
- {
- // The context must be locked when changing the number of output channels.
- AudioContext::AutoLocker contextLocker(*context());
-
- // Do any necesssary re-configuration to the output's number of channels.
- output(0)->setNumberOfChannels(numberOfChannels);
- }
+ float sampleRate = this->sampleRate();
+ if (numberOfChannels == m_sourceNumberOfChannels && sourceSampleRate == sampleRate)
+ return;
+
+ // The sample-rate must be equal to the context's sample-rate.
+ if (!numberOfChannels || numberOfChannels > AudioContext::maxNumberOfChannels() || sourceSampleRate != sampleRate) {
+ // process() will generate silence for these uninitialized values.
+ LOG(Media, "MediaStreamAudioSourceNode::setFormat(%u, %f) - unhandled format change", static_cast<unsigned>(numberOfChannels), sourceSampleRate);
+ m_sourceNumberOfChannels = 0;
+ return;
+ }
+
+ // Synchronize with process().
+ std::lock_guard<Lock> lock(m_processMutex);
+
+ m_sourceNumberOfChannels = numberOfChannels;
+ m_sourceSampleRate = sourceSampleRate;
+
+ if (sourceSampleRate == sampleRate)
+ m_multiChannelResampler = nullptr;
+ else {
+ double scaleFactor = sourceSampleRate / sampleRate;
+ m_multiChannelResampler = std::make_unique<MultiChannelResampler>(scaleFactor, numberOfChannels);
+ }
+
+ m_sourceNumberOfChannels = numberOfChannels;
+
+ {
+ // The context must be locked when changing the number of output channels.
+ AudioContext::AutoLocker contextLocker(context());
+
+ // Do any necesssary re-configuration to the output's number of channels.
+ output(0)->setNumberOfChannels(numberOfChannels);
}
}
void MediaStreamAudioSourceNode::process(size_t numberOfFrames)
{
AudioBus* outputBus = output(0)->bus();
+ AudioSourceProvider* provider = m_audioTrack->audioSourceProvider();
- if (!audioSourceProvider()) {
- outputBus->zero();
- return;
- }
-
- if (!mediaStream() || m_sourceNumberOfChannels != outputBus->numberOfChannels()) {
+ if (!mediaStream() || !m_sourceNumberOfChannels || !m_sourceSampleRate || !provider) {
outputBus->zero();
return;
}
@@ -103,18 +117,21 @@ void MediaStreamAudioSourceNode::process(size_t numberOfFrames)
// Use std::try_to_lock to avoid contention in the real-time audio thread.
// If we fail to acquire the lock then the MediaStream must be in the middle of
// a format change, so we output silence in this case.
- std::unique_lock<std::mutex> lock(m_processMutex, std::try_to_lock);
+ std::unique_lock<Lock> lock(m_processMutex, std::try_to_lock);
if (!lock.owns_lock()) {
// We failed to acquire the lock.
outputBus->zero();
return;
}
- audioSourceProvider()->provideInput(outputBus, numberOfFrames);
-}
-
-void MediaStreamAudioSourceNode::reset()
-{
+ if (m_multiChannelResampler.get()) {
+ ASSERT(m_sourceSampleRate != sampleRate());
+ m_multiChannelResampler->process(provider, outputBus, numberOfFrames);
+ } else {
+ // Bypass the resampler completely if the source is at the context's sample-rate.
+ ASSERT(m_sourceSampleRate == sampleRate());
+ provider->provideInput(outputBus, numberOfFrames);
+ }
}
} // namespace WebCore