1 /*
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
20 #define MAX_CHANNELS 8
21
22 //#include <cctype>
23 #include <dlfcn.h>
24 #include <unistd.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27
28 #include <aaudio/AAudio.h>
29 #include <aaudio/AAudioTesting.h>
30
31 #include "AAudioExampleUtils.h"
32
33
34 static void (*s_setUsage)(AAudioStreamBuilder* builder, aaudio_usage_t usage) = nullptr;
35 static void (*s_setContentType)(AAudioStreamBuilder* builder,
36 aaudio_content_type_t contentType) = nullptr;
37 static void (*s_setInputPreset)(AAudioStreamBuilder* builder,
38 aaudio_input_preset_t inputPreset) = nullptr;
39 static void (*s_setAllowedCapturePolicy)(AAudioStreamBuilder* builder,
40 aaudio_allowed_capture_policy_t usage) = nullptr;
41 static void (*s_setPrivacySensitive)(AAudioStreamBuilder* builder,
42 bool privacySensitive) = nullptr;
43
44 static bool s_loadAttempted = false;
45 static aaudio_usage_t (*s_getUsage)(AAudioStream *stream) = nullptr;
46 static aaudio_content_type_t (*s_getContentType)(AAudioStream *stream) = nullptr;
47 static aaudio_input_preset_t (*s_getInputPreset)(AAudioStream *stream) = nullptr;
48 static aaudio_allowed_capture_policy_t (*s_getAllowedCapturePolicy)(AAudioStream *stream) = nullptr;
49 static bool (*s_isPrivacySensitive)(AAudioStream *stream) = nullptr;
50
51 // Link to test functions in shared library.
loadFutureFunctions()52 static void loadFutureFunctions() {
53 if (s_loadAttempted) return; // only try once
54 s_loadAttempted = true;
55
56 void *handle = dlopen("libaaudio.so", RTLD_NOW);
57 if (handle != nullptr) {
58 s_setUsage = (void (*)(AAudioStreamBuilder *, aaudio_usage_t))
59 dlsym(handle, "AAudioStreamBuilder_setUsage");
60 if (s_setUsage == nullptr) goto error;
61
62 s_setContentType = (void (*)(AAudioStreamBuilder *, aaudio_content_type_t))
63 dlsym(handle, "AAudioStreamBuilder_setContentType");
64 if (s_setContentType == nullptr) goto error;
65
66 s_setInputPreset = (void (*)(AAudioStreamBuilder *, aaudio_input_preset_t))
67 dlsym(handle, "AAudioStreamBuilder_setInputPreset");
68 if (s_setInputPreset == nullptr) goto error;
69
70 s_setAllowedCapturePolicy = (void (*)(AAudioStreamBuilder *, aaudio_input_preset_t))
71 dlsym(handle, "AAudioStreamBuilder_setAllowedCapturePolicy");
72 if (s_setAllowedCapturePolicy == nullptr) goto error;
73
74 s_setPrivacySensitive = (void (*)(AAudioStreamBuilder *, bool))
75 dlsym(handle, "AAudioStreamBuilder_setPrivacySensitive");
76 if (s_setPrivacySensitive == nullptr) goto error;
77
78 s_getUsage = (aaudio_usage_t (*)(AAudioStream *))
79 dlsym(handle, "AAudioStream_getUsage");
80 if (s_getUsage == nullptr) goto error;
81
82 s_getContentType = (aaudio_content_type_t (*)(AAudioStream *))
83 dlsym(handle, "AAudioStream_getContentType");
84 if (s_getContentType == nullptr) goto error;
85
86 s_getInputPreset = (aaudio_input_preset_t (*)(AAudioStream *))
87 dlsym(handle, "AAudioStream_getInputPreset");
88 if (s_getInputPreset == nullptr) goto error;
89
90 s_getAllowedCapturePolicy = (aaudio_input_preset_t (*)(AAudioStream *))
91 dlsym(handle, "AAudioStream_getAllowedCapturePolicy");
92 if (s_getAllowedCapturePolicy == nullptr) goto error;
93
94 s_isPrivacySensitive = (bool (*)(AAudioStream *))
95 dlsym(handle, "AAudioStream_isPrivacySensitive");
96 if (s_isPrivacySensitive == nullptr) goto error;
97 }
98 return;
99
100 error:
101 // prevent any calls to these functions
102 s_setUsage = nullptr;
103 s_setContentType = nullptr;
104 s_setInputPreset = nullptr;
105 s_setPrivacySensitive = nullptr;
106 s_getUsage = nullptr;
107 s_getContentType = nullptr;
108 s_getInputPreset = nullptr;
109 s_isPrivacySensitive = nullptr;
110 dlclose(handle);
111 return;
112 }
113
114 class AAudioParameters {
115 public:
116
117 /**
118 * This is also known as samplesPerFrame.
119 */
getChannelCount()120 int32_t getChannelCount() const {
121 return mChannelCount;
122 }
123
setChannelCount(int32_t channelCount)124 void setChannelCount(int32_t channelCount) {
125 if (channelCount > MAX_CHANNELS) {
126 printf("Sorry, MAX of %d channels!\n", MAX_CHANNELS);
127 channelCount = MAX_CHANNELS;
128 }
129 mChannelCount = channelCount;
130 }
131
getSampleRate()132 int32_t getSampleRate() const {
133 return mSampleRate;
134 }
135
setSampleRate(int32_t sampleRate)136 void setSampleRate(int32_t sampleRate) {
137 mSampleRate = sampleRate;
138 }
139
getFormat()140 aaudio_format_t getFormat() const {
141 return mFormat;
142 }
143
setFormat(aaudio_format_t format)144 void setFormat(aaudio_format_t format) {
145 mFormat = format;
146 }
147
getSharingMode()148 aaudio_sharing_mode_t getSharingMode() const {
149 return mSharingMode;
150 }
151
setSharingMode(aaudio_sharing_mode_t sharingMode)152 void setSharingMode(aaudio_sharing_mode_t sharingMode) {
153 mSharingMode = sharingMode;
154 }
155
getBufferCapacity()156 int32_t getBufferCapacity() const {
157 return mBufferCapacity;
158 }
159
setBufferCapacity(int32_t frames)160 void setBufferCapacity(int32_t frames) {
161 mBufferCapacity = frames;
162 }
163
getPerformanceMode()164 int32_t getPerformanceMode() const {
165 return mPerformanceMode;
166 }
167
setPerformanceMode(aaudio_performance_mode_t performanceMode)168 void setPerformanceMode(aaudio_performance_mode_t performanceMode) {
169 mPerformanceMode = performanceMode;
170 }
171
getUsage()172 aaudio_usage_t getUsage() const {
173 return mUsage;
174 }
175
setUsage(aaudio_usage_t usage)176 void setUsage(aaudio_usage_t usage) {
177 mUsage = usage;
178 }
179
getContentType()180 aaudio_content_type_t getContentType() const {
181 return mContentType;
182 }
183
setContentType(aaudio_content_type_t contentType)184 void setContentType(aaudio_content_type_t contentType) {
185 mContentType = contentType;
186 }
187
getInputPreset()188 aaudio_input_preset_t getInputPreset() const {
189 return mInputPreset;
190 }
191
setInputPreset(aaudio_input_preset_t inputPreset)192 void setInputPreset(aaudio_input_preset_t inputPreset) {
193 mInputPreset = inputPreset;
194 }
195
getAllowedCapturePolicy()196 aaudio_allowed_capture_policy_t getAllowedCapturePolicy() const {
197 return mAllowedCapturePolicy;
198 }
199
setAllowedCapturePolicy(aaudio_allowed_capture_policy_t policy)200 void setAllowedCapturePolicy(aaudio_allowed_capture_policy_t policy) {
201 mAllowedCapturePolicy = policy;
202 }
203
getDeviceId()204 int32_t getDeviceId() const {
205 return mDeviceId;
206 }
207
setDeviceId(int32_t deviceId)208 void setDeviceId(int32_t deviceId) {
209 mDeviceId = deviceId;
210 }
211
getNumberOfBursts()212 int32_t getNumberOfBursts() const {
213 return mNumberOfBursts;
214 }
215
setNumberOfBursts(int32_t numBursts)216 void setNumberOfBursts(int32_t numBursts) {
217 mNumberOfBursts = numBursts;
218 }
219
getFramesPerCallback()220 int32_t getFramesPerCallback() const {
221 return mFramesPerCallback;
222 }
setFramesPerCallback(int32_t size)223 void setFramesPerCallback(int32_t size) {
224 mFramesPerCallback = size;
225 }
226
isPrivacySensitive()227 int32_t isPrivacySensitive() const {
228 return mPrivacySensitive;
229 }
230
setPrivacySensitive(int32_t privacySensitive)231 void setPrivacySensitive(int32_t privacySensitive) {
232 mPrivacySensitive = privacySensitive;
233 }
234
235 /**
236 * Apply these parameters to a stream builder.
237 * @param builder
238 */
applyParameters(AAudioStreamBuilder * builder)239 void applyParameters(AAudioStreamBuilder *builder) const {
240 AAudioStreamBuilder_setBufferCapacityInFrames(builder, getBufferCapacity());
241 AAudioStreamBuilder_setChannelCount(builder, mChannelCount);
242 AAudioStreamBuilder_setDeviceId(builder, mDeviceId);
243 AAudioStreamBuilder_setFormat(builder, mFormat);
244 AAudioStreamBuilder_setFramesPerDataCallback(builder, mFramesPerCallback);
245 AAudioStreamBuilder_setPerformanceMode(builder, mPerformanceMode);
246 AAudioStreamBuilder_setSampleRate(builder, mSampleRate);
247 AAudioStreamBuilder_setSharingMode(builder, mSharingMode);
248
249 // Call P functions if supported.
250 loadFutureFunctions();
251 if (s_setUsage != nullptr) {
252 s_setUsage(builder, mUsage);
253 } else if (mUsage != AAUDIO_UNSPECIFIED){
254 printf("WARNING: setUsage not supported");
255 }
256 if (s_setContentType != nullptr) {
257 s_setContentType(builder, mContentType);
258 } else if (mContentType != AAUDIO_UNSPECIFIED){
259 printf("WARNING: setContentType not supported");
260 }
261 if (s_setInputPreset != nullptr) {
262 s_setInputPreset(builder, mInputPreset);
263 } else if (mInputPreset != AAUDIO_UNSPECIFIED){
264 printf("WARNING: setInputPreset not supported");
265 }
266
267 // Call Q functions if supported.
268 if (s_setAllowedCapturePolicy != nullptr) {
269 s_setAllowedCapturePolicy(builder, mAllowedCapturePolicy);
270 } else if (mAllowedCapturePolicy != AAUDIO_UNSPECIFIED){
271 printf("WARNING: setAllowedCapturePolicy not supported");
272 }
273
274 if (mPrivacySensitive != PRIVACY_SENSITIVE_DEFAULT) {
275 if (s_setPrivacySensitive != nullptr) {
276 s_setPrivacySensitive(builder,
277 mPrivacySensitive == PRIVACY_SENSITIVE_ENABLED);
278 } else {
279 printf("WARNING: setPrivacySensitive not supported");
280 }
281 }
282 }
283
284 static constexpr int32_t kDefaultNumberOfBursts = 2;
285
286 private:
287 int32_t mChannelCount = AAUDIO_UNSPECIFIED;
288 aaudio_format_t mFormat = AAUDIO_FORMAT_UNSPECIFIED;
289 int32_t mSampleRate = AAUDIO_UNSPECIFIED;
290
291 int32_t mBufferCapacity = AAUDIO_UNSPECIFIED;
292 int32_t mDeviceId = AAUDIO_UNSPECIFIED;
293 aaudio_sharing_mode_t mSharingMode = AAUDIO_SHARING_MODE_SHARED;
294 aaudio_performance_mode_t mPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE;
295
296 aaudio_usage_t mUsage = AAUDIO_UNSPECIFIED;
297 aaudio_content_type_t mContentType = AAUDIO_UNSPECIFIED;
298 aaudio_input_preset_t mInputPreset = AAUDIO_UNSPECIFIED;
299 aaudio_allowed_capture_policy_t mAllowedCapturePolicy = AAUDIO_UNSPECIFIED;
300
301 int32_t mNumberOfBursts = kDefaultNumberOfBursts;
302 int32_t mFramesPerCallback = AAUDIO_UNSPECIFIED;
303
304 enum {
305 PRIVACY_SENSITIVE_DEFAULT = -1,
306 PRIVACY_SENSITIVE_DISABLED = 0,
307 PRIVACY_SENSITIVE_ENABLED = 1,
308 };
309 int32_t mPrivacySensitive = PRIVACY_SENSITIVE_DEFAULT;
310 };
311
312 class AAudioArgsParser : public AAudioParameters {
313 public:
314 AAudioArgsParser() = default;
315 ~AAudioArgsParser() = default;
316
317 enum {
318 DEFAULT_DURATION_SECONDS = 5
319 };
320
321 /**
322 * @param arg
323 * @return true if the argument was not handled
324 */
parseArg(const char * arg)325 bool parseArg(const char *arg) {
326 bool unrecognized = false;
327 if (arg[0] == '-') {
328 char option = arg[1];
329 switch (option) {
330 case 'b':
331 setBufferCapacity(atoi(&arg[2]));
332 break;
333 case 'c':
334 setChannelCount(atoi(&arg[2]));
335 break;
336 case 'C':
337 setAllowedCapturePolicy(parseAllowedCapturePolicy(arg[2]));
338 break;
339 case 'd':
340 setDeviceId(atoi(&arg[2]));
341 break;
342 case 'f':
343 setFormat(atoi(&arg[2]));
344 break;
345 case 'i':
346 setInputPreset(atoi(&arg[2]));
347 break;
348 case 'm': {
349 aaudio_policy_t policy = AAUDIO_POLICY_AUTO;
350 if (strlen(arg) > 2) {
351 policy = atoi(&arg[2]);
352 }
353 if (AAudio_setMMapPolicy(policy) != AAUDIO_OK) {
354 printf("ERROR: invalid MMAP policy mode %i\n", policy);
355 }
356 } break;
357 case 'n':
358 setNumberOfBursts(atoi(&arg[2]));
359 break;
360 case 'p':
361 setPerformanceMode(parsePerformanceMode(arg[2]));
362 break;
363 case 'r':
364 setSampleRate(atoi(&arg[2]));
365 break;
366 case 's':
367 mDurationSeconds = atoi(&arg[2]);
368 break;
369 case 'u':
370 setUsage(atoi(&arg[2]));
371 break;
372 case 'x':
373 setSharingMode(AAUDIO_SHARING_MODE_EXCLUSIVE);
374 break;
375 case 'y':
376 setContentType(atoi(&arg[2]));
377 break;
378 case 'z':
379 setFramesPerCallback(atoi(&arg[2]));
380 break;
381 case 'S':
382 setPrivacySensitive(atoi(&arg[2]));
383 break;
384 default:
385 unrecognized = true;
386 break;
387 }
388 }
389 return unrecognized;
390 }
391
392 /**
393 *
394 * @param argc
395 * @param argv
396 * @return true if an unrecognized argument was passed
397 */
parseArgs(int argc,const char ** argv)398 bool parseArgs(int argc, const char **argv) {
399 for (int i = 1; i < argc; i++) {
400 const char *arg = argv[i];
401 if (parseArg(arg)) {
402 usage();
403 return true;
404 }
405
406 }
407 return false;
408 }
409
usage()410 static void usage() {
411 printf("-c{channels} -d{deviceId} -m{mmapPolicy} -n{burstsPerBuffer} -p{perfMode}");
412 printf(" -r{rate} -s{seconds} -x\n");
413 printf(" Default values are UNSPECIFIED unless otherwise stated.\n");
414 printf(" -b{bufferCapacity} frames\n");
415 printf(" -c{channels} for example 2 for stereo\n");
416 printf(" -C{a|s|n} set playback capture policy\n");
417 printf(" a = _ALL (default)\n");
418 printf(" s = _SYSTEM\n");
419 printf(" n = _NONE\n");
420 printf(" -d{deviceId} default is %d\n", AAUDIO_UNSPECIFIED);
421 printf(" -f{0|1|2} set format\n");
422 printf(" 0 = UNSPECIFIED\n");
423 printf(" 1 = PCM_I16\n");
424 printf(" 2 = PCM_FLOAT\n");
425 printf(" 3 = PCM_I24_PACKED\n");
426 printf(" 4 = PCM_I32\n");
427 printf(" -i{inputPreset} eg. 5 for AAUDIO_INPUT_PRESET_CAMCORDER\n");
428 printf(" -m{0|1|2|3} set MMAP policy\n");
429 printf(" 0 = _UNSPECIFIED, use aaudio.mmap_policy system property, default\n");
430 printf(" 1 = _NEVER, never use MMAP\n");
431 printf(" 2 = _AUTO, use MMAP if available, default for -m with no number\n");
432 printf(" 3 = _ALWAYS, use MMAP or fail\n");
433 printf(" -n{numberOfBursts} for setBufferSize, default %d\n", kDefaultNumberOfBursts);
434 printf(" -p{performanceMode} set output AAUDIO_PERFORMANCE_MODE*, default NONE\n");
435 printf(" n for _NONE\n");
436 printf(" l for _LATENCY\n");
437 printf(" p for _POWER_SAVING;\n");
438 printf(" -r{sampleRate} for example 44100\n");
439 printf(" -s{duration} in seconds, default is %d\n", DEFAULT_DURATION_SECONDS);
440 printf(" -u{usage} eg. 14 for AAUDIO_USAGE_GAME\n");
441 printf(" -x to use EXCLUSIVE mode\n");
442 printf(" -y{contentType} eg. 1 for AAUDIO_CONTENT_TYPE_SPEECH\n");
443 printf(" -z{callbackSize} or block size, in frames, default = 0\n");
444 printf(" -S{0|1} set privacy Sensitive enabled or disabled\n");
445 printf(" 0 = disabled\n");
446 printf(" 1 = enabled\n");
447 }
448
parseAllowedCapturePolicy(char c)449 static aaudio_performance_mode_t parseAllowedCapturePolicy(char c) {
450 aaudio_allowed_capture_policy_t policy = AAUDIO_ALLOW_CAPTURE_BY_ALL;
451 switch (c) {
452 case 'a':
453 policy = AAUDIO_ALLOW_CAPTURE_BY_ALL;
454 break;
455 case 's':
456 policy = AAUDIO_ALLOW_CAPTURE_BY_SYSTEM;
457 break;
458 case 'n':
459 policy = AAUDIO_ALLOW_CAPTURE_BY_NONE;
460 break;
461 default:
462 printf("ERROR: invalid playback capture policy %c\n", c);
463 break;
464 }
465 return policy;
466 }
467
parsePerformanceMode(char c)468 static aaudio_performance_mode_t parsePerformanceMode(char c) {
469 aaudio_performance_mode_t mode = AAUDIO_PERFORMANCE_MODE_NONE;
470 switch (c) {
471 case 'n':
472 mode = AAUDIO_PERFORMANCE_MODE_NONE;
473 break;
474 case 'l':
475 mode = AAUDIO_PERFORMANCE_MODE_LOW_LATENCY;
476 break;
477 case 'p':
478 mode = AAUDIO_PERFORMANCE_MODE_POWER_SAVING;
479 break;
480 default:
481 printf("ERROR: invalid performance mode %c\n", c);
482 break;
483 }
484 return mode;
485 }
486
487 /**
488 * Print stream parameters in comparison with requested values.
489 * @param stream
490 */
compareWithStream(AAudioStream * stream)491 void compareWithStream(AAudioStream *stream) const {
492
493 printf(" DeviceId: requested = %d, actual = %d\n",
494 getDeviceId(), AAudioStream_getDeviceId(stream));
495
496 aaudio_stream_state_t state = AAudioStream_getState(stream);
497 printf(" State: %s\n", AAudio_convertStreamStateToText(state));
498
499 // Check to see what kind of stream we actually got.
500 printf(" SampleRate: requested = %d, actual = %d\n",
501 getSampleRate(), AAudioStream_getSampleRate(stream));
502
503 printf(" ChannelCount: requested = %d, actual = %d\n",
504 getChannelCount(), AAudioStream_getChannelCount(stream));
505
506 printf(" DataFormat: requested = %d, actual = %d\n",
507 getFormat(), AAudioStream_getFormat(stream));
508
509 int32_t framesPerBurst = AAudioStream_getFramesPerBurst(stream);
510 printf(" Buffer: burst = %d\n", framesPerBurst);
511
512 int32_t sizeFrames = AAudioStream_getBufferSizeInFrames(stream);
513 if (framesPerBurst > 0) {
514 int32_t requestedSize = getNumberOfBursts() * framesPerBurst;
515 printf(" BufferSize: requested = %4d, actual = %4d = (%d * %d) + %d\n",
516 requestedSize,
517 sizeFrames,
518 (sizeFrames / framesPerBurst),
519 framesPerBurst,
520 (sizeFrames % framesPerBurst));
521 } else {
522 printf(" BufferSize: %d\n", sizeFrames);
523 }
524
525 int32_t capacityFrames = AAudioStream_getBufferCapacityInFrames(stream);
526 printf(" Capacity: requested = %4d, actual = %4d = (%d * %d) + %d\n",
527 getBufferCapacity(),
528 capacityFrames,
529 (capacityFrames / framesPerBurst),
530 framesPerBurst,
531 (capacityFrames % framesPerBurst));
532
533 printf(" CallbackSize: requested = %d, actual = %d\n", getFramesPerCallback(),
534 AAudioStream_getFramesPerDataCallback(stream));
535
536 printf(" SharingMode: requested = %s, actual = %s\n",
537 getSharingModeText(getSharingMode()),
538 getSharingModeText(AAudioStream_getSharingMode(stream)));
539
540 printf(" PerformanceMode: requested = %d, actual = %d\n",
541 getPerformanceMode(), AAudioStream_getPerformanceMode(stream));
542
543 loadFutureFunctions();
544
545 if (s_setUsage != nullptr) {
546 printf(" Usage: requested = %d, actual = %d\n",
547 getUsage(), s_getUsage(stream));
548 }
549 if (s_getContentType != nullptr) {
550 printf(" ContentType: requested = %d, actual = %d\n",
551 getContentType(), s_getContentType(stream));
552 }
553
554 if (AAudioStream_getDirection(stream) == AAUDIO_DIRECTION_INPUT) {
555 if (s_getInputPreset != nullptr) {
556 printf(" InputPreset: requested = %d, actual = %d\n",
557 getInputPreset(), s_getInputPreset(stream));
558 }
559 if (s_isPrivacySensitive != nullptr) {
560 printf(" Privacy Sensitive: requested = %d, actual = %d\n",
561 isPrivacySensitive(), s_isPrivacySensitive(stream));
562 }
563 }
564
565 printf(" Is MMAP used? %s\n", AAudioStream_isMMapUsed(stream)
566 ? "yes" : "no");
567
568 if (s_getAllowedCapturePolicy != nullptr) {
569 printf(" ContentType: requested = %d, actual = %d\n",
570 getAllowedCapturePolicy(), s_getAllowedCapturePolicy(stream));
571 }
572
573 }
574
getDurationSeconds()575 int32_t getDurationSeconds() const {
576 return mDurationSeconds;
577 }
578
setDurationSeconds(int32_t seconds)579 void setDurationSeconds(int32_t seconds) {
580 mDurationSeconds = seconds;
581 }
582
583 private:
584 int32_t mDurationSeconds = DEFAULT_DURATION_SECONDS;
585 };
586
587 #endif // AAUDIO_EXAMPLE_ARGS_PARSER_H
588