15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/win/audio_unified_win.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <Functiondiscoverykeys_devpkey.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/trace_event.h"
10a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#ifndef NDEBUG
11a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "base/file_util.h"
12a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "base/path_service.h"
13a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#endif
14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_com_initializer.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/win/audio_manager_win.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/win/avrt_wrapper_win.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/audio/win/core_audio_util_win.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::win::ScopedComPtr;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::win::ScopedCOMInitializer;
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::win::ScopedCoMem;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// Smoothing factor in exponential smoothing filter where 0 < alpha < 1.
25a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// Larger values of alpha reduce the level of smoothing.
26a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// See http://en.wikipedia.org/wiki/Exponential_smoothing for details.
27a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)static const double kAlpha = 0.1;
28a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
29a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// Compute a rate compensation which always attracts us back to a specified
30a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// target level over a period of |kCorrectionTimeSeconds|.
31a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)static const double kCorrectionTimeSeconds = 0.1;
32a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
33a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#ifndef NDEBUG
34a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// Max number of columns in the output text file |kUnifiedAudioDebugFileName|.
35a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// See LogElementNames enumerator for details on what each column represents.
36a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)static const size_t kMaxNumSampleTypes = 4;
37a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
38a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)static const size_t kMaxNumParams = 2;
39a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
40a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// Max number of rows in the output file |kUnifiedAudioDebugFileName|.
41a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// Each row corresponds to one set of sample values for (approximately) the
42a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// same time instant (stored in the first column).
43a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)static const size_t kMaxFileSamples = 10000;
44a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
45a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// Name of output debug file used for off-line analysis of measurements which
46a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// can be utilized for performance tuning of this class.
47a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)static const char kUnifiedAudioDebugFileName[] = "unified_win_debug.txt";
48a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
49a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// Name of output debug file used for off-line analysis of measurements.
50a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// This file will contain a list of audio parameters.
51a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)static const char kUnifiedAudioParamsFileName[] = "unified_win_params.txt";
52a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#endif
53a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use the acquired IAudioClock interface to derive a time stamp of the audio
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// sample which is currently playing through the speakers.
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static double SpeakerStreamPosInMilliseconds(IAudioClock* clock) {
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UINT64 device_frequency = 0, position = 0;
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (FAILED(clock->GetFrequency(&device_frequency)) ||
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FAILED(clock->GetPosition(&position, NULL))) {
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return 0.0;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return base::Time::kMillisecondsPerSecond *
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (static_cast<double>(position) / device_frequency);
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Get a time stamp in milliseconds given number of audio frames in |num_frames|
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// using the current sample rate |fs| as scale factor.
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Example: |num_frames| = 960 and |fs| = 48000 => 20 [ms].
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static double CurrentStreamPosInMilliseconds(UINT64 num_frames, DWORD fs) {
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return base::Time::kMillisecondsPerSecond *
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (static_cast<double>(num_frames) / fs);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Convert a timestamp in milliseconds to byte units given the audio format
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// in |format|.
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Example: |ts_milliseconds| equals 10, sample rate is 48000 and frame size
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// is 4 bytes per audio frame => 480 * 4 = 1920 [bytes].
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static int MillisecondsToBytes(double ts_milliseconds,
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               const WAVEFORMATPCMEX& format) {
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double seconds = ts_milliseconds / base::Time::kMillisecondsPerSecond;
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return static_cast<int>(seconds * format.Format.nSamplesPerSec *
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      format.Format.nBlockAlign + 0.5);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// Convert frame count to milliseconds given the audio format in |format|.
86a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)static double FrameCountToMilliseconds(int num_frames,
87a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                       const WAVEFORMATPCMEX& format) {
88a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  return (base::Time::kMillisecondsPerSecond * num_frames) /
89a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      static_cast<double>(format.Format.nSamplesPerSec);
90a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
91a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace media {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WASAPIUnifiedStream::WASAPIUnifiedStream(AudioManagerWin* manager,
95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                         const AudioParameters& params,
96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                         const std::string& input_device_id)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : creating_thread_id_(base::PlatformThread::CurrentId()),
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      manager_(manager),
99a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      params_(params),
100a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      input_channels_(params.input_channels()),
101a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      output_channels_(params.channels()),
102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      input_device_id_(input_device_id),
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      share_mode_(CoreAudioUtil::GetShareMode()),
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      opened_(false),
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      volume_(1.0),
106a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      output_buffer_size_frames_(0),
107a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      input_buffer_size_frames_(0),
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      endpoint_render_buffer_size_frames_(0),
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      endpoint_capture_buffer_size_frames_(0),
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      num_written_frames_(0),
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      total_delay_ms_(0.0),
112a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      total_delay_bytes_(0),
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      source_(NULL),
114a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      input_callback_received_(false),
115a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      io_sample_rate_ratio_(1),
116a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      target_fifo_frames_(0),
117a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      average_delta_(0),
118a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      fifo_rate_compensation_(1),
119a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      update_output_delay_(false),
120a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      capture_delay_ms_(0) {
121a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  TRACE_EVENT0("audio", "WASAPIUnifiedStream::WASAPIUnifiedStream");
122a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  VLOG(1) << "WASAPIUnifiedStream::WASAPIUnifiedStream()";
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(manager_);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  VLOG(1) << "Input channels : " << input_channels_;
126a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  VLOG(1) << "Output channels: " << output_channels_;
127a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  VLOG(1) << "Sample rate    : " << params_.sample_rate();
128a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  VLOG(1) << "Buffer size    : " << params.frames_per_buffer();
129a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
130a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#ifndef NDEBUG
131a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  input_time_stamps_.reset(new int64[kMaxFileSamples]);
132a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  num_frames_in_fifo_.reset(new int[kMaxFileSamples]);
133a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  resampler_margin_.reset(new int[kMaxFileSamples]);
134a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  fifo_rate_comps_.reset(new double[kMaxFileSamples]);
135a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  num_elements_.reset(new int[kMaxNumSampleTypes]);
136a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  std::fill(num_elements_.get(), num_elements_.get() + kMaxNumSampleTypes, 0);
137a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  input_params_.reset(new int[kMaxNumParams]);
138a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  output_params_.reset(new int[kMaxNumParams]);
139a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#endif
140a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG_IF(1, share_mode_ == AUDCLNT_SHAREMODE_EXCLUSIVE)
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      << "Core Audio (WASAPI) EXCLUSIVE MODE is enabled.";
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Load the Avrt DLL if not already loaded. Required to support MMCSS.
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool avrt_init = avrt::Initialize();
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(avrt_init) << "Failed to load the avrt.dll";
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // All events are auto-reset events and non-signaled initially.
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create the event which the audio engine will signal each time a buffer
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // has been recorded.
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  capture_event_.Set(CreateEvent(NULL, FALSE, FALSE, NULL));
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create the event which will be set in Stop() when straeming shall stop.
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stop_streaming_event_.Set(CreateEvent(NULL, FALSE, FALSE, NULL));
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WASAPIUnifiedStream::~WASAPIUnifiedStream() {
159a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  VLOG(1) << "WASAPIUnifiedStream::~WASAPIUnifiedStream()";
160a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#ifndef NDEBUG
161a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::FilePath data_file_name;
162a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  PathService::Get(base::DIR_EXE, &data_file_name);
163a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  data_file_name = data_file_name.AppendASCII(kUnifiedAudioDebugFileName);
164a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  data_file_ = base::OpenFile(data_file_name, "wt");
165a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DVLOG(1) << ">> Output file " << data_file_name.value() << " is created.";
166a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
167a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  size_t n = 0;
168a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  size_t elements_to_write = *std::min_element(
169a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      num_elements_.get(), num_elements_.get() + kMaxNumSampleTypes);
170a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  while (n < elements_to_write) {
171a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    fprintf(data_file_, "%I64d %d %d %10.9f\n",
172a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        input_time_stamps_[n],
173a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        num_frames_in_fifo_[n],
174a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        resampler_margin_[n],
175a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        fifo_rate_comps_[n]);
176a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    ++n;
177a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
178a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::CloseFile(data_file_);
179a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
180a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::FilePath param_file_name;
181a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  PathService::Get(base::DIR_EXE, &param_file_name);
182a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  param_file_name = param_file_name.AppendASCII(kUnifiedAudioParamsFileName);
183a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  param_file_ = base::OpenFile(param_file_name, "wt");
184a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DVLOG(1) << ">> Output file " << param_file_name.value() << " is created.";
185a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  fprintf(param_file_, "%d %d\n", input_params_[0], input_params_[1]);
186a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  fprintf(param_file_, "%d %d\n", output_params_[0], output_params_[1]);
187a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::CloseFile(param_file_);
188a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#endif
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WASAPIUnifiedStream::Open() {
192a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  TRACE_EVENT0("audio", "WASAPIUnifiedStream::Open");
193a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DVLOG(1) << "WASAPIUnifiedStream::Open()";
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(GetCurrentThreadId(), creating_thread_id_);
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (opened_)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
198a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  AudioParameters hw_output_params;
199a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  HRESULT hr = CoreAudioUtil::GetPreferredAudioParameters(
200a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      eRender, eConsole, &hw_output_params);
201a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (FAILED(hr)) {
202a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    LOG(ERROR) << "Failed to get preferred output audio parameters.";
203a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return false;
204a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
205a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
206a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  AudioParameters hw_input_params;
207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (input_device_id_ == AudioManagerBase::kDefaultDeviceId) {
208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Query native parameters for the default capture device.
209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    hr = CoreAudioUtil::GetPreferredAudioParameters(
210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        eCapture, eConsole, &hw_input_params);
211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  } else {
212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Query native parameters for the capture device given by
213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // |input_device_id_|.
214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    hr = CoreAudioUtil::GetPreferredAudioParameters(
215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        input_device_id_, &hw_input_params);
216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
217a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (FAILED(hr)) {
218a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    LOG(ERROR) << "Failed to get preferred input audio parameters.";
219a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return false;
220a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
221a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
222a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // It is currently only possible to open up the output audio device using
223a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // the native number of channels.
224a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (output_channels_ != hw_output_params.channels()) {
225a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    LOG(ERROR) << "Audio device does not support requested output channels.";
226a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return false;
227a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
228a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
229a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // It is currently only possible to open up the input audio device using
230a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // the native number of channels. If the client asks for a higher channel
231a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // count, we will do channel upmixing in this class. The most typical
232a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // example is that the client provides stereo but the hardware can only be
233a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // opened in mono mode. We will do mono to stereo conversion in this case.
234a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (input_channels_ < hw_input_params.channels()) {
235a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    LOG(ERROR) << "Audio device does not support requested input channels.";
236a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return false;
237a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  } else if (input_channels_ > hw_input_params.channels()) {
238a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    ChannelLayout input_layout =
239a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        GuessChannelLayout(hw_input_params.channels());
240a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    ChannelLayout output_layout = GuessChannelLayout(input_channels_);
241a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    channel_mixer_.reset(new ChannelMixer(input_layout, output_layout));
242a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    DVLOG(1) << "Remixing input channel layout from " << input_layout
243a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)             << " to " << output_layout << "; from "
244a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)             << hw_input_params.channels() << " channels to "
245a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)             << input_channels_;
246a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
247a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
248a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (hw_output_params.sample_rate() != params_.sample_rate()) {
249a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    LOG(ERROR) << "Requested sample-rate: " << params_.sample_rate()
250a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)               << " must match the hardware sample-rate: "
251a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)               << hw_output_params.sample_rate();
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (hw_output_params.frames_per_buffer() != params_.frames_per_buffer()) {
256a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    LOG(ERROR) << "Requested buffer size: " << params_.frames_per_buffer()
257a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)               << " must match the hardware buffer size: "
258a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)               << hw_output_params.frames_per_buffer();
259a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return false;
260a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
261a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
262a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Set up WAVEFORMATPCMEX structures for input and output given the specified
263a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // audio parameters.
264a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  SetIOFormats(hw_input_params, params_);
265a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
266a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Create the input and output busses.
267a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  input_bus_ = AudioBus::Create(
268a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      hw_input_params.channels(), input_buffer_size_frames_);
269a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  output_bus_ = AudioBus::Create(params_);
270a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
271a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // One extra bus is needed for the input channel mixing case.
272a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (channel_mixer_) {
273a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    DCHECK_LT(hw_input_params.channels(), input_channels_);
2747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // The size of the |channel_bus_| must be the same as the size of the
2757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // output bus to ensure that the channel manager can deal with both
2767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // resampled and non-resampled data as input.
2777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    channel_bus_ = AudioBus::Create(
2787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        input_channels_, params_.frames_per_buffer());
279a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
280a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
281a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Check if FIFO and resampling is required to match the input rate to the
282a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // output rate. If so, a special thread loop, optimized for this case, will
283a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // be used. This mode is also called varispeed mode.
284a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Note that we can also use this mode when input and output rates are the
285a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // same but native buffer sizes differ (can happen if two different audio
286a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // devices are used). For this case, the resampler uses a target ratio of
287a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // 1.0 but SetRatio is called to compensate for clock-drift. The FIFO is
288a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // required to compensate for the difference in buffer sizes.
289a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // TODO(henrika): we could perhaps improve the performance for the second
290a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // case here by only using the FIFO and avoid resampling. Not sure how much
291a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // that would give and we risk not compensation for clock drift.
292a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (hw_input_params.sample_rate() != params_.sample_rate() ||
293a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      hw_input_params.frames_per_buffer() != params_.frames_per_buffer()) {
294a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    DoVarispeedInitialization(hw_input_params, params_);
295a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
296a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
297a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Render side (event driven only in varispeed mode):
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedComPtr<IAudioClient> audio_output_client =
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CoreAudioUtil::CreateDefaultClient(eRender, eConsole);
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!audio_output_client)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!CoreAudioUtil::IsFormatSupported(audio_output_client,
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        share_mode_,
306a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                        &output_format_)) {
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (share_mode_ == AUDCLNT_SHAREMODE_SHARED) {
311a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // The |render_event_| will be NULL unless varispeed mode is utilized.
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    hr = CoreAudioUtil::SharedModeInitialize(
313a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        audio_output_client, &output_format_, render_event_.Get(),
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        &endpoint_render_buffer_size_frames_);
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // TODO(henrika): add support for AUDCLNT_SHAREMODE_EXCLUSIVE.
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (FAILED(hr))
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedComPtr<IAudioRenderClient> audio_render_client =
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CoreAudioUtil::CreateRenderClient(audio_output_client);
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!audio_render_client)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
326a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Capture side (always event driven but format depends on varispeed or not):
327eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
328eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedComPtr<IAudioClient> audio_input_client;
329eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (input_device_id_ == AudioManagerBase::kDefaultDeviceId) {
330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    audio_input_client = CoreAudioUtil::CreateDefaultClient(eCapture, eConsole);
331eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  } else {
332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    ScopedComPtr<IMMDevice> audio_input_device(
333eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CoreAudioUtil::CreateDevice(input_device_id_));
334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    audio_input_client = CoreAudioUtil::CreateClient(audio_input_device);
335eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!audio_input_client)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!CoreAudioUtil::IsFormatSupported(audio_input_client,
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        share_mode_,
341a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                        &input_format_)) {
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (share_mode_ == AUDCLNT_SHAREMODE_SHARED) {
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Include valid event handle for event-driven initialization.
347a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // The input side is always event driven independent of if varispeed is
348a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // used or not.
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    hr = CoreAudioUtil::SharedModeInitialize(
350a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        audio_input_client, &input_format_, capture_event_.Get(),
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        &endpoint_capture_buffer_size_frames_);
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // TODO(henrika): add support for AUDCLNT_SHAREMODE_EXCLUSIVE.
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (FAILED(hr))
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ScopedComPtr<IAudioCaptureClient> audio_capture_client =
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CoreAudioUtil::CreateCaptureClient(audio_input_client);
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!audio_capture_client)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
363a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Varispeed mode requires additional preparations.
364a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (VarispeedMode())
365a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    ResetVarispeed();
366a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Store all valid COM interfaces.
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_output_client_ = audio_output_client;
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_render_client_ = audio_render_client;
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_input_client_ = audio_input_client;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_capture_client_ = audio_capture_client;
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  opened_ = true;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SUCCEEDED(hr);
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WASAPIUnifiedStream::Start(AudioSourceCallback* callback) {
378a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  TRACE_EVENT0("audio", "WASAPIUnifiedStream::Start");
379a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DVLOG(1) << "WASAPIUnifiedStream::Start()";
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(GetCurrentThreadId(), creating_thread_id_);
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(callback);
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(opened_);
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (audio_io_thread_) {
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK_EQ(callback, source_);
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  source_ = callback;
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
391a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (VarispeedMode()) {
392a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    ResetVarispeed();
393a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    fifo_rate_compensation_ = 1.0;
394a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    average_delta_ = 0.0;
395a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    input_callback_received_ = false;
396a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    update_output_delay_ = false;
397a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
398a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
399a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Create and start the thread that will listen for capture events.
400a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // We will also listen on render events on the same thread if varispeed
401a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // mode is utilized.
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_io_thread_.reset(
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new base::DelegateSimpleThread(this, "wasapi_io_thread"));
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_io_thread_->Start();
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!audio_io_thread_->HasBeenStarted()) {
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(ERROR) << "Failed to start WASAPI IO thread.";
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start input streaming data between the endpoint buffer and the audio
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // engine.
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HRESULT hr = audio_input_client_->Start();
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FAILED(hr)) {
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StopAndJoinThread(hr);
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Ensure that the endpoint buffer is prepared with silence.
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (share_mode_ == AUDCLNT_SHAREMODE_SHARED) {
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!CoreAudioUtil::FillRenderEndpointBufferWithSilence(
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             audio_output_client_, audio_render_client_)) {
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DLOG(WARNING) << "Failed to prepare endpoint buffers with silence.";
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  num_written_frames_ = endpoint_render_buffer_size_frames_;
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start output streaming data between the endpoint buffer and the audio
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // engine.
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hr = audio_output_client_->Start();
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FAILED(hr)) {
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StopAndJoinThread(hr);
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WASAPIUnifiedStream::Stop() {
438a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  TRACE_EVENT0("audio", "WASAPIUnifiedStream::Stop");
439a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DVLOG(1) << "WASAPIUnifiedStream::Stop()";
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(GetCurrentThreadId(), creating_thread_id_);
441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!audio_io_thread_)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Stop input audio streaming.
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HRESULT hr = audio_input_client_->Stop();
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FAILED(hr)) {
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG_IF(ERROR, hr != AUDCLNT_E_NOT_INITIALIZED)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << "Failed to stop input streaming: " << std::hex << hr;
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Stop output audio streaming.
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hr = audio_output_client_->Stop();
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FAILED(hr)) {
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG_IF(ERROR, hr != AUDCLNT_E_NOT_INITIALIZED)
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << "Failed to stop output streaming: " << std::hex << hr;
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait until the thread completes and perform cleanup.
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetEvent(stop_streaming_event_.Get());
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_io_thread_->Join();
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_io_thread_.reset();
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that we don't quit the main thread loop immediately next
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // time Start() is called.
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResetEvent(stop_streaming_event_.Get());
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Clear source callback, it'll be set again on the next Start() call.
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  source_ = NULL;
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Flush all pending data and reset the audio clock stream position to 0.
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hr = audio_output_client_->Reset();
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FAILED(hr)) {
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG_IF(ERROR, hr != AUDCLNT_E_NOT_INITIALIZED)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << "Failed to reset output streaming: " << std::hex << hr;
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_input_client_->Reset();
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FAILED(hr)) {
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG_IF(ERROR, hr != AUDCLNT_E_NOT_INITIALIZED)
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << "Failed to reset input streaming: " << std::hex << hr;
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Extra safety check to ensure that the buffers are cleared.
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the buffers are not cleared correctly, the next call to Start()
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // would fail with AUDCLNT_E_BUFFER_ERROR at IAudioRenderClient::GetBuffer().
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(henrika): this check is is only needed for shared-mode streams.
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UINT32 num_queued_frames = 0;
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_output_client_->GetCurrentPadding(&num_queued_frames);
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(0u, num_queued_frames);
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WASAPIUnifiedStream::Close() {
493a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  TRACE_EVENT0("audio", "WASAPIUnifiedStream::Close");
494a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DVLOG(1) << "WASAPIUnifiedStream::Close()";
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(GetCurrentThreadId(), creating_thread_id_);
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It is valid to call Close() before calling open or Start().
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It is also valid to call Close() after Start() has been called.
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Stop();
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Inform the audio manager that we have been closed. This will cause our
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // destruction.
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  manager_->ReleaseOutputStream(this);
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WASAPIUnifiedStream::SetVolume(double volume) {
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "SetVolume(volume=" << volume << ")";
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (volume < 0 || volume > 1)
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  volume_ = volume;
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WASAPIUnifiedStream::GetVolume(double* volume) {
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "GetVolume()";
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *volume = static_cast<double>(volume_);
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
519a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void WASAPIUnifiedStream::ProvideInput(int frame_delay, AudioBus* audio_bus) {
520a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // TODO(henrika): utilize frame_delay?
521a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // A non-zero framed delay means multiple callbacks were necessary to
522a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // fulfill the requested number of frames.
523a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (frame_delay > 0)
524a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    DVLOG(3) << "frame_delay: " << frame_delay;
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
526a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#ifndef NDEBUG
527a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  resampler_margin_[num_elements_[RESAMPLER_MARGIN]] =
528a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    fifo_->frames() - audio_bus->frames();
529a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  num_elements_[RESAMPLER_MARGIN]++;
530a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#endif
531a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
532a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (fifo_->frames() < audio_bus->frames()) {
533a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    DVLOG(ERROR) << "Not enough data in the FIFO ("
534a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                 << fifo_->frames() << " < " << audio_bus->frames() << ")";
535a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    audio_bus->Zero();
536a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return;
537a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
538a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
539a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  fifo_->Consume(audio_bus, 0, audio_bus->frames());
540a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
541a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
542a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void WASAPIUnifiedStream::SetIOFormats(const AudioParameters& input_params,
543a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                       const AudioParameters& output_params) {
544a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  for (int n = 0; n < 2; ++n) {
545a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    const AudioParameters& params = (n == 0) ? input_params : output_params;
546a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    WAVEFORMATPCMEX* xformat = (n == 0) ? &input_format_ : &output_format_;
547a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    WAVEFORMATEX* format = &xformat->Format;
548a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
549a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // Begin with the WAVEFORMATEX structure that specifies the basic format.
550a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    format->wFormatTag = WAVE_FORMAT_EXTENSIBLE;
551a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    format->nChannels =  params.channels();
552a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    format->nSamplesPerSec = params.sample_rate();
553a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    format->wBitsPerSample = params.bits_per_sample();
554a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    format->nBlockAlign = (format->wBitsPerSample / 8) * format->nChannels;
555a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    format->nAvgBytesPerSec = format->nSamplesPerSec * format->nBlockAlign;
556a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    format->cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
557a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
558a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // Add the parts which are unique to WAVE_FORMAT_EXTENSIBLE.
559a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // Note that we always open up using the native channel layout.
560a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    (*xformat).Samples.wValidBitsPerSample = format->wBitsPerSample;
5611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    (*xformat).dwChannelMask =
5621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        CoreAudioUtil::GetChannelConfig(
5631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)            std::string(), n == 0 ? eCapture : eRender);
564a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    (*xformat).SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
565a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
566a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
567a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  input_buffer_size_frames_ = input_params.frames_per_buffer();
568a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  output_buffer_size_frames_ = output_params.frames_per_buffer();
569a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  VLOG(1) << "#audio frames per input buffer : " << input_buffer_size_frames_;
570a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  VLOG(1) << "#audio frames per output buffer: " << output_buffer_size_frames_;
571a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
572a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#ifndef NDEBUG
573a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  input_params_[0] = input_format_.Format.nSamplesPerSec;
574a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  input_params_[1] = input_buffer_size_frames_;
575a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  output_params_[0] = output_format_.Format.nSamplesPerSec;
576a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  output_params_[1] = output_buffer_size_frames_;
577a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#endif
578a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
579a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
580a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void WASAPIUnifiedStream::DoVarispeedInitialization(
581a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    const AudioParameters& input_params, const AudioParameters& output_params) {
582a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DVLOG(1) << "WASAPIUnifiedStream::DoVarispeedInitialization()";
583a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
584a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // A FIFO is required in this mode for input to output buffering.
585a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Note that it will add some latency.
586a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  fifo_.reset(new AudioFifo(input_params.channels(), kFifoSize));
587a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  VLOG(1) << "Using FIFO of size " << fifo_->max_frames()
588a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)          << " (#channels=" << input_params.channels() << ")";
589a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
590a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Create the multi channel resampler using the initial sample rate ratio.
591a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // We will call MultiChannelResampler::SetRatio() during runtime to
592a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // allow arbitrary combinations of input and output devices running off
593a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // different clocks and using different drivers, with potentially
594a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // differing sample-rates. Note that the requested block size is given by
595a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // the native input buffer size |input_buffer_size_frames_|.
596a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  io_sample_rate_ratio_ = input_params.sample_rate() /
597a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      static_cast<double>(output_params.sample_rate());
598a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DVLOG(2) << "io_sample_rate_ratio: " << io_sample_rate_ratio_;
599a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  resampler_.reset(new MultiChannelResampler(
600a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      input_params.channels(), io_sample_rate_ratio_, input_buffer_size_frames_,
601a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      base::Bind(&WASAPIUnifiedStream::ProvideInput, base::Unretained(this))));
602a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  VLOG(1) << "Resampling from " << input_params.sample_rate() << " to "
603a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)          << output_params.sample_rate();
604a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
605a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // The optimal number of frames we'd like to keep in the FIFO at all times.
606a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // The actual size will vary but the goal is to ensure that the average size
607a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // is given by this value.
608a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  target_fifo_frames_ = kTargetFifoSafetyFactor * input_buffer_size_frames_;
609a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  VLOG(1) << "Target FIFO size: " <<  target_fifo_frames_;
610a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
611a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Create the event which the audio engine will signal each time it
612a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // wants an audio buffer to render.
613a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  render_event_.Set(CreateEvent(NULL, FALSE, FALSE, NULL));
614a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
615a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Allocate memory for temporary audio bus used to store resampled input
616a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // audio.
617a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  resampled_bus_ = AudioBus::Create(
618a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      input_params.channels(), output_buffer_size_frames_);
619a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
620a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Buffer initial silence corresponding to target I/O buffering.
621a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  ResetVarispeed();
622a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
623a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
624a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void WASAPIUnifiedStream::ResetVarispeed() {
625a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DCHECK(VarispeedMode());
626a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
627a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Buffer initial silence corresponding to target I/O buffering.
628a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  fifo_->Clear();
629a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  scoped_ptr<AudioBus> silence =
630a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      AudioBus::Create(input_format_.Format.nChannels,
631a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                       target_fifo_frames_);
632a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  silence->Zero();
633a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  fifo_->Push(silence.get());
634a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  resampler_->Flush();
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WASAPIUnifiedStream::Run() {
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedCOMInitializer com_init(ScopedCOMInitializer::kMTA);
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Increase the thread priority.
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_io_thread_->SetThreadPriority(base::kThreadPriority_RealtimeAudio);
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Enable MMCSS to ensure that this thread receives prioritized access to
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // CPU resources.
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(henrika): investigate if it is possible to include these additional
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // settings in SetThreadPriority() as well.
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD task_index = 0;
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HANDLE mm_task = avrt::AvSetMmThreadCharacteristics(L"Pro Audio",
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                      &task_index);
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool mmcss_is_ok =
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (mm_task && avrt::AvSetMmThreadPriority(mm_task, AVRT_PRIORITY_CRITICAL));
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!mmcss_is_ok) {
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Failed to enable MMCSS on this thread. It is not fatal but can lead
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // to reduced QoS at high load.
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DWORD err = GetLastError();
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Failed to enable MMCSS (error code=" << err << ").";
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The IAudioClock interface enables us to monitor a stream's data
6602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // rate and the current position in the stream. Allocate it before we
6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // start spinning.
6622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ScopedComPtr<IAudioClock> audio_output_clock;
6632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HRESULT hr = audio_output_client_->GetService(
6642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      __uuidof(IAudioClock), audio_output_clock.ReceiveVoid());
6652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LOG_IF(WARNING, FAILED(hr)) << "Failed to create IAudioClock: "
6662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              << std::hex << hr;
6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool streaming = true;
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool error = false;
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
671a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  HANDLE wait_array[3];
672a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  size_t num_handles = 0;
673a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  wait_array[num_handles++] = stop_streaming_event_;
674a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  wait_array[num_handles++] = capture_event_;
675a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (render_event_) {
676a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // One extra event handle is needed in varispeed mode.
677a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    wait_array[num_handles++] = render_event_;
678a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
680a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Keep streaming audio until stop event is signaled.
681a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Capture events are always used but render events are only active in
682a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // varispeed mode.
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (streaming && !error) {
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Wait for a close-down event, or a new capture event.
685a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    DWORD wait_result = WaitForMultipleObjects(num_handles,
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               wait_array,
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               FALSE,
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               INFINITE);
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (wait_result) {
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case WAIT_OBJECT_0 + 0:
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // |stop_streaming_event_| has been set.
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        streaming = false;
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case WAIT_OBJECT_0 + 1:
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // |capture_event_| has been set
696a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        if (VarispeedMode()) {
697a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)          ProcessInputAudio();
698a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        } else {
699a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)          ProcessInputAudio();
700a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)          ProcessOutputAudio(audio_output_clock);
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
703a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      case WAIT_OBJECT_0 + 2:
704a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        DCHECK(VarispeedMode());
705a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        // |render_event_| has been set
706a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        ProcessOutputAudio(audio_output_clock);
707a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        break;
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        error = true;
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (streaming && error) {
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Stop audio streaming since something has gone wrong in our main thread
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // loop. Note that, we are still in a "started" state, hence a Stop() call
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // is required to join the thread properly.
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    audio_input_client_->Stop();
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    audio_output_client_->Stop();
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PLOG(ERROR) << "WASAPI streaming failed.";
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Disable MMCSS.
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (mm_task && !avrt::AvRevertMmThreadCharacteristics(mm_task)) {
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PLOG(WARNING) << "Failed to disable MMCSS";
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
729a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void WASAPIUnifiedStream::ProcessInputAudio() {
730a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  TRACE_EVENT0("audio", "WASAPIUnifiedStream::ProcessInputAudio");
731a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
732a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  BYTE* data_ptr = NULL;
733a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  UINT32 num_captured_frames = 0;
734a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DWORD flags = 0;
735a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  UINT64 device_position = 0;
736a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  UINT64 capture_time_stamp = 0;
737a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
738a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  const int bytes_per_sample = input_format_.Format.wBitsPerSample >> 3;
739a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
740a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::TimeTicks now_tick = base::TimeTicks::HighResNow();
741a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
742a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#ifndef NDEBUG
743a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (VarispeedMode()) {
744a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    input_time_stamps_[num_elements_[INPUT_TIME_STAMP]] =
745a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        now_tick.ToInternalValue();
746a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    num_elements_[INPUT_TIME_STAMP]++;
747a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
748a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#endif
749a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
750a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Retrieve the amount of data in the capture endpoint buffer.
751a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // |endpoint_capture_time_stamp| is the value of the performance
752a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // counter at the time that the audio endpoint device recorded
753a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // the device position of the first audio frame in the data packet.
754a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  HRESULT hr = audio_capture_client_->GetBuffer(&data_ptr,
755a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                                &num_captured_frames,
756a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                                &flags,
757a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                                &device_position,
758a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                                &capture_time_stamp);
759a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (FAILED(hr)) {
760a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    DLOG(ERROR) << "Failed to get data from the capture buffer";
761a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return;
762a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
763a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
764a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (hr == AUDCLNT_S_BUFFER_EMPTY) {
765a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // The return coded is a success code but a new packet is *not* available
766a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // and none of the output parameters in the GetBuffer() call contains valid
767a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // values. Best we can do is to deliver silence and avoid setting
768a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // |input_callback_received_| since this only seems to happen for the
769a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // initial event(s) on some devices.
770a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    input_bus_->Zero();
771a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  } else {
772a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // Valid data has been recorded and it is now OK to set the flag which
773a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // informs the render side that capturing has started.
774a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    input_callback_received_ = true;
775a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
776a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
777a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (num_captured_frames != 0) {
778a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    if (flags & AUDCLNT_BUFFERFLAGS_SILENT) {
779a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      // Clear out the capture buffer since silence is reported.
780a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      input_bus_->Zero();
781a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    } else {
782a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      // Store captured data in an audio bus after de-interleaving
783a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      // the data to match the audio bus structure.
784a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      input_bus_->FromInterleaved(
785a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)          data_ptr, num_captured_frames, bytes_per_sample);
786a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    }
787a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
788a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
789a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  hr = audio_capture_client_->ReleaseBuffer(num_captured_frames);
790a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DLOG_IF(ERROR, FAILED(hr)) << "Failed to release capture buffer";
791a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
792a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Buffer input into FIFO if varispeed mode is used. The render event
793a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // will drive resampling of this data to match the output side.
794a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (VarispeedMode()) {
795a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    int available_frames = fifo_->max_frames() - fifo_->frames();
796a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    if (input_bus_->frames() <= available_frames) {
797a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      fifo_->Push(input_bus_.get());
798a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    }
799a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#ifndef NDEBUG
800a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    num_frames_in_fifo_[num_elements_[NUM_FRAMES_IN_FIFO]] =
801a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        fifo_->frames();
802a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    num_elements_[NUM_FRAMES_IN_FIFO]++;
803a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#endif
804a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
805a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
806a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Save resource by not asking for new delay estimates each time.
807a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // These estimates are fairly stable and it is perfectly safe to only
808a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // sample at a rate of ~1Hz.
809a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // TODO(henrika): we might have to increase the update rate in varispeed
810a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // mode since the delay variations are higher in this mode.
811a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if ((now_tick - last_delay_sample_time_).InMilliseconds() >
812a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      kTimeDiffInMillisecondsBetweenDelayMeasurements &&
813a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      input_callback_received_) {
814a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // Calculate the estimated capture delay, i.e., the latency between
815a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // the recording time and the time we when we are notified about
816a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // the recorded data. Note that the capture time stamp is given in
817a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // 100-nanosecond (0.1 microseconds) units.
818a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    base::TimeDelta diff =
819a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      now_tick - base::TimeTicks::FromInternalValue(0.1 * capture_time_stamp);
820a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    capture_delay_ms_ = diff.InMillisecondsF();
821a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
822a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    last_delay_sample_time_ = now_tick;
823a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    update_output_delay_ = true;
824a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
825a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
826a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
827a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void WASAPIUnifiedStream::ProcessOutputAudio(IAudioClock* audio_output_clock) {
828a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  TRACE_EVENT0("audio", "WASAPIUnifiedStream::ProcessOutputAudio");
829a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
830a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (!input_callback_received_) {
831a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    if (share_mode_ == AUDCLNT_SHAREMODE_SHARED) {
832a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      if (!CoreAudioUtil::FillRenderEndpointBufferWithSilence(
833a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)              audio_output_client_, audio_render_client_))
834a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        DLOG(WARNING) << "Failed to prepare endpoint buffers with silence.";
835a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    }
836a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return;
837a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
838a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
839a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Rate adjusted resampling is required in varispeed mode. It means that
840a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // recorded audio samples will be read from the FIFO, resampled to match the
841a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // output sample-rate and then stored in |resampled_bus_|.
842a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (VarispeedMode()) {
843a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // Calculate a varispeed rate scalar factor to compensate for drift between
844a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // input and output.  We use the actual number of frames still in the FIFO
845a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // compared with the ideal value of |target_fifo_frames_|.
846a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    int delta = fifo_->frames() - target_fifo_frames_;
847a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
848a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // Average |delta| because it can jitter back/forth quite frequently
849a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // by +/- the hardware buffer-size *if* the input and output callbacks are
850a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // happening at almost exactly the same time.  Also, if the input and output
851a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // sample-rates are different then |delta| will jitter quite a bit due to
852a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // the rate conversion happening in the varispeed, plus the jittering of
853a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // the callbacks.  The average value is what's important here.
854a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // We use an exponential smoothing filter to reduce the variations.
855a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    average_delta_ += kAlpha * (delta - average_delta_);
856a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
857a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // Compute a rate compensation which always attracts us back to the
858a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // |target_fifo_frames_| over a period of kCorrectionTimeSeconds.
859a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    double correction_time_frames =
860a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        kCorrectionTimeSeconds * output_format_.Format.nSamplesPerSec;
861a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    fifo_rate_compensation_ =
862a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        (correction_time_frames + average_delta_) / correction_time_frames;
863a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
864a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#ifndef NDEBUG
865a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    fifo_rate_comps_[num_elements_[RATE_COMPENSATION]] =
866a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        fifo_rate_compensation_;
867a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    num_elements_[RATE_COMPENSATION]++;
868a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#endif
869a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
870a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // Adjust for FIFO drift.
871a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    const double new_ratio = io_sample_rate_ratio_ * fifo_rate_compensation_;
872a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    resampler_->SetRatio(new_ratio);
873a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // Get resampled input audio from FIFO where the size is given by the
874a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // output side.
875a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    resampler_->Resample(resampled_bus_->frames(), resampled_bus_.get());
876a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
877a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
878a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Derive a new total delay estimate if the capture side has set the
879a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // |update_output_delay_| flag.
880a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (update_output_delay_) {
881a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // Calculate the estimated render delay, i.e., the time difference
882a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // between the time when data is added to the endpoint buffer and
883a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // when the data is played out on the actual speaker.
884a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    const double stream_pos = CurrentStreamPosInMilliseconds(
885a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        num_written_frames_ + output_buffer_size_frames_,
886a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        output_format_.Format.nSamplesPerSec);
887a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    const double speaker_pos =
888a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        SpeakerStreamPosInMilliseconds(audio_output_clock);
889a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    const double render_delay_ms = stream_pos - speaker_pos;
890a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    const double fifo_delay_ms = VarispeedMode() ?
891a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      FrameCountToMilliseconds(target_fifo_frames_, input_format_) : 0;
892a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
893a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // Derive the total delay, i.e., the sum of the input and output
894a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // delays. Also convert the value into byte units. An extra FIFO delay
895a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // is added for varispeed usage cases.
896a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    total_delay_ms_ = VarispeedMode() ?
897a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      capture_delay_ms_ + render_delay_ms + fifo_delay_ms :
898a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      capture_delay_ms_ + render_delay_ms;
899a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    DVLOG(2) << "total_delay_ms   : " << total_delay_ms_;
900a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    DVLOG(3) << " capture_delay_ms: " << capture_delay_ms_;
901a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    DVLOG(3) << " render_delay_ms : " << render_delay_ms;
902a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    DVLOG(3) << " fifo_delay_ms   : " << fifo_delay_ms;
903a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    total_delay_bytes_ = MillisecondsToBytes(total_delay_ms_, output_format_);
904a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
905a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // Wait for new signal from the capture side.
906a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    update_output_delay_ = false;
907a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
908a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
909a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Select source depending on if varispeed is utilized or not.
910a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Also, the source might be the output of a channel mixer if channel mixing
911a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // is required to match the native input channels to the number of input
912a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // channels used by the client (given by |input_channels_| in this case).
913a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  AudioBus* input_bus = VarispeedMode() ?
914a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      resampled_bus_.get() : input_bus_.get();
915a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (channel_mixer_) {
9167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    DCHECK_EQ(input_bus->frames(), channel_bus_->frames());
917a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // Most common case is 1->2 channel upmixing.
918a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    channel_mixer_->Transform(input_bus, channel_bus_.get());
919a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // Use the output from the channel mixer as new input bus.
920a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    input_bus = channel_bus_.get();
921a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
922a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
923a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Prepare for rendering by calling OnMoreIOData().
924a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  int frames_filled = source_->OnMoreIOData(
925a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      input_bus,
926a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      output_bus_.get(),
927a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      AudioBuffersState(0, total_delay_bytes_));
928a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DCHECK_EQ(frames_filled, output_bus_->frames());
929a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
930a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Keep track of number of rendered frames since we need it for
931a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // our delay calculations.
932a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  num_written_frames_ += frames_filled;
933a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
934a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Derive the the amount of available space in the endpoint buffer.
935a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Avoid render attempt if there is no room for a captured packet.
936a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  UINT32 num_queued_frames = 0;
937a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  audio_output_client_->GetCurrentPadding(&num_queued_frames);
938a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (endpoint_render_buffer_size_frames_ - num_queued_frames <
939a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      output_buffer_size_frames_)
940a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return;
941a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
942a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Grab all available space in the rendering endpoint buffer
943a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // into which the client can write a data packet.
944a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  uint8* audio_data = NULL;
945a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  HRESULT hr = audio_render_client_->GetBuffer(output_buffer_size_frames_,
946a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                               &audio_data);
947a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (FAILED(hr)) {
948a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    DLOG(ERROR) << "Failed to access render buffer";
949a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return;
950a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
951a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
952a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  const int bytes_per_sample = output_format_.Format.wBitsPerSample >> 3;
953a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
954a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Convert the audio bus content to interleaved integer data using
955a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // |audio_data| as destination.
956a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  output_bus_->Scale(volume_);
957a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  output_bus_->ToInterleaved(
958a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      output_buffer_size_frames_, bytes_per_sample, audio_data);
959a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
960a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Release the buffer space acquired in the GetBuffer() call.
961a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  audio_render_client_->ReleaseBuffer(output_buffer_size_frames_, 0);
962a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DLOG_IF(ERROR, FAILED(hr)) << "Failed to release render buffer";
963a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
964a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  return;
965a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
966a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WASAPIUnifiedStream::HandleError(HRESULT err) {
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK((started() && GetCurrentThreadId() == audio_io_thread_->tid()) ||
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (!started() && GetCurrentThreadId() == creating_thread_id_));
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED() << "Error code: " << std::hex << err;
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (source_)
9722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    source_->OnError(this);
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WASAPIUnifiedStream::StopAndJoinThread(HRESULT err) {
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(GetCurrentThreadId() == creating_thread_id_);
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(audio_io_thread_.get());
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetEvent(stop_streaming_event_.Get());
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_io_thread_->Join();
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_io_thread_.reset();
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HandleError(err);
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace media
985