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