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 31using 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 38int32_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 55static 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; 108 for (int i = 0; i < numSamples; i++) { 109 float sample = *source++; 110 *destination++ = clipAndClampFloatToPcm16(sample, scaler); 111 } 112} 113 114void 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; 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 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; 200 } 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: 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 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: 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 284audio_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 301aaudio_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 318int32_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 333static 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 351int32_t AAudioProperty_getMMapPolicy() { 352 return AAudioProperty_getMMapProperty(AAUDIO_PROP_MMAP_POLICY, 353 AAUDIO_UNSPECIFIED, __func__); 354} 355 356int32_t AAudioProperty_getMMapExclusivePolicy() { 357 return AAudioProperty_getMMapProperty(AAUDIO_PROP_MMAP_EXCLUSIVE_POLICY, 358 AAUDIO_UNSPECIFIED, __func__); 359} 360 361int32_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 372int32_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 387int32_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 402int32_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