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 */ 33android::status_t AAudioConvert_aaudioToAndroidStatus(aaudio_result_t result); 34 35/** 36 * Convert an Android status into the closest matching AAudio result. 37 */ 38aaudio_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 */ 48void 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 */ 66void 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 */ 90void 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 */ 108void 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 */ 128void 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 */ 148void 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 */ 162int32_t AAudioConvert_framesToBytes(int32_t numFrames, 163 int32_t bytesPerFrame, 164 int32_t *sizeInBytes); 165 166audio_format_t AAudioConvert_aaudioToAndroidDataFormat(aaudio_format_t aaudio_format); 167 168aaudio_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 */ 173int32_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 */ 184int32_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 */ 192int32_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 */ 200int32_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 */ 213int32_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 */ 222int32_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 */ 236int32_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 */ 248static 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 */ 271template <class T> 272class SimpleDoubleBuffer { 273public: 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 314private: 315 T mValues[2]; 316 std::atomic<int> mCounter{0}; 317}; 318 319class Timestamp { 320public: 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 332private: 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 */ 347class AtomicRequestor { 348public: 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 365private: 366 std::atomic<int> mRequested{0}; 367 std::atomic<int> mAcknowledged{0}; 368}; 369#endif //UTILITY_AAUDIO_UTILITIES_H 370