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 #ifndef UTILITY_AAUDIO_UTILITIES_H
     18 #define UTILITY_AAUDIO_UTILITIES_H
     19 
     20 #include <algorithm>
     21 #include <functional>
     22 #include <stdint.h>
     23 #include <sys/types.h>
     24 
     25 #include <utils/Errors.h>
     26 #include <hardware/audio.h>
     27 
     28 #include "aaudio/AAudio.h"
     29 
     30 /**
     31  * Convert an AAudio result into the closest matching Android status.
     32  */
     33 android::status_t AAudioConvert_aaudioToAndroidStatus(aaudio_result_t result);
     34 
     35 /**
     36  * Convert an Android status into the closest matching AAudio result.
     37  */
     38 aaudio_result_t AAudioConvert_androidToAAudioResult(android::status_t status);
     39 
     40 /**
     41  * Convert an array of floats to an array of int16_t.
     42  *
     43  * @param source
     44  * @param destination
     45  * @param numSamples number of values in the array
     46  * @param amplitude level between 0.0 and 1.0
     47  */
     48 void AAudioConvert_floatToPcm16(const float *source,
     49                                 int16_t *destination,
     50                                 int32_t numSamples,
     51                                 float amplitude);
     52 
     53 /**
     54  * Convert floats to int16_t and scale by a linear ramp.
     55  *
     56  * The ramp stops just short of reaching amplitude2 so that the next
     57  * ramp can start at amplitude2 without causing a discontinuity.
     58  *
     59  * @param source
     60  * @param destination
     61  * @param numFrames
     62  * @param samplesPerFrame AKA number of channels
     63  * @param amplitude1 level at start of ramp, between 0.0 and 1.0
     64  * @param amplitude2 level past end of ramp, between 0.0 and 1.0
     65  */
     66 void AAudioConvert_floatToPcm16(const float *source,
     67                                 int16_t *destination,
     68                                 int32_t numFrames,
     69                                 int32_t samplesPerFrame,
     70                                 float amplitude1,
     71                                 float amplitude2);
     72 
     73 /**
     74  * Convert int16_t array to float array ranging from -1.0 to +1.0.
     75  * @param source
     76  * @param destination
     77  * @param numSamples
     78  */
     79 //void AAudioConvert_pcm16ToFloat(const int16_t *source, int32_t numSamples,
     80 //                                float *destination);
     81 
     82 /**
     83  *
     84  * Convert int16_t array to float array ranging from +/- amplitude.
     85  * @param source
     86  * @param destination
     87  * @param numSamples
     88  * @param amplitude
     89  */
     90 void AAudioConvert_pcm16ToFloat(const int16_t *source,
     91                                 float *destination,
     92                                 int32_t numSamples,
     93                                 float amplitude);
     94 
     95 /**
     96  * Convert floats to int16_t and scale by a linear ramp.
     97  *
     98  * The ramp stops just short of reaching amplitude2 so that the next
     99  * ramp can start at amplitude2 without causing a discontinuity.
    100  *
    101  * @param source
    102  * @param destination
    103  * @param numFrames
    104  * @param samplesPerFrame AKA number of channels
    105  * @param amplitude1 level at start of ramp, between 0.0 and 1.0
    106  * @param amplitude2 level at end of ramp, between 0.0 and 1.0
    107  */
    108 void AAudioConvert_pcm16ToFloat(const int16_t *source,
    109                                 float *destination,
    110                                 int32_t numFrames,
    111                                 int32_t samplesPerFrame,
    112                                 float amplitude1,
    113                                 float amplitude2);
    114 
    115 /**
    116  * Scale floats by a linear ramp.
    117  *
    118  * The ramp stops just short of reaching amplitude2 so that the next
    119  * ramp can start at amplitude2 without causing a discontinuity.
    120  *
    121  * @param source
    122  * @param destination
    123  * @param numFrames
    124  * @param samplesPerFrame
    125  * @param amplitude1
    126  * @param amplitude2
    127  */
    128 void AAudio_linearRamp(const float *source,
    129                        float *destination,
    130                        int32_t numFrames,
    131                        int32_t samplesPerFrame,
    132                        float amplitude1,
    133                        float amplitude2);
    134 
    135 /**
    136  * Scale int16_t's by a linear ramp.
    137  *
    138  * The ramp stops just short of reaching amplitude2 so that the next
    139  * ramp can start at amplitude2 without causing a discontinuity.
    140  *
    141  * @param source
    142  * @param destination
    143  * @param numFrames
    144  * @param samplesPerFrame
    145  * @param amplitude1
    146  * @param amplitude2
    147  */
    148 void AAudio_linearRamp(const int16_t *source,
    149                        int16_t *destination,
    150                        int32_t numFrames,
    151                        int32_t samplesPerFrame,
    152                        float amplitude1,
    153                        float amplitude2);
    154 
    155 /**
    156  * Calculate the number of bytes and prevent numeric overflow.
    157  * @param numFrames frame count
    158  * @param bytesPerFrame size of a frame in bytes
    159  * @param sizeInBytes total size in bytes
    160  * @return AAUDIO_OK or negative error, eg. AAUDIO_ERROR_OUT_OF_RANGE
    161  */
    162 int32_t AAudioConvert_framesToBytes(int32_t numFrames,
    163                                             int32_t bytesPerFrame,
    164                                             int32_t *sizeInBytes);
    165 
    166 audio_format_t AAudioConvert_aaudioToAndroidDataFormat(aaudio_format_t aaudio_format);
    167 
    168 aaudio_format_t AAudioConvert_androidToAAudioDataFormat(audio_format_t format);
    169 
    170 /**
    171  * @return the size of a sample of the given format in bytes or AAUDIO_ERROR_ILLEGAL_ARGUMENT
    172  */
    173 int32_t AAudioConvert_formatToSizeInBytes(aaudio_format_t format);
    174 
    175 
    176 // Note that this code may be replaced by Settings or by some other system configuration tool.
    177 
    178 #define AAUDIO_PROP_MMAP_POLICY           "aaudio.mmap_policy"
    179 
    180 /**
    181  * Read system property.
    182  * @return AAUDIO_UNSPECIFIED, AAUDIO_POLICY_NEVER or AAUDIO_POLICY_AUTO or AAUDIO_POLICY_ALWAYS
    183  */
    184 int32_t AAudioProperty_getMMapPolicy();
    185 
    186 #define AAUDIO_PROP_MMAP_EXCLUSIVE_POLICY "aaudio.mmap_exclusive_policy"
    187 
    188 /**
    189  * Read system property.
    190  * @return AAUDIO_UNSPECIFIED, AAUDIO_POLICY_NEVER or AAUDIO_POLICY_AUTO or AAUDIO_POLICY_ALWAYS
    191  */
    192 int32_t AAudioProperty_getMMapExclusivePolicy();
    193 
    194 #define AAUDIO_PROP_MIXER_BURSTS           "aaudio.mixer_bursts"
    195 
    196 /**
    197  * Read system property.
    198  * @return number of bursts per AAudio service mixer cycle
    199  */
    200 int32_t AAudioProperty_getMixerBursts();
    201 
    202 #define AAUDIO_PROP_HW_BURST_MIN_USEC      "aaudio.hw_burst_min_usec"
    203 
    204 /**
    205  * Read a system property that specifies the number of extra microseconds that a thread
    206  * should sleep when waiting for another thread to service a FIFO. This is used
    207  * to avoid the waking thread from being overly optimistic about the other threads
    208  * wakeup timing. This value should be set high enough to cover typical scheduling jitter
    209  * for a real-time thread.
    210  *
    211  * @return number of microseconds to delay the wakeup.
    212  */
    213 int32_t AAudioProperty_getWakeupDelayMicros();
    214 
    215 #define AAUDIO_PROP_WAKEUP_DELAY_USEC      "aaudio.wakeup_delay_usec"
    216 
    217 /**
    218  * Read a system property that specifies the minimum sleep time when polling the FIFO.
    219  *
    220  * @return minimum number of microseconds to sleep.
    221  */
    222 int32_t AAudioProperty_getMinimumSleepMicros();
    223 
    224 #define AAUDIO_PROP_MINIMUM_SLEEP_USEC      "aaudio.minimum_sleep_usec"
    225 
    226 /**
    227  * Read system property.
    228  * This is handy in case the DMA is bursting too quickly for the CPU to keep up.
    229  * For example, there may be a DMA burst every 100 usec but you only
    230  * want to feed the MMAP buffer every 2000 usec.
    231  *
    232  * This will affect the framesPerBurst for an MMAP stream.
    233  *
    234  * @return minimum number of microseconds for a MMAP HW burst
    235  */
    236 int32_t AAudioProperty_getHardwareBurstMinMicros();
    237 
    238 /**
    239  * Try a function f until it returns true.
    240  *
    241  * The function is always called at least once.
    242  *
    243  * @param f the function to evaluate, which returns a bool.
    244  * @param times the number of times to evaluate f.
    245  * @param sleepMs the sleep time per check of f, if greater than 0.
    246  * @return true if f() eventually returns true.
    247  */
    248 static inline bool AAudio_tryUntilTrue(
    249         std::function<bool()> f, int times, int sleepMs) {
    250     static const useconds_t US_PER_MS = 1000;
    251 
    252     sleepMs = std::max(sleepMs, 0);
    253     for (;;) {
    254         if (f()) return true;
    255         if (times <= 1) return false;
    256         --times;
    257         usleep(sleepMs * US_PER_MS);
    258     }
    259 }
    260 
    261 
    262 /**
    263  * Simple double buffer for a structure that can be written occasionally and read occasionally.
    264  * This allows a SINGLE writer with multiple readers.
    265  *
    266  * It is OK if the FIFO overflows and we lose old values.
    267  * It is also OK if we read an old value.
    268  * Thread may return a non-atomic result if the other thread is rapidly writing
    269  * new values on another core.
    270  */
    271 template <class T>
    272 class SimpleDoubleBuffer {
    273 public:
    274     SimpleDoubleBuffer()
    275             : mValues() {}
    276 
    277     __attribute__((no_sanitize("integer")))
    278     void write(T value) {
    279         int index = mCounter.load() & 1;
    280         mValues[index] = value;
    281         mCounter++; // Increment AFTER updating storage, OK if it wraps.
    282     }
    283 
    284     /**
    285      * This should only be called by the same thread that calls write() or when
    286      * no other thread is calling write.
    287      */
    288     void clear() {
    289         mCounter.store(0);
    290     }
    291 
    292     T read() const {
    293         T result;
    294         int before;
    295         int after;
    296         int timeout = 3;
    297         do {
    298             // Check to see if a write occurred while were reading.
    299             before = mCounter.load();
    300             int index = (before & 1) ^ 1;
    301             result = mValues[index];
    302             after = mCounter.load();
    303         } while ((after != before) && (after > 0) && (--timeout > 0));
    304         return result;
    305     }
    306 
    307     /**
    308      * @return true if at least one value has been written
    309      */
    310     bool isValid() const {
    311         return mCounter.load() > 0;
    312     }
    313 
    314 private:
    315     T                    mValues[2];
    316     std::atomic<int>     mCounter{0};
    317 };
    318 
    319 class Timestamp {
    320 public:
    321     Timestamp()
    322             : mPosition(0)
    323             , mNanoseconds(0) {}
    324     Timestamp(int64_t position, int64_t nanoseconds)
    325             : mPosition(position)
    326             , mNanoseconds(nanoseconds) {}
    327 
    328     int64_t getPosition() const { return mPosition; }
    329 
    330     int64_t getNanoseconds() const { return mNanoseconds; }
    331 
    332 private:
    333     // These cannot be const because we need to implement the copy assignment operator.
    334     int64_t mPosition;
    335     int64_t mNanoseconds;
    336 };
    337 
    338 
    339 /**
    340  * Pass a request to another thread.
    341  * This is used when one thread, A, wants another thread, B, to do something.
    342  * A naive approach would be for A to set a flag and for B to clear it when done.
    343  * But that creates a race condition. This technique avoids the race condition.
    344  *
    345  * Assumes only one requester and one acknowledger.
    346  */
    347 class AtomicRequestor {
    348 public:
    349 
    350     __attribute__((no_sanitize("integer")))
    351     void request() {
    352         mRequested++;
    353     }
    354 
    355     __attribute__((no_sanitize("integer")))
    356     bool isRequested() {
    357         return (mRequested.load() - mAcknowledged.load()) > 0;
    358     }
    359 
    360     __attribute__((no_sanitize("integer")))
    361     void acknowledge() {
    362         mAcknowledged++;
    363     }
    364 
    365 private:
    366     std::atomic<int> mRequested{0};
    367     std::atomic<int> mAcknowledged{0};
    368 };
    369 #endif //UTILITY_AAUDIO_UTILITIES_H
    370