/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef AAUDIO_EXAMPLE_ARGS_PARSER_H #define AAUDIO_EXAMPLE_ARGS_PARSER_H #define MAX_CHANNELS 8 //#include #include #include #include #include #include #include #include "AAudioExampleUtils.h" static void (*s_setUsage)(AAudioStreamBuilder* builder, aaudio_usage_t usage) = nullptr; static void (*s_setContentType)(AAudioStreamBuilder* builder, aaudio_content_type_t contentType) = nullptr; static void (*s_setInputPreset)(AAudioStreamBuilder* builder, aaudio_input_preset_t inputPreset) = nullptr; static void (*s_setAllowedCapturePolicy)(AAudioStreamBuilder* builder, aaudio_allowed_capture_policy_t usage) = nullptr; static void (*s_setPrivacySensitive)(AAudioStreamBuilder* builder, bool privacySensitive) = nullptr; static bool s_loadAttempted = false; static aaudio_usage_t (*s_getUsage)(AAudioStream *stream) = nullptr; static aaudio_content_type_t (*s_getContentType)(AAudioStream *stream) = nullptr; static aaudio_input_preset_t (*s_getInputPreset)(AAudioStream *stream) = nullptr; static aaudio_allowed_capture_policy_t (*s_getAllowedCapturePolicy)(AAudioStream *stream) = nullptr; static bool (*s_isPrivacySensitive)(AAudioStream *stream) = nullptr; // Link to test functions in shared library. static void loadFutureFunctions() { if (s_loadAttempted) return; // only try once s_loadAttempted = true; void *handle = dlopen("libaaudio.so", RTLD_NOW); if (handle != nullptr) { s_setUsage = (void (*)(AAudioStreamBuilder *, aaudio_usage_t)) dlsym(handle, "AAudioStreamBuilder_setUsage"); if (s_setUsage == nullptr) goto error; s_setContentType = (void (*)(AAudioStreamBuilder *, aaudio_content_type_t)) dlsym(handle, "AAudioStreamBuilder_setContentType"); if (s_setContentType == nullptr) goto error; s_setInputPreset = (void (*)(AAudioStreamBuilder *, aaudio_input_preset_t)) dlsym(handle, "AAudioStreamBuilder_setInputPreset"); if (s_setInputPreset == nullptr) goto error; s_setAllowedCapturePolicy = (void (*)(AAudioStreamBuilder *, aaudio_input_preset_t)) dlsym(handle, "AAudioStreamBuilder_setAllowedCapturePolicy"); if (s_setAllowedCapturePolicy == nullptr) goto error; s_setPrivacySensitive = (void (*)(AAudioStreamBuilder *, bool)) dlsym(handle, "AAudioStreamBuilder_setPrivacySensitive"); if (s_setPrivacySensitive == nullptr) goto error; s_getUsage = (aaudio_usage_t (*)(AAudioStream *)) dlsym(handle, "AAudioStream_getUsage"); if (s_getUsage == nullptr) goto error; s_getContentType = (aaudio_content_type_t (*)(AAudioStream *)) dlsym(handle, "AAudioStream_getContentType"); if (s_getContentType == nullptr) goto error; s_getInputPreset = (aaudio_input_preset_t (*)(AAudioStream *)) dlsym(handle, "AAudioStream_getInputPreset"); if (s_getInputPreset == nullptr) goto error; s_getAllowedCapturePolicy = (aaudio_input_preset_t (*)(AAudioStream *)) dlsym(handle, "AAudioStream_getAllowedCapturePolicy"); if (s_getAllowedCapturePolicy == nullptr) goto error; s_isPrivacySensitive = (bool (*)(AAudioStream *)) dlsym(handle, "AAudioStream_isPrivacySensitive"); if (s_isPrivacySensitive == nullptr) goto error; } return; error: // prevent any calls to these functions s_setUsage = nullptr; s_setContentType = nullptr; s_setInputPreset = nullptr; s_setPrivacySensitive = nullptr; s_getUsage = nullptr; s_getContentType = nullptr; s_getInputPreset = nullptr; s_isPrivacySensitive = nullptr; dlclose(handle); return; } class AAudioParameters { public: /** * This is also known as samplesPerFrame. */ int32_t getChannelCount() const { return mChannelCount; } void setChannelCount(int32_t channelCount) { if (channelCount > MAX_CHANNELS) { printf("Sorry, MAX of %d channels!\n", MAX_CHANNELS); channelCount = MAX_CHANNELS; } mChannelCount = channelCount; } int32_t getSampleRate() const { return mSampleRate; } void setSampleRate(int32_t sampleRate) { mSampleRate = sampleRate; } aaudio_format_t getFormat() const { return mFormat; } void setFormat(aaudio_format_t format) { mFormat = format; } aaudio_sharing_mode_t getSharingMode() const { return mSharingMode; } void setSharingMode(aaudio_sharing_mode_t sharingMode) { mSharingMode = sharingMode; } int32_t getBufferCapacity() const { return mBufferCapacity; } void setBufferCapacity(int32_t frames) { mBufferCapacity = frames; } int32_t getPerformanceMode() const { return mPerformanceMode; } void setPerformanceMode(aaudio_performance_mode_t performanceMode) { mPerformanceMode = performanceMode; } aaudio_usage_t getUsage() const { return mUsage; } void setUsage(aaudio_usage_t usage) { mUsage = usage; } aaudio_content_type_t getContentType() const { return mContentType; } void setContentType(aaudio_content_type_t contentType) { mContentType = contentType; } aaudio_input_preset_t getInputPreset() const { return mInputPreset; } void setInputPreset(aaudio_input_preset_t inputPreset) { mInputPreset = inputPreset; } aaudio_allowed_capture_policy_t getAllowedCapturePolicy() const { return mAllowedCapturePolicy; } void setAllowedCapturePolicy(aaudio_allowed_capture_policy_t policy) { mAllowedCapturePolicy = policy; } int32_t getDeviceId() const { return mDeviceId; } void setDeviceId(int32_t deviceId) { mDeviceId = deviceId; } int32_t getNumberOfBursts() const { return mNumberOfBursts; } void setNumberOfBursts(int32_t numBursts) { mNumberOfBursts = numBursts; } int32_t getFramesPerCallback() const { return mFramesPerCallback; } void setFramesPerCallback(int32_t size) { mFramesPerCallback = size; } int32_t isPrivacySensitive() const { return mPrivacySensitive; } void setPrivacySensitive(int32_t privacySensitive) { mPrivacySensitive = privacySensitive; } /** * Apply these parameters to a stream builder. * @param builder */ void applyParameters(AAudioStreamBuilder *builder) const { AAudioStreamBuilder_setBufferCapacityInFrames(builder, getBufferCapacity()); AAudioStreamBuilder_setChannelCount(builder, mChannelCount); AAudioStreamBuilder_setDeviceId(builder, mDeviceId); AAudioStreamBuilder_setFormat(builder, mFormat); AAudioStreamBuilder_setFramesPerDataCallback(builder, mFramesPerCallback); AAudioStreamBuilder_setPerformanceMode(builder, mPerformanceMode); AAudioStreamBuilder_setSampleRate(builder, mSampleRate); AAudioStreamBuilder_setSharingMode(builder, mSharingMode); // Call P functions if supported. loadFutureFunctions(); if (s_setUsage != nullptr) { s_setUsage(builder, mUsage); } else if (mUsage != AAUDIO_UNSPECIFIED){ printf("WARNING: setUsage not supported"); } if (s_setContentType != nullptr) { s_setContentType(builder, mContentType); } else if (mContentType != AAUDIO_UNSPECIFIED){ printf("WARNING: setContentType not supported"); } if (s_setInputPreset != nullptr) { s_setInputPreset(builder, mInputPreset); } else if (mInputPreset != AAUDIO_UNSPECIFIED){ printf("WARNING: setInputPreset not supported"); } // Call Q functions if supported. if (s_setAllowedCapturePolicy != nullptr) { s_setAllowedCapturePolicy(builder, mAllowedCapturePolicy); } else if (mAllowedCapturePolicy != AAUDIO_UNSPECIFIED){ printf("WARNING: setAllowedCapturePolicy not supported"); } if (mPrivacySensitive != PRIVACY_SENSITIVE_DEFAULT) { if (s_setPrivacySensitive != nullptr) { s_setPrivacySensitive(builder, mPrivacySensitive == PRIVACY_SENSITIVE_ENABLED); } else { printf("WARNING: setPrivacySensitive not supported"); } } } static constexpr int32_t kDefaultNumberOfBursts = 2; private: int32_t mChannelCount = AAUDIO_UNSPECIFIED; aaudio_format_t mFormat = AAUDIO_FORMAT_UNSPECIFIED; int32_t mSampleRate = AAUDIO_UNSPECIFIED; int32_t mBufferCapacity = AAUDIO_UNSPECIFIED; int32_t mDeviceId = AAUDIO_UNSPECIFIED; aaudio_sharing_mode_t mSharingMode = AAUDIO_SHARING_MODE_SHARED; aaudio_performance_mode_t mPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE; aaudio_usage_t mUsage = AAUDIO_UNSPECIFIED; aaudio_content_type_t mContentType = AAUDIO_UNSPECIFIED; aaudio_input_preset_t mInputPreset = AAUDIO_UNSPECIFIED; aaudio_allowed_capture_policy_t mAllowedCapturePolicy = AAUDIO_UNSPECIFIED; int32_t mNumberOfBursts = kDefaultNumberOfBursts; int32_t mFramesPerCallback = AAUDIO_UNSPECIFIED; enum { PRIVACY_SENSITIVE_DEFAULT = -1, PRIVACY_SENSITIVE_DISABLED = 0, PRIVACY_SENSITIVE_ENABLED = 1, }; int32_t mPrivacySensitive = PRIVACY_SENSITIVE_DEFAULT; }; class AAudioArgsParser : public AAudioParameters { public: AAudioArgsParser() = default; ~AAudioArgsParser() = default; enum { DEFAULT_DURATION_SECONDS = 5 }; /** * @param arg * @return true if the argument was not handled */ bool parseArg(const char *arg) { bool unrecognized = false; if (arg[0] == '-') { char option = arg[1]; switch (option) { case 'b': setBufferCapacity(atoi(&arg[2])); break; case 'c': setChannelCount(atoi(&arg[2])); break; case 'C': setAllowedCapturePolicy(parseAllowedCapturePolicy(arg[2])); break; case 'd': setDeviceId(atoi(&arg[2])); break; case 'f': setFormat(atoi(&arg[2])); break; case 'i': setInputPreset(atoi(&arg[2])); break; case 'm': { aaudio_policy_t policy = AAUDIO_POLICY_AUTO; if (strlen(arg) > 2) { policy = atoi(&arg[2]); } if (AAudio_setMMapPolicy(policy) != AAUDIO_OK) { printf("ERROR: invalid MMAP policy mode %i\n", policy); } } break; case 'n': setNumberOfBursts(atoi(&arg[2])); break; case 'p': setPerformanceMode(parsePerformanceMode(arg[2])); break; case 'r': setSampleRate(atoi(&arg[2])); break; case 's': mDurationSeconds = atoi(&arg[2]); break; case 'u': setUsage(atoi(&arg[2])); break; case 'x': setSharingMode(AAUDIO_SHARING_MODE_EXCLUSIVE); break; case 'y': setContentType(atoi(&arg[2])); break; case 'z': setFramesPerCallback(atoi(&arg[2])); break; case 'S': setPrivacySensitive(atoi(&arg[2])); break; default: unrecognized = true; break; } } return unrecognized; } /** * * @param argc * @param argv * @return true if an unrecognized argument was passed */ bool parseArgs(int argc, const char **argv) { for (int i = 1; i < argc; i++) { const char *arg = argv[i]; if (parseArg(arg)) { usage(); return true; } } return false; } static void usage() { printf("-c{channels} -d{deviceId} -m{mmapPolicy} -n{burstsPerBuffer} -p{perfMode}"); printf(" -r{rate} -s{seconds} -x\n"); printf(" Default values are UNSPECIFIED unless otherwise stated.\n"); printf(" -b{bufferCapacity} frames\n"); printf(" -c{channels} for example 2 for stereo\n"); printf(" -C{a|s|n} set playback capture policy\n"); printf(" a = _ALL (default)\n"); printf(" s = _SYSTEM\n"); printf(" n = _NONE\n"); printf(" -d{deviceId} default is %d\n", AAUDIO_UNSPECIFIED); printf(" -f{0|1|2} set format\n"); printf(" 0 = UNSPECIFIED\n"); printf(" 1 = PCM_I16\n"); printf(" 2 = PCM_FLOAT\n"); printf(" 3 = PCM_I24_PACKED\n"); printf(" 4 = PCM_I32\n"); printf(" -i{inputPreset} eg. 5 for AAUDIO_INPUT_PRESET_CAMCORDER\n"); printf(" -m{0|1|2|3} set MMAP policy\n"); printf(" 0 = _UNSPECIFIED, use aaudio.mmap_policy system property, default\n"); printf(" 1 = _NEVER, never use MMAP\n"); printf(" 2 = _AUTO, use MMAP if available, default for -m with no number\n"); printf(" 3 = _ALWAYS, use MMAP or fail\n"); printf(" -n{numberOfBursts} for setBufferSize, default %d\n", kDefaultNumberOfBursts); printf(" -p{performanceMode} set output AAUDIO_PERFORMANCE_MODE*, default NONE\n"); printf(" n for _NONE\n"); printf(" l for _LATENCY\n"); printf(" p for _POWER_SAVING;\n"); printf(" -r{sampleRate} for example 44100\n"); printf(" -s{duration} in seconds, default is %d\n", DEFAULT_DURATION_SECONDS); printf(" -u{usage} eg. 14 for AAUDIO_USAGE_GAME\n"); printf(" -x to use EXCLUSIVE mode\n"); printf(" -y{contentType} eg. 1 for AAUDIO_CONTENT_TYPE_SPEECH\n"); printf(" -z{callbackSize} or block size, in frames, default = 0\n"); printf(" -S{0|1} set privacy Sensitive enabled or disabled\n"); printf(" 0 = disabled\n"); printf(" 1 = enabled\n"); } static aaudio_performance_mode_t parseAllowedCapturePolicy(char c) { aaudio_allowed_capture_policy_t policy = AAUDIO_ALLOW_CAPTURE_BY_ALL; switch (c) { case 'a': policy = AAUDIO_ALLOW_CAPTURE_BY_ALL; break; case 's': policy = AAUDIO_ALLOW_CAPTURE_BY_SYSTEM; break; case 'n': policy = AAUDIO_ALLOW_CAPTURE_BY_NONE; break; default: printf("ERROR: invalid playback capture policy %c\n", c); break; } return policy; } static aaudio_performance_mode_t parsePerformanceMode(char c) { aaudio_performance_mode_t mode = AAUDIO_PERFORMANCE_MODE_NONE; switch (c) { case 'n': mode = AAUDIO_PERFORMANCE_MODE_NONE; break; case 'l': mode = AAUDIO_PERFORMANCE_MODE_LOW_LATENCY; break; case 'p': mode = AAUDIO_PERFORMANCE_MODE_POWER_SAVING; break; default: printf("ERROR: invalid performance mode %c\n", c); break; } return mode; } /** * Print stream parameters in comparison with requested values. * @param stream */ void compareWithStream(AAudioStream *stream) const { printf(" DeviceId: requested = %d, actual = %d\n", getDeviceId(), AAudioStream_getDeviceId(stream)); aaudio_stream_state_t state = AAudioStream_getState(stream); printf(" State: %s\n", AAudio_convertStreamStateToText(state)); // Check to see what kind of stream we actually got. printf(" SampleRate: requested = %d, actual = %d\n", getSampleRate(), AAudioStream_getSampleRate(stream)); printf(" ChannelCount: requested = %d, actual = %d\n", getChannelCount(), AAudioStream_getChannelCount(stream)); printf(" DataFormat: requested = %d, actual = %d\n", getFormat(), AAudioStream_getFormat(stream)); int32_t framesPerBurst = AAudioStream_getFramesPerBurst(stream); printf(" Buffer: burst = %d\n", framesPerBurst); int32_t sizeFrames = AAudioStream_getBufferSizeInFrames(stream); if (framesPerBurst > 0) { int32_t requestedSize = getNumberOfBursts() * framesPerBurst; printf(" BufferSize: requested = %4d, actual = %4d = (%d * %d) + %d\n", requestedSize, sizeFrames, (sizeFrames / framesPerBurst), framesPerBurst, (sizeFrames % framesPerBurst)); } else { printf(" BufferSize: %d\n", sizeFrames); } int32_t capacityFrames = AAudioStream_getBufferCapacityInFrames(stream); printf(" Capacity: requested = %4d, actual = %4d = (%d * %d) + %d\n", getBufferCapacity(), capacityFrames, (capacityFrames / framesPerBurst), framesPerBurst, (capacityFrames % framesPerBurst)); printf(" CallbackSize: requested = %d, actual = %d\n", getFramesPerCallback(), AAudioStream_getFramesPerDataCallback(stream)); printf(" SharingMode: requested = %s, actual = %s\n", getSharingModeText(getSharingMode()), getSharingModeText(AAudioStream_getSharingMode(stream))); printf(" PerformanceMode: requested = %d, actual = %d\n", getPerformanceMode(), AAudioStream_getPerformanceMode(stream)); loadFutureFunctions(); if (s_setUsage != nullptr) { printf(" Usage: requested = %d, actual = %d\n", getUsage(), s_getUsage(stream)); } if (s_getContentType != nullptr) { printf(" ContentType: requested = %d, actual = %d\n", getContentType(), s_getContentType(stream)); } if (AAudioStream_getDirection(stream) == AAUDIO_DIRECTION_INPUT) { if (s_getInputPreset != nullptr) { printf(" InputPreset: requested = %d, actual = %d\n", getInputPreset(), s_getInputPreset(stream)); } if (s_isPrivacySensitive != nullptr) { printf(" Privacy Sensitive: requested = %d, actual = %d\n", isPrivacySensitive(), s_isPrivacySensitive(stream)); } } printf(" Is MMAP used? %s\n", AAudioStream_isMMapUsed(stream) ? "yes" : "no"); if (s_getAllowedCapturePolicy != nullptr) { printf(" ContentType: requested = %d, actual = %d\n", getAllowedCapturePolicy(), s_getAllowedCapturePolicy(stream)); } } int32_t getDurationSeconds() const { return mDurationSeconds; } void setDurationSeconds(int32_t seconds) { mDurationSeconds = seconds; } private: int32_t mDurationSeconds = DEFAULT_DURATION_SECONDS; }; #endif // AAUDIO_EXAMPLE_ARGS_PARSER_H