1e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk/* 2e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * Copyright 2016 The Android Open Source Project 3e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * 4e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * Licensed under the Apache License, Version 2.0 (the "License"); 5e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * you may not use this file except in compliance with the License. 6e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * You may obtain a copy of the License at 7e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * 8e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * http://www.apache.org/licenses/LICENSE-2.0 9e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * 10e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * Unless required by applicable law or agreed to in writing, software 11e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * distributed under the License is distributed on an "AS IS" BASIS, 12e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * See the License for the specific language governing permissions and 14e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * limitations under the License. 15e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk */ 16e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 175ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk#define LOG_TAG "AAudio" 18e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk//#define LOG_NDEBUG 0 19e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include <utils/Log.h> 20e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 21c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burk#include <cutils/properties.h> 22e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include <stdint.h> 23e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include <sys/types.h> 24e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include <utils/Errors.h> 25e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 26a4eb0d86a29be2763be5fac51727858d5095794bPhil Burk#include "aaudio/AAudio.h" 27d04aeea00bdaa999821e1a15c437ea648bd07195Phil Burk#include <aaudio/AAudioTesting.h> 28d04aeea00bdaa999821e1a15c437ea648bd07195Phil Burk 29d04aeea00bdaa999821e1a15c437ea648bd07195Phil Burk#include "utility/AAudioUtilities.h" 30e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 31e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burkusing namespace android; 32e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 33e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk// This is 3 dB, (10^(3/20)), to match the maximum headroom in AudioTrack for float data. 34e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk// It is designed to allow occasional transient peaks. 35e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk#define MAX_HEADROOM (1.41253754f) 36e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk#define MIN_HEADROOM (0 - MAX_HEADROOM) 37e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk 389dca9824da74d50be02bc81f539cc77b7bde678aPhil Burkint32_t AAudioConvert_formatToSizeInBytes(aaudio_format_t format) { 393316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int32_t size = AAUDIO_ERROR_ILLEGAL_ARGUMENT; 40d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk switch (format) { 415ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_FORMAT_PCM_I16: 42e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk size = sizeof(int16_t); 43e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk break; 445ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_FORMAT_PCM_FLOAT: 45e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk size = sizeof(float); 46e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk break; 47e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk default: 48e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk break; 49e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 50e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return size; 51e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 52e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 53e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk 545204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk// TODO expose and call clamp16_from_float function in primitives.h 55e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burkstatic inline int16_t clamp16_from_float(float f) { 56e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk /* Offset is used to expand the valid range of [-1.0, 1.0) into the 16 lsbs of the 57e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk * floating point significand. The normal shift is 3<<22, but the -15 offset 58e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk * is used to multiply by 32768. 59e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk */ 60e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk static const float offset = (float)(3 << (22 - 15)); 61e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk /* zero = (0x10f << 22) = 0x43c00000 (not directly used) */ 62e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk static const int32_t limneg = (0x10f << 22) /*zero*/ - 32768; /* 0x43bf8000 */ 63e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk static const int32_t limpos = (0x10f << 22) /*zero*/ + 32767; /* 0x43c07fff */ 64e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk 65e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk union { 66e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float f; 67e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk int32_t i; 68e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk } u; 69e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk 70e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk u.f = f + offset; /* recenter valid range */ 71e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk /* Now the valid range is represented as integers between [limneg, limpos]. 72e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk * Clamp using the fact that float representation (as an integer) is an ordered set. 73e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk */ 74e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk if (u.i < limneg) 75e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk u.i = -32768; 76e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk else if (u.i > limpos) 77e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk u.i = 32767; 78e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk return u.i; /* Return lower 16 bits, the part of interest in the significand. */ 79e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk} 80e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk 81e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk// Same but without clipping. 82e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk// Convert -1.0f to +1.0f to -32768 to +32767 83e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burkstatic inline int16_t floatToInt16(float f) { 84e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk static const float offset = (float)(3 << (22 - 15)); 85e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk union { 86e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float f; 87e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk int32_t i; 88e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk } u; 89e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk u.f = f + offset; /* recenter valid range */ 90e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk return u.i; /* Return lower 16 bits, the part of interest in the significand. */ 91e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk} 92e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk 93e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burkstatic float clipAndClampFloatToPcm16(float sample, float scaler) { 94e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk // Clip to valid range of a float sample to prevent excessive volume. 95e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk if (sample > MAX_HEADROOM) sample = MAX_HEADROOM; 96e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk else if (sample < MIN_HEADROOM) sample = MIN_HEADROOM; 97e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk 98e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk // Scale and convert to a short. 99e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float fval = sample * scaler; 100e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk return clamp16_from_float(fval); 101e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk} 102e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk 103e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burkvoid AAudioConvert_floatToPcm16(const float *source, 104e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk int16_t *destination, 105e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk int32_t numSamples, 106e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float amplitude) { 107e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float scaler = amplitude; 108e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk for (int i = 0; i < numSamples; i++) { 109e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float sample = *source++; 110e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk *destination++ = clipAndClampFloatToPcm16(sample, scaler); 111e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk } 112e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk} 113e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk 114e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burkvoid AAudioConvert_floatToPcm16(const float *source, 115e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk int16_t *destination, 116e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk int32_t numFrames, 117e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk int32_t samplesPerFrame, 118e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float amplitude1, 119e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float amplitude2) { 120e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float scaler = amplitude1; 121e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk // divide by numFrames so that we almost reach amplitude2 122e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float delta = (amplitude2 - amplitude1) / numFrames; 123e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) { 124e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk for (int sampleIndex = 0; sampleIndex < samplesPerFrame; sampleIndex++) { 125e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float sample = *source++; 126e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk *destination++ = clipAndClampFloatToPcm16(sample, scaler); 127e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk } 128e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk scaler += delta; 129e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 130e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 131e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 132e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk#define SHORT_SCALE 32768 133e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk 134e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burkvoid AAudioConvert_pcm16ToFloat(const int16_t *source, 135e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float *destination, 136e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk int32_t numSamples, 137e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float amplitude) { 138e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float scaler = amplitude / SHORT_SCALE; 139e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk for (int i = 0; i < numSamples; i++) { 140e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk destination[i] = source[i] * scaler; 141e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk } 142e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk} 143e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk 144e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk// This code assumes amplitude1 and amplitude2 are between 0.0 and 1.0 145e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burkvoid AAudioConvert_pcm16ToFloat(const int16_t *source, 146e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float *destination, 147e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk int32_t numFrames, 148e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk int32_t samplesPerFrame, 149e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float amplitude1, 150e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float amplitude2) { 151e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float scaler = amplitude1 / SHORT_SCALE; 152e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float delta = (amplitude2 - amplitude1) / (SHORT_SCALE * (float) numFrames); 153e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) { 154e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk for (int sampleIndex = 0; sampleIndex < samplesPerFrame; sampleIndex++) { 155e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk *destination++ = *source++ * scaler; 156e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk } 157e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk scaler += delta; 158e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk } 159e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk} 160e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk 161e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk// This code assumes amplitude1 and amplitude2 are between 0.0 and 1.0 162e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burkvoid AAudio_linearRamp(const float *source, 163e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float *destination, 164e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk int32_t numFrames, 165e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk int32_t samplesPerFrame, 166e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float amplitude1, 167e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float amplitude2) { 168e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float scaler = amplitude1; 169e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float delta = (amplitude2 - amplitude1) / numFrames; 170e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) { 171e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk for (int sampleIndex = 0; sampleIndex < samplesPerFrame; sampleIndex++) { 172e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float sample = *source++; 173e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk 174e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk // Clip to valid range of a float sample to prevent excessive volume. 175e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk if (sample > MAX_HEADROOM) sample = MAX_HEADROOM; 176e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk else if (sample < MIN_HEADROOM) sample = MIN_HEADROOM; 177e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk 178e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk *destination++ = sample * scaler; 179e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk } 180e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk scaler += delta; 181e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk } 182e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk} 183e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk 184e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk// This code assumes amplitude1 and amplitude2 are between 0.0 and 1.0 185e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burkvoid AAudio_linearRamp(const int16_t *source, 186e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk int16_t *destination, 187e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk int32_t numFrames, 188e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk int32_t samplesPerFrame, 189e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float amplitude1, 190e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float amplitude2) { 191e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float scaler = amplitude1 / SHORT_SCALE; 192e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float delta = (amplitude2 - amplitude1) / (SHORT_SCALE * (float) numFrames); 193e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) { 194e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk for (int sampleIndex = 0; sampleIndex < samplesPerFrame; sampleIndex++) { 195e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk // No need to clip because int16_t range is inherently limited. 196e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float sample = *source++ * scaler; 197e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk *destination++ = floatToInt16(sample); 198e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk } 199e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk scaler += delta; 200e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 201e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 202e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 2035ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkstatus_t AAudioConvert_aaudioToAndroidStatus(aaudio_result_t result) { 2045ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk // This covers the case for AAUDIO_OK and for positive results. 205dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk if (result >= 0) { 206dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk return result; 207dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk } 208dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk status_t status; 209dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk switch (result) { 2105ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_ERROR_DISCONNECTED: 2115ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_ERROR_INVALID_HANDLE: 212dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk status = DEAD_OBJECT; 213dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk break; 2145ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_ERROR_INVALID_STATE: 215dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk status = INVALID_OPERATION; 216dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk break; 21771f35bb687476694882a617ba4a810a0bb56fe23Phil Burk case AAUDIO_ERROR_INVALID_RATE: 21871f35bb687476694882a617ba4a810a0bb56fe23Phil Burk case AAUDIO_ERROR_INVALID_FORMAT: 2195ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_ERROR_ILLEGAL_ARGUMENT: 2205204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk case AAUDIO_ERROR_OUT_OF_RANGE: 221dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk status = BAD_VALUE; 222dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk break; 2235ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_ERROR_WOULD_BLOCK: 224dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk status = WOULD_BLOCK; 225dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk break; 2265204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk case AAUDIO_ERROR_NULL: 2275204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk status = UNEXPECTED_NULL; 2285204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk break; 2295204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk // TODO translate these result codes 2305204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk case AAUDIO_ERROR_INTERNAL: 2315204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk case AAUDIO_ERROR_UNIMPLEMENTED: 2325204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk case AAUDIO_ERROR_UNAVAILABLE: 2335204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk case AAUDIO_ERROR_NO_FREE_HANDLES: 2345204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk case AAUDIO_ERROR_NO_MEMORY: 2355204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk case AAUDIO_ERROR_TIMEOUT: 2365204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk case AAUDIO_ERROR_NO_SERVICE: 237dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk default: 238dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk status = UNKNOWN_ERROR; 239dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk break; 240dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk } 241dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk return status; 242dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk} 243dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk 2445ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AAudioConvert_androidToAAudioResult(status_t status) { 245dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk // This covers the case for OK and for positive result. 246dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk if (status >= 0) { 247dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk return status; 248e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 2495ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_result_t result; 250dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk switch (status) { 251dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk case BAD_TYPE: 2525ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk result = AAUDIO_ERROR_INVALID_HANDLE; 253dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk break; 254dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk case DEAD_OBJECT: 25571f35bb687476694882a617ba4a810a0bb56fe23Phil Burk result = AAUDIO_ERROR_NO_SERVICE; 256e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk break; 257e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk case INVALID_OPERATION: 2585ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk result = AAUDIO_ERROR_INVALID_STATE; 259e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk break; 2605204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk case UNEXPECTED_NULL: 2615204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk result = AAUDIO_ERROR_NULL; 2625204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk break; 2635204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk case BAD_VALUE: 26417fff38dd9d467bc5fb6cd5b9a6b183951c7750dPhil Burk result = AAUDIO_ERROR_ILLEGAL_ARGUMENT; 2655204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk break; 266e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk case WOULD_BLOCK: 2675ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk result = AAUDIO_ERROR_WOULD_BLOCK; 268e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk break; 269e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk default: 2705ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk result = AAUDIO_ERROR_INTERNAL; 271e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk break; 272e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 273e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return result; 274e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 275e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 2769dca9824da74d50be02bc81f539cc77b7bde678aPhil Burkaudio_format_t AAudioConvert_aaudioToAndroidDataFormat(aaudio_format_t aaudioFormat) { 277e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk audio_format_t androidFormat; 2785ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk switch (aaudioFormat) { 2795ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_FORMAT_PCM_I16: 280e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk androidFormat = AUDIO_FORMAT_PCM_16_BIT; 281e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk break; 2825ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_FORMAT_PCM_FLOAT: 283e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk androidFormat = AUDIO_FORMAT_PCM_FLOAT; 284e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk break; 285e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk default: 286e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk androidFormat = AUDIO_FORMAT_DEFAULT; 2875ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk ALOGE("AAudioConvert_aaudioToAndroidDataFormat 0x%08X unrecognized", aaudioFormat); 288e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk break; 289e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 290e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return androidFormat; 291e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 292e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 2939dca9824da74d50be02bc81f539cc77b7bde678aPhil Burkaaudio_format_t AAudioConvert_androidToAAudioDataFormat(audio_format_t androidFormat) { 2949dca9824da74d50be02bc81f539cc77b7bde678aPhil Burk aaudio_format_t aaudioFormat = AAUDIO_FORMAT_INVALID; 295e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk switch (androidFormat) { 296e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk case AUDIO_FORMAT_PCM_16_BIT: 2975ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudioFormat = AAUDIO_FORMAT_PCM_I16; 298e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk break; 299e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk case AUDIO_FORMAT_PCM_FLOAT: 3005ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudioFormat = AAUDIO_FORMAT_PCM_FLOAT; 301e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk break; 302e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk default: 3035ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudioFormat = AAUDIO_FORMAT_INVALID; 3045ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk ALOGE("AAudioConvert_androidToAAudioDataFormat 0x%08X unrecognized", androidFormat); 305e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk break; 306e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 3075ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return aaudioFormat; 308e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 309e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 3103316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkint32_t AAudioConvert_framesToBytes(int32_t numFrames, 3113316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int32_t bytesPerFrame, 3123316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int32_t *sizeInBytes) { 313e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // TODO implement more elegantly 314e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk const int32_t maxChannels = 256; // ridiculously large 3153316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk const int32_t maxBytesPerFrame = maxChannels * sizeof(float); 316e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // Prevent overflow by limiting multiplicands. 317e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk if (bytesPerFrame > maxBytesPerFrame || numFrames > (0x3FFFFFFF / maxBytesPerFrame)) { 318e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk ALOGE("size overflow, numFrames = %d, frameSize = %zd", numFrames, bytesPerFrame); 3195ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_OUT_OF_RANGE; 320e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 321e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk *sizeInBytes = numFrames * bytesPerFrame; 3225ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_OK; 323e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 324c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burk 325c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burkstatic int32_t AAudioProperty_getMMapProperty(const char *propName, 326c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burk int32_t defaultValue, 327c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burk const char * caller) { 32887c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk int32_t prop = property_get_int32(propName, defaultValue); 329c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burk switch (prop) { 330d04aeea00bdaa999821e1a15c437ea648bd07195Phil Burk case AAUDIO_UNSPECIFIED: 331d04aeea00bdaa999821e1a15c437ea648bd07195Phil Burk case AAUDIO_POLICY_NEVER: 332d04aeea00bdaa999821e1a15c437ea648bd07195Phil Burk case AAUDIO_POLICY_ALWAYS: 333d04aeea00bdaa999821e1a15c437ea648bd07195Phil Burk case AAUDIO_POLICY_AUTO: 334c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burk break; 335c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burk default: 336c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burk ALOGE("%s: invalid = %d", caller, prop); 337c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burk prop = defaultValue; 338c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burk break; 339c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burk } 340c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burk return prop; 341c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burk} 342c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burk 343d04aeea00bdaa999821e1a15c437ea648bd07195Phil Burkint32_t AAudioProperty_getMMapPolicy() { 344d04aeea00bdaa999821e1a15c437ea648bd07195Phil Burk return AAudioProperty_getMMapProperty(AAUDIO_PROP_MMAP_POLICY, 345d04aeea00bdaa999821e1a15c437ea648bd07195Phil Burk AAUDIO_UNSPECIFIED, __func__); 346c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burk} 347c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burk 348d04aeea00bdaa999821e1a15c437ea648bd07195Phil Burkint32_t AAudioProperty_getMMapExclusivePolicy() { 349d04aeea00bdaa999821e1a15c437ea648bd07195Phil Burk return AAudioProperty_getMMapProperty(AAUDIO_PROP_MMAP_EXCLUSIVE_POLICY, 350d04aeea00bdaa999821e1a15c437ea648bd07195Phil Burk AAUDIO_UNSPECIFIED, __func__); 351c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burk} 352c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burk 353c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burkint32_t AAudioProperty_getMixerBursts() { 35487c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk const int32_t defaultBursts = 2; // arbitrary, use 2 for double buffered 355c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burk const int32_t maxBursts = 1024; // arbitrary 35687c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk int32_t prop = property_get_int32(AAUDIO_PROP_MIXER_BURSTS, defaultBursts); 357c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burk if (prop < 1 || prop > maxBursts) { 358c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burk ALOGE("AAudioProperty_getMixerBursts: invalid = %d", prop); 359c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burk prop = defaultBursts; 360c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burk } 361c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burk return prop; 362c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burk} 363c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burk 364c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burkint32_t AAudioProperty_getHardwareBurstMinMicros() { 365c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burk const int32_t defaultMicros = 1000; // arbitrary 366c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burk const int32_t maxMicros = 1000 * 1000; // arbitrary 367c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burk int32_t prop = property_get_int32(AAUDIO_PROP_HW_BURST_MIN_USEC, defaultMicros); 368c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burk if (prop < 1 || prop > maxMicros) { 369c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burk ALOGE("AAudioProperty_getHardwareBurstMinMicros: invalid = %d", prop); 370c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burk prop = defaultMicros; 371c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burk } 372c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burk return prop; 373c8f69a08a409fd163873d725c63f8d60259ae21dPhil Burk} 374