• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
loadFutureFunctions()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      */
getChannelCount()96     int32_t getChannelCount() const {
97         return mChannelCount;
98     }
99 
setChannelCount(int32_t channelCount)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 
getSampleRate()108     int32_t getSampleRate() const {
109         return mSampleRate;
110     }
111 
setSampleRate(int32_t sampleRate)112     void setSampleRate(int32_t sampleRate) {
113         mSampleRate = sampleRate;
114     }
115 
getFormat()116     aaudio_format_t getFormat() const {
117         return mFormat;
118     }
119 
setFormat(aaudio_format_t format)120     void setFormat(aaudio_format_t format) {
121         mFormat = format;
122     }
123 
getSharingMode()124     aaudio_sharing_mode_t getSharingMode() const {
125         return mSharingMode;
126     }
127 
setSharingMode(aaudio_sharing_mode_t sharingMode)128     void setSharingMode(aaudio_sharing_mode_t sharingMode) {
129         mSharingMode = sharingMode;
130     }
131 
getBufferCapacity()132     int32_t getBufferCapacity() const {
133         return mBufferCapacity;
134     }
135 
setBufferCapacity(int32_t frames)136     void setBufferCapacity(int32_t frames) {
137         mBufferCapacity = frames;
138     }
139 
getPerformanceMode()140     int32_t getPerformanceMode() const {
141         return mPerformanceMode;
142     }
143 
setPerformanceMode(aaudio_performance_mode_t performanceMode)144     void setPerformanceMode(aaudio_performance_mode_t performanceMode) {
145         mPerformanceMode = performanceMode;
146     }
147 
getUsage()148     aaudio_usage_t getUsage() const {
149         return mUsage;
150     }
151 
setUsage(aaudio_usage_t usage)152     void setUsage(aaudio_usage_t usage) {
153         mUsage = usage;
154     }
155 
getContentType()156     aaudio_content_type_t getContentType() const {
157         return mContentType;
158     }
159 
setContentType(aaudio_content_type_t contentType)160     void setContentType(aaudio_content_type_t contentType) {
161         mContentType = contentType;
162     }
163 
getInputPreset()164     aaudio_input_preset_t getInputPreset() const {
165         return mInputPreset;
166     }
167 
setInputPreset(aaudio_input_preset_t inputPreset)168     void setInputPreset(aaudio_input_preset_t inputPreset) {
169         mInputPreset = inputPreset;
170     }
171 
getDeviceId()172     int32_t getDeviceId() const {
173         return mDeviceId;
174     }
175 
setDeviceId(int32_t deviceId)176     void setDeviceId(int32_t deviceId) {
177         mDeviceId = deviceId;
178     }
179 
getNumberOfBursts()180     int32_t getNumberOfBursts() const {
181         return mNumberOfBursts;
182     }
183 
setNumberOfBursts(int32_t numBursts)184     void setNumberOfBursts(int32_t numBursts) {
185         mNumberOfBursts = numBursts;
186     }
187 
188     /**
189      * Apply these parameters to a stream builder.
190      * @param builder
191      */
applyParameters(AAudioStreamBuilder * builder)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      */
parseArg(const char * arg)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      */
parseArgs(int argc,const char ** argv)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 
usage()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 
parsePerformanceMode(char c)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      */
compareWithStream(AAudioStream * stream)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 
getDurationSeconds()436     int32_t getDurationSeconds() const {
437         return mDurationSeconds;
438     }
439 
setDurationSeconds(int32_t seconds)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