1 /*
2  * Copyright 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 package com.mobileer.oboetester;
18 
19 import android.content.res.Resources;
20 
21 import java.util.HashMap;
22 
23 /**
24  * Container for the properties of a Stream.
25  *
26  * This can be used to build a stream, or as a base class for a Stream,
27  * or as a way to report the properties of a Stream.
28  */
29 
30 public class StreamConfiguration {
31     public static final int UNSPECIFIED = 0;
32 
33     // These must match order in Spinner and in native code and in AAudio.h
34     public static final int NATIVE_API_UNSPECIFIED = 0;
35     public static final int NATIVE_API_OPENSLES = 1;
36     public static final int NATIVE_API_AAUDIO = 2;
37 
38     public static final int SHARING_MODE_EXCLUSIVE = 0; // must match AAUDIO
39     public static final int SHARING_MODE_SHARED = 1; // must match AAUDIO
40 
41     public static final int AUDIO_FORMAT_PCM_16 = 1; // must match AAUDIO
42     public static final int AUDIO_FORMAT_PCM_FLOAT = 2; // must match AAUDIO
43     public static final int AUDIO_FORMAT_PCM_24 = 3; // must match AAUDIO
44     public static final int AUDIO_FORMAT_PCM_32 = 4; // must match AAUDIO
45 
46     public static final int DIRECTION_OUTPUT = 0; // must match AAUDIO
47     public static final int DIRECTION_INPUT = 1; // must match AAUDIO
48 
49     public static final int SESSION_ID_NONE = -1; // must match AAUDIO
50     public static final int SESSION_ID_ALLOCATE = 0; // must match AAUDIO
51 
52     public static final int PERFORMANCE_MODE_NONE = 10; // must match AAUDIO
53     public static final int PERFORMANCE_MODE_POWER_SAVING = 11; // must match AAUDIO
54     public static final int PERFORMANCE_MODE_LOW_LATENCY = 12; // must match AAUDIO
55 
56     public static final int RATE_CONVERSION_QUALITY_NONE = 0; // must match Oboe
57     public static final int RATE_CONVERSION_QUALITY_FASTEST = 1; // must match Oboe
58     public static final int RATE_CONVERSION_QUALITY_LOW = 2; // must match Oboe
59     public static final int RATE_CONVERSION_QUALITY_MEDIUM = 3; // must match Oboe
60     public static final int RATE_CONVERSION_QUALITY_HIGH = 4; // must match Oboe
61     public static final int RATE_CONVERSION_QUALITY_BEST = 5; // must match Oboe
62 
63     public static final int STREAM_STATE_STARTING = 3; // must match Oboe
64     public static final int STREAM_STATE_STARTED = 4; // must match Oboe
65 
66     public static final int INPUT_PRESET_GENERIC = 1; // must match Oboe
67     public static final int INPUT_PRESET_CAMCORDER = 5; // must match Oboe
68     public static final int INPUT_PRESET_VOICE_RECOGNITION = 6; // must match Oboe
69     public static final int INPUT_PRESET_VOICE_COMMUNICATION = 7; // must match Oboe
70     public static final int INPUT_PRESET_UNPROCESSED = 9; // must match Oboe
71     public static final int INPUT_PRESET_VOICE_PERFORMANCE = 10; // must match Oboe
72 
73     public static final int ERROR_DISCONNECTED = -899; // must match Oboe
74 
75     public static final int USAGE_MEDIA = 1;
76     public static final int USAGE_VOICE_COMMUNICATION = 2;
77     public static final int USAGE_VOICE_COMMUNICATION_SIGNALLING = 3;
78     public static final int USAGE_ALARM = 4;
79     public static final int USAGE_NOTIFICATION = 5;
80     public static final int USAGE_NOTIFICATION_RINGTONE = 6;
81     public static final int USAGE_NOTIFICATION_EVENT = 10;
82     public static final int USAGE_ASSISTANCE_ACCESSIBILITY = 11;
83     public static final int USAGE_ASSISTANCE_NAVIGATION_GUIDANCE = 12;
84     public static final int USAGE_ASSISTANCE_SONIFICATION = 13;
85     public static final int USAGE_GAME = 14;
86     public static final int USAGE_ASSISTANT = 16;
87 
88     public static final int[] usages = {
89              USAGE_MEDIA,
90             USAGE_VOICE_COMMUNICATION,
91             USAGE_VOICE_COMMUNICATION_SIGNALLING,
92             USAGE_ALARM,
93             USAGE_NOTIFICATION,
94             USAGE_NOTIFICATION_RINGTONE,
95             USAGE_NOTIFICATION_EVENT,
96             USAGE_ASSISTANCE_ACCESSIBILITY,
97             USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
98             USAGE_ASSISTANCE_SONIFICATION,
99             USAGE_GAME,
100             USAGE_ASSISTANT};
101 
102     private int mNativeApi;
103     private int mBufferCapacityInFrames;
104     private int mChannelCount;
105     private int mDeviceId;
106     private int mSessionId;
107     private int mDirection; // does not get reset
108     private int mFormat;
109     private int mSampleRate;
110     private int mSharingMode;
111     private int mPerformanceMode;
112     private boolean mFormatConversionAllowed;
113     private boolean mChannelConversionAllowed;
114     private int mRateConversionQuality;
115     private int mInputPreset;
116     private int mUsage;
117     private static HashMap<String,Integer> mUsageStringToIntegerMap;
118 
119     private int mFramesPerBurst = 0;
120 
121     private boolean mMMap = false;
122 
StreamConfiguration()123     public StreamConfiguration() {
124         reset();
125     }
126 
127     static {
128         // Build map for Usage string-to-int conversion.
129         mUsageStringToIntegerMap = new HashMap<String,Integer>();
130         for (int usage : usages) {
convertUsageToText(usage)131             mUsageStringToIntegerMap.put(convertUsageToText(usage), usage);
132         }
133     }
134 
reset()135     public void reset() {
136         mNativeApi = NATIVE_API_UNSPECIFIED;
137         mBufferCapacityInFrames = UNSPECIFIED;
138         mChannelCount = UNSPECIFIED;
139         mDeviceId = UNSPECIFIED;
140         mSessionId = -1;
141         mFormat = AUDIO_FORMAT_PCM_FLOAT;
142         mSampleRate = UNSPECIFIED;
143         mSharingMode = SHARING_MODE_EXCLUSIVE;
144         mPerformanceMode = PERFORMANCE_MODE_LOW_LATENCY;
145         mInputPreset = INPUT_PRESET_VOICE_RECOGNITION;
146         mUsage = 0; // FIXME add USAGE_*
147         mFormatConversionAllowed = false;
148         mChannelConversionAllowed = false;
149         mRateConversionQuality = RATE_CONVERSION_QUALITY_NONE;
150         mMMap = NativeEngine.isMMapSupported();
151     }
152 
getFramesPerBurst()153     public int getFramesPerBurst() {
154         return mFramesPerBurst;
155     }
156 
setFramesPerBurst(int framesPerBurst)157     public void setFramesPerBurst(int framesPerBurst) {
158         this.mFramesPerBurst = framesPerBurst;
159     }
160 
getBufferCapacityInFrames()161     public int getBufferCapacityInFrames() {
162         return mBufferCapacityInFrames;
163     }
164 
setBufferCapacityInFrames(int bufferCapacityInFrames)165     public void setBufferCapacityInFrames(int bufferCapacityInFrames) {
166         this.mBufferCapacityInFrames = bufferCapacityInFrames;
167     }
168 
getFormat()169     public int getFormat() {
170         return mFormat;
171     }
172 
setFormat(int format)173     public void setFormat(int format) {
174         this.mFormat = format;
175     }
176 
getDirection()177     public int getDirection() {
178         return mDirection;
179     }
180 
setDirection(int direction)181     public void setDirection(int direction) {
182         this.mDirection = direction;
183     }
184 
getPerformanceMode()185     public int getPerformanceMode() {
186         return mPerformanceMode;
187     }
188 
setPerformanceMode(int performanceMode)189     public void setPerformanceMode(int performanceMode) {
190         this.mPerformanceMode = performanceMode;
191     }
192 
convertPerformanceModeToText(int performanceMode)193     static String convertPerformanceModeToText(int performanceMode) {
194         switch(performanceMode) {
195             case PERFORMANCE_MODE_NONE:
196                 return "NO";
197             case PERFORMANCE_MODE_POWER_SAVING:
198                 return "PS";
199             case PERFORMANCE_MODE_LOW_LATENCY:
200                 return "LL";
201             default:
202                 return "??";
203         }
204     }
205 
getInputPreset()206     public int getInputPreset() { return mInputPreset; }
setInputPreset(int inputPreset)207     public void setInputPreset(int inputPreset) {
208         this.mInputPreset = inputPreset;
209     }
210 
getUsage()211     public int getUsage() { return mUsage; }
setUsage(int Usage)212     public void setUsage(int Usage) {
213         this.mUsage = Usage;
214     }
215 
convertUsageToText(int usage)216     static String convertUsageToText(int usage) {
217         switch(usage) {
218             case USAGE_MEDIA:
219                 return "Media";
220             case USAGE_VOICE_COMMUNICATION:
221                 return "VoiceComm";
222             case USAGE_VOICE_COMMUNICATION_SIGNALLING:
223                 return "VoiceCommSig";
224             case USAGE_ALARM:
225                 return "Alarm";
226             case USAGE_NOTIFICATION:
227                 return "Notification";
228             case USAGE_NOTIFICATION_RINGTONE:
229                 return "Ringtone";
230             case USAGE_NOTIFICATION_EVENT:
231                 return "Event";
232             case USAGE_ASSISTANCE_ACCESSIBILITY:
233                 return "Accessability";
234             case USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
235                 return "Navigation";
236             case USAGE_ASSISTANCE_SONIFICATION:
237                 return "Sonification";
238             case USAGE_GAME:
239                 return "Game";
240             case USAGE_ASSISTANT:
241                 return "Assistant";
242             default:
243                 return "?=" + usage;
244         }
245     }
246 
convertTextToUsage(String text)247     public static int convertTextToUsage(String text) {
248         return mUsageStringToIntegerMap.get(text);
249     }
250 
getSharingMode()251     public int getSharingMode() {
252         return mSharingMode;
253     }
254 
setSharingMode(int sharingMode)255     public void setSharingMode(int sharingMode) {
256         this.mSharingMode = sharingMode;
257     }
258 
convertSharingModeToText(int sharingMode)259     static String convertSharingModeToText(int sharingMode) {
260         switch(sharingMode) {
261             case SHARING_MODE_SHARED:
262                 return "SH";
263             case SHARING_MODE_EXCLUSIVE:
264                 return "EX";
265             default:
266                 return "??";
267         }
268     }
269 
convertFormatToText(int format)270     public static String convertFormatToText(int format) {
271         switch(format) {
272             case UNSPECIFIED:
273                 return "Unspecified";
274             case AUDIO_FORMAT_PCM_16:
275                 return "I16";
276             case AUDIO_FORMAT_PCM_24:
277                 return "I24";
278             case AUDIO_FORMAT_PCM_32:
279                 return "I32";
280             case AUDIO_FORMAT_PCM_FLOAT:
281                 return "Float";
282             default:
283                 return "Invalid";
284         }
285     }
286 
convertNativeApiToText(int api)287     public static String convertNativeApiToText(int api) {
288         switch(api) {
289             case NATIVE_API_UNSPECIFIED:
290                 return "Unspec";
291             case NATIVE_API_AAUDIO:
292                 return "AAudio";
293             case NATIVE_API_OPENSLES:
294                 return "OpenSL";
295             default:
296                 return "Invalid";
297         }
298     }
299 
300 
dump()301     public String dump() {
302         String prefix = (getDirection() == DIRECTION_INPUT) ? "in" : "out";
303         StringBuffer message = new StringBuffer();
304         message.append(String.format("%s.channels = %d\n", prefix, mChannelCount));
305         message.append(String.format("%s.perf = %s\n", prefix,
306                 convertPerformanceModeToText(mPerformanceMode).toLowerCase()));
307         if (getDirection() == DIRECTION_INPUT) {
308             message.append(String.format("%s.preset = %s\n", prefix,
309                     convertInputPresetToText(mInputPreset).toLowerCase()));
310         } else {
311             message.append(String.format("%s.preset = %s\n", prefix,
312                     convertUsageToText(mUsage).toLowerCase()));
313         }
314         message.append(String.format("%s.sharing = %s\n", prefix,
315                 convertSharingModeToText(mSharingMode).toLowerCase()));
316         message.append(String.format("%s.api = %s\n", prefix,
317                 convertNativeApiToText(getNativeApi()).toLowerCase()));
318         message.append(String.format("%s.rate = %d\n", prefix, mSampleRate));
319         message.append(String.format("%s.device = %d\n", prefix, mDeviceId));
320         message.append(String.format("%s.mmap = %s\n", prefix, isMMap() ? "yes" : "no"));
321         message.append(String.format("%s.rate.conversion.quality = %d\n", prefix, mRateConversionQuality));
322         return message.toString();
323     }
324 
325     // text must match menu values
326     public static final String NAME_INPUT_PRESET_GENERIC = "Generic";
327     public static final String NAME_INPUT_PRESET_CAMCORDER = "Camcorder";
328     public static final String NAME_INPUT_PRESET_VOICE_RECOGNITION = "VoiceRec";
329     public static final String NAME_INPUT_PRESET_VOICE_COMMUNICATION = "VoiceComm";
330     public static final String NAME_INPUT_PRESET_UNPROCESSED = "Unprocessed";
331     public static final String NAME_INPUT_PRESET_VOICE_PERFORMANCE = "Performance";
332 
convertInputPresetToText(int inputPreset)333     public static String convertInputPresetToText(int inputPreset) {
334         switch(inputPreset) {
335             case INPUT_PRESET_GENERIC:
336                 return NAME_INPUT_PRESET_GENERIC;
337             case INPUT_PRESET_CAMCORDER:
338                 return NAME_INPUT_PRESET_CAMCORDER;
339             case INPUT_PRESET_VOICE_RECOGNITION:
340                 return NAME_INPUT_PRESET_VOICE_RECOGNITION;
341             case INPUT_PRESET_VOICE_COMMUNICATION:
342                 return NAME_INPUT_PRESET_VOICE_COMMUNICATION;
343             case INPUT_PRESET_UNPROCESSED:
344                 return NAME_INPUT_PRESET_UNPROCESSED;
345             case INPUT_PRESET_VOICE_PERFORMANCE:
346                 return NAME_INPUT_PRESET_VOICE_PERFORMANCE;
347             default:
348                 return "Invalid";
349         }
350     }
351 
matchInputPreset(String text, int preset)352     private static boolean matchInputPreset(String text, int preset) {
353         return convertInputPresetToText(preset).toLowerCase().equals(text);
354     }
355 
356     /**
357      * Case insensitive.
358      * @param text
359      * @return inputPreset, eg. INPUT_PRESET_CAMCORDER
360      */
convertTextToInputPreset(String text)361     public static int convertTextToInputPreset(String text) {
362         text = text.toLowerCase();
363         if (matchInputPreset(text, INPUT_PRESET_GENERIC)) {
364             return INPUT_PRESET_GENERIC;
365         } else if (matchInputPreset(text, INPUT_PRESET_CAMCORDER)) {
366             return INPUT_PRESET_CAMCORDER;
367         } else if (matchInputPreset(text, INPUT_PRESET_VOICE_RECOGNITION)) {
368             return INPUT_PRESET_VOICE_RECOGNITION;
369         } else if (matchInputPreset(text, INPUT_PRESET_VOICE_COMMUNICATION)) {
370             return INPUT_PRESET_VOICE_COMMUNICATION;
371         } else if (matchInputPreset(text, INPUT_PRESET_UNPROCESSED)) {
372             return INPUT_PRESET_UNPROCESSED;
373         } else if (matchInputPreset(text, INPUT_PRESET_VOICE_PERFORMANCE)) {
374             return INPUT_PRESET_VOICE_PERFORMANCE;
375         }
376         return -1;
377     }
378 
getChannelCount()379     public int getChannelCount() {
380         return mChannelCount;
381     }
382 
setChannelCount(int channelCount)383     public void setChannelCount(int channelCount) {
384         this.mChannelCount = channelCount;
385     }
386 
getSampleRate()387     public int getSampleRate() {
388         return mSampleRate;
389     }
390 
setSampleRate(int sampleRate)391     public void setSampleRate(int sampleRate) {
392         this.mSampleRate = sampleRate;
393     }
394 
getDeviceId()395     public int getDeviceId() {
396         return mDeviceId;
397     }
398 
setDeviceId(int deviceId)399     public void setDeviceId(int deviceId) {
400         this.mDeviceId = deviceId;
401     }
402 
getSessionId()403     public int getSessionId() {
404         return mSessionId;
405     }
406 
setSessionId(int sessionId)407     public void setSessionId(int sessionId) {
408         mSessionId = sessionId;
409     }
410 
isMMap()411     public boolean isMMap() {
412         return mMMap;
413     }
414 
setMMap(boolean b)415     public void setMMap(boolean b) { mMMap = b; }
416 
getNativeApi()417     public int getNativeApi() {
418         return mNativeApi;
419     }
420 
setNativeApi(int nativeApi)421     public void setNativeApi(int nativeApi) {
422         mNativeApi = nativeApi;
423     }
424 
setChannelConversionAllowed(boolean b)425     public void setChannelConversionAllowed(boolean b) { mChannelConversionAllowed = b; }
426 
getChannelConversionAllowed()427     public boolean getChannelConversionAllowed() {
428         return mChannelConversionAllowed;
429     }
430 
setFormatConversionAllowed(boolean b)431     public void setFormatConversionAllowed(boolean b) {
432         mFormatConversionAllowed = b;
433     }
434 
getFormatConversionAllowed()435     public boolean getFormatConversionAllowed() {
436         return mFormatConversionAllowed;
437     }
438 
setRateConversionQuality(int quality)439     public void setRateConversionQuality(int quality) { mRateConversionQuality = quality; }
440 
getRateConversionQuality()441     public int getRateConversionQuality() {
442         return mRateConversionQuality;
443     }
444 
445 }
446