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