Home | History | Annotate | Download | only in utility
      1 /*
      2  * Copyright 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #define LOG_TAG "AAudio"
     18 //#define LOG_NDEBUG 0
     19 #include <utils/Log.h>
     20 
     21 #include <cutils/properties.h>
     22 #include <stdint.h>
     23 #include <sys/types.h>
     24 #include <utils/Errors.h>
     25 
     26 #include "aaudio/AAudio.h"
     27 #include <aaudio/AAudioTesting.h>
     28 
     29 #include "utility/AAudioUtilities.h"
     30 
     31 using namespace android;
     32 
     33 // This is 3 dB, (10^(3/20)), to match the maximum headroom in AudioTrack for float data.
     34 // It is designed to allow occasional transient peaks.
     35 #define MAX_HEADROOM (1.41253754f)
     36 #define MIN_HEADROOM (0 - MAX_HEADROOM)
     37 
     38 int32_t AAudioConvert_formatToSizeInBytes(aaudio_format_t format) {
     39     int32_t size = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
     40     switch (format) {
     41         case AAUDIO_FORMAT_PCM_I16:
     42             size = sizeof(int16_t);
     43             break;
     44         case AAUDIO_FORMAT_PCM_FLOAT:
     45             size = sizeof(float);
     46             break;
     47         default:
     48             break;
     49     }
     50     return size;
     51 }
     52 
     53 
     54 // TODO expose and call clamp16_from_float function in primitives.h
     55 static inline int16_t clamp16_from_float(float f) {
     56     /* Offset is used to expand the valid range of [-1.0, 1.0) into the 16 lsbs of the
     57      * floating point significand. The normal shift is 3<<22, but the -15 offset
     58      * is used to multiply by 32768.
     59      */
     60     static const float offset = (float)(3 << (22 - 15));
     61     /* zero = (0x10f << 22) =  0x43c00000 (not directly used) */
     62     static const int32_t limneg = (0x10f << 22) /*zero*/ - 32768; /* 0x43bf8000 */
     63     static const int32_t limpos = (0x10f << 22) /*zero*/ + 32767; /* 0x43c07fff */
     64 
     65     union {
     66         float f;
     67         int32_t i;
     68     } u;
     69 
     70     u.f = f + offset; /* recenter valid range */
     71     /* Now the valid range is represented as integers between [limneg, limpos].
     72      * Clamp using the fact that float representation (as an integer) is an ordered set.
     73      */
     74     if (u.i < limneg)
     75         u.i = -32768;
     76     else if (u.i > limpos)
     77         u.i = 32767;
     78     return u.i; /* Return lower 16 bits, the part of interest in the significand. */
     79 }
     80 
     81 // Same but without clipping.
     82 // Convert -1.0f to +1.0f to -32768 to +32767
     83 static inline int16_t floatToInt16(float f) {
     84     static const float offset = (float)(3 << (22 - 15));
     85     union {
     86         float f;
     87         int32_t i;
     88     } u;
     89     u.f = f + offset; /* recenter valid range */
     90     return u.i; /* Return lower 16 bits, the part of interest in the significand. */
     91 }
     92 
     93 static float clipAndClampFloatToPcm16(float sample, float scaler) {
     94     // Clip to valid range of a float sample to prevent excessive volume.
     95     if (sample > MAX_HEADROOM) sample = MAX_HEADROOM;
     96     else if (sample < MIN_HEADROOM) sample = MIN_HEADROOM;
     97 
     98     // Scale and convert to a short.
     99     float fval = sample * scaler;
    100     return clamp16_from_float(fval);
    101 }
    102 
    103 void AAudioConvert_floatToPcm16(const float *source,
    104                                 int16_t *destination,
    105                                 int32_t numSamples,
    106                                 float amplitude) {
    107     float scaler = amplitude;
    108     for (int i = 0; i < numSamples; i++) {
    109         float sample = *source++;
    110         *destination++ = clipAndClampFloatToPcm16(sample, scaler);
    111     }
    112 }
    113 
    114 void AAudioConvert_floatToPcm16(const float *source,
    115                                 int16_t *destination,
    116                                 int32_t numFrames,
    117                                 int32_t samplesPerFrame,
    118                                 float amplitude1,
    119                                 float amplitude2) {
    120     float scaler = amplitude1;
    121     // divide by numFrames so that we almost reach amplitude2
    122     float delta = (amplitude2 - amplitude1) / numFrames;
    123     for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) {
    124         for (int sampleIndex = 0; sampleIndex < samplesPerFrame; sampleIndex++) {
    125             float sample = *source++;
    126             *destination++ = clipAndClampFloatToPcm16(sample, scaler);
    127         }
    128         scaler += delta;
    129     }
    130 }
    131 
    132 #define SHORT_SCALE  32768
    133 
    134 void AAudioConvert_pcm16ToFloat(const int16_t *source,
    135                                 float *destination,
    136                                 int32_t numSamples,
    137                                 float amplitude) {
    138     float scaler = amplitude / SHORT_SCALE;
    139     for (int i = 0; i < numSamples; i++) {
    140         destination[i] = source[i] * scaler;
    141     }
    142 }
    143 
    144 // This code assumes amplitude1 and amplitude2 are between 0.0 and 1.0
    145 void AAudioConvert_pcm16ToFloat(const int16_t *source,
    146                                 float *destination,
    147                                 int32_t numFrames,
    148                                 int32_t samplesPerFrame,
    149                                 float amplitude1,
    150                                 float amplitude2) {
    151     float scaler = amplitude1 / SHORT_SCALE;
    152     float delta = (amplitude2 - amplitude1) / (SHORT_SCALE * (float) numFrames);
    153     for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) {
    154         for (int sampleIndex = 0; sampleIndex < samplesPerFrame; sampleIndex++) {
    155             *destination++ = *source++ * scaler;
    156         }
    157         scaler += delta;
    158     }
    159 }
    160 
    161 // This code assumes amplitude1 and amplitude2 are between 0.0 and 1.0
    162 void AAudio_linearRamp(const float *source,
    163                        float *destination,
    164                        int32_t numFrames,
    165                        int32_t samplesPerFrame,
    166                        float amplitude1,
    167                        float amplitude2) {
    168     float scaler = amplitude1;
    169     float delta = (amplitude2 - amplitude1) / numFrames;
    170     for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) {
    171         for (int sampleIndex = 0; sampleIndex < samplesPerFrame; sampleIndex++) {
    172             float sample = *source++;
    173 
    174             // Clip to valid range of a float sample to prevent excessive volume.
    175             if (sample > MAX_HEADROOM) sample = MAX_HEADROOM;
    176             else if (sample < MIN_HEADROOM) sample = MIN_HEADROOM;
    177 
    178             *destination++ = sample * scaler;
    179         }
    180         scaler += delta;
    181     }
    182 }
    183 
    184 // This code assumes amplitude1 and amplitude2 are between 0.0 and 1.0
    185 void AAudio_linearRamp(const int16_t *source,
    186                        int16_t *destination,
    187                        int32_t numFrames,
    188                        int32_t samplesPerFrame,
    189                        float amplitude1,
    190                        float amplitude2) {
    191     float scaler = amplitude1 / SHORT_SCALE;
    192     float delta = (amplitude2 - amplitude1) / (SHORT_SCALE * (float) numFrames);
    193     for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) {
    194         for (int sampleIndex = 0; sampleIndex < samplesPerFrame; sampleIndex++) {
    195             // No need to clip because int16_t range is inherently limited.
    196             float sample =  *source++ * scaler;
    197             *destination++ =  floatToInt16(sample);
    198         }
    199         scaler += delta;
    200     }
    201 }
    202 
    203 status_t AAudioConvert_aaudioToAndroidStatus(aaudio_result_t result) {
    204     // This covers the case for AAUDIO_OK and for positive results.
    205     if (result >= 0) {
    206         return result;
    207     }
    208     status_t status;
    209     switch (result) {
    210     case AAUDIO_ERROR_DISCONNECTED:
    211     case AAUDIO_ERROR_NO_SERVICE:
    212         status = DEAD_OBJECT;
    213         break;
    214     case AAUDIO_ERROR_INVALID_HANDLE:
    215         status = BAD_TYPE;
    216         break;
    217     case AAUDIO_ERROR_INVALID_STATE:
    218         status = INVALID_OPERATION;
    219         break;
    220     case AAUDIO_ERROR_INVALID_RATE:
    221     case AAUDIO_ERROR_INVALID_FORMAT:
    222     case AAUDIO_ERROR_ILLEGAL_ARGUMENT:
    223     case AAUDIO_ERROR_OUT_OF_RANGE:
    224         status = BAD_VALUE;
    225         break;
    226     case AAUDIO_ERROR_WOULD_BLOCK:
    227         status = WOULD_BLOCK;
    228         break;
    229     case AAUDIO_ERROR_NULL:
    230         status = UNEXPECTED_NULL;
    231         break;
    232     case AAUDIO_ERROR_UNAVAILABLE:
    233         status = NOT_ENOUGH_DATA;
    234         break;
    235 
    236     // TODO translate these result codes
    237     case AAUDIO_ERROR_INTERNAL:
    238     case AAUDIO_ERROR_UNIMPLEMENTED:
    239     case AAUDIO_ERROR_NO_FREE_HANDLES:
    240     case AAUDIO_ERROR_NO_MEMORY:
    241     case AAUDIO_ERROR_TIMEOUT:
    242     default:
    243         status = UNKNOWN_ERROR;
    244         break;
    245     }
    246     return status;
    247 }
    248 
    249 aaudio_result_t AAudioConvert_androidToAAudioResult(status_t status) {
    250     // This covers the case for OK and for positive result.
    251     if (status >= 0) {
    252         return status;
    253     }
    254     aaudio_result_t result;
    255     switch (status) {
    256     case BAD_TYPE:
    257         result = AAUDIO_ERROR_INVALID_HANDLE;
    258         break;
    259     case DEAD_OBJECT:
    260         result = AAUDIO_ERROR_NO_SERVICE;
    261         break;
    262     case INVALID_OPERATION:
    263         result = AAUDIO_ERROR_INVALID_STATE;
    264         break;
    265     case UNEXPECTED_NULL:
    266         result = AAUDIO_ERROR_NULL;
    267         break;
    268     case BAD_VALUE:
    269         result = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
    270         break;
    271     case WOULD_BLOCK:
    272         result = AAUDIO_ERROR_WOULD_BLOCK;
    273         break;
    274     case NOT_ENOUGH_DATA:
    275         result = AAUDIO_ERROR_UNAVAILABLE;
    276         break;
    277     default:
    278         result = AAUDIO_ERROR_INTERNAL;
    279         break;
    280     }
    281     return result;
    282 }
    283 
    284 audio_format_t AAudioConvert_aaudioToAndroidDataFormat(aaudio_format_t aaudioFormat) {
    285     audio_format_t androidFormat;
    286     switch (aaudioFormat) {
    287     case AAUDIO_FORMAT_PCM_I16:
    288         androidFormat = AUDIO_FORMAT_PCM_16_BIT;
    289         break;
    290     case AAUDIO_FORMAT_PCM_FLOAT:
    291         androidFormat = AUDIO_FORMAT_PCM_FLOAT;
    292         break;
    293     default:
    294         androidFormat = AUDIO_FORMAT_DEFAULT;
    295         ALOGE("AAudioConvert_aaudioToAndroidDataFormat 0x%08X unrecognized", aaudioFormat);
    296         break;
    297     }
    298     return androidFormat;
    299 }
    300 
    301 aaudio_format_t AAudioConvert_androidToAAudioDataFormat(audio_format_t androidFormat) {
    302     aaudio_format_t aaudioFormat = AAUDIO_FORMAT_INVALID;
    303     switch (androidFormat) {
    304     case AUDIO_FORMAT_PCM_16_BIT:
    305         aaudioFormat = AAUDIO_FORMAT_PCM_I16;
    306         break;
    307     case AUDIO_FORMAT_PCM_FLOAT:
    308         aaudioFormat = AAUDIO_FORMAT_PCM_FLOAT;
    309         break;
    310     default:
    311         aaudioFormat = AAUDIO_FORMAT_INVALID;
    312         ALOGE("AAudioConvert_androidToAAudioDataFormat 0x%08X unrecognized", androidFormat);
    313         break;
    314     }
    315     return aaudioFormat;
    316 }
    317 
    318 int32_t AAudioConvert_framesToBytes(int32_t numFrames,
    319                                             int32_t bytesPerFrame,
    320                                             int32_t *sizeInBytes) {
    321     // TODO implement more elegantly
    322     const int32_t maxChannels = 256; // ridiculously large
    323     const int32_t maxBytesPerFrame = maxChannels * sizeof(float);
    324     // Prevent overflow by limiting multiplicands.
    325     if (bytesPerFrame > maxBytesPerFrame || numFrames > (0x3FFFFFFF / maxBytesPerFrame)) {
    326         ALOGE("size overflow, numFrames = %d, frameSize = %zd", numFrames, bytesPerFrame);
    327         return AAUDIO_ERROR_OUT_OF_RANGE;
    328     }
    329     *sizeInBytes = numFrames * bytesPerFrame;
    330     return AAUDIO_OK;
    331 }
    332 
    333 static int32_t AAudioProperty_getMMapProperty(const char *propName,
    334                                               int32_t defaultValue,
    335                                               const char * caller) {
    336     int32_t prop = property_get_int32(propName, defaultValue);
    337     switch (prop) {
    338         case AAUDIO_UNSPECIFIED:
    339         case AAUDIO_POLICY_NEVER:
    340         case AAUDIO_POLICY_ALWAYS:
    341         case AAUDIO_POLICY_AUTO:
    342             break;
    343         default:
    344             ALOGE("%s: invalid = %d", caller, prop);
    345             prop = defaultValue;
    346             break;
    347     }
    348     return prop;
    349 }
    350 
    351 int32_t AAudioProperty_getMMapPolicy() {
    352     return AAudioProperty_getMMapProperty(AAUDIO_PROP_MMAP_POLICY,
    353                                           AAUDIO_UNSPECIFIED, __func__);
    354 }
    355 
    356 int32_t AAudioProperty_getMMapExclusivePolicy() {
    357     return AAudioProperty_getMMapProperty(AAUDIO_PROP_MMAP_EXCLUSIVE_POLICY,
    358                                           AAUDIO_UNSPECIFIED, __func__);
    359 }
    360 
    361 int32_t AAudioProperty_getMixerBursts() {
    362     const int32_t defaultBursts = 2; // arbitrary, use 2 for double buffered
    363     const int32_t maxBursts = 1024; // arbitrary
    364     int32_t prop = property_get_int32(AAUDIO_PROP_MIXER_BURSTS, defaultBursts);
    365     if (prop < 1 || prop > maxBursts) {
    366         ALOGE("AAudioProperty_getMixerBursts: invalid = %d", prop);
    367         prop = defaultBursts;
    368     }
    369     return prop;
    370 }
    371 
    372 int32_t AAudioProperty_getWakeupDelayMicros() {
    373     const int32_t minMicros = 0; // arbitrary
    374     const int32_t defaultMicros = 200; // arbitrary, based on some observed jitter
    375     const int32_t maxMicros = 5000; // arbitrary, probably don't want more than 500
    376     int32_t prop = property_get_int32(AAUDIO_PROP_WAKEUP_DELAY_USEC, defaultMicros);
    377     if (prop < minMicros) {
    378         ALOGW("AAudioProperty_getWakeupDelayMicros: clipped %d to %d", prop, minMicros);
    379         prop = minMicros;
    380     } else if (prop > maxMicros) {
    381         ALOGW("AAudioProperty_getWakeupDelayMicros: clipped %d to %d", prop, maxMicros);
    382         prop = maxMicros;
    383     }
    384     return prop;
    385 }
    386 
    387 int32_t AAudioProperty_getMinimumSleepMicros() {
    388     const int32_t minMicros = 20; // arbitrary
    389     const int32_t defaultMicros = 200; // arbitrary
    390     const int32_t maxMicros = 2000; // arbitrary
    391     int32_t prop = property_get_int32(AAUDIO_PROP_MINIMUM_SLEEP_USEC, defaultMicros);
    392     if (prop < minMicros) {
    393         ALOGW("AAudioProperty_getMinimumSleepMicros: clipped %d to %d", prop, minMicros);
    394         prop = minMicros;
    395     } else if (prop > maxMicros) {
    396         ALOGW("AAudioProperty_getMinimumSleepMicros: clipped %d to %d", prop, maxMicros);
    397         prop = maxMicros;
    398     }
    399     return prop;
    400 }
    401 
    402 int32_t AAudioProperty_getHardwareBurstMinMicros() {
    403     const int32_t defaultMicros = 1000; // arbitrary
    404     const int32_t maxMicros = 1000 * 1000; // arbitrary
    405     int32_t prop = property_get_int32(AAUDIO_PROP_HW_BURST_MIN_USEC, defaultMicros);
    406     if (prop < 1 || prop > maxMicros) {
    407         ALOGE("AAudioProperty_getHardwareBurstMinMicros: invalid = %d, use %d",
    408               prop, defaultMicros);
    409         prop = defaultMicros;
    410     }
    411     return prop;
    412 }
    413