SpeechRecognitionCaptureSourceImpl.cpp [plain text]
#include "config.h"
#include "SpeechRecognitionCaptureSourceImpl.h"
#if ENABLE(MEDIA_STREAM)
#include "SpeechRecognitionUpdate.h"
#if PLATFORM(COCOA)
#include "CAAudioStreamDescription.h"
#include "WebAudioBufferList.h"
#endif
namespace WebCore {
#if !RELEASE_LOG_DISABLED
static const void* nextLogIdentifier()
{
static uint64_t logIdentifier = cryptographicallyRandomNumber();
return reinterpret_cast<const void*>(++logIdentifier);
}
static RefPtr<Logger>& nullLogger()
{
static NeverDestroyed<RefPtr<Logger>> logger;
return logger;
}
#endif
SpeechRecognitionCaptureSourceImpl::SpeechRecognitionCaptureSourceImpl(SpeechRecognitionConnectionClientIdentifier identifier, DataCallback&& dataCallback, StateUpdateCallback&& stateUpdateCallback, Ref<RealtimeMediaSource>&& source)
: m_clientIdentifier(identifier)
, m_dataCallback(WTFMove(dataCallback))
, m_stateUpdateCallback(WTFMove(stateUpdateCallback))
, m_source(WTFMove(source))
{
m_source->addAudioSampleObserver(*this);
m_source->addObserver(*this);
m_source->start();
#if !RELEASE_LOG_DISABLED
if (!nullLogger().get()) {
nullLogger() = Logger::create(this);
nullLogger()->setEnabled(this, false);
}
m_source->setLogger(*nullLogger(), nextLogIdentifier());
#endif
auto weakThis = makeWeakPtr(this);
}
SpeechRecognitionCaptureSourceImpl::~SpeechRecognitionCaptureSourceImpl()
{
m_source->removeAudioSampleObserver(*this);
m_source->removeObserver(*this);
m_source->stop();
}
void SpeechRecognitionCaptureSourceImpl::audioSamplesAvailable(const MediaTime& time, const PlatformAudioData& data, const AudioStreamDescription& description, size_t sampleCount)
{
#if PLATFORM(COCOA)
ASSERT(description.platformDescription().type == PlatformDescription::CAAudioStreamBasicType);
auto audioDescription = toCAAudioStreamDescription(description);
if (!m_dataSource || !m_dataSource->inputDescription() || *m_dataSource->inputDescription() != description) {
auto dataSource = AudioSampleDataSource::create(description.sampleRate() * 1, m_source.get());
if (dataSource->setInputFormat(audioDescription)) {
callOnMainThread([this, weakThis = makeWeakPtr(this)] {
if (weakThis)
m_stateUpdateCallback(SpeechRecognitionUpdate::createError(m_clientIdentifier, SpeechRecognitionError { SpeechRecognitionErrorType::AudioCapture, "Unable to set input format" }));
});
return;
}
if (dataSource->setOutputFormat(audioDescription)) {
callOnMainThread([this, weakThis = makeWeakPtr(this)] {
if (weakThis)
m_stateUpdateCallback(SpeechRecognitionUpdate::createError(m_clientIdentifier, SpeechRecognitionError { SpeechRecognitionErrorType::AudioCapture, "Unable to set output format" }));
});
return;
}
if (auto locker = tryHoldLock(m_dataSourceLock))
m_dataSource = WTFMove(dataSource);
else
return;
}
m_dataSource->pushSamples(time, data, sampleCount);
callOnMainThread([this, weakThis = makeWeakPtr(this), time, audioDescription, sampleCount] {
if (!weakThis)
return;
auto data = WebAudioBufferList { audioDescription, static_cast<uint32_t>(sampleCount) };
{
auto locker = holdLock(m_dataSourceLock);
m_dataSource->pullSamples(*data.list(), sampleCount, time.timeValue(), 0, AudioSampleDataSource::Copy);
}
m_dataCallback(time, data, audioDescription, sampleCount);
});
#else
m_dataCallback(time, data, description, sampleCount);
#endif
}
void SpeechRecognitionCaptureSourceImpl::sourceStarted()
{
ASSERT(isMainThread());
m_stateUpdateCallback(SpeechRecognitionUpdate::create(m_clientIdentifier, SpeechRecognitionUpdateType::AudioStart));
}
void SpeechRecognitionCaptureSourceImpl::sourceStopped()
{
ASSERT(isMainThread());
ASSERT(m_source->captureDidFail());
m_stateUpdateCallback(SpeechRecognitionUpdate::createError(m_clientIdentifier, SpeechRecognitionError { SpeechRecognitionErrorType::AudioCapture, "Source is stopped" }));
}
void SpeechRecognitionCaptureSourceImpl::sourceMutedChanged()
{
ASSERT(isMainThread());
m_stateUpdateCallback(SpeechRecognitionUpdate::createError(m_clientIdentifier, SpeechRecognitionError { SpeechRecognitionErrorType::AudioCapture, "Source is muted" }));
}
void SpeechRecognitionCaptureSourceImpl::mute()
{
m_source->setMuted(true);
}
}
#endif