aaudio: command line argument parser

Generic parser that is used in multiple examples.

Added -n{numberOfBursts} for buffer size.

This is being used to test the MMAP features.

Bug: 63002656
Test: this is a test
Change-Id: Idf7560f9bb3ed7834f6c4686dd6009f27f04220e
Merged-In: Idf7560f9bb3ed7834f6c4686dd6009f27f04220e
diff --git a/media/libaaudio/examples/utils/AAudioArgsParser.h b/media/libaaudio/examples/utils/AAudioArgsParser.h
new file mode 100644
index 0000000..54217a5
--- /dev/null
+++ b/media/libaaudio/examples/utils/AAudioArgsParser.h
@@ -0,0 +1,288 @@
+/*
+ * 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
+
+#include <cctype>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <aaudio/AAudio.h>
+#include <aaudio/AAudioTesting.h>
+#include <AAudioExampleUtils.h>
+
+// TODO use this as a base class within AAudio
+class AAudioParameters {
+public:
+
+    /**
+     * This is also known as samplesPerFrame.
+     */
+    int32_t getChannelCount() const {
+        return mChannelCount;
+    }
+
+    void setChannelCount(int32_t channelCount) {
+        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;
+    }
+
+    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;
+    }
+
+    /**
+     * Apply these parameters to a stream builder.
+     * @param builder
+     */
+    void applyParameters(AAudioStreamBuilder *builder) const {
+        AAudioStreamBuilder_setChannelCount(builder, mChannelCount);
+        AAudioStreamBuilder_setFormat(builder, mFormat);
+        AAudioStreamBuilder_setSampleRate(builder, mSampleRate);
+        AAudioStreamBuilder_setBufferCapacityInFrames(builder, mBufferCapacity);
+        AAudioStreamBuilder_setDeviceId(builder, mDeviceId);
+        AAudioStreamBuilder_setSharingMode(builder, mSharingMode);
+        AAudioStreamBuilder_setPerformanceMode(builder, mPerformanceMode);
+    }
+
+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;
+
+    int32_t                    mNumberOfBursts = AAUDIO_UNSPECIFIED;
+};
+
+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 'd':
+                    mDurationSeconds = atoi(&arg[2]);
+                    break;
+                case 'm':
+                    AAudio_setMMapPolicy(AAUDIO_POLICY_AUTO);
+                    break;
+                case 'n':
+                    setNumberOfBursts(atoi(&arg[2]));
+                    break;
+                case 'p':
+                    setPerformanceMode(parsePerformanceMode(arg[2]));
+                    break;
+                case 'r':
+                    setSampleRate(atoi(&arg[2]));
+                    break;
+                case 'x':
+                    setSharingMode(AAUDIO_SHARING_MODE_EXCLUSIVE);
+                    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{duration} -m -n{burstsPerBuffer} -p{perfMode} -r{rate} -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("      -d{duration} in seconds, default is %d\n", DEFAULT_DURATION_SECONDS);
+        printf("      -m enable MMAP\n");
+        printf("      -n{numberOfBursts} for setBufferSize\n");
+        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("      -x to use EXCLUSIVE mode\n");
+    }
+
+    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) {
+
+        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);
+        int32_t sizeFrames = AAudioStream_getBufferSizeInFrames(stream);
+        printf("  Buffer:       burst     = %d\n", framesPerBurst);
+        if (framesPerBurst > 0) {
+            printf("  Buffer:       size      = %d = (%d * %d) + %d\n",
+                   sizeFrames,
+                   (sizeFrames / framesPerBurst),
+                   framesPerBurst,
+                   (sizeFrames % framesPerBurst));
+        }
+        printf("  Capacity:     requested = %d, actual = %d\n", getBufferCapacity(),
+               AAudioStream_getBufferCapacityInFrames(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));
+        printf("  Is MMAP used? %s\n", AAudioStream_isMMapUsed(stream)
+               ? "yes" : "no");
+
+    }
+
+    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