• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 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 #define LOG_TAG "AAudio"
18 //#define LOG_NDEBUG 0
19 #include <utils/Log.h>
20 
21 #include <cutils/properties.h>
22 #include <stdint.h>
23 #include <sys/types.h>
24 #include <utils/Errors.h>
25 
26 #include "aaudio/AAudio.h"
27 #include <aaudio/AAudioTesting.h>
28 
29 #include "utility/AAudioUtilities.h"
30 
31 using namespace android;
32 
33 // This is 3 dB, (10^(3/20)), to match the maximum headroom in AudioTrack for float data.
34 // It is designed to allow occasional transient peaks.
35 #define MAX_HEADROOM (1.41253754f)
36 #define MIN_HEADROOM (0 - MAX_HEADROOM)
37 
AAudioConvert_formatToSizeInBytes(aaudio_format_t format)38 int32_t AAudioConvert_formatToSizeInBytes(aaudio_format_t format) {
39     int32_t size = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
40     switch (format) {
41         case AAUDIO_FORMAT_PCM_I16:
42             size = sizeof(int16_t);
43             break;
44         case AAUDIO_FORMAT_PCM_FLOAT:
45             size = sizeof(float);
46             break;
47         default:
48             break;
49     }
50     return size;
51 }
52 
53 
54 // TODO expose and call clamp16_from_float function in primitives.h
clamp16_from_float(float f)55 static inline int16_t clamp16_from_float(float f) {
56     /* Offset is used to expand the valid range of [-1.0, 1.0) into the 16 lsbs of the
57      * floating point significand. The normal shift is 3<<22, but the -15 offset
58      * is used to multiply by 32768.
59      */
60     static const float offset = (float)(3 << (22 - 15));
61     /* zero = (0x10f << 22) =  0x43c00000 (not directly used) */
62     static const int32_t limneg = (0x10f << 22) /*zero*/ - 32768; /* 0x43bf8000 */
63     static const int32_t limpos = (0x10f << 22) /*zero*/ + 32767; /* 0x43c07fff */
64 
65     union {
66         float f;
67         int32_t i;
68     } u;
69 
70     u.f = f + offset; /* recenter valid range */
71     /* Now the valid range is represented as integers between [limneg, limpos].
72      * Clamp using the fact that float representation (as an integer) is an ordered set.
73      */
74     if (u.i < limneg)
75         u.i = -32768;
76     else if (u.i > limpos)
77         u.i = 32767;
78     return u.i; /* Return lower 16 bits, the part of interest in the significand. */
79 }
80 
81 // Same but without clipping.
82 // Convert -1.0f to +1.0f to -32768 to +32767
floatToInt16(float f)83 static inline int16_t floatToInt16(float f) {
84     static const float offset = (float)(3 << (22 - 15));
85     union {
86         float f;
87         int32_t i;
88     } u;
89     u.f = f + offset; /* recenter valid range */
90     return u.i; /* Return lower 16 bits, the part of interest in the significand. */
91 }
92 
clipAndClampFloatToPcm16(float sample,float scaler)93 static float clipAndClampFloatToPcm16(float sample, float scaler) {
94     // Clip to valid range of a float sample to prevent excessive volume.
95     if (sample > MAX_HEADROOM) sample = MAX_HEADROOM;
96     else if (sample < MIN_HEADROOM) sample = MIN_HEADROOM;
97 
98     // Scale and convert to a short.
99     float fval = sample * scaler;
100     return clamp16_from_float(fval);
101 }
102 
AAudioConvert_floatToPcm16(const float * source,int16_t * destination,int32_t numSamples,float amplitude)103 void AAudioConvert_floatToPcm16(const float *source,
104                                 int16_t *destination,
105                                 int32_t numSamples,
106                                 float amplitude) {
107     float scaler = amplitude;
108     for (int i = 0; i < numSamples; i++) {
109         float sample = *source++;
110         *destination++ = clipAndClampFloatToPcm16(sample, scaler);
111     }
112 }
113 
AAudioConvert_floatToPcm16(const float * source,int16_t * destination,int32_t numFrames,int32_t samplesPerFrame,float amplitude1,float amplitude2)114 void AAudioConvert_floatToPcm16(const float *source,
115                                 int16_t *destination,
116                                 int32_t numFrames,
117                                 int32_t samplesPerFrame,
118                                 float amplitude1,
119                                 float amplitude2) {
120     float scaler = amplitude1;
121     // divide by numFrames so that we almost reach amplitude2
122     float delta = (amplitude2 - amplitude1) / numFrames;
123     for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) {
124         for (int sampleIndex = 0; sampleIndex < samplesPerFrame; sampleIndex++) {
125             float sample = *source++;
126             *destination++ = clipAndClampFloatToPcm16(sample, scaler);
127         }
128         scaler += delta;
129     }
130 }
131 
132 #define SHORT_SCALE  32768
133 
AAudioConvert_pcm16ToFloat(const int16_t * source,float * destination,int32_t numSamples,float amplitude)134 void AAudioConvert_pcm16ToFloat(const int16_t *source,
135                                 float *destination,
136                                 int32_t numSamples,
137                                 float amplitude) {
138     float scaler = amplitude / SHORT_SCALE;
139     for (int i = 0; i < numSamples; i++) {
140         destination[i] = source[i] * scaler;
141     }
142 }
143 
144 // This code assumes amplitude1 and amplitude2 are between 0.0 and 1.0
AAudioConvert_pcm16ToFloat(const int16_t * source,float * destination,int32_t numFrames,int32_t samplesPerFrame,float amplitude1,float amplitude2)145 void AAudioConvert_pcm16ToFloat(const int16_t *source,
146                                 float *destination,
147                                 int32_t numFrames,
148                                 int32_t samplesPerFrame,
149                                 float amplitude1,
150                                 float amplitude2) {
151     float scaler = amplitude1 / SHORT_SCALE;
152     float delta = (amplitude2 - amplitude1) / (SHORT_SCALE * (float) numFrames);
153     for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) {
154         for (int sampleIndex = 0; sampleIndex < samplesPerFrame; sampleIndex++) {
155             *destination++ = *source++ * scaler;
156         }
157         scaler += delta;
158     }
159 }
160 
161 // This code assumes amplitude1 and amplitude2 are between 0.0 and 1.0
AAudio_linearRamp(const float * source,float * destination,int32_t numFrames,int32_t samplesPerFrame,float amplitude1,float amplitude2)162 void AAudio_linearRamp(const float *source,
163                        float *destination,
164                        int32_t numFrames,
165                        int32_t samplesPerFrame,
166                        float amplitude1,
167                        float amplitude2) {
168     float scaler = amplitude1;
169     float delta = (amplitude2 - amplitude1) / numFrames;
170     for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) {
171         for (int sampleIndex = 0; sampleIndex < samplesPerFrame; sampleIndex++) {
172             float sample = *source++;
173 
174             // Clip to valid range of a float sample to prevent excessive volume.
175             if (sample > MAX_HEADROOM) sample = MAX_HEADROOM;
176             else if (sample < MIN_HEADROOM) sample = MIN_HEADROOM;
177 
178             *destination++ = sample * scaler;
179         }
180         scaler += delta;
181     }
182 }
183 
184 // This code assumes amplitude1 and amplitude2 are between 0.0 and 1.0
AAudio_linearRamp(const int16_t * source,int16_t * destination,int32_t numFrames,int32_t samplesPerFrame,float amplitude1,float amplitude2)185 void AAudio_linearRamp(const int16_t *source,
186                        int16_t *destination,
187                        int32_t numFrames,
188                        int32_t samplesPerFrame,
189                        float amplitude1,
190                        float amplitude2) {
191     float scaler = amplitude1 / SHORT_SCALE;
192     float delta = (amplitude2 - amplitude1) / (SHORT_SCALE * (float) numFrames);
193     for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) {
194         for (int sampleIndex = 0; sampleIndex < samplesPerFrame; sampleIndex++) {
195             // No need to clip because int16_t range is inherently limited.
196             float sample =  *source++ * scaler;
197             *destination++ =  floatToInt16(sample);
198         }
199         scaler += delta;
200     }
201 }
202 
AAudioConvert_aaudioToAndroidStatus(aaudio_result_t result)203 status_t AAudioConvert_aaudioToAndroidStatus(aaudio_result_t result) {
204     // This covers the case for AAUDIO_OK and for positive results.
205     if (result >= 0) {
206         return result;
207     }
208     status_t status;
209     switch (result) {
210     case AAUDIO_ERROR_DISCONNECTED:
211     case AAUDIO_ERROR_NO_SERVICE:
212         status = DEAD_OBJECT;
213         break;
214     case AAUDIO_ERROR_INVALID_HANDLE:
215         status = BAD_TYPE;
216         break;
217     case AAUDIO_ERROR_INVALID_STATE:
218         status = INVALID_OPERATION;
219         break;
220     case AAUDIO_ERROR_INVALID_RATE:
221     case AAUDIO_ERROR_INVALID_FORMAT:
222     case AAUDIO_ERROR_ILLEGAL_ARGUMENT:
223     case AAUDIO_ERROR_OUT_OF_RANGE:
224         status = BAD_VALUE;
225         break;
226     case AAUDIO_ERROR_WOULD_BLOCK:
227         status = WOULD_BLOCK;
228         break;
229     case AAUDIO_ERROR_NULL:
230         status = UNEXPECTED_NULL;
231         break;
232     case AAUDIO_ERROR_UNAVAILABLE:
233         status = NOT_ENOUGH_DATA;
234         break;
235 
236     // TODO translate these result codes
237     case AAUDIO_ERROR_INTERNAL:
238     case AAUDIO_ERROR_UNIMPLEMENTED:
239     case AAUDIO_ERROR_NO_FREE_HANDLES:
240     case AAUDIO_ERROR_NO_MEMORY:
241     case AAUDIO_ERROR_TIMEOUT:
242     default:
243         status = UNKNOWN_ERROR;
244         break;
245     }
246     return status;
247 }
248 
AAudioConvert_androidToAAudioResult(status_t status)249 aaudio_result_t AAudioConvert_androidToAAudioResult(status_t status) {
250     // This covers the case for OK and for positive result.
251     if (status >= 0) {
252         return status;
253     }
254     aaudio_result_t result;
255     switch (status) {
256     case BAD_TYPE:
257         result = AAUDIO_ERROR_INVALID_HANDLE;
258         break;
259     case DEAD_OBJECT:
260         result = AAUDIO_ERROR_NO_SERVICE;
261         break;
262     case INVALID_OPERATION:
263         result = AAUDIO_ERROR_INVALID_STATE;
264         break;
265     case UNEXPECTED_NULL:
266         result = AAUDIO_ERROR_NULL;
267         break;
268     case BAD_VALUE:
269         result = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
270         break;
271     case WOULD_BLOCK:
272         result = AAUDIO_ERROR_WOULD_BLOCK;
273         break;
274     case NOT_ENOUGH_DATA:
275         result = AAUDIO_ERROR_UNAVAILABLE;
276         break;
277     default:
278         result = AAUDIO_ERROR_INTERNAL;
279         break;
280     }
281     return result;
282 }
283 
AAudioConvert_aaudioToAndroidDataFormat(aaudio_format_t aaudioFormat)284 audio_format_t AAudioConvert_aaudioToAndroidDataFormat(aaudio_format_t aaudioFormat) {
285     audio_format_t androidFormat;
286     switch (aaudioFormat) {
287     case AAUDIO_FORMAT_PCM_I16:
288         androidFormat = AUDIO_FORMAT_PCM_16_BIT;
289         break;
290     case AAUDIO_FORMAT_PCM_FLOAT:
291         androidFormat = AUDIO_FORMAT_PCM_FLOAT;
292         break;
293     default:
294         androidFormat = AUDIO_FORMAT_DEFAULT;
295         ALOGE("AAudioConvert_aaudioToAndroidDataFormat 0x%08X unrecognized", aaudioFormat);
296         break;
297     }
298     return androidFormat;
299 }
300 
AAudioConvert_androidToAAudioDataFormat(audio_format_t androidFormat)301 aaudio_format_t AAudioConvert_androidToAAudioDataFormat(audio_format_t androidFormat) {
302     aaudio_format_t aaudioFormat = AAUDIO_FORMAT_INVALID;
303     switch (androidFormat) {
304     case AUDIO_FORMAT_PCM_16_BIT:
305         aaudioFormat = AAUDIO_FORMAT_PCM_I16;
306         break;
307     case AUDIO_FORMAT_PCM_FLOAT:
308         aaudioFormat = AAUDIO_FORMAT_PCM_FLOAT;
309         break;
310     default:
311         aaudioFormat = AAUDIO_FORMAT_INVALID;
312         ALOGE("AAudioConvert_androidToAAudioDataFormat 0x%08X unrecognized", androidFormat);
313         break;
314     }
315     return aaudioFormat;
316 }
317 
AAudioConvert_framesToBytes(int32_t numFrames,int32_t bytesPerFrame,int32_t * sizeInBytes)318 int32_t AAudioConvert_framesToBytes(int32_t numFrames,
319                                             int32_t bytesPerFrame,
320                                             int32_t *sizeInBytes) {
321     // TODO implement more elegantly
322     const int32_t maxChannels = 256; // ridiculously large
323     const int32_t maxBytesPerFrame = maxChannels * sizeof(float);
324     // Prevent overflow by limiting multiplicands.
325     if (bytesPerFrame > maxBytesPerFrame || numFrames > (0x3FFFFFFF / maxBytesPerFrame)) {
326         ALOGE("size overflow, numFrames = %d, frameSize = %zd", numFrames, bytesPerFrame);
327         return AAUDIO_ERROR_OUT_OF_RANGE;
328     }
329     *sizeInBytes = numFrames * bytesPerFrame;
330     return AAUDIO_OK;
331 }
332 
AAudioProperty_getMMapProperty(const char * propName,int32_t defaultValue,const char * caller)333 static int32_t AAudioProperty_getMMapProperty(const char *propName,
334                                               int32_t defaultValue,
335                                               const char * caller) {
336     int32_t prop = property_get_int32(propName, defaultValue);
337     switch (prop) {
338         case AAUDIO_UNSPECIFIED:
339         case AAUDIO_POLICY_NEVER:
340         case AAUDIO_POLICY_ALWAYS:
341         case AAUDIO_POLICY_AUTO:
342             break;
343         default:
344             ALOGE("%s: invalid = %d", caller, prop);
345             prop = defaultValue;
346             break;
347     }
348     return prop;
349 }
350 
AAudioProperty_getMMapPolicy()351 int32_t AAudioProperty_getMMapPolicy() {
352     return AAudioProperty_getMMapProperty(AAUDIO_PROP_MMAP_POLICY,
353                                           AAUDIO_UNSPECIFIED, __func__);
354 }
355 
AAudioProperty_getMMapExclusivePolicy()356 int32_t AAudioProperty_getMMapExclusivePolicy() {
357     return AAudioProperty_getMMapProperty(AAUDIO_PROP_MMAP_EXCLUSIVE_POLICY,
358                                           AAUDIO_UNSPECIFIED, __func__);
359 }
360 
AAudioProperty_getMixerBursts()361 int32_t AAudioProperty_getMixerBursts() {
362     const int32_t defaultBursts = 2; // arbitrary, use 2 for double buffered
363     const int32_t maxBursts = 1024; // arbitrary
364     int32_t prop = property_get_int32(AAUDIO_PROP_MIXER_BURSTS, defaultBursts);
365     if (prop < 1 || prop > maxBursts) {
366         ALOGE("AAudioProperty_getMixerBursts: invalid = %d", prop);
367         prop = defaultBursts;
368     }
369     return prop;
370 }
371 
AAudioProperty_getWakeupDelayMicros()372 int32_t AAudioProperty_getWakeupDelayMicros() {
373     const int32_t minMicros = 0; // arbitrary
374     const int32_t defaultMicros = 200; // arbitrary, based on some observed jitter
375     const int32_t maxMicros = 5000; // arbitrary, probably don't want more than 500
376     int32_t prop = property_get_int32(AAUDIO_PROP_WAKEUP_DELAY_USEC, defaultMicros);
377     if (prop < minMicros) {
378         ALOGW("AAudioProperty_getWakeupDelayMicros: clipped %d to %d", prop, minMicros);
379         prop = minMicros;
380     } else if (prop > maxMicros) {
381         ALOGW("AAudioProperty_getWakeupDelayMicros: clipped %d to %d", prop, maxMicros);
382         prop = maxMicros;
383     }
384     return prop;
385 }
386 
AAudioProperty_getMinimumSleepMicros()387 int32_t AAudioProperty_getMinimumSleepMicros() {
388     const int32_t minMicros = 20; // arbitrary
389     const int32_t defaultMicros = 200; // arbitrary
390     const int32_t maxMicros = 2000; // arbitrary
391     int32_t prop = property_get_int32(AAUDIO_PROP_MINIMUM_SLEEP_USEC, defaultMicros);
392     if (prop < minMicros) {
393         ALOGW("AAudioProperty_getMinimumSleepMicros: clipped %d to %d", prop, minMicros);
394         prop = minMicros;
395     } else if (prop > maxMicros) {
396         ALOGW("AAudioProperty_getMinimumSleepMicros: clipped %d to %d", prop, maxMicros);
397         prop = maxMicros;
398     }
399     return prop;
400 }
401 
AAudioProperty_getHardwareBurstMinMicros()402 int32_t AAudioProperty_getHardwareBurstMinMicros() {
403     const int32_t defaultMicros = 1000; // arbitrary
404     const int32_t maxMicros = 1000 * 1000; // arbitrary
405     int32_t prop = property_get_int32(AAUDIO_PROP_HW_BURST_MIN_USEC, defaultMicros);
406     if (prop < 1 || prop > maxMicros) {
407         ALOGE("AAudioProperty_getHardwareBurstMinMicros: invalid = %d, use %d",
408               prop, defaultMicros);
409         prop = defaultMicros;
410     }
411     return prop;
412 }
413