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 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 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 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 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 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 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 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 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 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 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 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_INVALID_HANDLE: 212 status = DEAD_OBJECT; 213 break; 214 case AAUDIO_ERROR_INVALID_STATE: 215 status = INVALID_OPERATION; 216 break; 217 case AAUDIO_ERROR_INVALID_RATE: 218 case AAUDIO_ERROR_INVALID_FORMAT: 219 case AAUDIO_ERROR_ILLEGAL_ARGUMENT: 220 case AAUDIO_ERROR_OUT_OF_RANGE: 221 status = BAD_VALUE; 222 break; 223 case AAUDIO_ERROR_WOULD_BLOCK: 224 status = WOULD_BLOCK; 225 break; 226 case AAUDIO_ERROR_NULL: 227 status = UNEXPECTED_NULL; 228 break; 229 // TODO translate these result codes 230 case AAUDIO_ERROR_INTERNAL: 231 case AAUDIO_ERROR_UNIMPLEMENTED: 232 case AAUDIO_ERROR_UNAVAILABLE: 233 case AAUDIO_ERROR_NO_FREE_HANDLES: 234 case AAUDIO_ERROR_NO_MEMORY: 235 case AAUDIO_ERROR_TIMEOUT: 236 case AAUDIO_ERROR_NO_SERVICE: 237 default: 238 status = UNKNOWN_ERROR; 239 break; 240 } 241 return status; 242 } 243 244 aaudio_result_t AAudioConvert_androidToAAudioResult(status_t status) { 245 // This covers the case for OK and for positive result. 246 if (status >= 0) { 247 return status; 248 } 249 aaudio_result_t result; 250 switch (status) { 251 case BAD_TYPE: 252 result = AAUDIO_ERROR_INVALID_HANDLE; 253 break; 254 case DEAD_OBJECT: 255 result = AAUDIO_ERROR_NO_SERVICE; 256 break; 257 case INVALID_OPERATION: 258 result = AAUDIO_ERROR_INVALID_STATE; 259 break; 260 case UNEXPECTED_NULL: 261 result = AAUDIO_ERROR_NULL; 262 break; 263 case BAD_VALUE: 264 result = AAUDIO_ERROR_ILLEGAL_ARGUMENT; 265 break; 266 case WOULD_BLOCK: 267 result = AAUDIO_ERROR_WOULD_BLOCK; 268 break; 269 default: 270 result = AAUDIO_ERROR_INTERNAL; 271 break; 272 } 273 return result; 274 } 275 276 audio_format_t AAudioConvert_aaudioToAndroidDataFormat(aaudio_format_t aaudioFormat) { 277 audio_format_t androidFormat; 278 switch (aaudioFormat) { 279 case AAUDIO_FORMAT_PCM_I16: 280 androidFormat = AUDIO_FORMAT_PCM_16_BIT; 281 break; 282 case AAUDIO_FORMAT_PCM_FLOAT: 283 androidFormat = AUDIO_FORMAT_PCM_FLOAT; 284 break; 285 default: 286 androidFormat = AUDIO_FORMAT_DEFAULT; 287 ALOGE("AAudioConvert_aaudioToAndroidDataFormat 0x%08X unrecognized", aaudioFormat); 288 break; 289 } 290 return androidFormat; 291 } 292 293 aaudio_format_t AAudioConvert_androidToAAudioDataFormat(audio_format_t androidFormat) { 294 aaudio_format_t aaudioFormat = AAUDIO_FORMAT_INVALID; 295 switch (androidFormat) { 296 case AUDIO_FORMAT_PCM_16_BIT: 297 aaudioFormat = AAUDIO_FORMAT_PCM_I16; 298 break; 299 case AUDIO_FORMAT_PCM_FLOAT: 300 aaudioFormat = AAUDIO_FORMAT_PCM_FLOAT; 301 break; 302 default: 303 aaudioFormat = AAUDIO_FORMAT_INVALID; 304 ALOGE("AAudioConvert_androidToAAudioDataFormat 0x%08X unrecognized", androidFormat); 305 break; 306 } 307 return aaudioFormat; 308 } 309 310 int32_t AAudioConvert_framesToBytes(int32_t numFrames, 311 int32_t bytesPerFrame, 312 int32_t *sizeInBytes) { 313 // TODO implement more elegantly 314 const int32_t maxChannels = 256; // ridiculously large 315 const int32_t maxBytesPerFrame = maxChannels * sizeof(float); 316 // Prevent overflow by limiting multiplicands. 317 if (bytesPerFrame > maxBytesPerFrame || numFrames > (0x3FFFFFFF / maxBytesPerFrame)) { 318 ALOGE("size overflow, numFrames = %d, frameSize = %zd", numFrames, bytesPerFrame); 319 return AAUDIO_ERROR_OUT_OF_RANGE; 320 } 321 *sizeInBytes = numFrames * bytesPerFrame; 322 return AAUDIO_OK; 323 } 324 325 static int32_t AAudioProperty_getMMapProperty(const char *propName, 326 int32_t defaultValue, 327 const char * caller) { 328 int32_t prop = property_get_int32(propName, defaultValue); 329 switch (prop) { 330 case AAUDIO_UNSPECIFIED: 331 case AAUDIO_POLICY_NEVER: 332 case AAUDIO_POLICY_ALWAYS: 333 case AAUDIO_POLICY_AUTO: 334 break; 335 default: 336 ALOGE("%s: invalid = %d", caller, prop); 337 prop = defaultValue; 338 break; 339 } 340 return prop; 341 } 342 343 int32_t AAudioProperty_getMMapPolicy() { 344 return AAudioProperty_getMMapProperty(AAUDIO_PROP_MMAP_POLICY, 345 AAUDIO_UNSPECIFIED, __func__); 346 } 347 348 int32_t AAudioProperty_getMMapExclusivePolicy() { 349 return AAudioProperty_getMMapProperty(AAUDIO_PROP_MMAP_EXCLUSIVE_POLICY, 350 AAUDIO_UNSPECIFIED, __func__); 351 } 352 353 int32_t AAudioProperty_getMixerBursts() { 354 const int32_t defaultBursts = 2; // arbitrary, use 2 for double buffered 355 const int32_t maxBursts = 1024; // arbitrary 356 int32_t prop = property_get_int32(AAUDIO_PROP_MIXER_BURSTS, defaultBursts); 357 if (prop < 1 || prop > maxBursts) { 358 ALOGE("AAudioProperty_getMixerBursts: invalid = %d", prop); 359 prop = defaultBursts; 360 } 361 return prop; 362 } 363 364 int32_t AAudioProperty_getHardwareBurstMinMicros() { 365 const int32_t defaultMicros = 1000; // arbitrary 366 const int32_t maxMicros = 1000 * 1000; // arbitrary 367 int32_t prop = property_get_int32(AAUDIO_PROP_HW_BURST_MIN_USEC, defaultMicros); 368 if (prop < 1 || prop > maxMicros) { 369 ALOGE("AAudioProperty_getHardwareBurstMinMicros: invalid = %d", prop); 370 prop = defaultMicros; 371 } 372 return prop; 373 } 374