chromium/chromeos/ash/services/libassistant/audio/audio_input_stream.cc

// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chromeos/ash/services/libassistant/audio/audio_input_stream.h"

#include "base/notreached.h"
#include "chromeos/ash/services/libassistant/buildflags.h"
#include "chromeos/ash/services/libassistant/public/mojom/audio_input_controller.mojom.h"
#include "chromeos/ash/services/libassistant/public/mojom/platform_delegate.mojom.h"

#if BUILDFLAG(ENABLE_FAKE_ASSISTANT_MICROPHONE)
#include "chromeos/ash/services/libassistant/audio/fake_input_device.h"
#endif  // BUILDFLAG(ENABLE_FAKE_ASSISTANT_MICROPHONE)

namespace ash::libassistant {

namespace {

#if !BUILDFLAG(ENABLE_FAKE_ASSISTANT_MICROPHONE)
audio::DeadStreamDetection ToDeadStreamDetection(bool detect_dead_stream) {
  return detect_dead_stream ? audio::DeadStreamDetection::kEnabled
                            : audio::DeadStreamDetection::kDisabled;
}
#endif  // !BUILDFLAG(ENABLE_FAKE_ASSISTANT_MICROPHONE)

}  // namespace

AudioInputStream::AudioInputStream(
    mojom::PlatformDelegate* delegate,
    const std::string& device_id,
    bool detect_dead_stream,
    assistant_client::BufferFormat buffer_format,
    media::AudioCapturerSource::CaptureCallback* capture_callback)
    : device_id_(device_id),
      detect_dead_stream_(detect_dead_stream),
      buffer_format_(buffer_format),
      delegate_(delegate),
      capture_callback_(capture_callback) {
  Start();
}

AudioInputStream::~AudioInputStream() {
  Stop();
}

void AudioInputStream::Start() {
  mojo::PendingRemote<media::mojom::AudioStreamFactory> audio_stream_factory;
  delegate_->BindAudioStreamFactory(
      audio_stream_factory.InitWithNewPipeAndPassReceiver());

#if BUILDFLAG(ENABLE_FAKE_ASSISTANT_MICROPHONE)
  source_ = CreateFakeInputDevice();
#else
  source_ =
      audio::CreateInputDevice(std::move(audio_stream_factory), device_id(),
                               ToDeadStreamDetection(detect_dead_stream_));
#endif  // BUILDFLAG(ENABLE_FAKE_ASSISTANT_MICROPHONE)

  source_->Initialize(GetAudioParameters(), capture_callback_);
  source_->Start();
}

void AudioInputStream::Stop() {
  if (source_) {
    source_->Stop();
    source_.reset();
  }
}

media::AudioParameters AudioInputStream::GetAudioParameters() const {
  // AUDIO_PCM_LINEAR and AUDIO_PCM_LOW_LATENCY are the same on CRAS.
  auto result = media::AudioParameters(
      media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
      media::ChannelLayoutConfig::Guess(buffer_format_.num_channels),
      buffer_format_.sample_rate,
      buffer_format_.sample_rate / 10 /* buffer size for 100 ms */);

  // Set the HOTWORD mask so CRAS knows the device is used for HOTWORD purpose
  // and is able to conduct the tuning specifically for the scenario. Whether
  // the HOTWORD is conducted by a hotword device or other devices like
  // internal mic will be determined by the device_id passed to CRAS.
  result.set_effects(media::AudioParameters::PlatformEffectsMask::HOTWORD);

  return result;
}

}  // namespace ash::libassistant