blob: dc6a67169c0f739cc7cd43d98cbdae8bfbe809be [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
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
Phil Burke572f462017-04-20 13:03:19 -070040/**
Phil Burk4e1af9f2018-01-03 15:54:35 -080041 * Convert an aaudio_session_id_t to a value that is safe to pass to AudioFlinger.
42 * @param sessionId
43 * @return safe value
44 */
45audio_session_t AAudioConvert_aaudioToAndroidSessionId(aaudio_session_id_t sessionId);
46
47/**
Phil Burke572f462017-04-20 13:03:19 -070048 * 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 */
55void AAudioConvert_floatToPcm16(const float *source,
56 int16_t *destination,
57 int32_t numSamples,
58 float amplitude);
Phil Burk5ed503c2017-02-01 09:38:15 -080059
Phil Burke572f462017-04-20 13:03:19 -070060/**
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 */
73void 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 */
97void 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 */
115void 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 */
135void 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 */
155void AAudio_linearRamp(const int16_t *source,
156 int16_t *destination,
157 int32_t numFrames,
158 int32_t samplesPerFrame,
159 float amplitude1,
160 float amplitude2);
Phil Burk5ed503c2017-02-01 09:38:15 -0800161
162/**
163 * Calculate the number of bytes and prevent numeric overflow.
164 * @param numFrames frame count
165 * @param bytesPerFrame size of a frame in bytes
166 * @param sizeInBytes total size in bytes
167 * @return AAUDIO_OK or negative error, eg. AAUDIO_ERROR_OUT_OF_RANGE
168 */
Phil Burk3316d5e2017-02-15 11:23:01 -0800169int32_t AAudioConvert_framesToBytes(int32_t numFrames,
170 int32_t bytesPerFrame,
171 int32_t *sizeInBytes);
Phil Burk5ed503c2017-02-01 09:38:15 -0800172
Phil Burk9dca9822017-05-26 14:27:43 -0700173audio_format_t AAudioConvert_aaudioToAndroidDataFormat(aaudio_format_t aaudio_format);
Phil Burk5ed503c2017-02-01 09:38:15 -0800174
Phil Burk9dca9822017-05-26 14:27:43 -0700175aaudio_format_t AAudioConvert_androidToAAudioDataFormat(audio_format_t format);
Phil Burk5ed503c2017-02-01 09:38:15 -0800176
Phil Burkd4ccc622017-12-20 15:32:44 -0800177
178/**
179 * Note that this function does not validate the passed in value.
180 * That is done somewhere else.
181 * @return internal value
182 */
183
184audio_usage_t AAudioConvert_usageToInternal(aaudio_usage_t usage);
185
186/**
187 * Note that this function does not validate the passed in value.
188 * That is done somewhere else.
189 * @return internal value
190 */
191audio_content_type_t AAudioConvert_contentTypeToInternal(aaudio_content_type_t contentType);
192
193/**
194 * Note that this function does not validate the passed in value.
195 * That is done somewhere else.
196 * @return internal audio source
197 */
198audio_source_t AAudioConvert_inputPresetToAudioSource(aaudio_input_preset_t preset);
199
Phil Burk5ed503c2017-02-01 09:38:15 -0800200/**
201 * @return the size of a sample of the given format in bytes or AAUDIO_ERROR_ILLEGAL_ARGUMENT
202 */
Phil Burk9dca9822017-05-26 14:27:43 -0700203int32_t AAudioConvert_formatToSizeInBytes(aaudio_format_t format);
Phil Burk5ed503c2017-02-01 09:38:15 -0800204
Phil Burkc8f69a02017-05-11 15:53:06 -0700205
206// Note that this code may be replaced by Settings or by some other system configuration tool.
207
Phil Burkd04aeea2017-05-23 13:56:41 -0700208#define AAUDIO_PROP_MMAP_POLICY "aaudio.mmap_policy"
Phil Burkc8f69a02017-05-11 15:53:06 -0700209
210/**
211 * Read system property.
Phil Burkd04aeea2017-05-23 13:56:41 -0700212 * @return AAUDIO_UNSPECIFIED, AAUDIO_POLICY_NEVER or AAUDIO_POLICY_AUTO or AAUDIO_POLICY_ALWAYS
Phil Burkc8f69a02017-05-11 15:53:06 -0700213 */
Phil Burkd04aeea2017-05-23 13:56:41 -0700214int32_t AAudioProperty_getMMapPolicy();
Phil Burkc8f69a02017-05-11 15:53:06 -0700215
Phil Burkd04aeea2017-05-23 13:56:41 -0700216#define AAUDIO_PROP_MMAP_EXCLUSIVE_POLICY "aaudio.mmap_exclusive_policy"
Phil Burkc8f69a02017-05-11 15:53:06 -0700217
218/**
219 * Read system property.
Phil Burkd04aeea2017-05-23 13:56:41 -0700220 * @return AAUDIO_UNSPECIFIED, AAUDIO_POLICY_NEVER or AAUDIO_POLICY_AUTO or AAUDIO_POLICY_ALWAYS
Phil Burkc8f69a02017-05-11 15:53:06 -0700221 */
Phil Burkd04aeea2017-05-23 13:56:41 -0700222int32_t AAudioProperty_getMMapExclusivePolicy();
Phil Burkc8f69a02017-05-11 15:53:06 -0700223
224#define AAUDIO_PROP_MIXER_BURSTS "aaudio.mixer_bursts"
225
226/**
227 * Read system property.
Phil Burkfd34a932017-07-19 07:03:52 -0700228 * @return number of bursts per AAudio service mixer cycle
Phil Burkc8f69a02017-05-11 15:53:06 -0700229 */
230int32_t AAudioProperty_getMixerBursts();
231
232#define AAUDIO_PROP_HW_BURST_MIN_USEC "aaudio.hw_burst_min_usec"
233
234/**
Phil Burkfd34a932017-07-19 07:03:52 -0700235 * Read a system property that specifies the number of extra microseconds that a thread
236 * should sleep when waiting for another thread to service a FIFO. This is used
237 * to avoid the waking thread from being overly optimistic about the other threads
238 * wakeup timing. This value should be set high enough to cover typical scheduling jitter
239 * for a real-time thread.
240 *
241 * @return number of microseconds to delay the wakeup.
242 */
243int32_t AAudioProperty_getWakeupDelayMicros();
244
245#define AAUDIO_PROP_WAKEUP_DELAY_USEC "aaudio.wakeup_delay_usec"
246
247/**
248 * Read a system property that specifies the minimum sleep time when polling the FIFO.
249 *
250 * @return minimum number of microseconds to sleep.
251 */
252int32_t AAudioProperty_getMinimumSleepMicros();
253
254#define AAUDIO_PROP_MINIMUM_SLEEP_USEC "aaudio.minimum_sleep_usec"
255
256/**
Phil Burkc8f69a02017-05-11 15:53:06 -0700257 * Read system property.
258 * This is handy in case the DMA is bursting too quickly for the CPU to keep up.
259 * For example, there may be a DMA burst every 100 usec but you only
260 * want to feed the MMAP buffer every 2000 usec.
261 *
262 * This will affect the framesPerBurst for an MMAP stream.
263 *
264 * @return minimum number of microseconds for a MMAP HW burst
265 */
266int32_t AAudioProperty_getHardwareBurstMinMicros();
267
Phil Burk5cc83c32017-11-28 15:43:18 -0800268
269/**
270 * Is flush allowed for the given state?
271 * @param state
272 * @return AAUDIO_OK if allowed or an error
273 */
274aaudio_result_t AAudio_isFlushAllowed(aaudio_stream_state_t state);
275
Andy Hung47c5e532017-06-26 18:28:00 -0700276/**
277 * Try a function f until it returns true.
278 *
279 * The function is always called at least once.
280 *
281 * @param f the function to evaluate, which returns a bool.
282 * @param times the number of times to evaluate f.
283 * @param sleepMs the sleep time per check of f, if greater than 0.
284 * @return true if f() eventually returns true.
285 */
286static inline bool AAudio_tryUntilTrue(
287 std::function<bool()> f, int times, int sleepMs) {
288 static const useconds_t US_PER_MS = 1000;
289
290 sleepMs = std::max(sleepMs, 0);
291 for (;;) {
292 if (f()) return true;
293 if (times <= 1) return false;
294 --times;
295 usleep(sleepMs * US_PER_MS);
296 }
297}
298
Phil Burk97350f92017-07-21 15:59:44 -0700299
300/**
301 * Simple double buffer for a structure that can be written occasionally and read occasionally.
302 * This allows a SINGLE writer with multiple readers.
303 *
304 * It is OK if the FIFO overflows and we lose old values.
305 * It is also OK if we read an old value.
306 * Thread may return a non-atomic result if the other thread is rapidly writing
307 * new values on another core.
308 */
309template <class T>
310class SimpleDoubleBuffer {
311public:
312 SimpleDoubleBuffer()
Phil Burkbcc36742017-08-31 17:24:51 -0700313 : mValues() {}
Phil Burk97350f92017-07-21 15:59:44 -0700314
315 __attribute__((no_sanitize("integer")))
316 void write(T value) {
317 int index = mCounter.load() & 1;
318 mValues[index] = value;
319 mCounter++; // Increment AFTER updating storage, OK if it wraps.
320 }
321
Phil Burkbcc36742017-08-31 17:24:51 -0700322 /**
323 * This should only be called by the same thread that calls write() or when
324 * no other thread is calling write.
325 */
326 void clear() {
327 mCounter.store(0);
328 }
329
Phil Burk97350f92017-07-21 15:59:44 -0700330 T read() const {
331 T result;
332 int before;
333 int after;
334 int timeout = 3;
335 do {
336 // Check to see if a write occurred while were reading.
337 before = mCounter.load();
338 int index = (before & 1) ^ 1;
339 result = mValues[index];
340 after = mCounter.load();
Phil Burkbcc36742017-08-31 17:24:51 -0700341 } while ((after != before) && (after > 0) && (--timeout > 0));
Phil Burk97350f92017-07-21 15:59:44 -0700342 return result;
343 }
344
345 /**
346 * @return true if at least one value has been written
347 */
348 bool isValid() const {
349 return mCounter.load() > 0;
350 }
351
352private:
353 T mValues[2];
Phil Burkbcc36742017-08-31 17:24:51 -0700354 std::atomic<int> mCounter{0};
Phil Burk97350f92017-07-21 15:59:44 -0700355};
356
357class Timestamp {
358public:
359 Timestamp()
360 : mPosition(0)
361 , mNanoseconds(0) {}
362 Timestamp(int64_t position, int64_t nanoseconds)
363 : mPosition(position)
364 , mNanoseconds(nanoseconds) {}
365
366 int64_t getPosition() const { return mPosition; }
367
368 int64_t getNanoseconds() const { return mNanoseconds; }
369
370private:
371 // These cannot be const because we need to implement the copy assignment operator.
372 int64_t mPosition;
373 int64_t mNanoseconds;
374};
375
Phil Burkbcc36742017-08-31 17:24:51 -0700376
377/**
378 * Pass a request to another thread.
379 * This is used when one thread, A, wants another thread, B, to do something.
380 * A naive approach would be for A to set a flag and for B to clear it when done.
381 * But that creates a race condition. This technique avoids the race condition.
382 *
383 * Assumes only one requester and one acknowledger.
384 */
385class AtomicRequestor {
386public:
Phil Burk2d5ba532017-09-06 14:36:11 -0700387
388 __attribute__((no_sanitize("integer")))
Phil Burkbcc36742017-08-31 17:24:51 -0700389 void request() {
Phil Burkbcc36742017-08-31 17:24:51 -0700390 mRequested++;
391 }
392
Phil Burk2d5ba532017-09-06 14:36:11 -0700393 __attribute__((no_sanitize("integer")))
Phil Burkbcc36742017-08-31 17:24:51 -0700394 bool isRequested() {
Phil Burk2d5ba532017-09-06 14:36:11 -0700395 return (mRequested.load() - mAcknowledged.load()) > 0;
Phil Burkbcc36742017-08-31 17:24:51 -0700396 }
397
Phil Burk2d5ba532017-09-06 14:36:11 -0700398 __attribute__((no_sanitize("integer")))
Phil Burkbcc36742017-08-31 17:24:51 -0700399 void acknowledge() {
400 mAcknowledged++;
401 }
402
403private:
404 std::atomic<int> mRequested{0};
405 std::atomic<int> mAcknowledged{0};
406};
Phil Burk5ed503c2017-02-01 09:38:15 -0800407#endif //UTILITY_AAUDIO_UTILITIES_H