blob: 2199067098f551b1fc4e864877b62fdc2afba055 [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>
Jonas Olssona4d87372019-07-05 19:08:33 +020014
henrika86d907c2015-09-07 16:09:50 +020015#include <memory>
16
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "api/array_view.h"
Danil Chapovalov1c41be62019-04-01 09:16:12 +020018#include "api/task_queue/default_task_queue_factory.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "modules/audio_device/mock_audio_device_buffer.h"
20#include "test/gmock.h"
21#include "test/gtest.h"
henrika86d907c2015-09-07 16:09:50 +020022
23using ::testing::_;
24using ::testing::AtLeast;
25using ::testing::InSequence;
26using ::testing::Return;
27
28namespace webrtc {
29
henrikabb6f7522017-05-30 02:01:30 -070030const int kSampleRate = 44100;
henrika29e865a2018-04-24 13:22:31 +020031const int kChannels = 2;
henrikabb6f7522017-05-30 02:01:30 -070032const int kSamplesPer10Ms = kSampleRate * 10 / 1000;
33
henrika86d907c2015-09-07 16:09:50 +020034// The fake audio data is 0,1,..SCHAR_MAX-1,0,1,... This is to make it easy
35// to detect errors. This function verifies that the buffers contain such data.
36// E.g. if there are two buffers of size 3, buffer 1 would contain 0,1,2 and
37// buffer 2 would contain 3,4,5. Note that SCHAR_MAX is 127 so wrap-around
38// will happen.
39// |buffer| is the audio buffer to verify.
henrika8d7393b2018-04-19 13:40:15 +020040bool VerifyBuffer(const int16_t* buffer, int buffer_number, int size) {
henrika86d907c2015-09-07 16:09:50 +020041 int start_value = (buffer_number * size) % SCHAR_MAX;
42 for (int i = 0; i < size; ++i) {
43 if (buffer[i] != (i + start_value) % SCHAR_MAX) {
44 return false;
45 }
46 }
47 return true;
48}
49
50// This function replaces the real AudioDeviceBuffer::GetPlayoutData when it's
51// called (which is done implicitly when calling GetBufferData). It writes the
52// sequence 0,1,..SCHAR_MAX-1,0,1,... to the buffer. Note that this is likely a
53// buffer of different size than the one VerifyBuffer verifies.
54// |iteration| is the number of calls made to UpdateBuffer prior to this call.
55// |samples_per_10_ms| is the number of samples that should be written to the
56// buffer (|arg0|).
57ACTION_P2(UpdateBuffer, iteration, samples_per_10_ms) {
henrika8d7393b2018-04-19 13:40:15 +020058 int16_t* buffer = static_cast<int16_t*>(arg0);
59 int start_value = (iteration * samples_per_10_ms) % SCHAR_MAX;
60 for (int i = 0; i < samples_per_10_ms; ++i) {
henrika86d907c2015-09-07 16:09:50 +020061 buffer[i] = (i + start_value) % SCHAR_MAX;
62 }
henrika29e865a2018-04-24 13:22:31 +020063 // Should return samples per channel.
64 return samples_per_10_ms / kChannels;
henrika86d907c2015-09-07 16:09:50 +020065}
66
67// Writes a periodic ramp pattern to the supplied |buffer|. See UpdateBuffer()
68// for details.
henrika8d7393b2018-04-19 13:40:15 +020069void UpdateInputBuffer(int16_t* buffer, int iteration, int size) {
henrika86d907c2015-09-07 16:09:50 +020070 int start_value = (iteration * size) % SCHAR_MAX;
71 for (int i = 0; i < size; ++i) {
72 buffer[i] = (i + start_value) % SCHAR_MAX;
73 }
74}
75
76// Action macro which verifies that the recorded 10ms chunk of audio data
77// (in |arg0|) contains the correct reference values even if they have been
78// supplied using a buffer size that is smaller or larger than 10ms.
79// See VerifyBuffer() for details.
80ACTION_P2(VerifyInputBuffer, iteration, samples_per_10_ms) {
henrika8d7393b2018-04-19 13:40:15 +020081 const int16_t* buffer = static_cast<const int16_t*>(arg0);
82 int start_value = (iteration * samples_per_10_ms) % SCHAR_MAX;
83 for (int i = 0; i < samples_per_10_ms; ++i) {
henrika86d907c2015-09-07 16:09:50 +020084 EXPECT_EQ(buffer[i], (i + start_value) % SCHAR_MAX);
85 }
86 return 0;
87}
88
henrikabb6f7522017-05-30 02:01:30 -070089void RunFineBufferTest(int frame_size_in_samples) {
henrika8d7393b2018-04-19 13:40:15 +020090 const int kFrameSizeSamples = frame_size_in_samples;
henrika86d907c2015-09-07 16:09:50 +020091 const int kNumberOfFrames = 5;
92 // Ceiling of integer division: 1 + ((x - 1) / y)
93 const int kNumberOfUpdateBufferCalls =
94 1 + ((kNumberOfFrames * frame_size_in_samples - 1) / kSamplesPer10Ms);
95
Danil Chapovalov1c41be62019-04-01 09:16:12 +020096 auto task_queue_factory = CreateDefaultTaskQueueFactory();
97 MockAudioDeviceBuffer audio_device_buffer(task_queue_factory.get());
henrika29e865a2018-04-24 13:22:31 +020098 audio_device_buffer.SetPlayoutSampleRate(kSampleRate);
99 audio_device_buffer.SetPlayoutChannels(kChannels);
100 audio_device_buffer.SetRecordingSampleRate(kSampleRate);
101 audio_device_buffer.SetRecordingChannels(kChannels);
102
henrika86d907c2015-09-07 16:09:50 +0200103 EXPECT_CALL(audio_device_buffer, RequestPlayoutData(_))
104 .WillRepeatedly(Return(kSamplesPer10Ms));
105 {
106 InSequence s;
107 for (int i = 0; i < kNumberOfUpdateBufferCalls; ++i) {
108 EXPECT_CALL(audio_device_buffer, GetPlayoutData(_))
henrika29e865a2018-04-24 13:22:31 +0200109 .WillOnce(UpdateBuffer(i, kChannels * kSamplesPer10Ms))
henrika86d907c2015-09-07 16:09:50 +0200110 .RetiresOnSaturation();
111 }
112 }
113 {
114 InSequence s;
115 for (int j = 0; j < kNumberOfUpdateBufferCalls - 1; ++j) {
116 EXPECT_CALL(audio_device_buffer, SetRecordedBuffer(_, kSamplesPer10Ms))
henrika29e865a2018-04-24 13:22:31 +0200117 .WillOnce(VerifyInputBuffer(j, kChannels * kSamplesPer10Ms))
henrika86d907c2015-09-07 16:09:50 +0200118 .RetiresOnSaturation();
119 }
120 }
Fredrik Solenberg1a50cd52018-01-16 09:19:38 +0100121 EXPECT_CALL(audio_device_buffer, SetVQEData(_, _))
henrika86d907c2015-09-07 16:09:50 +0200122 .Times(kNumberOfUpdateBufferCalls - 1);
123 EXPECT_CALL(audio_device_buffer, DeliverRecordedData())
124 .Times(kNumberOfUpdateBufferCalls - 1)
henrika29e865a2018-04-24 13:22:31 +0200125 .WillRepeatedly(Return(0));
henrika86d907c2015-09-07 16:09:50 +0200126
henrika29e865a2018-04-24 13:22:31 +0200127 FineAudioBuffer fine_buffer(&audio_device_buffer);
128 std::unique_ptr<int16_t[]> out_buffer(
129 new int16_t[kChannels * kFrameSizeSamples]);
130 std::unique_ptr<int16_t[]> in_buffer(
131 new int16_t[kChannels * kFrameSizeSamples]);
henrika86d907c2015-09-07 16:09:50 +0200132
henrika86d907c2015-09-07 16:09:50 +0200133 for (int i = 0; i < kNumberOfFrames; ++i) {
henrikabb6f7522017-05-30 02:01:30 -0700134 fine_buffer.GetPlayoutData(
henrika29e865a2018-04-24 13:22:31 +0200135 rtc::ArrayView<int16_t>(out_buffer.get(),
136 kChannels * kFrameSizeSamples),
137 0);
138 EXPECT_TRUE(
139 VerifyBuffer(out_buffer.get(), i, kChannels * kFrameSizeSamples));
140 UpdateInputBuffer(in_buffer.get(), i, kChannels * kFrameSizeSamples);
henrikabb6f7522017-05-30 02:01:30 -0700141 fine_buffer.DeliverRecordedData(
henrika29e865a2018-04-24 13:22:31 +0200142 rtc::ArrayView<const int16_t>(in_buffer.get(),
143 kChannels * kFrameSizeSamples),
144 0);
henrika86d907c2015-09-07 16:09:50 +0200145 }
146}
147
148TEST(FineBufferTest, BufferLessThan10ms) {
henrika86d907c2015-09-07 16:09:50 +0200149 const int kFrameSizeSamples = kSamplesPer10Ms - 50;
henrikabb6f7522017-05-30 02:01:30 -0700150 RunFineBufferTest(kFrameSizeSamples);
henrika86d907c2015-09-07 16:09:50 +0200151}
152
153TEST(FineBufferTest, GreaterThan10ms) {
henrika86d907c2015-09-07 16:09:50 +0200154 const int kFrameSizeSamples = kSamplesPer10Ms + 50;
henrikabb6f7522017-05-30 02:01:30 -0700155 RunFineBufferTest(kFrameSizeSamples);
henrika86d907c2015-09-07 16:09:50 +0200156}
157
158} // namespace webrtc