blob: a3198d7ed68099253888c928fa11a990e29bead0 [file] [log] [blame]
Phil Burk5ed503c2017-02-01 09:38:15 -08001/*
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
Phil Burkc8f69a02017-05-11 15:53:06 -070021#include <cutils/properties.h>
Phil Burk5ed503c2017-02-01 09:38:15 -080022#include <stdint.h>
23#include <sys/types.h>
24#include <utils/Errors.h>
25
Phil Burka4eb0d82017-04-12 15:44:06 -070026#include "aaudio/AAudio.h"
Phil Burkd04aeea2017-05-23 13:56:41 -070027#include <aaudio/AAudioTesting.h>
28
29#include "utility/AAudioUtilities.h"
Phil Burk5ed503c2017-02-01 09:38:15 -080030
31using namespace android;
32
Phil Burke572f462017-04-20 13:03:19 -070033// 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
Phil Burk9dca9822017-05-26 14:27:43 -070038int32_t AAudioConvert_formatToSizeInBytes(aaudio_format_t format) {
Phil Burk3316d5e2017-02-15 11:23:01 -080039 int32_t size = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
Phil Burk5ed503c2017-02-01 09:38:15 -080040 switch (format) {
41 case AAUDIO_FORMAT_PCM_I16:
42 size = sizeof(int16_t);
43 break;
Phil Burk5ed503c2017-02-01 09:38:15 -080044 case AAUDIO_FORMAT_PCM_FLOAT:
45 size = sizeof(float);
46 break;
47 default:
48 break;
49 }
50 return size;
51}
52
Phil Burke572f462017-04-20 13:03:19 -070053
Phil Burk5204d312017-05-04 17:16:13 -070054// TODO expose and call clamp16_from_float function in primitives.h
Phil Burke572f462017-04-20 13:03:19 -070055static 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
83static 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
93static 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
103void AAudioConvert_floatToPcm16(const float *source,
104 int16_t *destination,
105 int32_t numSamples,
106 float amplitude) {
107 float scaler = amplitude;
Phil Burk5ed503c2017-02-01 09:38:15 -0800108 for (int i = 0; i < numSamples; i++) {
Phil Burke572f462017-04-20 13:03:19 -0700109 float sample = *source++;
110 *destination++ = clipAndClampFloatToPcm16(sample, scaler);
Phil Burk5ed503c2017-02-01 09:38:15 -0800111 }
112}
113
Phil Burke572f462017-04-20 13:03:19 -0700114void 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
134void AAudioConvert_pcm16ToFloat(const int16_t *source,
135 float *destination,
136 int32_t numSamples,
137 float amplitude) {
138 float scaler = amplitude / SHORT_SCALE;
Phil Burk5ed503c2017-02-01 09:38:15 -0800139 for (int i = 0; i < numSamples; i++) {
Phil Burke572f462017-04-20 13:03:19 -0700140 destination[i] = source[i] * scaler;
141 }
142}
143
144// This code assumes amplitude1 and amplitude2 are between 0.0 and 1.0
145void 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
162void 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
185void 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;
Phil Burk5ed503c2017-02-01 09:38:15 -0800200 }
201}
202
203status_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:
Eric Laurenta2f296e2017-06-21 18:51:47 -0700211 case AAUDIO_ERROR_NO_SERVICE:
Phil Burk5ed503c2017-02-01 09:38:15 -0800212 status = DEAD_OBJECT;
213 break;
Eric Laurenta2f296e2017-06-21 18:51:47 -0700214 case AAUDIO_ERROR_INVALID_HANDLE:
215 status = BAD_TYPE;
216 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800217 case AAUDIO_ERROR_INVALID_STATE:
218 status = INVALID_OPERATION;
219 break;
Phil Burk71f35bb2017-04-13 16:05:07 -0700220 case AAUDIO_ERROR_INVALID_RATE:
221 case AAUDIO_ERROR_INVALID_FORMAT:
Phil Burk5ed503c2017-02-01 09:38:15 -0800222 case AAUDIO_ERROR_ILLEGAL_ARGUMENT:
Phil Burk5204d312017-05-04 17:16:13 -0700223 case AAUDIO_ERROR_OUT_OF_RANGE:
Phil Burk5ed503c2017-02-01 09:38:15 -0800224 status = BAD_VALUE;
225 break;
226 case AAUDIO_ERROR_WOULD_BLOCK:
227 status = WOULD_BLOCK;
228 break;
Phil Burk5204d312017-05-04 17:16:13 -0700229 case AAUDIO_ERROR_NULL:
230 status = UNEXPECTED_NULL;
231 break;
Phil Burk940083c2017-07-17 17:00:02 -0700232 case AAUDIO_ERROR_UNAVAILABLE:
233 status = NOT_ENOUGH_DATA;
234 break;
235
Phil Burk5204d312017-05-04 17:16:13 -0700236 // TODO translate these result codes
Phil Burk5204d312017-05-04 17:16:13 -0700237 case AAUDIO_ERROR_INTERNAL:
Phil Burk5204d312017-05-04 17:16:13 -0700238 case AAUDIO_ERROR_UNIMPLEMENTED:
Phil Burk5204d312017-05-04 17:16:13 -0700239 case AAUDIO_ERROR_NO_FREE_HANDLES:
240 case AAUDIO_ERROR_NO_MEMORY:
241 case AAUDIO_ERROR_TIMEOUT:
Phil Burk5ed503c2017-02-01 09:38:15 -0800242 default:
243 status = UNKNOWN_ERROR;
244 break;
245 }
246 return status;
247}
248
249aaudio_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:
Phil Burk71f35bb2017-04-13 16:05:07 -0700260 result = AAUDIO_ERROR_NO_SERVICE;
Phil Burk5ed503c2017-02-01 09:38:15 -0800261 break;
262 case INVALID_OPERATION:
263 result = AAUDIO_ERROR_INVALID_STATE;
264 break;
Eric Laurenta2f296e2017-06-21 18:51:47 -0700265 case UNEXPECTED_NULL:
266 result = AAUDIO_ERROR_NULL;
267 break;
268 case BAD_VALUE:
269 result = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
270 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800271 case WOULD_BLOCK:
272 result = AAUDIO_ERROR_WOULD_BLOCK;
273 break;
Phil Burk940083c2017-07-17 17:00:02 -0700274 case NOT_ENOUGH_DATA:
275 result = AAUDIO_ERROR_UNAVAILABLE;
276 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800277 default:
278 result = AAUDIO_ERROR_INTERNAL;
279 break;
280 }
281 return result;
282}
283
Phil Burk9dca9822017-05-26 14:27:43 -0700284audio_format_t AAudioConvert_aaudioToAndroidDataFormat(aaudio_format_t aaudioFormat) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800285 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;
Phil Burk5ed503c2017-02-01 09:38:15 -0800293 default:
294 androidFormat = AUDIO_FORMAT_DEFAULT;
295 ALOGE("AAudioConvert_aaudioToAndroidDataFormat 0x%08X unrecognized", aaudioFormat);
296 break;
297 }
298 return androidFormat;
299}
300
Phil Burk9dca9822017-05-26 14:27:43 -0700301aaudio_format_t AAudioConvert_androidToAAudioDataFormat(audio_format_t androidFormat) {
302 aaudio_format_t aaudioFormat = AAUDIO_FORMAT_INVALID;
Phil Burk5ed503c2017-02-01 09:38:15 -0800303 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;
Phil Burk5ed503c2017-02-01 09:38:15 -0800310 default:
311 aaudioFormat = AAUDIO_FORMAT_INVALID;
312 ALOGE("AAudioConvert_androidToAAudioDataFormat 0x%08X unrecognized", androidFormat);
313 break;
314 }
315 return aaudioFormat;
316}
317
Phil Burk3316d5e2017-02-15 11:23:01 -0800318int32_t AAudioConvert_framesToBytes(int32_t numFrames,
319 int32_t bytesPerFrame,
320 int32_t *sizeInBytes) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800321 // TODO implement more elegantly
322 const int32_t maxChannels = 256; // ridiculously large
Phil Burk3316d5e2017-02-15 11:23:01 -0800323 const int32_t maxBytesPerFrame = maxChannels * sizeof(float);
Phil Burk5ed503c2017-02-01 09:38:15 -0800324 // 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}
Phil Burkc8f69a02017-05-11 15:53:06 -0700332
333static int32_t AAudioProperty_getMMapProperty(const char *propName,
334 int32_t defaultValue,
335 const char * caller) {
Phil Burk87c9f642017-05-17 07:22:39 -0700336 int32_t prop = property_get_int32(propName, defaultValue);
Phil Burkc8f69a02017-05-11 15:53:06 -0700337 switch (prop) {
Phil Burkd04aeea2017-05-23 13:56:41 -0700338 case AAUDIO_UNSPECIFIED:
339 case AAUDIO_POLICY_NEVER:
340 case AAUDIO_POLICY_ALWAYS:
341 case AAUDIO_POLICY_AUTO:
Phil Burkc8f69a02017-05-11 15:53:06 -0700342 break;
343 default:
344 ALOGE("%s: invalid = %d", caller, prop);
345 prop = defaultValue;
346 break;
347 }
348 return prop;
349}
350
Phil Burkd04aeea2017-05-23 13:56:41 -0700351int32_t AAudioProperty_getMMapPolicy() {
352 return AAudioProperty_getMMapProperty(AAUDIO_PROP_MMAP_POLICY,
353 AAUDIO_UNSPECIFIED, __func__);
Phil Burkc8f69a02017-05-11 15:53:06 -0700354}
355
Phil Burkd04aeea2017-05-23 13:56:41 -0700356int32_t AAudioProperty_getMMapExclusivePolicy() {
357 return AAudioProperty_getMMapProperty(AAUDIO_PROP_MMAP_EXCLUSIVE_POLICY,
358 AAUDIO_UNSPECIFIED, __func__);
Phil Burkc8f69a02017-05-11 15:53:06 -0700359}
360
361int32_t AAudioProperty_getMixerBursts() {
Phil Burk87c9f642017-05-17 07:22:39 -0700362 const int32_t defaultBursts = 2; // arbitrary, use 2 for double buffered
Phil Burkc8f69a02017-05-11 15:53:06 -0700363 const int32_t maxBursts = 1024; // arbitrary
Phil Burk87c9f642017-05-17 07:22:39 -0700364 int32_t prop = property_get_int32(AAUDIO_PROP_MIXER_BURSTS, defaultBursts);
Phil Burkc8f69a02017-05-11 15:53:06 -0700365 if (prop < 1 || prop > maxBursts) {
366 ALOGE("AAudioProperty_getMixerBursts: invalid = %d", prop);
367 prop = defaultBursts;
368 }
369 return prop;
370}
371
372int32_t AAudioProperty_getHardwareBurstMinMicros() {
373 const int32_t defaultMicros = 1000; // arbitrary
374 const int32_t maxMicros = 1000 * 1000; // arbitrary
375 int32_t prop = property_get_int32(AAUDIO_PROP_HW_BURST_MIN_USEC, defaultMicros);
376 if (prop < 1 || prop > maxMicros) {
377 ALOGE("AAudioProperty_getHardwareBurstMinMicros: invalid = %d", prop);
378 prop = defaultMicros;
379 }
380 return prop;
381}