blob: 87b8b0d22d611a229d36fa7c2961a97cb67d461d [file] [log] [blame]
Phil Burk5ed503c2017-02-01 09:38:15 -08001/*
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 <stdint.h>
22#include <sys/types.h>
23#include <utils/Errors.h>
24
Phil Burka4eb0d82017-04-12 15:44:06 -070025#include "aaudio/AAudio.h"
Phil Burk5ed503c2017-02-01 09:38:15 -080026#include "AAudioUtilities.h"
27
28using namespace android;
29
Phil Burk3316d5e2017-02-15 11:23:01 -080030int32_t AAudioConvert_formatToSizeInBytes(aaudio_audio_format_t format) {
31 int32_t size = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
Phil Burk5ed503c2017-02-01 09:38:15 -080032 switch (format) {
33 case AAUDIO_FORMAT_PCM_I16:
34 size = sizeof(int16_t);
35 break;
Phil Burk5ed503c2017-02-01 09:38:15 -080036 case AAUDIO_FORMAT_PCM_FLOAT:
37 size = sizeof(float);
38 break;
39 default:
40 break;
41 }
42 return size;
43}
44
45// TODO This similar to a function in audio_utils. Consider using that instead.
46void AAudioConvert_floatToPcm16(const float *source, int32_t numSamples, int16_t *destination) {
47 for (int i = 0; i < numSamples; i++) {
48 float fval = source[i];
49 fval += 1.0; // to avoid discontinuity at 0.0 caused by truncation
50 fval *= 32768.0f;
51 int32_t sample = (int32_t) fval;
52 // clip to 16-bit range
53 if (sample < 0) sample = 0;
54 else if (sample > 0x0FFFF) sample = 0x0FFFF;
55 sample -= 32768; // center at zero
56 destination[i] = (int16_t) sample;
57 }
58}
59
60void AAudioConvert_pcm16ToFloat(const float *source, int32_t numSamples, int16_t *destination) {
61 for (int i = 0; i < numSamples; i++) {
62 destination[i] = source[i] * (1.0f / 32768.0f);
63 }
64}
65
66status_t AAudioConvert_aaudioToAndroidStatus(aaudio_result_t result) {
67 // This covers the case for AAUDIO_OK and for positive results.
68 if (result >= 0) {
69 return result;
70 }
71 status_t status;
72 switch (result) {
73 case AAUDIO_ERROR_DISCONNECTED:
74 case AAUDIO_ERROR_INVALID_HANDLE:
75 status = DEAD_OBJECT;
76 break;
77 case AAUDIO_ERROR_INVALID_STATE:
78 status = INVALID_OPERATION;
79 break;
80 case AAUDIO_ERROR_UNEXPECTED_VALUE: // TODO redundant?
81 case AAUDIO_ERROR_ILLEGAL_ARGUMENT:
82 status = BAD_VALUE;
83 break;
84 case AAUDIO_ERROR_WOULD_BLOCK:
85 status = WOULD_BLOCK;
86 break;
87 // TODO add more result codes
88 default:
89 status = UNKNOWN_ERROR;
90 break;
91 }
92 return status;
93}
94
95aaudio_result_t AAudioConvert_androidToAAudioResult(status_t status) {
96 // This covers the case for OK and for positive result.
97 if (status >= 0) {
98 return status;
99 }
100 aaudio_result_t result;
101 switch (status) {
102 case BAD_TYPE:
103 result = AAUDIO_ERROR_INVALID_HANDLE;
104 break;
105 case DEAD_OBJECT:
106 result = AAUDIO_ERROR_DISCONNECTED;
107 break;
108 case INVALID_OPERATION:
109 result = AAUDIO_ERROR_INVALID_STATE;
110 break;
111 case BAD_VALUE:
112 result = AAUDIO_ERROR_UNEXPECTED_VALUE;
113 break;
114 case WOULD_BLOCK:
115 result = AAUDIO_ERROR_WOULD_BLOCK;
116 break;
117 // TODO add more status codes
118 default:
119 result = AAUDIO_ERROR_INTERNAL;
120 break;
121 }
122 return result;
123}
124
125audio_format_t AAudioConvert_aaudioToAndroidDataFormat(aaudio_audio_format_t aaudioFormat) {
126 audio_format_t androidFormat;
127 switch (aaudioFormat) {
128 case AAUDIO_FORMAT_PCM_I16:
129 androidFormat = AUDIO_FORMAT_PCM_16_BIT;
130 break;
131 case AAUDIO_FORMAT_PCM_FLOAT:
132 androidFormat = AUDIO_FORMAT_PCM_FLOAT;
133 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800134 default:
135 androidFormat = AUDIO_FORMAT_DEFAULT;
136 ALOGE("AAudioConvert_aaudioToAndroidDataFormat 0x%08X unrecognized", aaudioFormat);
137 break;
138 }
139 return androidFormat;
140}
141
142aaudio_audio_format_t AAudioConvert_androidToAAudioDataFormat(audio_format_t androidFormat) {
143 aaudio_audio_format_t aaudioFormat = AAUDIO_FORMAT_INVALID;
144 switch (androidFormat) {
145 case AUDIO_FORMAT_PCM_16_BIT:
146 aaudioFormat = AAUDIO_FORMAT_PCM_I16;
147 break;
148 case AUDIO_FORMAT_PCM_FLOAT:
149 aaudioFormat = AAUDIO_FORMAT_PCM_FLOAT;
150 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800151 default:
152 aaudioFormat = AAUDIO_FORMAT_INVALID;
153 ALOGE("AAudioConvert_androidToAAudioDataFormat 0x%08X unrecognized", androidFormat);
154 break;
155 }
156 return aaudioFormat;
157}
158
Phil Burk3316d5e2017-02-15 11:23:01 -0800159int32_t AAudioConvert_framesToBytes(int32_t numFrames,
160 int32_t bytesPerFrame,
161 int32_t *sizeInBytes) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800162 // TODO implement more elegantly
163 const int32_t maxChannels = 256; // ridiculously large
Phil Burk3316d5e2017-02-15 11:23:01 -0800164 const int32_t maxBytesPerFrame = maxChannels * sizeof(float);
Phil Burk5ed503c2017-02-01 09:38:15 -0800165 // Prevent overflow by limiting multiplicands.
166 if (bytesPerFrame > maxBytesPerFrame || numFrames > (0x3FFFFFFF / maxBytesPerFrame)) {
167 ALOGE("size overflow, numFrames = %d, frameSize = %zd", numFrames, bytesPerFrame);
168 return AAUDIO_ERROR_OUT_OF_RANGE;
169 }
170 *sizeInBytes = numFrames * bytesPerFrame;
171 return AAUDIO_OK;
172}