blob: b6ba299543fee4cf08318cee2f3bfdec11bd26b2 [file] [log] [blame]
Don Turner7dcf25d2018-07-18 15:21:07 +01001#include <oboe/Oboe.h>/*
2 * Copyright 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <gtest/gtest.h>
18#include <oboe/Oboe.h>
Don Turner67a5fe92018-08-24 12:50:00 +010019#include <android/api-level.h>
Don Turner7dcf25d2018-07-18 15:21:07 +010020
21using namespace oboe;
22
Phil Burk47063462020-01-28 10:21:07 -080023class CallbackSizeMonitor : public AudioStreamCallback {
Phil Burk8f495712020-01-27 14:30:10 -080024public:
25 DataCallbackResult onAudioReady(AudioStream *oboeStream, void *audioData, int32_t numFrames) override {
Phil Burk47063462020-01-28 10:21:07 -080026 framesPerCallback = numFrames;
Phil Burk8f495712020-01-27 14:30:10 -080027 return DataCallbackResult::Continue;
28 }
Phil Burk47063462020-01-28 10:21:07 -080029
30 // This is exposed publicly so that the number of frames per callback can be tested.
Phil Burk8f495712020-01-27 14:30:10 -080031 std::atomic<int32_t> framesPerCallback{0};
32};
Don Turner7dcf25d2018-07-18 15:21:07 +010033
34class StreamOpen : public ::testing::Test {
35
36protected:
37
Don Turner67a5fe92018-08-24 12:50:00 +010038 bool openStream(){
Don Turner7dcf25d2018-07-18 15:21:07 +010039 Result r = mBuilder.openStream(&mStream);
40 EXPECT_EQ(r, Result::OK) << "Failed to open stream " << convertToText(r);
Phil Burk8f495712020-01-27 14:30:10 -080041 EXPECT_EQ(0, openCount) << "Should start with a fresh object every time.";
42 openCount++;
Don Turner7dcf25d2018-07-18 15:21:07 +010043 return (r == Result::OK);
44 }
45
46 void closeStream(){
Don Turner67a5fe92018-08-24 12:50:00 +010047 if (mStream != nullptr){
48 Result r = mStream->close();
49 if (r != Result::OK){
50 FAIL() << "Failed to close stream. " << convertToText(r);
51 }
Don Turner7dcf25d2018-07-18 15:21:07 +010052 }
Phil Burk8f495712020-01-27 14:30:10 -080053 usleep(500 * 1000); // give previous stream time to settle
Don Turner7dcf25d2018-07-18 15:21:07 +010054 }
55
56 AudioStreamBuilder mBuilder;
57 AudioStream *mStream = nullptr;
Phil Burk8f495712020-01-27 14:30:10 -080058 int32_t openCount = 0;
Don Turner7dcf25d2018-07-18 15:21:07 +010059};
60
61TEST_F(StreamOpen, ForOpenSLESDefaultSampleRateIsUsed){
62
63 DefaultStreamValues::SampleRate = 44100;
Phil Burk8f495712020-01-27 14:30:10 -080064 DefaultStreamValues::FramesPerBurst = 192;
Don Turner67a5fe92018-08-24 12:50:00 +010065 mBuilder.setAudioApi(AudioApi::OpenSLES);
66 openStream();
Don Turnerdcb55a42018-07-19 20:21:16 +010067 ASSERT_EQ(mStream->getSampleRate(), 44100);
Don Turner7dcf25d2018-07-18 15:21:07 +010068 closeStream();
69}
70
71TEST_F(StreamOpen, ForOpenSLESDefaultFramesPerBurstIsUsed){
72
Phil Burk8f495712020-01-27 14:30:10 -080073 DefaultStreamValues::SampleRate = 48000;
74 DefaultStreamValues::FramesPerBurst = 128; // used for low latency
Don Turner67a5fe92018-08-24 12:50:00 +010075 mBuilder.setAudioApi(AudioApi::OpenSLES);
Phil Burk8f495712020-01-27 14:30:10 -080076 mBuilder.setPerformanceMode(PerformanceMode::LowLatency);
Don Turner67a5fe92018-08-24 12:50:00 +010077 openStream();
Don Turnerdcb55a42018-07-19 20:21:16 +010078 ASSERT_EQ(mStream->getFramesPerBurst(), 128);
Don Turner7dcf25d2018-07-18 15:21:07 +010079 closeStream();
80}
81
82TEST_F(StreamOpen, ForOpenSLESDefaultChannelCountIsUsed){
83
84 DefaultStreamValues::ChannelCount = 1;
Don Turner67a5fe92018-08-24 12:50:00 +010085 mBuilder.setAudioApi(AudioApi::OpenSLES);
86 openStream();
Don Turnerdcb55a42018-07-19 20:21:16 +010087 ASSERT_EQ(mStream->getChannelCount(), 1);
Don Turner7dcf25d2018-07-18 15:21:07 +010088 closeStream();
Don Turner09282b52018-07-19 20:22:12 +010089}
Phil Burk9a6262c2018-08-24 18:16:25 -070090
91TEST_F(StreamOpen, OutputForOpenSLESPerformanceModeShouldBeNone){
92 // We will not get a LowLatency stream if we request 16000 Hz.
93 mBuilder.setSampleRate(16000);
94 mBuilder.setPerformanceMode(PerformanceMode::LowLatency);
95 mBuilder.setDirection(Direction::Output);
Don Turner67a5fe92018-08-24 12:50:00 +010096 mBuilder.setAudioApi(AudioApi::OpenSLES);
Phil Burk47063462020-01-28 10:21:07 -080097 openStream();
Phil Burk9a6262c2018-08-24 18:16:25 -070098 ASSERT_EQ((int)mStream->getPerformanceMode(), (int)PerformanceMode::None);
99 closeStream();
100}
101
102TEST_F(StreamOpen, InputForOpenSLESPerformanceModeShouldBeNone){
103 // We will not get a LowLatency stream if we request 16000 Hz.
104 mBuilder.setSampleRate(16000);
105 mBuilder.setPerformanceMode(PerformanceMode::LowLatency);
106 mBuilder.setDirection(Direction::Input);
Don Turner67a5fe92018-08-24 12:50:00 +0100107 mBuilder.setAudioApi(AudioApi::OpenSLES);
Phil Burk47063462020-01-28 10:21:07 -0800108 openStream();
109 ASSERT_EQ((int)mStream->getPerformanceMode(), (int)PerformanceMode::None);
Don Turner67a5fe92018-08-24 12:50:00 +0100110 closeStream();
111}
Phil Burk8f495712020-01-27 14:30:10 -0800112
113// Make sure the callback is called with the requested FramesPerCallback
114TEST_F(StreamOpen, OpenSLESFramesPerCallback) {
Phil Burk47063462020-01-28 10:21:07 -0800115 const int kRequestedFramesPerCallback = 417;
116 CallbackSizeMonitor callback;
117
Phil Burk8f495712020-01-27 14:30:10 -0800118 DefaultStreamValues::SampleRate = 48000;
119 DefaultStreamValues::ChannelCount = 2;
120 DefaultStreamValues::FramesPerBurst = 192;
121 mBuilder.setAudioApi(AudioApi::OpenSLES);
122 mBuilder.setFramesPerCallback(kRequestedFramesPerCallback);
123 mBuilder.setCallback(&callback);
124 openStream();
125 ASSERT_EQ(mStream->requestStart(), Result::OK);
126 int timeout = 20;
127 while (callback.framesPerCallback == 0 && timeout > 0) {
Phil Burk47063462020-01-28 10:21:07 -0800128 usleep(50 * 1000);
129 timeout--;
130 }
Phil Burk8f495712020-01-27 14:30:10 -0800131 ASSERT_EQ(kRequestedFramesPerCallback, callback.framesPerCallback);
132 ASSERT_EQ(kRequestedFramesPerCallback, mStream->getFramesPerCallback());
133 ASSERT_EQ(mStream->requestStop(), Result::OK);
134 closeStream();
135}
136
137/* TODO - This is hanging!
138// Make sure the LowLatency callback has the requested FramesPerCallback.
139TEST_F(StreamOpen, AAudioFramesPerCallbackLowLatency) {
Phil Burk47063462020-01-28 10:21:07 -0800140 const int kRequestedFramesPerCallback = 192;
141 CallbackSizeMonitor callback;
Phil Burk8f495712020-01-27 14:30:10 -0800142
143 mBuilder.setAudioApi(AudioApi::AAudio);
144 mBuilder.setFramesPerCallback(kRequestedFramesPerCallback);
145 mBuilder.setCallback(&callback);
146 mBuilder.setPerformanceMode(PerformanceMode::LowLatency);
147 openStream();
148 ASSERT_EQ(kRequestedFramesPerCallback, mStream->getFramesPerCallback());
149 ASSERT_EQ(mStream->requestStart(), Result::OK);
150 int timeout = 20;
151 while (callback.framesPerCallback == 0 && timeout > 0) {
Phil Burk47063462020-01-28 10:21:07 -0800152 usleep(50 * 1000);
153 timeout--;
154 }
Phil Burk8f495712020-01-27 14:30:10 -0800155 ASSERT_EQ(kRequestedFramesPerCallback, callback.framesPerCallback);
156 ASSERT_EQ(mStream->requestStop(), Result::OK);
157 closeStream();
158}
159*/
160
161/* TODO - This is hanging!
162// Make sure the regular callback has the requested FramesPerCallback.
163TEST_F(StreamOpen, AAudioFramesPerCallbackNone) {
Phil Burk47063462020-01-28 10:21:07 -0800164 const int kRequestedFramesPerCallback = 1024;
165 CallbackSizeMonitor callback;
Phil Burk8f495712020-01-27 14:30:10 -0800166
167 mBuilder.setAudioApi(AudioApi::AAudio);
168 mBuilder.setFramesPerCallback(kRequestedFramesPerCallback);
169 mBuilder.setCallback(&callback);
170 mBuilder.setPerformanceMode(PerformanceMode::None);
171 openStream();
172 ASSERT_EQ(kRequestedFramesPerCallback, mStream->getFramesPerCallback());
173 ASSERT_EQ(mStream->setBufferSizeInFrames(mStream->getBufferCapacityInFrames()), Result::OK);
174 ASSERT_EQ(mStream->requestStart(), Result::OK);
175 int timeout = 20;
176 while (callback.framesPerCallback == 0 && timeout > 0) {
Phil Burk47063462020-01-28 10:21:07 -0800177 usleep(50 * 1000);
178 timeout--;
179 }
Phil Burk8f495712020-01-27 14:30:10 -0800180 ASSERT_EQ(kRequestedFramesPerCallback, callback.framesPerCallback);
181 ASSERT_EQ(mStream->requestStop(), Result::OK);
182 closeStream();
183}
184*/
185
Don Turner67a5fe92018-08-24 12:50:00 +0100186TEST_F(StreamOpen, RecordingFormatUnspecifiedReturnsI16BeforeMarshmallow){
187
188 if (getSdkVersion() < __ANDROID_API_M__){
189 mBuilder.setDirection(Direction::Input);
190 mBuilder.setFormat(AudioFormat::Unspecified);
191 openStream();
192 ASSERT_EQ(mStream->getFormat(), AudioFormat::I16);
193 closeStream();
194 }
195}
196
197TEST_F(StreamOpen, RecordingFormatUnspecifiedReturnsFloatOnMarshmallowAndLater){
198
199 if (getSdkVersion() >= __ANDROID_API_M__){
200 mBuilder.setDirection(Direction::Input);
201 mBuilder.setFormat(AudioFormat::Unspecified);
202 openStream();
203 ASSERT_EQ(mStream->getFormat(), AudioFormat::Float);
204 closeStream();
205 }
206}
207
208TEST_F(StreamOpen, RecordingFormatFloatReturnsErrorBeforeMarshmallow){
209
210 if (getSdkVersion() < __ANDROID_API_M__){
211 mBuilder.setDirection(Direction::Input);
212 mBuilder.setFormat(AudioFormat::Float);
213 Result r = mBuilder.openStream(&mStream);
214 ASSERT_EQ(r, Result::ErrorInvalidFormat) << convertToText(r);
215 closeStream();
216 }
217}
218
219TEST_F(StreamOpen, RecordingFormatFloatReturnsFloatOnMarshmallowAndLater){
220
221 if (getSdkVersion() >= __ANDROID_API_M__){
222 mBuilder.setDirection(Direction::Input);
223 mBuilder.setFormat(AudioFormat::Float);
224 openStream();
225 ASSERT_EQ(mStream->getFormat(), AudioFormat::Float);
226 closeStream();
227 }
228}
229
230TEST_F(StreamOpen, RecordingFormatI16ReturnsI16){
231
232 mBuilder.setDirection(Direction::Input);
233 mBuilder.setFormat(AudioFormat::I16);
234 openStream();
235 ASSERT_EQ(mStream->getFormat(), AudioFormat::I16);
236 closeStream();
237}
238
239TEST_F(StreamOpen, PlaybackFormatUnspecifiedReturnsI16BeforeLollipop){
240
241 if (getSdkVersion() < __ANDROID_API_L__){
242 mBuilder.setDirection(Direction::Output);
243 mBuilder.setFormat(AudioFormat::Unspecified);
244 openStream();
245 ASSERT_EQ(mStream->getFormat(), AudioFormat::I16);
246 closeStream();
247 }
248}
249
250TEST_F(StreamOpen, PlaybackFormatUnspecifiedReturnsFloatOnLollipopAndLater){
251
252 if (getSdkVersion() >= __ANDROID_API_L__){
253 mBuilder.setDirection(Direction::Output);
254 mBuilder.setFormat(AudioFormat::Unspecified);
255 openStream();
256 ASSERT_EQ(mStream->getFormat(), AudioFormat::Float);
257 closeStream();
258 }
259}
260
261TEST_F(StreamOpen, PlaybackFormatFloatReturnsErrorBeforeLollipop){
262
263 if (getSdkVersion() < __ANDROID_API_L__){
264 mBuilder.setDirection(Direction::Output);
265 mBuilder.setFormat(AudioFormat::Float);
266 Result r = mBuilder.openStream(&mStream);
267 ASSERT_EQ(r, Result::ErrorInvalidFormat);
268 closeStream();
269 }
270}
271
272TEST_F(StreamOpen, PlaybackFormatFloatReturnsFloatOnLollipopAndLater){
273
274 if (getSdkVersion() >= __ANDROID_API_L__){
275 mBuilder.setDirection(Direction::Output);
276 mBuilder.setFormat(AudioFormat::Float);
277 openStream();
278 ASSERT_EQ(mStream->getFormat(), AudioFormat::Float);
279 closeStream();
280 }
281}
282
283TEST_F(StreamOpen, PlaybackFormatI16ReturnsI16){
284
285 mBuilder.setDirection(Direction::Output);
286 mBuilder.setFormat(AudioFormat::I16);
287 openStream();
288 ASSERT_EQ(mStream->getFormat(), AudioFormat::I16);
Phil Burk9a6262c2018-08-24 18:16:25 -0700289 closeStream();
290}
Don Turner8c369cf2019-01-07 18:02:24 +0000291
292TEST_F(StreamOpen, LowLatencyStreamHasBufferSizeOfTwoBursts){
293
294 if (mBuilder.isAAudioRecommended()){
295 mBuilder.setDirection(Direction::Output);
296 mBuilder.setPerformanceMode(PerformanceMode::LowLatency);
297 openStream();
298 ASSERT_EQ(mStream->getBufferSizeInFrames(), mStream->getFramesPerBurst() * 2);
299 closeStream();
300 }
301}