blob: fa8ba646bce1f9cf12f9e014b8ffa13930afd806 [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"
Danil Chapovalov1c41be62019-04-01 09:16:12 +020017#include "api/task_queue/default_task_queue_factory.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "modules/audio_device/mock_audio_device_buffer.h"
19#include "test/gmock.h"
20#include "test/gtest.h"
henrika86d907c2015-09-07 16:09:50 +020021
22using ::testing::_;
23using ::testing::AtLeast;
24using ::testing::InSequence;
25using ::testing::Return;
26
27namespace webrtc {
28
henrikabb6f7522017-05-30 02:01:30 -070029const int kSampleRate = 44100;
henrika29e865a2018-04-24 13:22:31 +020030const int kChannels = 2;
henrikabb6f7522017-05-30 02:01:30 -070031const int kSamplesPer10Ms = kSampleRate * 10 / 1000;
32
henrika86d907c2015-09-07 16:09:50 +020033// The fake audio data is 0,1,..SCHAR_MAX-1,0,1,... This is to make it easy
34// to detect errors. This function verifies that the buffers contain such data.
35// E.g. if there are two buffers of size 3, buffer 1 would contain 0,1,2 and
36// buffer 2 would contain 3,4,5. Note that SCHAR_MAX is 127 so wrap-around
37// will happen.
38// |buffer| is the audio buffer to verify.
henrika8d7393b2018-04-19 13:40:15 +020039bool VerifyBuffer(const int16_t* buffer, int buffer_number, int size) {
henrika86d907c2015-09-07 16:09:50 +020040 int start_value = (buffer_number * size) % SCHAR_MAX;
41 for (int i = 0; i < size; ++i) {
42 if (buffer[i] != (i + start_value) % SCHAR_MAX) {
43 return false;
44 }
45 }
46 return true;
47}
48
49// This function replaces the real AudioDeviceBuffer::GetPlayoutData when it's
50// called (which is done implicitly when calling GetBufferData). It writes the
51// sequence 0,1,..SCHAR_MAX-1,0,1,... to the buffer. Note that this is likely a
52// buffer of different size than the one VerifyBuffer verifies.
53// |iteration| is the number of calls made to UpdateBuffer prior to this call.
54// |samples_per_10_ms| is the number of samples that should be written to the
55// buffer (|arg0|).
56ACTION_P2(UpdateBuffer, iteration, samples_per_10_ms) {
henrika8d7393b2018-04-19 13:40:15 +020057 int16_t* buffer = static_cast<int16_t*>(arg0);
58 int start_value = (iteration * samples_per_10_ms) % SCHAR_MAX;
59 for (int i = 0; i < samples_per_10_ms; ++i) {
henrika86d907c2015-09-07 16:09:50 +020060 buffer[i] = (i + start_value) % SCHAR_MAX;
61 }
henrika29e865a2018-04-24 13:22:31 +020062 // Should return samples per channel.
63 return samples_per_10_ms / kChannels;
henrika86d907c2015-09-07 16:09:50 +020064}
65
66// Writes a periodic ramp pattern to the supplied |buffer|. See UpdateBuffer()
67// for details.
henrika8d7393b2018-04-19 13:40:15 +020068void UpdateInputBuffer(int16_t* buffer, int iteration, int size) {
henrika86d907c2015-09-07 16:09:50 +020069 int start_value = (iteration * size) % SCHAR_MAX;
70 for (int i = 0; i < size; ++i) {
71 buffer[i] = (i + start_value) % SCHAR_MAX;
72 }
73}
74
75// Action macro which verifies that the recorded 10ms chunk of audio data
76// (in |arg0|) contains the correct reference values even if they have been
77// supplied using a buffer size that is smaller or larger than 10ms.
78// See VerifyBuffer() for details.
79ACTION_P2(VerifyInputBuffer, iteration, samples_per_10_ms) {
henrika8d7393b2018-04-19 13:40:15 +020080 const int16_t* buffer = static_cast<const int16_t*>(arg0);
81 int start_value = (iteration * samples_per_10_ms) % SCHAR_MAX;
82 for (int i = 0; i < samples_per_10_ms; ++i) {
henrika86d907c2015-09-07 16:09:50 +020083 EXPECT_EQ(buffer[i], (i + start_value) % SCHAR_MAX);
84 }
85 return 0;
86}
87
henrikabb6f7522017-05-30 02:01:30 -070088void RunFineBufferTest(int frame_size_in_samples) {
henrika8d7393b2018-04-19 13:40:15 +020089 const int kFrameSizeSamples = frame_size_in_samples;
henrika86d907c2015-09-07 16:09:50 +020090 const int kNumberOfFrames = 5;
91 // Ceiling of integer division: 1 + ((x - 1) / y)
92 const int kNumberOfUpdateBufferCalls =
93 1 + ((kNumberOfFrames * frame_size_in_samples - 1) / kSamplesPer10Ms);
94
Danil Chapovalov1c41be62019-04-01 09:16:12 +020095 auto task_queue_factory = CreateDefaultTaskQueueFactory();
96 MockAudioDeviceBuffer audio_device_buffer(task_queue_factory.get());
henrika29e865a2018-04-24 13:22:31 +020097 audio_device_buffer.SetPlayoutSampleRate(kSampleRate);
98 audio_device_buffer.SetPlayoutChannels(kChannels);
99 audio_device_buffer.SetRecordingSampleRate(kSampleRate);
100 audio_device_buffer.SetRecordingChannels(kChannels);
101
henrika86d907c2015-09-07 16:09:50 +0200102 EXPECT_CALL(audio_device_buffer, RequestPlayoutData(_))
103 .WillRepeatedly(Return(kSamplesPer10Ms));
104 {
105 InSequence s;
106 for (int i = 0; i < kNumberOfUpdateBufferCalls; ++i) {
107 EXPECT_CALL(audio_device_buffer, GetPlayoutData(_))
henrika29e865a2018-04-24 13:22:31 +0200108 .WillOnce(UpdateBuffer(i, kChannels * kSamplesPer10Ms))
henrika86d907c2015-09-07 16:09:50 +0200109 .RetiresOnSaturation();
110 }
111 }
112 {
113 InSequence s;
114 for (int j = 0; j < kNumberOfUpdateBufferCalls - 1; ++j) {
115 EXPECT_CALL(audio_device_buffer, SetRecordedBuffer(_, kSamplesPer10Ms))
henrika29e865a2018-04-24 13:22:31 +0200116 .WillOnce(VerifyInputBuffer(j, kChannels * kSamplesPer10Ms))
henrika86d907c2015-09-07 16:09:50 +0200117 .RetiresOnSaturation();
118 }
119 }
Fredrik Solenberg1a50cd52018-01-16 09:19:38 +0100120 EXPECT_CALL(audio_device_buffer, SetVQEData(_, _))
henrika86d907c2015-09-07 16:09:50 +0200121 .Times(kNumberOfUpdateBufferCalls - 1);
122 EXPECT_CALL(audio_device_buffer, DeliverRecordedData())
123 .Times(kNumberOfUpdateBufferCalls - 1)
henrika29e865a2018-04-24 13:22:31 +0200124 .WillRepeatedly(Return(0));
henrika86d907c2015-09-07 16:09:50 +0200125
henrika29e865a2018-04-24 13:22:31 +0200126 FineAudioBuffer fine_buffer(&audio_device_buffer);
127 std::unique_ptr<int16_t[]> out_buffer(
128 new int16_t[kChannels * kFrameSizeSamples]);
129 std::unique_ptr<int16_t[]> in_buffer(
130 new int16_t[kChannels * kFrameSizeSamples]);
henrika86d907c2015-09-07 16:09:50 +0200131
henrika86d907c2015-09-07 16:09:50 +0200132 for (int i = 0; i < kNumberOfFrames; ++i) {
henrikabb6f7522017-05-30 02:01:30 -0700133 fine_buffer.GetPlayoutData(
henrika29e865a2018-04-24 13:22:31 +0200134 rtc::ArrayView<int16_t>(out_buffer.get(),
135 kChannels * kFrameSizeSamples),
136 0);
137 EXPECT_TRUE(
138 VerifyBuffer(out_buffer.get(), i, kChannels * kFrameSizeSamples));
139 UpdateInputBuffer(in_buffer.get(), i, kChannels * kFrameSizeSamples);
henrikabb6f7522017-05-30 02:01:30 -0700140 fine_buffer.DeliverRecordedData(
henrika29e865a2018-04-24 13:22:31 +0200141 rtc::ArrayView<const int16_t>(in_buffer.get(),
142 kChannels * kFrameSizeSamples),
143 0);
henrika86d907c2015-09-07 16:09:50 +0200144 }
145}
146
147TEST(FineBufferTest, BufferLessThan10ms) {
henrika86d907c2015-09-07 16:09:50 +0200148 const int kFrameSizeSamples = kSamplesPer10Ms - 50;
henrikabb6f7522017-05-30 02:01:30 -0700149 RunFineBufferTest(kFrameSizeSamples);
henrika86d907c2015-09-07 16:09:50 +0200150}
151
152TEST(FineBufferTest, GreaterThan10ms) {
henrika86d907c2015-09-07 16:09:50 +0200153 const int kFrameSizeSamples = kSamplesPer10Ms + 50;
henrikabb6f7522017-05-30 02:01:30 -0700154 RunFineBufferTest(kFrameSizeSamples);
henrika86d907c2015-09-07 16:09:50 +0200155}
156
157} // namespace webrtc