blob: eb6925aa754ee68a0a3ffbafc9c74cf31e7e27be [file] [log] [blame]
Phil Burk44795232017-06-30 16:27:38 -07001/*
2 * Copyright (C) 2017 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#ifndef AAUDIO_EXAMPLE_ARGS_PARSER_H
18#define AAUDIO_EXAMPLE_ARGS_PARSER_H
19
Phil Burk67ed9da2017-09-06 16:26:52 -070020#define MAX_CHANNELS 8
21
Phil Burk4e98efa2018-02-05 18:41:55 -080022//#include <cctype>
23#include <dlfcn.h>
Phil Burk44795232017-06-30 16:27:38 -070024#include <unistd.h>
25#include <stdio.h>
26#include <stdlib.h>
27
28#include <aaudio/AAudio.h>
29#include <aaudio/AAudioTesting.h>
Phil Burka5222e22017-07-28 13:31:14 -070030
31#include "AAudioExampleUtils.h"
Phil Burk44795232017-06-30 16:27:38 -070032
Phil Burk4e98efa2018-02-05 18:41:55 -080033
34static void (*s_setUsage)(AAudioStreamBuilder* builder, aaudio_usage_t usage) = nullptr;
35static void (*s_setContentType)(AAudioStreamBuilder* builder,
36 aaudio_content_type_t contentType) = nullptr;
37static void (*s_setInputPreset)(AAudioStreamBuilder* builder,
38 aaudio_input_preset_t inputPreset) = nullptr;
39
40static bool s_loadAttempted = false;
41static aaudio_usage_t (*s_getUsage)(AAudioStream *stream) = nullptr;
42static aaudio_content_type_t (*s_getContentType)(AAudioStream *stream) = nullptr;
43static aaudio_input_preset_t (*s_getInputPreset)(AAudioStream *stream) = nullptr;
44
45// Link to test functions in shared library.
46static void loadFutureFunctions() {
47 if (s_loadAttempted) return; // only try once
48 s_loadAttempted = true;
49
50 void *handle = dlopen("libaaudio.so", RTLD_NOW);
51 if (handle != nullptr) {
52 s_setUsage = (void (*)(AAudioStreamBuilder *, aaudio_usage_t))
53 dlsym(handle, "AAudioStreamBuilder_setUsage");
54 if (s_setUsage == nullptr) goto error;
55
56 s_setContentType = (void (*)(AAudioStreamBuilder *, aaudio_content_type_t))
57 dlsym(handle, "AAudioStreamBuilder_setContentType");
58 if (s_setContentType == nullptr) goto error;
59
60 s_setInputPreset = (void (*)(AAudioStreamBuilder *, aaudio_input_preset_t))
61 dlsym(handle, "AAudioStreamBuilder_setInputPreset");
62 if (s_setInputPreset == nullptr) goto error;
63
64 s_getUsage = (aaudio_usage_t (*)(AAudioStream *))
65 dlsym(handle, "AAudioStream_getUsage");
66 if (s_getUsage == nullptr) goto error;
67
68 s_getContentType = (aaudio_content_type_t (*)(AAudioStream *))
69 dlsym(handle, "AAudioStream_getContentType");
70 if (s_getContentType == nullptr) goto error;
71
72 s_getInputPreset = (aaudio_input_preset_t (*)(AAudioStream *))
73 dlsym(handle, "AAudioStream_getInputPreset");
74 if (s_getInputPreset == nullptr) goto error;
75 }
76 return;
77
78error:
79 // prevent any calls to these functions
80 s_setUsage = nullptr;
81 s_setContentType = nullptr;
82 s_setInputPreset = nullptr;
83 s_getUsage = nullptr;
84 s_getContentType = nullptr;
85 s_getInputPreset = nullptr;
86 dlclose(handle);
87 return;
88}
89
Phil Burk44795232017-06-30 16:27:38 -070090// TODO use this as a base class within AAudio
91class AAudioParameters {
92public:
93
94 /**
95 * This is also known as samplesPerFrame.
96 */
97 int32_t getChannelCount() const {
98 return mChannelCount;
99 }
100
101 void setChannelCount(int32_t channelCount) {
Phil Burk67ed9da2017-09-06 16:26:52 -0700102 if (channelCount > MAX_CHANNELS) {
103 printf("Sorry, MAX of %d channels!\n", MAX_CHANNELS);
104 channelCount = MAX_CHANNELS;
105 }
Phil Burk44795232017-06-30 16:27:38 -0700106 mChannelCount = channelCount;
107 }
108
109 int32_t getSampleRate() const {
110 return mSampleRate;
111 }
112
113 void setSampleRate(int32_t sampleRate) {
114 mSampleRate = sampleRate;
115 }
116
117 aaudio_format_t getFormat() const {
118 return mFormat;
119 }
120
121 void setFormat(aaudio_format_t format) {
122 mFormat = format;
123 }
124
125 aaudio_sharing_mode_t getSharingMode() const {
126 return mSharingMode;
127 }
128
129 void setSharingMode(aaudio_sharing_mode_t sharingMode) {
130 mSharingMode = sharingMode;
131 }
132
133 int32_t getBufferCapacity() const {
134 return mBufferCapacity;
135 }
136
137 void setBufferCapacity(int32_t frames) {
138 mBufferCapacity = frames;
139 }
140
141 int32_t getPerformanceMode() const {
142 return mPerformanceMode;
143 }
144
145 void setPerformanceMode(aaudio_performance_mode_t performanceMode) {
146 mPerformanceMode = performanceMode;
147 }
148
Phil Burk6d6f3f62018-01-12 17:27:54 -0800149 aaudio_usage_t getUsage() const {
150 return mUsage;
151 }
152
153 void setUsage(aaudio_usage_t usage) {
154 mUsage = usage;
155 }
156
157 aaudio_content_type_t getContentType() const {
158 return mContentType;
159 }
160
161 void setContentType(aaudio_content_type_t contentType) {
162 mContentType = contentType;
163 }
164
165 aaudio_input_preset_t getInputPreset() const {
166 return mInputPreset;
167 }
168
169 void setInputPreset(aaudio_input_preset_t inputPreset) {
170 mInputPreset = inputPreset;
171 }
172
Phil Burk44795232017-06-30 16:27:38 -0700173 int32_t getDeviceId() const {
174 return mDeviceId;
175 }
176
177 void setDeviceId(int32_t deviceId) {
178 mDeviceId = deviceId;
179 }
180
181 int32_t getNumberOfBursts() const {
182 return mNumberOfBursts;
183 }
184
185 void setNumberOfBursts(int32_t numBursts) {
186 mNumberOfBursts = numBursts;
187 }
188
189 /**
190 * Apply these parameters to a stream builder.
191 * @param builder
192 */
193 void applyParameters(AAudioStreamBuilder *builder) const {
194 AAudioStreamBuilder_setChannelCount(builder, mChannelCount);
195 AAudioStreamBuilder_setFormat(builder, mFormat);
196 AAudioStreamBuilder_setSampleRate(builder, mSampleRate);
197 AAudioStreamBuilder_setBufferCapacityInFrames(builder, mBufferCapacity);
198 AAudioStreamBuilder_setDeviceId(builder, mDeviceId);
199 AAudioStreamBuilder_setSharingMode(builder, mSharingMode);
200 AAudioStreamBuilder_setPerformanceMode(builder, mPerformanceMode);
Phil Burk4e98efa2018-02-05 18:41:55 -0800201
202 // Call P functions if supported.
203 loadFutureFunctions();
204 if (s_setUsage != nullptr) {
205 s_setUsage(builder, mUsage);
206 } else if (mUsage != AAUDIO_UNSPECIFIED){
207 printf("WARNING: setUsage not supported");
208 }
209 if (s_setContentType != nullptr) {
210 s_setContentType(builder, mContentType);
211 } else if (mUsage != AAUDIO_UNSPECIFIED){
212 printf("WARNING: setContentType not supported");
213 }
214 if (s_setInputPreset != nullptr) {
215 s_setInputPreset(builder, mInputPreset);
216 } else if (mUsage != AAUDIO_UNSPECIFIED){
217 printf("WARNING: setInputPreset not supported");
218 }
Phil Burk44795232017-06-30 16:27:38 -0700219 }
220
221private:
222 int32_t mChannelCount = AAUDIO_UNSPECIFIED;
223 aaudio_format_t mFormat = AAUDIO_FORMAT_UNSPECIFIED;
224 int32_t mSampleRate = AAUDIO_UNSPECIFIED;
225
226 int32_t mBufferCapacity = AAUDIO_UNSPECIFIED;
227 int32_t mDeviceId = AAUDIO_UNSPECIFIED;
228 aaudio_sharing_mode_t mSharingMode = AAUDIO_SHARING_MODE_SHARED;
229 aaudio_performance_mode_t mPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE;
230
Phil Burk6d6f3f62018-01-12 17:27:54 -0800231 aaudio_usage_t mUsage = AAUDIO_UNSPECIFIED;
232 aaudio_content_type_t mContentType = AAUDIO_UNSPECIFIED;
233 aaudio_input_preset_t mInputPreset = AAUDIO_UNSPECIFIED;
234
Phil Burkfcf9efd2017-07-14 08:25:08 -0700235 int32_t mNumberOfBursts = AAUDIO_UNSPECIFIED;
Phil Burk44795232017-06-30 16:27:38 -0700236};
237
238class AAudioArgsParser : public AAudioParameters {
239public:
240 AAudioArgsParser() = default;
241 ~AAudioArgsParser() = default;
242
243 enum {
244 DEFAULT_DURATION_SECONDS = 5
245 };
246
247 /**
248 * @param arg
249 * @return true if the argument was not handled
250 */
251 bool parseArg(const char *arg) {
252 bool unrecognized = false;
253 if (arg[0] == '-') {
254 char option = arg[1];
255 switch (option) {
256 case 'b':
257 setBufferCapacity(atoi(&arg[2]));
258 break;
259 case 'c':
260 setChannelCount(atoi(&arg[2]));
261 break;
262 case 'd':
Phil Burke008d022017-08-23 12:56:15 -0700263 setDeviceId(atoi(&arg[2]));
264 break;
Phil Burk6d6f3f62018-01-12 17:27:54 -0800265 case 'i':
266 setInputPreset(atoi(&arg[2]));
Phil Burk44795232017-06-30 16:27:38 -0700267 break;
Phil Burkfcf9efd2017-07-14 08:25:08 -0700268 case 'm': {
269 aaudio_policy_t policy = AAUDIO_POLICY_AUTO;
270 if (strlen(arg) > 2) {
271 policy = atoi(&arg[2]);
272 }
273 AAudio_setMMapPolicy(policy);
274 } break;
Phil Burk44795232017-06-30 16:27:38 -0700275 case 'n':
276 setNumberOfBursts(atoi(&arg[2]));
277 break;
278 case 'p':
279 setPerformanceMode(parsePerformanceMode(arg[2]));
280 break;
281 case 'r':
282 setSampleRate(atoi(&arg[2]));
283 break;
Phil Burk6d6f3f62018-01-12 17:27:54 -0800284 case 's':
285 mDurationSeconds = atoi(&arg[2]);
286 break;
287 case 'u':
288 setUsage(atoi(&arg[2]));
289 break;
Phil Burk44795232017-06-30 16:27:38 -0700290 case 'x':
291 setSharingMode(AAUDIO_SHARING_MODE_EXCLUSIVE);
292 break;
Phil Burk6d6f3f62018-01-12 17:27:54 -0800293 case 'y':
294 setContentType(atoi(&arg[2]));
295 break;
Phil Burk44795232017-06-30 16:27:38 -0700296 default:
297 unrecognized = true;
298 break;
299 }
300 }
301 return unrecognized;
302 }
303
304 /**
305 *
306 * @param argc
307 * @param argv
308 * @return true if an unrecognized argument was passed
309 */
310 bool parseArgs(int argc, const char **argv) {
311 for (int i = 1; i < argc; i++) {
312 const char *arg = argv[i];
313 if (parseArg(arg)) {
314 usage();
315 return true;
316 }
317
318 }
319 return false;
320 }
321
322 static void usage() {
Phil Burk6d6f3f62018-01-12 17:27:54 -0800323 printf("-c{channels} -d{deviceId} -m{mmapPolicy} -n{burstsPerBuffer} -p{perfMode}");
324 printf(" -r{rate} -s{seconds} -x\n");
Phil Burk44795232017-06-30 16:27:38 -0700325 printf(" Default values are UNSPECIFIED unless otherwise stated.\n");
326 printf(" -b{bufferCapacity} frames\n");
327 printf(" -c{channels} for example 2 for stereo\n");
Phil Burke008d022017-08-23 12:56:15 -0700328 printf(" -d{deviceId} default is %d\n", AAUDIO_UNSPECIFIED);
Phil Burk6d6f3f62018-01-12 17:27:54 -0800329 printf(" -i{inputPreset} eg. 5 for AAUDIO_INPUT_PRESET_CAMCORDER\n");
Phil Burkfcf9efd2017-07-14 08:25:08 -0700330 printf(" -m{0|1|2|3} set MMAP policy\n");
Phil Burk6d6f3f62018-01-12 17:27:54 -0800331 printf(" 0 = _UNSPECIFIED, use aaudio.mmap_policy system property, default\n");
332 printf(" 1 = _NEVER, never use MMAP\n");
333 printf(" 2 = _AUTO, use MMAP if available, default for -m with no number\n");
334 printf(" 3 = _ALWAYS, use MMAP or fail\n");
Phil Burk44795232017-06-30 16:27:38 -0700335 printf(" -n{numberOfBursts} for setBufferSize\n");
336 printf(" -p{performanceMode} set output AAUDIO_PERFORMANCE_MODE*, default NONE\n");
337 printf(" n for _NONE\n");
338 printf(" l for _LATENCY\n");
339 printf(" p for _POWER_SAVING;\n");
340 printf(" -r{sampleRate} for example 44100\n");
Phil Burk6d6f3f62018-01-12 17:27:54 -0800341 printf(" -s{duration} in seconds, default is %d\n", DEFAULT_DURATION_SECONDS);
342 printf(" -u{usage} eg. 14 for AAUDIO_USAGE_GAME\n");
Phil Burk44795232017-06-30 16:27:38 -0700343 printf(" -x to use EXCLUSIVE mode\n");
Phil Burk6d6f3f62018-01-12 17:27:54 -0800344 printf(" -y{contentType} eg. 1 for AAUDIO_CONTENT_TYPE_SPEECH\n");
Phil Burk44795232017-06-30 16:27:38 -0700345 }
346
347 static aaudio_performance_mode_t parsePerformanceMode(char c) {
348 aaudio_performance_mode_t mode = AAUDIO_PERFORMANCE_MODE_NONE;
349 switch (c) {
350 case 'n':
351 mode = AAUDIO_PERFORMANCE_MODE_NONE;
352 break;
353 case 'l':
354 mode = AAUDIO_PERFORMANCE_MODE_LOW_LATENCY;
355 break;
356 case 'p':
357 mode = AAUDIO_PERFORMANCE_MODE_POWER_SAVING;
358 break;
359 default:
360 printf("ERROR invalid performance mode %c\n", c);
361 break;
362 }
363 return mode;
364 }
365
366 /**
367 * Print stream parameters in comparison with requested values.
368 * @param stream
369 */
Phil Burka5222e22017-07-28 13:31:14 -0700370 void compareWithStream(AAudioStream *stream) const {
Phil Burk44795232017-06-30 16:27:38 -0700371
372 printf(" DeviceId: requested = %d, actual = %d\n",
373 getDeviceId(), AAudioStream_getDeviceId(stream));
374
375 aaudio_stream_state_t state = AAudioStream_getState(stream);
376 printf(" State: %s\n", AAudio_convertStreamStateToText(state));
377
378 // Check to see what kind of stream we actually got.
379 printf(" SampleRate: requested = %d, actual = %d\n",
380 getSampleRate(), AAudioStream_getSampleRate(stream));
381
382 printf(" ChannelCount: requested = %d, actual = %d\n",
383 getChannelCount(), AAudioStream_getChannelCount(stream));
384
385 printf(" DataFormat: requested = %d, actual = %d\n",
386 getFormat(), AAudioStream_getFormat(stream));
387
388 int32_t framesPerBurst = AAudioStream_getFramesPerBurst(stream);
389 int32_t sizeFrames = AAudioStream_getBufferSizeInFrames(stream);
390 printf(" Buffer: burst = %d\n", framesPerBurst);
391 if (framesPerBurst > 0) {
392 printf(" Buffer: size = %d = (%d * %d) + %d\n",
393 sizeFrames,
394 (sizeFrames / framesPerBurst),
395 framesPerBurst,
396 (sizeFrames % framesPerBurst));
397 }
398 printf(" Capacity: requested = %d, actual = %d\n", getBufferCapacity(),
399 AAudioStream_getBufferCapacityInFrames(stream));
400
401 printf(" SharingMode: requested = %s, actual = %s\n",
402 getSharingModeText(getSharingMode()),
403 getSharingModeText(AAudioStream_getSharingMode(stream)));
404
405 printf(" PerformanceMode: requested = %d, actual = %d\n",
406 getPerformanceMode(), AAudioStream_getPerformanceMode(stream));
Phil Burk6d6f3f62018-01-12 17:27:54 -0800407
Phil Burk4e98efa2018-02-05 18:41:55 -0800408 loadFutureFunctions();
Phil Burk6d6f3f62018-01-12 17:27:54 -0800409
Phil Burk4e98efa2018-02-05 18:41:55 -0800410 if (s_setUsage != nullptr) {
411 printf(" Usage: requested = %d, actual = %d\n",
412 getUsage(), s_getUsage(stream));
413 }
414 if (s_getContentType != nullptr) {
415 printf(" ContentType: requested = %d, actual = %d\n",
416 getContentType(), s_getContentType(stream));
417 }
418
419 if (AAudioStream_getDirection(stream) == AAUDIO_DIRECTION_INPUT
420 && s_getInputPreset != nullptr) {
421 printf(" InputPreset: requested = %d, actual = %d\n",
422 getInputPreset(), s_getInputPreset(stream));
Phil Burk6d6f3f62018-01-12 17:27:54 -0800423 }
424
Phil Burk44795232017-06-30 16:27:38 -0700425 printf(" Is MMAP used? %s\n", AAudioStream_isMMapUsed(stream)
426 ? "yes" : "no");
427
428 }
429
430 int32_t getDurationSeconds() const {
431 return mDurationSeconds;
432 }
433
434 void setDurationSeconds(int32_t seconds) {
435 mDurationSeconds = seconds;
436 }
437
438private:
439 int32_t mDurationSeconds = DEFAULT_DURATION_SECONDS;
440};
441
442#endif // AAUDIO_EXAMPLE_ARGS_PARSER_H