Home | History | Annotate | Download | only in utils
      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 
     40 static bool s_loadAttempted = false;
     41 static aaudio_usage_t (*s_getUsage)(AAudioStream *stream) = nullptr;
     42 static aaudio_content_type_t (*s_getContentType)(AAudioStream *stream) = nullptr;
     43 static aaudio_input_preset_t (*s_getInputPreset)(AAudioStream *stream) = nullptr;
     44 
     45 // Link to test functions in shared library.
     46 static 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 
     78 error:
     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 
     90 class AAudioParameters {
     91 public:
     92 
     93     /**
     94      * This is also known as samplesPerFrame.
     95      */
     96     int32_t getChannelCount() const {
     97         return mChannelCount;
     98     }
     99 
    100     void setChannelCount(int32_t channelCount) {
    101         if (channelCount > MAX_CHANNELS) {
    102             printf("Sorry, MAX of %d channels!\n", MAX_CHANNELS);
    103             channelCount = MAX_CHANNELS;
    104         }
    105         mChannelCount = channelCount;
    106     }
    107 
    108     int32_t getSampleRate() const {
    109         return mSampleRate;
    110     }
    111 
    112     void setSampleRate(int32_t sampleRate) {
    113         mSampleRate = sampleRate;
    114     }
    115 
    116     aaudio_format_t getFormat() const {
    117         return mFormat;
    118     }
    119 
    120     void setFormat(aaudio_format_t format) {
    121         mFormat = format;
    122     }
    123 
    124     aaudio_sharing_mode_t getSharingMode() const {
    125         return mSharingMode;
    126     }
    127 
    128     void setSharingMode(aaudio_sharing_mode_t sharingMode) {
    129         mSharingMode = sharingMode;
    130     }
    131 
    132     int32_t getBufferCapacity() const {
    133         return mBufferCapacity;
    134     }
    135 
    136     void setBufferCapacity(int32_t frames) {
    137         mBufferCapacity = frames;
    138     }
    139 
    140     int32_t getPerformanceMode() const {
    141         return mPerformanceMode;
    142     }
    143 
    144     void setPerformanceMode(aaudio_performance_mode_t performanceMode) {
    145         mPerformanceMode = performanceMode;
    146     }
    147 
    148     aaudio_usage_t getUsage() const {
    149         return mUsage;
    150     }
    151 
    152     void setUsage(aaudio_usage_t usage) {
    153         mUsage = usage;
    154     }
    155 
    156     aaudio_content_type_t getContentType() const {
    157         return mContentType;
    158     }
    159 
    160     void setContentType(aaudio_content_type_t contentType) {
    161         mContentType = contentType;
    162     }
    163 
    164     aaudio_input_preset_t getInputPreset() const {
    165         return mInputPreset;
    166     }
    167 
    168     void setInputPreset(aaudio_input_preset_t inputPreset) {
    169         mInputPreset = inputPreset;
    170     }
    171 
    172     int32_t getDeviceId() const {
    173         return mDeviceId;
    174     }
    175 
    176     void setDeviceId(int32_t deviceId) {
    177         mDeviceId = deviceId;
    178     }
    179 
    180     int32_t getNumberOfBursts() const {
    181         return mNumberOfBursts;
    182     }
    183 
    184     void setNumberOfBursts(int32_t numBursts) {
    185         mNumberOfBursts = numBursts;
    186     }
    187 
    188     /**
    189      * Apply these parameters to a stream builder.
    190      * @param builder
    191      */
    192     void applyParameters(AAudioStreamBuilder *builder) const {
    193         AAudioStreamBuilder_setChannelCount(builder, mChannelCount);
    194         AAudioStreamBuilder_setFormat(builder, mFormat);
    195         AAudioStreamBuilder_setSampleRate(builder, mSampleRate);
    196         AAudioStreamBuilder_setBufferCapacityInFrames(builder, mBufferCapacity);
    197         AAudioStreamBuilder_setDeviceId(builder, mDeviceId);
    198         AAudioStreamBuilder_setSharingMode(builder, mSharingMode);
    199         AAudioStreamBuilder_setPerformanceMode(builder, mPerformanceMode);
    200 
    201         // Call P functions if supported.
    202         loadFutureFunctions();
    203         if (s_setUsage != nullptr) {
    204             s_setUsage(builder, mUsage);
    205         } else if (mUsage != AAUDIO_UNSPECIFIED){
    206             printf("WARNING: setUsage not supported");
    207         }
    208         if (s_setContentType != nullptr) {
    209             s_setContentType(builder, mContentType);
    210         } else if (mUsage != AAUDIO_UNSPECIFIED){
    211             printf("WARNING: setContentType not supported");
    212         }
    213         if (s_setInputPreset != nullptr) {
    214             s_setInputPreset(builder, mInputPreset);
    215         } else if (mUsage != AAUDIO_UNSPECIFIED){
    216             printf("WARNING: setInputPreset not supported");
    217         }
    218     }
    219 
    220 private:
    221     int32_t                    mChannelCount    = AAUDIO_UNSPECIFIED;
    222     aaudio_format_t            mFormat          = AAUDIO_FORMAT_UNSPECIFIED;
    223     int32_t                    mSampleRate      = AAUDIO_UNSPECIFIED;
    224 
    225     int32_t                    mBufferCapacity  = AAUDIO_UNSPECIFIED;
    226     int32_t                    mDeviceId        = AAUDIO_UNSPECIFIED;
    227     aaudio_sharing_mode_t      mSharingMode     = AAUDIO_SHARING_MODE_SHARED;
    228     aaudio_performance_mode_t  mPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE;
    229 
    230     aaudio_usage_t             mUsage           = AAUDIO_UNSPECIFIED;
    231     aaudio_content_type_t      mContentType     = AAUDIO_UNSPECIFIED;
    232     aaudio_input_preset_t      mInputPreset     = AAUDIO_UNSPECIFIED;
    233 
    234     int32_t                    mNumberOfBursts  = AAUDIO_UNSPECIFIED;
    235 };
    236 
    237 class AAudioArgsParser : public AAudioParameters {
    238 public:
    239     AAudioArgsParser() = default;
    240     ~AAudioArgsParser() = default;
    241 
    242     enum {
    243         DEFAULT_DURATION_SECONDS = 5
    244     };
    245 
    246     /**
    247      * @param arg
    248      * @return true if the argument was not handled
    249      */
    250     bool parseArg(const char *arg) {
    251         bool unrecognized = false;
    252         if (arg[0] == '-') {
    253             char option = arg[1];
    254             switch (option) {
    255                 case 'b':
    256                     setBufferCapacity(atoi(&arg[2]));
    257                     break;
    258                 case 'c':
    259                     setChannelCount(atoi(&arg[2]));
    260                     break;
    261                 case 'd':
    262                     setDeviceId(atoi(&arg[2]));
    263                     break;
    264                 case 'f':
    265                     setFormat(atoi(&arg[2]));
    266                     break;
    267                 case 'i':
    268                     setInputPreset(atoi(&arg[2]));
    269                     break;
    270                 case 'm': {
    271                     aaudio_policy_t policy = AAUDIO_POLICY_AUTO;
    272                     if (strlen(arg) > 2) {
    273                         policy = atoi(&arg[2]);
    274                     }
    275                     AAudio_setMMapPolicy(policy);
    276                 } break;
    277                 case 'n':
    278                     setNumberOfBursts(atoi(&arg[2]));
    279                     break;
    280                 case 'p':
    281                     setPerformanceMode(parsePerformanceMode(arg[2]));
    282                     break;
    283                 case 'r':
    284                     setSampleRate(atoi(&arg[2]));
    285                     break;
    286                 case 's':
    287                     mDurationSeconds = atoi(&arg[2]);
    288                     break;
    289                 case 'u':
    290                     setUsage(atoi(&arg[2]));
    291                     break;
    292                 case 'x':
    293                     setSharingMode(AAUDIO_SHARING_MODE_EXCLUSIVE);
    294                     break;
    295                 case 'y':
    296                     setContentType(atoi(&arg[2]));
    297                     break;
    298                 default:
    299                     unrecognized = true;
    300                     break;
    301             }
    302         }
    303         return unrecognized;
    304     }
    305 
    306     /**
    307      *
    308      * @param argc
    309      * @param argv
    310      * @return true if an unrecognized argument was passed
    311      */
    312     bool parseArgs(int argc, const char **argv) {
    313         for (int i = 1; i < argc; i++) {
    314             const char *arg = argv[i];
    315             if (parseArg(arg)) {
    316                 usage();
    317                 return true;
    318             }
    319 
    320         }
    321         return false;
    322     }
    323 
    324     static void usage() {
    325         printf("-c{channels} -d{deviceId} -m{mmapPolicy} -n{burstsPerBuffer} -p{perfMode}");
    326         printf(" -r{rate} -s{seconds} -x\n");
    327         printf("      Default values are UNSPECIFIED unless otherwise stated.\n");
    328         printf("      -b{bufferCapacity} frames\n");
    329         printf("      -c{channels} for example 2 for stereo\n");
    330         printf("      -d{deviceId} default is %d\n", AAUDIO_UNSPECIFIED);
    331         printf("      -f{0|1|2} set format\n");
    332         printf("          0 = UNSPECIFIED\n");
    333         printf("          1 = PCM_I16\n");
    334         printf("          2 = FLOAT\n");
    335         printf("      -i{inputPreset} eg. 5 for AAUDIO_INPUT_PRESET_CAMCORDER\n");
    336         printf("      -m{0|1|2|3} set MMAP policy\n");
    337         printf("          0 = _UNSPECIFIED, use aaudio.mmap_policy system property, default\n");
    338         printf("          1 = _NEVER, never use MMAP\n");
    339         printf("          2 = _AUTO, use MMAP if available, default for -m with no number\n");
    340         printf("          3 = _ALWAYS, use MMAP or fail\n");
    341         printf("      -n{numberOfBursts} for setBufferSize\n");
    342         printf("      -p{performanceMode} set output AAUDIO_PERFORMANCE_MODE*, default NONE\n");
    343         printf("          n for _NONE\n");
    344         printf("          l for _LATENCY\n");
    345         printf("          p for _POWER_SAVING;\n");
    346         printf("      -r{sampleRate} for example 44100\n");
    347         printf("      -s{duration} in seconds, default is %d\n", DEFAULT_DURATION_SECONDS);
    348         printf("      -u{usage} eg. 14 for AAUDIO_USAGE_GAME\n");
    349         printf("      -x to use EXCLUSIVE mode\n");
    350         printf("      -y{contentType} eg. 1 for AAUDIO_CONTENT_TYPE_SPEECH\n");
    351     }
    352 
    353     static aaudio_performance_mode_t parsePerformanceMode(char c) {
    354         aaudio_performance_mode_t mode = AAUDIO_PERFORMANCE_MODE_NONE;
    355         switch (c) {
    356             case 'n':
    357                 mode = AAUDIO_PERFORMANCE_MODE_NONE;
    358                 break;
    359             case 'l':
    360                 mode = AAUDIO_PERFORMANCE_MODE_LOW_LATENCY;
    361                 break;
    362             case 'p':
    363                 mode = AAUDIO_PERFORMANCE_MODE_POWER_SAVING;
    364                 break;
    365             default:
    366                 printf("ERROR invalid performance mode %c\n", c);
    367                 break;
    368         }
    369         return mode;
    370     }
    371 
    372     /**
    373      * Print stream parameters in comparison with requested values.
    374      * @param stream
    375      */
    376     void compareWithStream(AAudioStream *stream) const {
    377 
    378         printf("  DeviceId:     requested = %d, actual = %d\n",
    379                getDeviceId(), AAudioStream_getDeviceId(stream));
    380 
    381         aaudio_stream_state_t state = AAudioStream_getState(stream);
    382         printf("  State:        %s\n", AAudio_convertStreamStateToText(state));
    383 
    384         // Check to see what kind of stream we actually got.
    385         printf("  SampleRate:   requested = %d, actual = %d\n",
    386                getSampleRate(), AAudioStream_getSampleRate(stream));
    387 
    388         printf("  ChannelCount: requested = %d, actual = %d\n",
    389                getChannelCount(), AAudioStream_getChannelCount(stream));
    390 
    391         printf("  DataFormat:   requested = %d, actual = %d\n",
    392                getFormat(), AAudioStream_getFormat(stream));
    393 
    394         int32_t framesPerBurst = AAudioStream_getFramesPerBurst(stream);
    395         int32_t sizeFrames = AAudioStream_getBufferSizeInFrames(stream);
    396         printf("  Buffer:       burst     = %d\n", framesPerBurst);
    397         if (framesPerBurst > 0) {
    398             printf("  Buffer:       size      = %d = (%d * %d) + %d\n",
    399                    sizeFrames,
    400                    (sizeFrames / framesPerBurst),
    401                    framesPerBurst,
    402                    (sizeFrames % framesPerBurst));
    403         }
    404         printf("  Capacity:     requested = %d, actual = %d\n", getBufferCapacity(),
    405                AAudioStream_getBufferCapacityInFrames(stream));
    406 
    407         printf("  SharingMode:  requested = %s, actual = %s\n",
    408                getSharingModeText(getSharingMode()),
    409                getSharingModeText(AAudioStream_getSharingMode(stream)));
    410 
    411         printf("  PerformanceMode: requested = %d, actual = %d\n",
    412                getPerformanceMode(), AAudioStream_getPerformanceMode(stream));
    413 
    414         loadFutureFunctions();
    415 
    416         if (s_setUsage != nullptr) {
    417             printf("  Usage:        requested = %d, actual = %d\n",
    418                    getUsage(), s_getUsage(stream));
    419         }
    420         if (s_getContentType != nullptr) {
    421             printf("  ContentType:  requested = %d, actual = %d\n",
    422                    getContentType(), s_getContentType(stream));
    423         }
    424 
    425         if (AAudioStream_getDirection(stream) == AAUDIO_DIRECTION_INPUT
    426             && s_getInputPreset != nullptr) {
    427                 printf("  InputPreset:  requested = %d, actual = %d\n",
    428                        getInputPreset(), s_getInputPreset(stream));
    429         }
    430 
    431         printf("  Is MMAP used? %s\n", AAudioStream_isMMapUsed(stream)
    432                ? "yes" : "no");
    433 
    434     }
    435 
    436     int32_t getDurationSeconds() const {
    437         return mDurationSeconds;
    438     }
    439 
    440     void setDurationSeconds(int32_t seconds) {
    441         mDurationSeconds = seconds;
    442     }
    443 
    444 private:
    445     int32_t      mDurationSeconds = DEFAULT_DURATION_SECONDS;
    446 };
    447 
    448 #endif // AAUDIO_EXAMPLE_ARGS_PARSER_H
    449