fine_audio_buffer_unittest.cc (5788B)
1 /* 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 11 #include "modules/audio_device/fine_audio_buffer.h" 12 13 #include <climits> 14 #include <cstdint> 15 #include <memory> 16 17 #include "api/array_view.h" 18 #include "modules/audio_device/mock_audio_device_buffer.h" 19 #include "test/create_test_environment.h" 20 #include "test/gmock.h" 21 #include "test/gtest.h" 22 23 using ::testing::_; 24 using ::testing::AtLeast; 25 using ::testing::InSequence; 26 using ::testing::Return; 27 28 namespace webrtc { 29 30 constexpr int kSampleRate = 44100; 31 constexpr int kChannels = 2; 32 constexpr int kSamplesPer10Ms = kSampleRate * 10 / 1000; 33 34 // 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. 40 bool VerifyBuffer(const int16_t* buffer, int buffer_number, int size) { 41 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`). 57 ACTION_P2(UpdateBuffer, iteration, samples_per_10_ms) { 58 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) { 61 buffer[i] = (i + start_value) % SCHAR_MAX; 62 } 63 // Should return samples per channel. 64 return samples_per_10_ms / kChannels; 65 } 66 67 // Writes a periodic ramp pattern to the supplied `buffer`. See UpdateBuffer() 68 // for details. 69 void UpdateInputBuffer(int16_t* buffer, int iteration, int size) { 70 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. 80 ACTION_P2(VerifyInputBuffer, iteration, samples_per_10_ms) { 81 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) { 84 EXPECT_EQ(buffer[i], (i + start_value) % SCHAR_MAX); 85 } 86 return 0; 87 } 88 89 void RunFineBufferTest(int frame_size_in_samples) { 90 const int kFrameSizeSamples = frame_size_in_samples; 91 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 96 MockAudioDeviceBuffer audio_device_buffer(CreateTestEnvironment()); 97 audio_device_buffer.SetPlayoutSampleRate(kSampleRate); 98 audio_device_buffer.SetPlayoutChannels(kChannels); 99 audio_device_buffer.SetRecordingSampleRate(kSampleRate); 100 audio_device_buffer.SetRecordingChannels(kChannels); 101 102 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(_)) 108 .WillOnce(UpdateBuffer(i, kChannels * kSamplesPer10Ms)) 109 .RetiresOnSaturation(); 110 } 111 } 112 { 113 InSequence s; 114 for (int j = 0; j < kNumberOfUpdateBufferCalls - 1; ++j) { 115 EXPECT_CALL(audio_device_buffer, SetRecordedBuffer(_, kSamplesPer10Ms, _)) 116 .WillOnce(VerifyInputBuffer(j, kChannels * kSamplesPer10Ms)) 117 .RetiresOnSaturation(); 118 } 119 } 120 EXPECT_CALL(audio_device_buffer, SetVQEData(_, _)) 121 .Times(kNumberOfUpdateBufferCalls - 1); 122 EXPECT_CALL(audio_device_buffer, DeliverRecordedData()) 123 .Times(kNumberOfUpdateBufferCalls - 1) 124 .WillRepeatedly(Return(0)); 125 126 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]); 131 132 for (int i = 0; i < kNumberOfFrames; ++i) { 133 fine_buffer.GetPlayoutData( 134 ArrayView<int16_t>(out_buffer.get(), kChannels * kFrameSizeSamples), 0); 135 EXPECT_TRUE( 136 VerifyBuffer(out_buffer.get(), i, kChannels * kFrameSizeSamples)); 137 UpdateInputBuffer(in_buffer.get(), i, kChannels * kFrameSizeSamples); 138 fine_buffer.DeliverRecordedData( 139 ArrayView<const int16_t>(in_buffer.get(), 140 kChannels * kFrameSizeSamples), 141 0); 142 } 143 } 144 145 TEST(FineBufferTest, BufferLessThan10ms) { 146 const int kFrameSizeSamples = kSamplesPer10Ms - 50; 147 RunFineBufferTest(kFrameSizeSamples); 148 } 149 150 TEST(FineBufferTest, GreaterThan10ms) { 151 const int kFrameSizeSamples = kSamplesPer10Ms + 50; 152 RunFineBufferTest(kFrameSizeSamples); 153 } 154 155 } // namespace webrtc