blob: 4a2a0a8b487af316a01ed14a3f1852dfb10335c9 [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
Phil Burkc8f69a02017-05-11 15:53:06 -070021#include <cutils/properties.h>
Phil Burk5ed503c2017-02-01 09:38:15 -080022#include <stdint.h>
23#include <sys/types.h>
24#include <utils/Errors.h>
25
Phil Burka4eb0d82017-04-12 15:44:06 -070026#include "aaudio/AAudio.h"
Phil Burkd04aeea2017-05-23 13:56:41 -070027#include <aaudio/AAudioTesting.h>
Phil Burkbba09002017-11-29 13:39:44 -080028#include <math.h>
Phil Burkd4ccc622017-12-20 15:32:44 -080029#include <system/audio-base.h>
Phil Burk41f19d82018-02-13 14:59:10 -080030#include <assert.h>
Phil Burkd04aeea2017-05-23 13:56:41 -070031
32#include "utility/AAudioUtilities.h"
Phil Burk5ed503c2017-02-01 09:38:15 -080033
34using namespace android;
35
Phil Burke572f462017-04-20 13:03:19 -070036// This is 3 dB, (10^(3/20)), to match the maximum headroom in AudioTrack for float data.
37// It is designed to allow occasional transient peaks.
38#define MAX_HEADROOM (1.41253754f)
39#define MIN_HEADROOM (0 - MAX_HEADROOM)
40
Phil Burk9dca9822017-05-26 14:27:43 -070041int32_t AAudioConvert_formatToSizeInBytes(aaudio_format_t format) {
Phil Burk3316d5e2017-02-15 11:23:01 -080042 int32_t size = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
Phil Burk5ed503c2017-02-01 09:38:15 -080043 switch (format) {
44 case AAUDIO_FORMAT_PCM_I16:
45 size = sizeof(int16_t);
46 break;
Phil Burk5ed503c2017-02-01 09:38:15 -080047 case AAUDIO_FORMAT_PCM_FLOAT:
48 size = sizeof(float);
49 break;
50 default:
51 break;
52 }
53 return size;
54}
55
Phil Burk5204d312017-05-04 17:16:13 -070056// TODO expose and call clamp16_from_float function in primitives.h
Phil Burke572f462017-04-20 13:03:19 -070057static inline int16_t clamp16_from_float(float f) {
Phil Burkbba09002017-11-29 13:39:44 -080058 static const float scale = 1 << 15;
59 return (int16_t) roundf(fmaxf(fminf(f * scale, scale - 1.f), -scale));
Phil Burke572f462017-04-20 13:03:19 -070060}
61
62static float clipAndClampFloatToPcm16(float sample, float scaler) {
63 // Clip to valid range of a float sample to prevent excessive volume.
64 if (sample > MAX_HEADROOM) sample = MAX_HEADROOM;
65 else if (sample < MIN_HEADROOM) sample = MIN_HEADROOM;
66
67 // Scale and convert to a short.
68 float fval = sample * scaler;
69 return clamp16_from_float(fval);
70}
71
72void AAudioConvert_floatToPcm16(const float *source,
73 int16_t *destination,
74 int32_t numSamples,
75 float amplitude) {
Phil Burk41f19d82018-02-13 14:59:10 -080076 const float scaler = amplitude;
Phil Burk5ed503c2017-02-01 09:38:15 -080077 for (int i = 0; i < numSamples; i++) {
Phil Burke572f462017-04-20 13:03:19 -070078 float sample = *source++;
79 *destination++ = clipAndClampFloatToPcm16(sample, scaler);
Phil Burk5ed503c2017-02-01 09:38:15 -080080 }
81}
82
Phil Burke572f462017-04-20 13:03:19 -070083void AAudioConvert_floatToPcm16(const float *source,
84 int16_t *destination,
85 int32_t numFrames,
86 int32_t samplesPerFrame,
87 float amplitude1,
88 float amplitude2) {
89 float scaler = amplitude1;
90 // divide by numFrames so that we almost reach amplitude2
91 float delta = (amplitude2 - amplitude1) / numFrames;
92 for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) {
93 for (int sampleIndex = 0; sampleIndex < samplesPerFrame; sampleIndex++) {
94 float sample = *source++;
95 *destination++ = clipAndClampFloatToPcm16(sample, scaler);
96 }
97 scaler += delta;
98 }
99}
100
101#define SHORT_SCALE 32768
102
103void AAudioConvert_pcm16ToFloat(const int16_t *source,
104 float *destination,
105 int32_t numSamples,
106 float amplitude) {
Phil Burk41f19d82018-02-13 14:59:10 -0800107 const float scaler = amplitude / SHORT_SCALE;
Phil Burk5ed503c2017-02-01 09:38:15 -0800108 for (int i = 0; i < numSamples; i++) {
Phil Burke572f462017-04-20 13:03:19 -0700109 destination[i] = source[i] * scaler;
110 }
111}
112
113// This code assumes amplitude1 and amplitude2 are between 0.0 and 1.0
114void AAudioConvert_pcm16ToFloat(const int16_t *source,
115 float *destination,
116 int32_t numFrames,
117 int32_t samplesPerFrame,
118 float amplitude1,
119 float amplitude2) {
120 float scaler = amplitude1 / SHORT_SCALE;
Phil Burk41f19d82018-02-13 14:59:10 -0800121 const float delta = (amplitude2 - amplitude1) / (SHORT_SCALE * (float) numFrames);
Phil Burke572f462017-04-20 13:03:19 -0700122 for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) {
123 for (int sampleIndex = 0; sampleIndex < samplesPerFrame; sampleIndex++) {
124 *destination++ = *source++ * scaler;
125 }
126 scaler += delta;
127 }
128}
129
130// This code assumes amplitude1 and amplitude2 are between 0.0 and 1.0
131void AAudio_linearRamp(const float *source,
132 float *destination,
133 int32_t numFrames,
134 int32_t samplesPerFrame,
135 float amplitude1,
136 float amplitude2) {
137 float scaler = amplitude1;
Phil Burk41f19d82018-02-13 14:59:10 -0800138 const float delta = (amplitude2 - amplitude1) / numFrames;
Phil Burke572f462017-04-20 13:03:19 -0700139 for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) {
140 for (int sampleIndex = 0; sampleIndex < samplesPerFrame; sampleIndex++) {
141 float sample = *source++;
142
143 // Clip to valid range of a float sample to prevent excessive volume.
144 if (sample > MAX_HEADROOM) sample = MAX_HEADROOM;
145 else if (sample < MIN_HEADROOM) sample = MIN_HEADROOM;
146
147 *destination++ = sample * scaler;
148 }
149 scaler += delta;
150 }
151}
152
153// This code assumes amplitude1 and amplitude2 are between 0.0 and 1.0
154void AAudio_linearRamp(const int16_t *source,
155 int16_t *destination,
156 int32_t numFrames,
157 int32_t samplesPerFrame,
158 float amplitude1,
159 float amplitude2) {
Phil Burkbba09002017-11-29 13:39:44 -0800160 // Because we are converting from int16 to 1nt16, we do not have to scale by 1/32768.
161 float scaler = amplitude1;
Phil Burk41f19d82018-02-13 14:59:10 -0800162 const float delta = (amplitude2 - amplitude1) / numFrames;
Phil Burke572f462017-04-20 13:03:19 -0700163 for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) {
164 for (int sampleIndex = 0; sampleIndex < samplesPerFrame; sampleIndex++) {
165 // No need to clip because int16_t range is inherently limited.
166 float sample = *source++ * scaler;
Phil Burkbba09002017-11-29 13:39:44 -0800167 *destination++ = (int16_t) roundf(sample);
Phil Burke572f462017-04-20 13:03:19 -0700168 }
169 scaler += delta;
Phil Burk5ed503c2017-02-01 09:38:15 -0800170 }
171}
172
Phil Burk41f19d82018-02-13 14:59:10 -0800173// *************************************************************************************
174// Convert Mono To Stereo at the same time as converting format.
175void AAudioConvert_formatMonoToStereo(const float *source,
176 int16_t *destination,
177 int32_t numFrames,
178 float amplitude) {
179 const float scaler = amplitude;
180 for (int i = 0; i < numFrames; i++) {
181 float sample = *source++;
182 int16_t sample16 = clipAndClampFloatToPcm16(sample, scaler);
183 *destination++ = sample16;
184 *destination++ = sample16;
185 }
186}
187
188void AAudioConvert_formatMonoToStereo(const float *source,
189 int16_t *destination,
190 int32_t numFrames,
191 float amplitude1,
192 float amplitude2) {
193 // divide by numFrames so that we almost reach amplitude2
194 const float delta = (amplitude2 - amplitude1) / numFrames;
195 for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) {
196 const float scaler = amplitude1 + (frameIndex * delta);
197 const float sample = *source++;
198 int16_t sample16 = clipAndClampFloatToPcm16(sample, scaler);
199 *destination++ = sample16;
200 *destination++ = sample16;
201 }
202}
203
204void AAudioConvert_formatMonoToStereo(const int16_t *source,
205 float *destination,
206 int32_t numFrames,
207 float amplitude) {
208 const float scaler = amplitude / SHORT_SCALE;
209 for (int i = 0; i < numFrames; i++) {
210 float sample = source[i] * scaler;
211 *destination++ = sample;
212 *destination++ = sample;
213 }
214}
215
216// This code assumes amplitude1 and amplitude2 are between 0.0 and 1.0
217void AAudioConvert_formatMonoToStereo(const int16_t *source,
218 float *destination,
219 int32_t numFrames,
220 float amplitude1,
221 float amplitude2) {
222 const float scaler1 = amplitude1 / SHORT_SCALE;
223 const float delta = (amplitude2 - amplitude1) / (SHORT_SCALE * (float) numFrames);
224 for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) {
225 float scaler = scaler1 + (frameIndex * delta);
226 float sample = source[frameIndex] * scaler;
227 *destination++ = sample;
228 *destination++ = sample;
229 }
230}
231
232// This code assumes amplitude1 and amplitude2 are between 0.0 and 1.0
233void AAudio_linearRampMonoToStereo(const float *source,
234 float *destination,
235 int32_t numFrames,
236 float amplitude1,
237 float amplitude2) {
238 const float delta = (amplitude2 - amplitude1) / numFrames;
239 for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) {
240 float sample = *source++;
241
242 // Clip to valid range of a float sample to prevent excessive volume.
243 if (sample > MAX_HEADROOM) sample = MAX_HEADROOM;
244 else if (sample < MIN_HEADROOM) sample = MIN_HEADROOM;
245
246 const float scaler = amplitude1 + (frameIndex * delta);
247 float sampleScaled = sample * scaler;
248 *destination++ = sampleScaled;
249 *destination++ = sampleScaled;
250 }
251}
252
253// This code assumes amplitude1 and amplitude2 are between 0.0 and 1.0
254void AAudio_linearRampMonoToStereo(const int16_t *source,
255 int16_t *destination,
256 int32_t numFrames,
257 float amplitude1,
258 float amplitude2) {
259 // Because we are converting from int16 to 1nt16, we do not have to scale by 1/32768.
260 const float delta = (amplitude2 - amplitude1) / numFrames;
261 for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) {
262 const float scaler = amplitude1 + (frameIndex * delta);
263 // No need to clip because int16_t range is inherently limited.
264 const float sample = *source++ * scaler;
265 int16_t sample16 = (int16_t) roundf(sample);
266 *destination++ = sample16;
267 *destination++ = sample16;
268 }
269}
270
271// *************************************************************************************
272void AAudioDataConverter::convert(
273 const FormattedData &source,
274 const FormattedData &destination,
275 int32_t numFrames,
276 float levelFrom,
277 float levelTo) {
278
279 if (source.channelCount == 1 && destination.channelCount == 2) {
280 convertMonoToStereo(source,
281 destination,
282 numFrames,
283 levelFrom,
284 levelTo);
285 } else {
286 // We only support mono to stereo conversion. Otherwise source and destination
287 // must match.
288 assert(source.channelCount == destination.channelCount);
289 convertChannelsMatch(source,
290 destination,
291 numFrames,
292 levelFrom,
293 levelTo);
294 }
295}
296
297void AAudioDataConverter::convertMonoToStereo(
298 const FormattedData &source,
299 const FormattedData &destination,
300 int32_t numFrames,
301 float levelFrom,
302 float levelTo) {
303
304 // The formats are validated when the stream is opened so we do not have to
305 // check for illegal combinations here.
306 if (source.format == AAUDIO_FORMAT_PCM_FLOAT) {
307 if (destination.format == AAUDIO_FORMAT_PCM_FLOAT) {
308 AAudio_linearRampMonoToStereo(
309 (const float *) source.data,
310 (float *) destination.data,
311 numFrames,
312 levelFrom,
313 levelTo);
314 } else if (destination.format == AAUDIO_FORMAT_PCM_I16) {
315 if (levelFrom != levelTo) {
316 AAudioConvert_formatMonoToStereo(
317 (const float *) source.data,
318 (int16_t *) destination.data,
319 numFrames,
320 levelFrom,
321 levelTo);
322 } else {
323 AAudioConvert_formatMonoToStereo(
324 (const float *) source.data,
325 (int16_t *) destination.data,
326 numFrames,
327 levelTo);
328 }
329 }
330 } else if (source.format == AAUDIO_FORMAT_PCM_I16) {
331 if (destination.format == AAUDIO_FORMAT_PCM_FLOAT) {
332 if (levelFrom != levelTo) {
333 AAudioConvert_formatMonoToStereo(
334 (const int16_t *) source.data,
335 (float *) destination.data,
336 numFrames,
337 levelFrom,
338 levelTo);
339 } else {
340 AAudioConvert_formatMonoToStereo(
341 (const int16_t *) source.data,
342 (float *) destination.data,
343 numFrames,
344 levelTo);
345 }
346 } else if (destination.format == AAUDIO_FORMAT_PCM_I16) {
347 AAudio_linearRampMonoToStereo(
348 (const int16_t *) source.data,
349 (int16_t *) destination.data,
350 numFrames,
351 levelFrom,
352 levelTo);
353 }
354 }
355}
356
357void AAudioDataConverter::convertChannelsMatch(
358 const FormattedData &source,
359 const FormattedData &destination,
360 int32_t numFrames,
361 float levelFrom,
362 float levelTo) {
363 const int32_t numSamples = numFrames * source.channelCount;
364
365 // The formats are validated when the stream is opened so we do not have to
366 // check for illegal combinations here.
367 if (source.format == AAUDIO_FORMAT_PCM_FLOAT) {
368 if (destination.format == AAUDIO_FORMAT_PCM_FLOAT) {
369 AAudio_linearRamp(
370 (const float *) source.data,
371 (float *) destination.data,
372 numFrames,
373 source.channelCount,
374 levelFrom,
375 levelTo);
376 } else if (destination.format == AAUDIO_FORMAT_PCM_I16) {
377 if (levelFrom != levelTo) {
378 AAudioConvert_floatToPcm16(
379 (const float *) source.data,
380 (int16_t *) destination.data,
381 numFrames,
382 source.channelCount,
383 levelFrom,
384 levelTo);
385 } else {
386 AAudioConvert_floatToPcm16(
387 (const float *) source.data,
388 (int16_t *) destination.data,
389 numSamples,
390 levelTo);
391 }
392 }
393 } else if (source.format == AAUDIO_FORMAT_PCM_I16) {
394 if (destination.format == AAUDIO_FORMAT_PCM_FLOAT) {
395 if (levelFrom != levelTo) {
396 AAudioConvert_pcm16ToFloat(
397 (const int16_t *) source.data,
398 (float *) destination.data,
399 numFrames,
400 source.channelCount,
401 levelFrom,
402 levelTo);
403 } else {
404 AAudioConvert_pcm16ToFloat(
405 (const int16_t *) source.data,
406 (float *) destination.data,
407 numSamples,
408 levelTo);
409 }
410 } else if (destination.format == AAUDIO_FORMAT_PCM_I16) {
411 AAudio_linearRamp(
412 (const int16_t *) source.data,
413 (int16_t *) destination.data,
414 numFrames,
415 source.channelCount,
416 levelFrom,
417 levelTo);
418 }
419 }
420}
421
Phil Burk5ed503c2017-02-01 09:38:15 -0800422status_t AAudioConvert_aaudioToAndroidStatus(aaudio_result_t result) {
423 // This covers the case for AAUDIO_OK and for positive results.
424 if (result >= 0) {
425 return result;
426 }
427 status_t status;
428 switch (result) {
429 case AAUDIO_ERROR_DISCONNECTED:
Eric Laurenta2f296e2017-06-21 18:51:47 -0700430 case AAUDIO_ERROR_NO_SERVICE:
Phil Burk5ed503c2017-02-01 09:38:15 -0800431 status = DEAD_OBJECT;
432 break;
Eric Laurenta2f296e2017-06-21 18:51:47 -0700433 case AAUDIO_ERROR_INVALID_HANDLE:
434 status = BAD_TYPE;
435 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800436 case AAUDIO_ERROR_INVALID_STATE:
437 status = INVALID_OPERATION;
438 break;
Phil Burk71f35bb2017-04-13 16:05:07 -0700439 case AAUDIO_ERROR_INVALID_RATE:
440 case AAUDIO_ERROR_INVALID_FORMAT:
Phil Burk5ed503c2017-02-01 09:38:15 -0800441 case AAUDIO_ERROR_ILLEGAL_ARGUMENT:
Phil Burk5204d312017-05-04 17:16:13 -0700442 case AAUDIO_ERROR_OUT_OF_RANGE:
Phil Burk5ed503c2017-02-01 09:38:15 -0800443 status = BAD_VALUE;
444 break;
445 case AAUDIO_ERROR_WOULD_BLOCK:
446 status = WOULD_BLOCK;
447 break;
Phil Burk5204d312017-05-04 17:16:13 -0700448 case AAUDIO_ERROR_NULL:
449 status = UNEXPECTED_NULL;
450 break;
Phil Burk940083c2017-07-17 17:00:02 -0700451 case AAUDIO_ERROR_UNAVAILABLE:
452 status = NOT_ENOUGH_DATA;
453 break;
454
Phil Burk5204d312017-05-04 17:16:13 -0700455 // TODO translate these result codes
Phil Burk5204d312017-05-04 17:16:13 -0700456 case AAUDIO_ERROR_INTERNAL:
Phil Burk5204d312017-05-04 17:16:13 -0700457 case AAUDIO_ERROR_UNIMPLEMENTED:
Phil Burk5204d312017-05-04 17:16:13 -0700458 case AAUDIO_ERROR_NO_FREE_HANDLES:
459 case AAUDIO_ERROR_NO_MEMORY:
460 case AAUDIO_ERROR_TIMEOUT:
Phil Burk5ed503c2017-02-01 09:38:15 -0800461 default:
462 status = UNKNOWN_ERROR;
463 break;
464 }
465 return status;
466}
467
468aaudio_result_t AAudioConvert_androidToAAudioResult(status_t status) {
469 // This covers the case for OK and for positive result.
470 if (status >= 0) {
471 return status;
472 }
473 aaudio_result_t result;
474 switch (status) {
475 case BAD_TYPE:
476 result = AAUDIO_ERROR_INVALID_HANDLE;
477 break;
478 case DEAD_OBJECT:
Phil Burk71f35bb2017-04-13 16:05:07 -0700479 result = AAUDIO_ERROR_NO_SERVICE;
Phil Burk5ed503c2017-02-01 09:38:15 -0800480 break;
481 case INVALID_OPERATION:
482 result = AAUDIO_ERROR_INVALID_STATE;
483 break;
Eric Laurenta2f296e2017-06-21 18:51:47 -0700484 case UNEXPECTED_NULL:
485 result = AAUDIO_ERROR_NULL;
486 break;
487 case BAD_VALUE:
488 result = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
489 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800490 case WOULD_BLOCK:
491 result = AAUDIO_ERROR_WOULD_BLOCK;
492 break;
Phil Burk940083c2017-07-17 17:00:02 -0700493 case NOT_ENOUGH_DATA:
494 result = AAUDIO_ERROR_UNAVAILABLE;
495 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800496 default:
497 result = AAUDIO_ERROR_INTERNAL;
498 break;
499 }
500 return result;
501}
502
Phil Burk4e1af9f2018-01-03 15:54:35 -0800503audio_session_t AAudioConvert_aaudioToAndroidSessionId(aaudio_session_id_t sessionId) {
Phil Burk67fdd892018-01-23 15:28:55 -0800504 // If not a regular sessionId then convert to a safe value of AUDIO_SESSION_ALLOCATE.
505 return (sessionId == AAUDIO_SESSION_ID_ALLOCATE || sessionId == AAUDIO_SESSION_ID_NONE)
Phil Burk4e1af9f2018-01-03 15:54:35 -0800506 ? AUDIO_SESSION_ALLOCATE
507 : (audio_session_t) sessionId;
508}
509
Phil Burk9dca9822017-05-26 14:27:43 -0700510audio_format_t AAudioConvert_aaudioToAndroidDataFormat(aaudio_format_t aaudioFormat) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800511 audio_format_t androidFormat;
512 switch (aaudioFormat) {
513 case AAUDIO_FORMAT_PCM_I16:
514 androidFormat = AUDIO_FORMAT_PCM_16_BIT;
515 break;
516 case AAUDIO_FORMAT_PCM_FLOAT:
517 androidFormat = AUDIO_FORMAT_PCM_FLOAT;
518 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800519 default:
520 androidFormat = AUDIO_FORMAT_DEFAULT;
521 ALOGE("AAudioConvert_aaudioToAndroidDataFormat 0x%08X unrecognized", aaudioFormat);
522 break;
523 }
524 return androidFormat;
525}
526
Phil Burk9dca9822017-05-26 14:27:43 -0700527aaudio_format_t AAudioConvert_androidToAAudioDataFormat(audio_format_t androidFormat) {
528 aaudio_format_t aaudioFormat = AAUDIO_FORMAT_INVALID;
Phil Burk5ed503c2017-02-01 09:38:15 -0800529 switch (androidFormat) {
530 case AUDIO_FORMAT_PCM_16_BIT:
531 aaudioFormat = AAUDIO_FORMAT_PCM_I16;
532 break;
533 case AUDIO_FORMAT_PCM_FLOAT:
534 aaudioFormat = AAUDIO_FORMAT_PCM_FLOAT;
535 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800536 default:
537 aaudioFormat = AAUDIO_FORMAT_INVALID;
538 ALOGE("AAudioConvert_androidToAAudioDataFormat 0x%08X unrecognized", androidFormat);
539 break;
540 }
541 return aaudioFormat;
542}
543
Phil Burkd4ccc622017-12-20 15:32:44 -0800544// Make a message string from the condition.
545#define STATIC_ASSERT(condition) static_assert(condition, #condition)
546
547audio_usage_t AAudioConvert_usageToInternal(aaudio_usage_t usage) {
548 // The public aaudio_content_type_t constants are supposed to have the same
549 // values as the internal audio_content_type_t values.
550 STATIC_ASSERT(AAUDIO_USAGE_MEDIA == AUDIO_USAGE_MEDIA);
551 STATIC_ASSERT(AAUDIO_USAGE_VOICE_COMMUNICATION == AUDIO_USAGE_VOICE_COMMUNICATION);
552 STATIC_ASSERT(AAUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING
553 == AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING);
554 STATIC_ASSERT(AAUDIO_USAGE_ALARM == AUDIO_USAGE_ALARM);
555 STATIC_ASSERT(AAUDIO_USAGE_NOTIFICATION == AUDIO_USAGE_NOTIFICATION);
556 STATIC_ASSERT(AAUDIO_USAGE_NOTIFICATION_RINGTONE
557 == AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE);
558 STATIC_ASSERT(AAUDIO_USAGE_NOTIFICATION_EVENT == AUDIO_USAGE_NOTIFICATION_EVENT);
559 STATIC_ASSERT(AAUDIO_USAGE_ASSISTANCE_ACCESSIBILITY == AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY);
560 STATIC_ASSERT(AAUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE
561 == AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE);
562 STATIC_ASSERT(AAUDIO_USAGE_ASSISTANCE_SONIFICATION == AUDIO_USAGE_ASSISTANCE_SONIFICATION);
563 STATIC_ASSERT(AAUDIO_USAGE_GAME == AUDIO_USAGE_GAME);
564 STATIC_ASSERT(AAUDIO_USAGE_ASSISTANT == AUDIO_USAGE_ASSISTANT);
565 if (usage == AAUDIO_UNSPECIFIED) {
566 usage = AAUDIO_USAGE_MEDIA;
567 }
568 return (audio_usage_t) usage; // same value
569}
570
571audio_content_type_t AAudioConvert_contentTypeToInternal(aaudio_content_type_t contentType) {
572 // The public aaudio_content_type_t constants are supposed to have the same
573 // values as the internal audio_content_type_t values.
574 STATIC_ASSERT(AAUDIO_CONTENT_TYPE_MUSIC == AUDIO_CONTENT_TYPE_MUSIC);
575 STATIC_ASSERT(AAUDIO_CONTENT_TYPE_SPEECH == AUDIO_CONTENT_TYPE_SPEECH);
576 STATIC_ASSERT(AAUDIO_CONTENT_TYPE_SONIFICATION == AUDIO_CONTENT_TYPE_SONIFICATION);
577 STATIC_ASSERT(AAUDIO_CONTENT_TYPE_MOVIE == AUDIO_CONTENT_TYPE_MOVIE);
578 if (contentType == AAUDIO_UNSPECIFIED) {
579 contentType = AAUDIO_CONTENT_TYPE_MUSIC;
580 }
581 return (audio_content_type_t) contentType; // same value
582}
583
584audio_source_t AAudioConvert_inputPresetToAudioSource(aaudio_input_preset_t preset) {
585 // The public aaudio_input_preset_t constants are supposed to have the same
586 // values as the internal audio_source_t values.
587 STATIC_ASSERT(AAUDIO_UNSPECIFIED == AUDIO_SOURCE_DEFAULT);
588 STATIC_ASSERT(AAUDIO_INPUT_PRESET_GENERIC == AUDIO_SOURCE_MIC);
589 STATIC_ASSERT(AAUDIO_INPUT_PRESET_CAMCORDER == AUDIO_SOURCE_CAMCORDER);
590 STATIC_ASSERT(AAUDIO_INPUT_PRESET_VOICE_RECOGNITION == AUDIO_SOURCE_VOICE_RECOGNITION);
591 STATIC_ASSERT(AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION == AUDIO_SOURCE_VOICE_COMMUNICATION);
592 STATIC_ASSERT(AAUDIO_INPUT_PRESET_UNPROCESSED == AUDIO_SOURCE_UNPROCESSED);
593 if (preset == AAUDIO_UNSPECIFIED) {
Phil Burkeaef9b92018-01-18 09:09:42 -0800594 preset = AAUDIO_INPUT_PRESET_VOICE_RECOGNITION;
Phil Burkd4ccc622017-12-20 15:32:44 -0800595 }
596 return (audio_source_t) preset; // same value
597}
598
Phil Burk3316d5e2017-02-15 11:23:01 -0800599int32_t AAudioConvert_framesToBytes(int32_t numFrames,
Phil Burk7f680132018-03-12 14:48:06 -0700600 int32_t bytesPerFrame,
601 int32_t *sizeInBytes) {
602 *sizeInBytes = 0;
603
604 if (numFrames < 0 || bytesPerFrame < 0) {
605 ALOGE("negative size, numFrames = %d, frameSize = %d", numFrames, bytesPerFrame);
606 return AAUDIO_ERROR_OUT_OF_RANGE;
607 }
608
609 // Prevent numeric overflow.
610 if (numFrames > (INT32_MAX / bytesPerFrame)) {
Yi Kong0f414de2017-12-15 13:48:50 -0800611 ALOGE("size overflow, numFrames = %d, frameSize = %d", numFrames, bytesPerFrame);
Phil Burk5ed503c2017-02-01 09:38:15 -0800612 return AAUDIO_ERROR_OUT_OF_RANGE;
613 }
Phil Burk7f680132018-03-12 14:48:06 -0700614
Phil Burk5ed503c2017-02-01 09:38:15 -0800615 *sizeInBytes = numFrames * bytesPerFrame;
616 return AAUDIO_OK;
617}
Phil Burkc8f69a02017-05-11 15:53:06 -0700618
619static int32_t AAudioProperty_getMMapProperty(const char *propName,
620 int32_t defaultValue,
621 const char * caller) {
Phil Burk87c9f642017-05-17 07:22:39 -0700622 int32_t prop = property_get_int32(propName, defaultValue);
Phil Burkc8f69a02017-05-11 15:53:06 -0700623 switch (prop) {
Phil Burkd04aeea2017-05-23 13:56:41 -0700624 case AAUDIO_UNSPECIFIED:
625 case AAUDIO_POLICY_NEVER:
626 case AAUDIO_POLICY_ALWAYS:
627 case AAUDIO_POLICY_AUTO:
Phil Burkc8f69a02017-05-11 15:53:06 -0700628 break;
629 default:
630 ALOGE("%s: invalid = %d", caller, prop);
631 prop = defaultValue;
632 break;
633 }
634 return prop;
635}
636
Phil Burkd04aeea2017-05-23 13:56:41 -0700637int32_t AAudioProperty_getMMapPolicy() {
638 return AAudioProperty_getMMapProperty(AAUDIO_PROP_MMAP_POLICY,
639 AAUDIO_UNSPECIFIED, __func__);
Phil Burkc8f69a02017-05-11 15:53:06 -0700640}
641
Phil Burkd04aeea2017-05-23 13:56:41 -0700642int32_t AAudioProperty_getMMapExclusivePolicy() {
643 return AAudioProperty_getMMapProperty(AAUDIO_PROP_MMAP_EXCLUSIVE_POLICY,
644 AAUDIO_UNSPECIFIED, __func__);
Phil Burkc8f69a02017-05-11 15:53:06 -0700645}
646
647int32_t AAudioProperty_getMixerBursts() {
Phil Burk87c9f642017-05-17 07:22:39 -0700648 const int32_t defaultBursts = 2; // arbitrary, use 2 for double buffered
Phil Burkc8f69a02017-05-11 15:53:06 -0700649 const int32_t maxBursts = 1024; // arbitrary
Phil Burk87c9f642017-05-17 07:22:39 -0700650 int32_t prop = property_get_int32(AAUDIO_PROP_MIXER_BURSTS, defaultBursts);
Phil Burkc8f69a02017-05-11 15:53:06 -0700651 if (prop < 1 || prop > maxBursts) {
652 ALOGE("AAudioProperty_getMixerBursts: invalid = %d", prop);
653 prop = defaultBursts;
654 }
655 return prop;
656}
657
Phil Burkfd34a932017-07-19 07:03:52 -0700658int32_t AAudioProperty_getWakeupDelayMicros() {
659 const int32_t minMicros = 0; // arbitrary
660 const int32_t defaultMicros = 200; // arbitrary, based on some observed jitter
661 const int32_t maxMicros = 5000; // arbitrary, probably don't want more than 500
662 int32_t prop = property_get_int32(AAUDIO_PROP_WAKEUP_DELAY_USEC, defaultMicros);
663 if (prop < minMicros) {
664 ALOGW("AAudioProperty_getWakeupDelayMicros: clipped %d to %d", prop, minMicros);
665 prop = minMicros;
666 } else if (prop > maxMicros) {
667 ALOGW("AAudioProperty_getWakeupDelayMicros: clipped %d to %d", prop, maxMicros);
668 prop = maxMicros;
669 }
670 return prop;
671}
672
673int32_t AAudioProperty_getMinimumSleepMicros() {
674 const int32_t minMicros = 20; // arbitrary
675 const int32_t defaultMicros = 200; // arbitrary
676 const int32_t maxMicros = 2000; // arbitrary
677 int32_t prop = property_get_int32(AAUDIO_PROP_MINIMUM_SLEEP_USEC, defaultMicros);
678 if (prop < minMicros) {
679 ALOGW("AAudioProperty_getMinimumSleepMicros: clipped %d to %d", prop, minMicros);
680 prop = minMicros;
681 } else if (prop > maxMicros) {
682 ALOGW("AAudioProperty_getMinimumSleepMicros: clipped %d to %d", prop, maxMicros);
683 prop = maxMicros;
684 }
685 return prop;
686}
687
Phil Burkc8f69a02017-05-11 15:53:06 -0700688int32_t AAudioProperty_getHardwareBurstMinMicros() {
689 const int32_t defaultMicros = 1000; // arbitrary
690 const int32_t maxMicros = 1000 * 1000; // arbitrary
691 int32_t prop = property_get_int32(AAUDIO_PROP_HW_BURST_MIN_USEC, defaultMicros);
692 if (prop < 1 || prop > maxMicros) {
Phil Burkfd34a932017-07-19 07:03:52 -0700693 ALOGE("AAudioProperty_getHardwareBurstMinMicros: invalid = %d, use %d",
694 prop, defaultMicros);
Phil Burkc8f69a02017-05-11 15:53:06 -0700695 prop = defaultMicros;
696 }
697 return prop;
698}
Phil Burk5cc83c32017-11-28 15:43:18 -0800699
700aaudio_result_t AAudio_isFlushAllowed(aaudio_stream_state_t state) {
701 aaudio_result_t result = AAUDIO_OK;
702 switch (state) {
703// Proceed with flushing.
704 case AAUDIO_STREAM_STATE_OPEN:
705 case AAUDIO_STREAM_STATE_PAUSED:
706 case AAUDIO_STREAM_STATE_STOPPED:
707 case AAUDIO_STREAM_STATE_FLUSHED:
708 break;
709
710// Transition from one inactive state to another.
711 case AAUDIO_STREAM_STATE_STARTING:
712 case AAUDIO_STREAM_STATE_STARTED:
713 case AAUDIO_STREAM_STATE_STOPPING:
714 case AAUDIO_STREAM_STATE_PAUSING:
715 case AAUDIO_STREAM_STATE_FLUSHING:
716 case AAUDIO_STREAM_STATE_CLOSING:
717 case AAUDIO_STREAM_STATE_CLOSED:
718 case AAUDIO_STREAM_STATE_DISCONNECTED:
719 default:
720 ALOGE("can only flush stream when PAUSED, OPEN or STOPPED, state = %s",
721 AAudio_convertStreamStateToText(state));
722 result = AAUDIO_ERROR_INVALID_STATE;
723 break;
724 }
725 return result;
726}