blob: 3673c34f47f173a5effdc92ad4af4ed55ea738b2 [file] [log] [blame]
Phil Burk5ed503c2017-02-01 09:38:15 -08001/*
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
Andy Hung47c5e532017-06-26 18:28:00 -070020#include <algorithm>
21#include <functional>
Phil Burk5ed503c2017-02-01 09:38:15 -080022#include <stdint.h>
23#include <sys/types.h>
24
25#include <utils/Errors.h>
Kevin Rocard6d7582e2018-01-11 19:28:14 -080026#include <system/audio.h>
Phil Burk5ed503c2017-02-01 09:38:15 -080027
Phil Burka4eb0d82017-04-12 15:44:06 -070028#include "aaudio/AAudio.h"
Phil Burk5ed503c2017-02-01 09:38:15 -080029
Phil Burk4e1af9f2018-01-03 15:54:35 -080030
31constexpr aaudio_session_id_t AAUDIO_SESSION_ID_MIN = 1; // must be positive
32
Phil Burk5ed503c2017-02-01 09:38:15 -080033/**
34 * Convert an AAudio result into the closest matching Android status.
35 */
36android::status_t AAudioConvert_aaudioToAndroidStatus(aaudio_result_t result);
37
38/**
39 * Convert an Android status into the closest matching AAudio result.
40 */
41aaudio_result_t AAudioConvert_androidToAAudioResult(android::status_t status);
42
Phil Burke572f462017-04-20 13:03:19 -070043/**
Phil Burk4e1af9f2018-01-03 15:54:35 -080044 * Convert an aaudio_session_id_t to a value that is safe to pass to AudioFlinger.
45 * @param sessionId
46 * @return safe value
47 */
48audio_session_t AAudioConvert_aaudioToAndroidSessionId(aaudio_session_id_t sessionId);
49
50/**
Phil Burke572f462017-04-20 13:03:19 -070051 * Convert an array of floats to an array of int16_t.
52 *
53 * @param source
54 * @param destination
55 * @param numSamples number of values in the array
56 * @param amplitude level between 0.0 and 1.0
57 */
58void AAudioConvert_floatToPcm16(const float *source,
59 int16_t *destination,
60 int32_t numSamples,
61 float amplitude);
Phil Burk5ed503c2017-02-01 09:38:15 -080062
Phil Burke572f462017-04-20 13:03:19 -070063/**
64 * Convert floats to int16_t and scale by a linear ramp.
65 *
66 * The ramp stops just short of reaching amplitude2 so that the next
67 * ramp can start at amplitude2 without causing a discontinuity.
68 *
69 * @param source
70 * @param destination
71 * @param numFrames
72 * @param samplesPerFrame AKA number of channels
73 * @param amplitude1 level at start of ramp, between 0.0 and 1.0
74 * @param amplitude2 level past end of ramp, between 0.0 and 1.0
75 */
76void AAudioConvert_floatToPcm16(const float *source,
77 int16_t *destination,
78 int32_t numFrames,
79 int32_t samplesPerFrame,
80 float amplitude1,
81 float amplitude2);
82
83/**
84 * Convert int16_t array to float array ranging from -1.0 to +1.0.
85 * @param source
86 * @param destination
87 * @param numSamples
88 */
89//void AAudioConvert_pcm16ToFloat(const int16_t *source, int32_t numSamples,
90// float *destination);
91
92/**
93 *
94 * Convert int16_t array to float array ranging from +/- amplitude.
95 * @param source
96 * @param destination
97 * @param numSamples
98 * @param amplitude
99 */
100void AAudioConvert_pcm16ToFloat(const int16_t *source,
101 float *destination,
102 int32_t numSamples,
103 float amplitude);
104
105/**
106 * Convert floats to int16_t and scale by a linear ramp.
107 *
108 * The ramp stops just short of reaching amplitude2 so that the next
109 * ramp can start at amplitude2 without causing a discontinuity.
110 *
111 * @param source
112 * @param destination
113 * @param numFrames
114 * @param samplesPerFrame AKA number of channels
115 * @param amplitude1 level at start of ramp, between 0.0 and 1.0
116 * @param amplitude2 level at end of ramp, between 0.0 and 1.0
117 */
118void AAudioConvert_pcm16ToFloat(const int16_t *source,
119 float *destination,
120 int32_t numFrames,
121 int32_t samplesPerFrame,
122 float amplitude1,
123 float amplitude2);
124
125/**
126 * Scale floats by a linear ramp.
127 *
128 * The ramp stops just short of reaching amplitude2 so that the next
129 * ramp can start at amplitude2 without causing a discontinuity.
130 *
131 * @param source
132 * @param destination
133 * @param numFrames
134 * @param samplesPerFrame
135 * @param amplitude1
136 * @param amplitude2
137 */
138void AAudio_linearRamp(const float *source,
139 float *destination,
140 int32_t numFrames,
141 int32_t samplesPerFrame,
142 float amplitude1,
143 float amplitude2);
144
145/**
146 * Scale int16_t's by a linear ramp.
147 *
148 * The ramp stops just short of reaching amplitude2 so that the next
149 * ramp can start at amplitude2 without causing a discontinuity.
150 *
151 * @param source
152 * @param destination
153 * @param numFrames
154 * @param samplesPerFrame
155 * @param amplitude1
156 * @param amplitude2
157 */
158void AAudio_linearRamp(const int16_t *source,
159 int16_t *destination,
160 int32_t numFrames,
161 int32_t samplesPerFrame,
162 float amplitude1,
163 float amplitude2);
Phil Burk5ed503c2017-02-01 09:38:15 -0800164
165/**
166 * Calculate the number of bytes and prevent numeric overflow.
167 * @param numFrames frame count
168 * @param bytesPerFrame size of a frame in bytes
169 * @param sizeInBytes total size in bytes
170 * @return AAUDIO_OK or negative error, eg. AAUDIO_ERROR_OUT_OF_RANGE
171 */
Phil Burk3316d5e2017-02-15 11:23:01 -0800172int32_t AAudioConvert_framesToBytes(int32_t numFrames,
173 int32_t bytesPerFrame,
174 int32_t *sizeInBytes);
Phil Burk5ed503c2017-02-01 09:38:15 -0800175
Phil Burk9dca9822017-05-26 14:27:43 -0700176audio_format_t AAudioConvert_aaudioToAndroidDataFormat(aaudio_format_t aaudio_format);
Phil Burk5ed503c2017-02-01 09:38:15 -0800177
Phil Burk9dca9822017-05-26 14:27:43 -0700178aaudio_format_t AAudioConvert_androidToAAudioDataFormat(audio_format_t format);
Phil Burk5ed503c2017-02-01 09:38:15 -0800179
Phil Burkd4ccc622017-12-20 15:32:44 -0800180
181/**
182 * Note that this function does not validate the passed in value.
183 * That is done somewhere else.
184 * @return internal value
185 */
186
187audio_usage_t AAudioConvert_usageToInternal(aaudio_usage_t usage);
188
189/**
190 * Note that this function does not validate the passed in value.
191 * That is done somewhere else.
192 * @return internal value
193 */
194audio_content_type_t AAudioConvert_contentTypeToInternal(aaudio_content_type_t contentType);
195
196/**
197 * Note that this function does not validate the passed in value.
198 * That is done somewhere else.
199 * @return internal audio source
200 */
201audio_source_t AAudioConvert_inputPresetToAudioSource(aaudio_input_preset_t preset);
202
Phil Burk5ed503c2017-02-01 09:38:15 -0800203/**
204 * @return the size of a sample of the given format in bytes or AAUDIO_ERROR_ILLEGAL_ARGUMENT
205 */
Phil Burk9dca9822017-05-26 14:27:43 -0700206int32_t AAudioConvert_formatToSizeInBytes(aaudio_format_t format);
Phil Burk5ed503c2017-02-01 09:38:15 -0800207
Phil Burkc8f69a02017-05-11 15:53:06 -0700208
209// Note that this code may be replaced by Settings or by some other system configuration tool.
210
Phil Burkd04aeea2017-05-23 13:56:41 -0700211#define AAUDIO_PROP_MMAP_POLICY "aaudio.mmap_policy"
Phil Burkc8f69a02017-05-11 15:53:06 -0700212
213/**
214 * Read system property.
Phil Burkd04aeea2017-05-23 13:56:41 -0700215 * @return AAUDIO_UNSPECIFIED, AAUDIO_POLICY_NEVER or AAUDIO_POLICY_AUTO or AAUDIO_POLICY_ALWAYS
Phil Burkc8f69a02017-05-11 15:53:06 -0700216 */
Phil Burkd04aeea2017-05-23 13:56:41 -0700217int32_t AAudioProperty_getMMapPolicy();
Phil Burkc8f69a02017-05-11 15:53:06 -0700218
Phil Burkd04aeea2017-05-23 13:56:41 -0700219#define AAUDIO_PROP_MMAP_EXCLUSIVE_POLICY "aaudio.mmap_exclusive_policy"
Phil Burkc8f69a02017-05-11 15:53:06 -0700220
221/**
222 * Read system property.
Phil Burkd04aeea2017-05-23 13:56:41 -0700223 * @return AAUDIO_UNSPECIFIED, AAUDIO_POLICY_NEVER or AAUDIO_POLICY_AUTO or AAUDIO_POLICY_ALWAYS
Phil Burkc8f69a02017-05-11 15:53:06 -0700224 */
Phil Burkd04aeea2017-05-23 13:56:41 -0700225int32_t AAudioProperty_getMMapExclusivePolicy();
Phil Burkc8f69a02017-05-11 15:53:06 -0700226
227#define AAUDIO_PROP_MIXER_BURSTS "aaudio.mixer_bursts"
228
229/**
230 * Read system property.
Phil Burkfd34a932017-07-19 07:03:52 -0700231 * @return number of bursts per AAudio service mixer cycle
Phil Burkc8f69a02017-05-11 15:53:06 -0700232 */
233int32_t AAudioProperty_getMixerBursts();
234
235#define AAUDIO_PROP_HW_BURST_MIN_USEC "aaudio.hw_burst_min_usec"
236
237/**
Phil Burkfd34a932017-07-19 07:03:52 -0700238 * Read a system property that specifies the number of extra microseconds that a thread
239 * should sleep when waiting for another thread to service a FIFO. This is used
240 * to avoid the waking thread from being overly optimistic about the other threads
241 * wakeup timing. This value should be set high enough to cover typical scheduling jitter
242 * for a real-time thread.
243 *
244 * @return number of microseconds to delay the wakeup.
245 */
246int32_t AAudioProperty_getWakeupDelayMicros();
247
248#define AAUDIO_PROP_WAKEUP_DELAY_USEC "aaudio.wakeup_delay_usec"
249
250/**
251 * Read a system property that specifies the minimum sleep time when polling the FIFO.
252 *
253 * @return minimum number of microseconds to sleep.
254 */
255int32_t AAudioProperty_getMinimumSleepMicros();
256
257#define AAUDIO_PROP_MINIMUM_SLEEP_USEC "aaudio.minimum_sleep_usec"
258
259/**
Phil Burkc8f69a02017-05-11 15:53:06 -0700260 * Read system property.
261 * This is handy in case the DMA is bursting too quickly for the CPU to keep up.
262 * For example, there may be a DMA burst every 100 usec but you only
263 * want to feed the MMAP buffer every 2000 usec.
264 *
265 * This will affect the framesPerBurst for an MMAP stream.
266 *
267 * @return minimum number of microseconds for a MMAP HW burst
268 */
269int32_t AAudioProperty_getHardwareBurstMinMicros();
270
Phil Burk5cc83c32017-11-28 15:43:18 -0800271
272/**
273 * Is flush allowed for the given state?
274 * @param state
275 * @return AAUDIO_OK if allowed or an error
276 */
277aaudio_result_t AAudio_isFlushAllowed(aaudio_stream_state_t state);
278
Andy Hung47c5e532017-06-26 18:28:00 -0700279/**
280 * Try a function f until it returns true.
281 *
282 * The function is always called at least once.
283 *
284 * @param f the function to evaluate, which returns a bool.
285 * @param times the number of times to evaluate f.
286 * @param sleepMs the sleep time per check of f, if greater than 0.
287 * @return true if f() eventually returns true.
288 */
289static inline bool AAudio_tryUntilTrue(
290 std::function<bool()> f, int times, int sleepMs) {
291 static const useconds_t US_PER_MS = 1000;
292
293 sleepMs = std::max(sleepMs, 0);
294 for (;;) {
295 if (f()) return true;
296 if (times <= 1) return false;
297 --times;
298 usleep(sleepMs * US_PER_MS);
299 }
300}
301
Phil Burk97350f92017-07-21 15:59:44 -0700302
303/**
304 * Simple double buffer for a structure that can be written occasionally and read occasionally.
305 * This allows a SINGLE writer with multiple readers.
306 *
307 * It is OK if the FIFO overflows and we lose old values.
308 * It is also OK if we read an old value.
309 * Thread may return a non-atomic result if the other thread is rapidly writing
310 * new values on another core.
311 */
312template <class T>
313class SimpleDoubleBuffer {
314public:
315 SimpleDoubleBuffer()
Phil Burkbcc36742017-08-31 17:24:51 -0700316 : mValues() {}
Phil Burk97350f92017-07-21 15:59:44 -0700317
318 __attribute__((no_sanitize("integer")))
319 void write(T value) {
320 int index = mCounter.load() & 1;
321 mValues[index] = value;
322 mCounter++; // Increment AFTER updating storage, OK if it wraps.
323 }
324
Phil Burkbcc36742017-08-31 17:24:51 -0700325 /**
326 * This should only be called by the same thread that calls write() or when
327 * no other thread is calling write.
328 */
329 void clear() {
330 mCounter.store(0);
331 }
332
Phil Burk97350f92017-07-21 15:59:44 -0700333 T read() const {
334 T result;
335 int before;
336 int after;
337 int timeout = 3;
338 do {
339 // Check to see if a write occurred while were reading.
340 before = mCounter.load();
341 int index = (before & 1) ^ 1;
342 result = mValues[index];
343 after = mCounter.load();
Phil Burkbcc36742017-08-31 17:24:51 -0700344 } while ((after != before) && (after > 0) && (--timeout > 0));
Phil Burk97350f92017-07-21 15:59:44 -0700345 return result;
346 }
347
348 /**
349 * @return true if at least one value has been written
350 */
351 bool isValid() const {
352 return mCounter.load() > 0;
353 }
354
355private:
356 T mValues[2];
Phil Burkbcc36742017-08-31 17:24:51 -0700357 std::atomic<int> mCounter{0};
Phil Burk97350f92017-07-21 15:59:44 -0700358};
359
360class Timestamp {
361public:
362 Timestamp()
363 : mPosition(0)
364 , mNanoseconds(0) {}
365 Timestamp(int64_t position, int64_t nanoseconds)
366 : mPosition(position)
367 , mNanoseconds(nanoseconds) {}
368
369 int64_t getPosition() const { return mPosition; }
370
371 int64_t getNanoseconds() const { return mNanoseconds; }
372
373private:
374 // These cannot be const because we need to implement the copy assignment operator.
375 int64_t mPosition;
376 int64_t mNanoseconds;
377};
378
Phil Burkbcc36742017-08-31 17:24:51 -0700379
380/**
381 * Pass a request to another thread.
382 * This is used when one thread, A, wants another thread, B, to do something.
383 * A naive approach would be for A to set a flag and for B to clear it when done.
384 * But that creates a race condition. This technique avoids the race condition.
385 *
386 * Assumes only one requester and one acknowledger.
387 */
388class AtomicRequestor {
389public:
Phil Burk2d5ba532017-09-06 14:36:11 -0700390
391 __attribute__((no_sanitize("integer")))
Phil Burkbcc36742017-08-31 17:24:51 -0700392 void request() {
Phil Burkbcc36742017-08-31 17:24:51 -0700393 mRequested++;
394 }
395
Phil Burk2d5ba532017-09-06 14:36:11 -0700396 __attribute__((no_sanitize("integer")))
Phil Burkbcc36742017-08-31 17:24:51 -0700397 bool isRequested() {
Phil Burk2d5ba532017-09-06 14:36:11 -0700398 return (mRequested.load() - mAcknowledged.load()) > 0;
Phil Burkbcc36742017-08-31 17:24:51 -0700399 }
400
Phil Burk2d5ba532017-09-06 14:36:11 -0700401 __attribute__((no_sanitize("integer")))
Phil Burkbcc36742017-08-31 17:24:51 -0700402 void acknowledge() {
403 mAcknowledged++;
404 }
405
406private:
407 std::atomic<int> mRequested{0};
408 std::atomic<int> mAcknowledged{0};
409};
Phil Burk5ed503c2017-02-01 09:38:15 -0800410#endif //UTILITY_AAUDIO_UTILITIES_H