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