blob: aea899c94ad4763664793efb37a365e794c64607 [file] [log] [blame]
henrika86d907c2015-09-07 16:09:50 +02001/*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/audio_device/fine_audio_buffer.h"
henrika86d907c2015-09-07 16:09:50 +020012
13#include <limits.h>
14#include <memory>
15
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "api/array_view.h"
17#include "modules/audio_device/mock_audio_device_buffer.h"
18#include "test/gmock.h"
19#include "test/gtest.h"
henrika86d907c2015-09-07 16:09:50 +020020
21using ::testing::_;
22using ::testing::AtLeast;
23using ::testing::InSequence;
24using ::testing::Return;
25
26namespace webrtc {
27
henrikabb6f7522017-05-30 02:01:30 -070028const int kSampleRate = 44100;
henrika29e865a2018-04-24 13:22:31 +020029const int kChannels = 2;
henrikabb6f7522017-05-30 02:01:30 -070030const int kSamplesPer10Ms = kSampleRate * 10 / 1000;
31
henrika86d907c2015-09-07 16:09:50 +020032// The fake audio data is 0,1,..SCHAR_MAX-1,0,1,... This is to make it easy
33// to detect errors. This function verifies that the buffers contain such data.
34// E.g. if there are two buffers of size 3, buffer 1 would contain 0,1,2 and
35// buffer 2 would contain 3,4,5. Note that SCHAR_MAX is 127 so wrap-around
36// will happen.
37// |buffer| is the audio buffer to verify.
henrika8d7393b2018-04-19 13:40:15 +020038bool VerifyBuffer(const int16_t* buffer, int buffer_number, int size) {
henrika86d907c2015-09-07 16:09:50 +020039 int start_value = (buffer_number * size) % SCHAR_MAX;
40 for (int i = 0; i < size; ++i) {
41 if (buffer[i] != (i + start_value) % SCHAR_MAX) {
42 return false;
43 }
44 }
45 return true;
46}
47
48// This function replaces the real AudioDeviceBuffer::GetPlayoutData when it's
49// called (which is done implicitly when calling GetBufferData). It writes the
50// sequence 0,1,..SCHAR_MAX-1,0,1,... to the buffer. Note that this is likely a
51// buffer of different size than the one VerifyBuffer verifies.
52// |iteration| is the number of calls made to UpdateBuffer prior to this call.
53// |samples_per_10_ms| is the number of samples that should be written to the
54// buffer (|arg0|).
55ACTION_P2(UpdateBuffer, iteration, samples_per_10_ms) {
henrika8d7393b2018-04-19 13:40:15 +020056 int16_t* buffer = static_cast<int16_t*>(arg0);
57 int start_value = (iteration * samples_per_10_ms) % SCHAR_MAX;
58 for (int i = 0; i < samples_per_10_ms; ++i) {
henrika86d907c2015-09-07 16:09:50 +020059 buffer[i] = (i + start_value) % SCHAR_MAX;
60 }
henrika29e865a2018-04-24 13:22:31 +020061 // Should return samples per channel.
62 return samples_per_10_ms / kChannels;
henrika86d907c2015-09-07 16:09:50 +020063}
64
65// Writes a periodic ramp pattern to the supplied |buffer|. See UpdateBuffer()
66// for details.
henrika8d7393b2018-04-19 13:40:15 +020067void UpdateInputBuffer(int16_t* buffer, int iteration, int size) {
henrika86d907c2015-09-07 16:09:50 +020068 int start_value = (iteration * size) % SCHAR_MAX;
69 for (int i = 0; i < size; ++i) {
70 buffer[i] = (i + start_value) % SCHAR_MAX;
71 }
72}
73
74// Action macro which verifies that the recorded 10ms chunk of audio data
75// (in |arg0|) contains the correct reference values even if they have been
76// supplied using a buffer size that is smaller or larger than 10ms.
77// See VerifyBuffer() for details.
78ACTION_P2(VerifyInputBuffer, iteration, samples_per_10_ms) {
henrika8d7393b2018-04-19 13:40:15 +020079 const int16_t* buffer = static_cast<const int16_t*>(arg0);
80 int start_value = (iteration * samples_per_10_ms) % SCHAR_MAX;
81 for (int i = 0; i < samples_per_10_ms; ++i) {
henrika86d907c2015-09-07 16:09:50 +020082 EXPECT_EQ(buffer[i], (i + start_value) % SCHAR_MAX);
83 }
84 return 0;
85}
86
henrikabb6f7522017-05-30 02:01:30 -070087void RunFineBufferTest(int frame_size_in_samples) {
henrika8d7393b2018-04-19 13:40:15 +020088 const int kFrameSizeSamples = frame_size_in_samples;
henrika86d907c2015-09-07 16:09:50 +020089 const int kNumberOfFrames = 5;
90 // Ceiling of integer division: 1 + ((x - 1) / y)
91 const int kNumberOfUpdateBufferCalls =
92 1 + ((kNumberOfFrames * frame_size_in_samples - 1) / kSamplesPer10Ms);
93
94 MockAudioDeviceBuffer audio_device_buffer;
henrika29e865a2018-04-24 13:22:31 +020095 audio_device_buffer.SetPlayoutSampleRate(kSampleRate);
96 audio_device_buffer.SetPlayoutChannels(kChannels);
97 audio_device_buffer.SetRecordingSampleRate(kSampleRate);
98 audio_device_buffer.SetRecordingChannels(kChannels);
99
henrika86d907c2015-09-07 16:09:50 +0200100 EXPECT_CALL(audio_device_buffer, RequestPlayoutData(_))
101 .WillRepeatedly(Return(kSamplesPer10Ms));
102 {
103 InSequence s;
104 for (int i = 0; i < kNumberOfUpdateBufferCalls; ++i) {
105 EXPECT_CALL(audio_device_buffer, GetPlayoutData(_))
henrika29e865a2018-04-24 13:22:31 +0200106 .WillOnce(UpdateBuffer(i, kChannels * kSamplesPer10Ms))
henrika86d907c2015-09-07 16:09:50 +0200107 .RetiresOnSaturation();
108 }
109 }
110 {
111 InSequence s;
112 for (int j = 0; j < kNumberOfUpdateBufferCalls - 1; ++j) {
113 EXPECT_CALL(audio_device_buffer, SetRecordedBuffer(_, kSamplesPer10Ms))
henrika29e865a2018-04-24 13:22:31 +0200114 .WillOnce(VerifyInputBuffer(j, kChannels * kSamplesPer10Ms))
henrika86d907c2015-09-07 16:09:50 +0200115 .RetiresOnSaturation();
116 }
117 }
Fredrik Solenberg1a50cd52018-01-16 09:19:38 +0100118 EXPECT_CALL(audio_device_buffer, SetVQEData(_, _))
henrika86d907c2015-09-07 16:09:50 +0200119 .Times(kNumberOfUpdateBufferCalls - 1);
120 EXPECT_CALL(audio_device_buffer, DeliverRecordedData())
121 .Times(kNumberOfUpdateBufferCalls - 1)
henrika29e865a2018-04-24 13:22:31 +0200122 .WillRepeatedly(Return(0));
henrika86d907c2015-09-07 16:09:50 +0200123
henrika29e865a2018-04-24 13:22:31 +0200124 FineAudioBuffer fine_buffer(&audio_device_buffer);
125 std::unique_ptr<int16_t[]> out_buffer(
126 new int16_t[kChannels * kFrameSizeSamples]);
127 std::unique_ptr<int16_t[]> in_buffer(
128 new int16_t[kChannels * kFrameSizeSamples]);
henrika86d907c2015-09-07 16:09:50 +0200129
henrika86d907c2015-09-07 16:09:50 +0200130 for (int i = 0; i < kNumberOfFrames; ++i) {
henrikabb6f7522017-05-30 02:01:30 -0700131 fine_buffer.GetPlayoutData(
henrika29e865a2018-04-24 13:22:31 +0200132 rtc::ArrayView<int16_t>(out_buffer.get(),
133 kChannels * kFrameSizeSamples),
134 0);
135 EXPECT_TRUE(
136 VerifyBuffer(out_buffer.get(), i, kChannels * kFrameSizeSamples));
137 UpdateInputBuffer(in_buffer.get(), i, kChannels * kFrameSizeSamples);
henrikabb6f7522017-05-30 02:01:30 -0700138 fine_buffer.DeliverRecordedData(
henrika29e865a2018-04-24 13:22:31 +0200139 rtc::ArrayView<const int16_t>(in_buffer.get(),
140 kChannels * kFrameSizeSamples),
141 0);
henrika86d907c2015-09-07 16:09:50 +0200142 }
143}
144
145TEST(FineBufferTest, BufferLessThan10ms) {
henrika86d907c2015-09-07 16:09:50 +0200146 const int kFrameSizeSamples = kSamplesPer10Ms - 50;
henrikabb6f7522017-05-30 02:01:30 -0700147 RunFineBufferTest(kFrameSizeSamples);
henrika86d907c2015-09-07 16:09:50 +0200148}
149
150TEST(FineBufferTest, GreaterThan10ms) {
henrika86d907c2015-09-07 16:09:50 +0200151 const int kFrameSizeSamples = kSamplesPer10Ms + 50;
henrikabb6f7522017-05-30 02:01:30 -0700152 RunFineBufferTest(kFrameSizeSamples);
henrika86d907c2015-09-07 16:09:50 +0200153}
154
155} // namespace webrtc