1// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "media/base/audio_hardware_config.h"
6
7#include <algorithm>
8#include <cmath>
9
10#include "base/logging.h"
11#include "build/build_config.h"
12
13using base::AutoLock;
14using media::AudioParameters;
15
16namespace media {
17
18#if !defined(OS_WIN)
19// Taken from "Bit Twiddling Hacks"
20// http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
21static uint32_t RoundUpToPowerOfTwo(uint32_t v) {
22  v--;
23  v |= v >> 1;
24  v |= v >> 2;
25  v |= v >> 4;
26  v |= v >> 8;
27  v |= v >> 16;
28  v++;
29  return v;
30}
31#endif
32
33AudioHardwareConfig::AudioHardwareConfig(
34    const AudioParameters& input_params,
35    const AudioParameters& output_params)
36    : input_params_(input_params),
37      output_params_(output_params) {}
38
39AudioHardwareConfig::~AudioHardwareConfig() {}
40
41int AudioHardwareConfig::GetOutputBufferSize() const {
42  AutoLock auto_lock(config_lock_);
43  return output_params_.frames_per_buffer();
44}
45
46int AudioHardwareConfig::GetOutputSampleRate() const {
47  AutoLock auto_lock(config_lock_);
48  return output_params_.sample_rate();
49}
50
51ChannelLayout AudioHardwareConfig::GetOutputChannelLayout() const {
52  AutoLock auto_lock(config_lock_);
53  return output_params_.channel_layout();
54}
55
56int AudioHardwareConfig::GetOutputChannels() const {
57  AutoLock auto_lock(config_lock_);
58  return output_params_.channels();
59}
60
61int AudioHardwareConfig::GetInputSampleRate() const {
62  AutoLock auto_lock(config_lock_);
63  return input_params_.sample_rate();
64}
65
66ChannelLayout AudioHardwareConfig::GetInputChannelLayout() const {
67  AutoLock auto_lock(config_lock_);
68  return input_params_.channel_layout();
69}
70
71int AudioHardwareConfig::GetInputChannels() const {
72  AutoLock auto_lock(config_lock_);
73  return input_params_.channels();
74}
75
76media::AudioParameters
77AudioHardwareConfig::GetInputConfig() const {
78  AutoLock auto_lock(config_lock_);
79  return input_params_;
80}
81
82media::AudioParameters
83AudioHardwareConfig::GetOutputConfig() const {
84  AutoLock auto_lock(config_lock_);
85  return output_params_;
86}
87
88void AudioHardwareConfig::UpdateInputConfig(
89    const AudioParameters& input_params) {
90  AutoLock auto_lock(config_lock_);
91  input_params_ = input_params;
92}
93
94void AudioHardwareConfig::UpdateOutputConfig(
95    const AudioParameters& output_params) {
96  AutoLock auto_lock(config_lock_);
97  output_params_ = output_params;
98}
99
100int AudioHardwareConfig::GetHighLatencyBufferSize() const {
101  AutoLock auto_lock(config_lock_);
102
103  // Empirically, we consider 20ms of samples to be high latency.
104  const double twenty_ms_size = 2.0 * output_params_.sample_rate() / 100;
105
106#if defined(OS_WIN)
107  // Windows doesn't use power of two buffer sizes, so we should always round up
108  // to the nearest multiple of the output buffer size.
109  const int high_latency_buffer_size =
110      std::ceil(twenty_ms_size / output_params_.frames_per_buffer()) *
111      output_params_.frames_per_buffer();
112#else
113  // On other platforms use the nearest higher power of two buffer size.  For a
114  // given sample rate, this works out to:
115  //
116  //     <= 3200   : 64
117  //     <= 6400   : 128
118  //     <= 12800  : 256
119  //     <= 25600  : 512
120  //     <= 51200  : 1024
121  //     <= 102400 : 2048
122  //     <= 204800 : 4096
123  //
124  // On Linux, the minimum hardware buffer size is 512, so the lower calculated
125  // values are unused.  OSX may have a value as low as 128.
126  const int high_latency_buffer_size = RoundUpToPowerOfTwo(twenty_ms_size);
127#endif  // defined(OS_WIN)
128
129  return std::max(output_params_.frames_per_buffer(), high_latency_buffer_size);
130}
131
132}  // namespace media
133