summaryrefslogtreecommitdiffstats
path: root/media/audio/audio_input_volume_unittest.cc
blob: c49187ed6225007aa9348a6a289cb300c399783e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <cmath>

#include "base/memory/scoped_ptr.h"
#include "base/win/scoped_com_initializer.h"
#include "media/audio/audio_io.h"
#include "media/audio/audio_manager_base.h"
#include "media/audio/audio_util.h"
#include "testing/gtest/include/gtest/gtest.h"

using base::win::ScopedCOMInitializer;

namespace media {

class AudioInputVolumeTest : public ::testing::Test {
 protected:
  AudioInputVolumeTest()
      : audio_manager_(AudioManager::Create()),
        com_init_(ScopedCOMInitializer::kMTA) {
  }

  bool CanRunAudioTests() {
#if defined(OS_WIN)
    // TODO(henrika): add support for volume control on Windows XP as well.
    // For now, we might as well signal false already here to avoid running
    // these tests on Windows XP.
    if (!media::IsWASAPISupported())
      return false;
#endif
    if (!audio_manager_.get())
      return false;

    return audio_manager_->HasAudioInputDevices();
  }

  // Helper method which checks if the stream has volume support.
  bool HasDeviceVolumeControl(AudioInputStream* stream) {
    if (!stream)
      return false;

    return (stream->GetMaxVolume() != 0.0);
  }

  AudioInputStream* CreateAndOpenStream(const std::string& device_id) {
    AudioParameters::Format format = AudioParameters::AUDIO_PCM_LOW_LATENCY;
    ChannelLayout channel_layout =
        media::GetAudioInputHardwareChannelLayout(device_id);
    int bits_per_sample = 16;
    int sample_rate =
        static_cast<int>(media::GetAudioInputHardwareSampleRate(device_id));
    int samples_per_packet = 0;
#if defined(OS_MACOSX)
    samples_per_packet = (sample_rate / 100);
#elif defined(OS_LINUX) || defined(OS_OPENBSD)
    samples_per_packet = (sample_rate / 100);
#elif defined(OS_WIN)
    if (sample_rate == 44100)
      samples_per_packet = 448;
    else
      samples_per_packet = (sample_rate / 100);
#else
#error Unsupported platform
#endif
    AudioInputStream* ais = audio_manager_->MakeAudioInputStream(
        AudioParameters(format, channel_layout, sample_rate, bits_per_sample,
                        samples_per_packet),
        device_id);
    EXPECT_TRUE(NULL != ais);

#if defined(OS_LINUX) || defined(OS_OPENBSD)
    // Some linux devices do not support our settings, we may fail to open
    // those devices.
    if (!ais->Open()) {
      // Default device should always be able to be opened.
      EXPECT_TRUE(AudioManagerBase::kDefaultDeviceId != device_id);
      ais->Close();
      ais = NULL;
    }
#elif defined(OS_WIN) || defined(OS_MACOSX)
    EXPECT_TRUE(ais->Open());
#endif

    return ais;
  }

  scoped_ptr<AudioManager> audio_manager_;
  ScopedCOMInitializer com_init_;
};

TEST_F(AudioInputVolumeTest, InputVolumeTest) {
  if (!CanRunAudioTests())
    return;

  // Retrieve a list of all available input devices.
  AudioDeviceNames device_names;
  audio_manager_->GetAudioInputDeviceNames(&device_names);
  if (device_names.empty()) {
    LOG(WARNING) << "Could not find any available input device";
    return;
  }

  // Scan all available input devices and repeat the same test for all of them.
  for (AudioDeviceNames::const_iterator it = device_names.begin();
       it != device_names.end();
       ++it) {
    AudioInputStream* ais = CreateAndOpenStream(it->unique_id);
    if (!ais) {
      DLOG(WARNING) << "Failed to open stream for device " << it->unique_id;
      continue;
    }

    if (!HasDeviceVolumeControl(ais)) {
      DLOG(WARNING) << "Device: " << it->unique_id
                    << ", does not have volume control.";
      ais->Close();
      continue;
    }

    double max_volume = ais->GetMaxVolume();
    EXPECT_GT(max_volume, 0.0);

    // Store the current input-device volume level.
    double original_volume = ais->GetVolume();
    EXPECT_GE(original_volume, 0.0);
#if defined(OS_WIN) || defined(OS_MACOSX)
    // Note that |original_volume| can be higher than |max_volume| on Linux.
    EXPECT_LE(original_volume, max_volume);
#endif

    // Set the volume to the maxiumum level..
    ais->SetVolume(max_volume);
    double current_volume = ais->GetVolume();
    EXPECT_EQ(max_volume, current_volume);

    // Set the volume to the mininum level (=0).
    double new_volume = 0.0;
    ais->SetVolume(new_volume);
    current_volume = ais->GetVolume();
    EXPECT_EQ(new_volume, current_volume);

    // Set the volume to the mid level (50% of max).
    // Verify that the absolute error is small enough.
    new_volume = max_volume / 2;
    ais->SetVolume(new_volume);
    current_volume = ais->GetVolume();
    EXPECT_LT(current_volume, max_volume);
    EXPECT_GT(current_volume, 0);
    EXPECT_NEAR(current_volume, new_volume, 0.25 * max_volume);

    // Restores the volume to the original value.
    ais->SetVolume(original_volume);
    current_volume = ais->GetVolume();
    EXPECT_EQ(original_volume, current_volume);

    ais->Close();
  }
}

}  // namespace media