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