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