blob: cea88fbe0d0559cee9a15fd709168ef050f23942 [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
Phil Burk41f19d82018-02-13 14:59:10 -0800162class AAudioDataConverter {
163public:
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
183private:
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
Phil Burk5ed503c2017-02-01 09:38:15 -0800197/**
198 * Calculate the number of bytes and prevent numeric overflow.
199 * @param numFrames frame count
200 * @param bytesPerFrame size of a frame in bytes
201 * @param sizeInBytes total size in bytes
202 * @return AAUDIO_OK or negative error, eg. AAUDIO_ERROR_OUT_OF_RANGE
203 */
Phil Burk3316d5e2017-02-15 11:23:01 -0800204int32_t AAudioConvert_framesToBytes(int32_t numFrames,
205 int32_t bytesPerFrame,
206 int32_t *sizeInBytes);
Phil Burk5ed503c2017-02-01 09:38:15 -0800207
Phil Burk9dca9822017-05-26 14:27:43 -0700208audio_format_t AAudioConvert_aaudioToAndroidDataFormat(aaudio_format_t aaudio_format);
Phil Burk5ed503c2017-02-01 09:38:15 -0800209
Phil Burk9dca9822017-05-26 14:27:43 -0700210aaudio_format_t AAudioConvert_androidToAAudioDataFormat(audio_format_t format);
Phil Burk5ed503c2017-02-01 09:38:15 -0800211
Phil Burkd4ccc622017-12-20 15:32:44 -0800212
213/**
214 * Note that this function does not validate the passed in value.
215 * That is done somewhere else.
216 * @return internal value
217 */
218
219audio_usage_t AAudioConvert_usageToInternal(aaudio_usage_t usage);
220
221/**
222 * Note that this function does not validate the passed in value.
223 * That is done somewhere else.
224 * @return internal value
225 */
226audio_content_type_t AAudioConvert_contentTypeToInternal(aaudio_content_type_t contentType);
227
228/**
229 * Note that this function does not validate the passed in value.
230 * That is done somewhere else.
231 * @return internal audio source
232 */
233audio_source_t AAudioConvert_inputPresetToAudioSource(aaudio_input_preset_t preset);
234
Phil Burk5ed503c2017-02-01 09:38:15 -0800235/**
236 * @return the size of a sample of the given format in bytes or AAUDIO_ERROR_ILLEGAL_ARGUMENT
237 */
Phil Burk9dca9822017-05-26 14:27:43 -0700238int32_t AAudioConvert_formatToSizeInBytes(aaudio_format_t format);
Phil Burk5ed503c2017-02-01 09:38:15 -0800239
Phil Burkc8f69a02017-05-11 15:53:06 -0700240
241// Note that this code may be replaced by Settings or by some other system configuration tool.
242
Phil Burkd04aeea2017-05-23 13:56:41 -0700243#define AAUDIO_PROP_MMAP_POLICY "aaudio.mmap_policy"
Phil Burkc8f69a02017-05-11 15:53:06 -0700244
245/**
246 * Read system property.
Phil Burkd04aeea2017-05-23 13:56:41 -0700247 * @return AAUDIO_UNSPECIFIED, AAUDIO_POLICY_NEVER or AAUDIO_POLICY_AUTO or AAUDIO_POLICY_ALWAYS
Phil Burkc8f69a02017-05-11 15:53:06 -0700248 */
Phil Burkd04aeea2017-05-23 13:56:41 -0700249int32_t AAudioProperty_getMMapPolicy();
Phil Burkc8f69a02017-05-11 15:53:06 -0700250
Phil Burkd04aeea2017-05-23 13:56:41 -0700251#define AAUDIO_PROP_MMAP_EXCLUSIVE_POLICY "aaudio.mmap_exclusive_policy"
Phil Burkc8f69a02017-05-11 15:53:06 -0700252
253/**
254 * Read system property.
Phil Burkd04aeea2017-05-23 13:56:41 -0700255 * @return AAUDIO_UNSPECIFIED, AAUDIO_POLICY_NEVER or AAUDIO_POLICY_AUTO or AAUDIO_POLICY_ALWAYS
Phil Burkc8f69a02017-05-11 15:53:06 -0700256 */
Phil Burkd04aeea2017-05-23 13:56:41 -0700257int32_t AAudioProperty_getMMapExclusivePolicy();
Phil Burkc8f69a02017-05-11 15:53:06 -0700258
259#define AAUDIO_PROP_MIXER_BURSTS "aaudio.mixer_bursts"
260
261/**
262 * Read system property.
Phil Burkfd34a932017-07-19 07:03:52 -0700263 * @return number of bursts per AAudio service mixer cycle
Phil Burkc8f69a02017-05-11 15:53:06 -0700264 */
265int32_t AAudioProperty_getMixerBursts();
266
267#define AAUDIO_PROP_HW_BURST_MIN_USEC "aaudio.hw_burst_min_usec"
268
269/**
Phil Burkfd34a932017-07-19 07:03:52 -0700270 * Read a system property that specifies the number of extra microseconds that a thread
271 * should sleep when waiting for another thread to service a FIFO. This is used
272 * to avoid the waking thread from being overly optimistic about the other threads
273 * wakeup timing. This value should be set high enough to cover typical scheduling jitter
274 * for a real-time thread.
275 *
276 * @return number of microseconds to delay the wakeup.
277 */
278int32_t AAudioProperty_getWakeupDelayMicros();
279
280#define AAUDIO_PROP_WAKEUP_DELAY_USEC "aaudio.wakeup_delay_usec"
281
282/**
283 * Read a system property that specifies the minimum sleep time when polling the FIFO.
284 *
285 * @return minimum number of microseconds to sleep.
286 */
287int32_t AAudioProperty_getMinimumSleepMicros();
288
289#define AAUDIO_PROP_MINIMUM_SLEEP_USEC "aaudio.minimum_sleep_usec"
290
291/**
Phil Burkc8f69a02017-05-11 15:53:06 -0700292 * Read system property.
293 * This is handy in case the DMA is bursting too quickly for the CPU to keep up.
294 * For example, there may be a DMA burst every 100 usec but you only
295 * want to feed the MMAP buffer every 2000 usec.
296 *
297 * This will affect the framesPerBurst for an MMAP stream.
298 *
299 * @return minimum number of microseconds for a MMAP HW burst
300 */
301int32_t AAudioProperty_getHardwareBurstMinMicros();
302
Phil Burk5cc83c32017-11-28 15:43:18 -0800303
304/**
305 * Is flush allowed for the given state?
306 * @param state
307 * @return AAUDIO_OK if allowed or an error
308 */
309aaudio_result_t AAudio_isFlushAllowed(aaudio_stream_state_t state);
310
Andy Hung47c5e532017-06-26 18:28:00 -0700311/**
312 * Try a function f until it returns true.
313 *
314 * The function is always called at least once.
315 *
316 * @param f the function to evaluate, which returns a bool.
317 * @param times the number of times to evaluate f.
318 * @param sleepMs the sleep time per check of f, if greater than 0.
319 * @return true if f() eventually returns true.
320 */
321static inline bool AAudio_tryUntilTrue(
322 std::function<bool()> f, int times, int sleepMs) {
323 static const useconds_t US_PER_MS = 1000;
324
325 sleepMs = std::max(sleepMs, 0);
326 for (;;) {
327 if (f()) return true;
328 if (times <= 1) return false;
329 --times;
330 usleep(sleepMs * US_PER_MS);
331 }
332}
333
Phil Burk97350f92017-07-21 15:59:44 -0700334
335/**
336 * Simple double buffer for a structure that can be written occasionally and read occasionally.
337 * This allows a SINGLE writer with multiple readers.
338 *
339 * It is OK if the FIFO overflows and we lose old values.
340 * It is also OK if we read an old value.
341 * Thread may return a non-atomic result if the other thread is rapidly writing
342 * new values on another core.
343 */
344template <class T>
345class SimpleDoubleBuffer {
346public:
347 SimpleDoubleBuffer()
Phil Burkbcc36742017-08-31 17:24:51 -0700348 : mValues() {}
Phil Burk97350f92017-07-21 15:59:44 -0700349
350 __attribute__((no_sanitize("integer")))
351 void write(T value) {
352 int index = mCounter.load() & 1;
353 mValues[index] = value;
354 mCounter++; // Increment AFTER updating storage, OK if it wraps.
355 }
356
Phil Burkbcc36742017-08-31 17:24:51 -0700357 /**
358 * This should only be called by the same thread that calls write() or when
359 * no other thread is calling write.
360 */
361 void clear() {
362 mCounter.store(0);
363 }
364
Phil Burk97350f92017-07-21 15:59:44 -0700365 T read() const {
366 T result;
367 int before;
368 int after;
369 int timeout = 3;
370 do {
371 // Check to see if a write occurred while were reading.
372 before = mCounter.load();
373 int index = (before & 1) ^ 1;
374 result = mValues[index];
375 after = mCounter.load();
Phil Burkbcc36742017-08-31 17:24:51 -0700376 } while ((after != before) && (after > 0) && (--timeout > 0));
Phil Burk97350f92017-07-21 15:59:44 -0700377 return result;
378 }
379
380 /**
381 * @return true if at least one value has been written
382 */
383 bool isValid() const {
384 return mCounter.load() > 0;
385 }
386
387private:
388 T mValues[2];
Phil Burkbcc36742017-08-31 17:24:51 -0700389 std::atomic<int> mCounter{0};
Phil Burk97350f92017-07-21 15:59:44 -0700390};
391
392class Timestamp {
393public:
394 Timestamp()
395 : mPosition(0)
396 , mNanoseconds(0) {}
397 Timestamp(int64_t position, int64_t nanoseconds)
398 : mPosition(position)
399 , mNanoseconds(nanoseconds) {}
400
401 int64_t getPosition() const { return mPosition; }
402
403 int64_t getNanoseconds() const { return mNanoseconds; }
404
405private:
406 // These cannot be const because we need to implement the copy assignment operator.
407 int64_t mPosition;
408 int64_t mNanoseconds;
409};
410
Phil Burkbcc36742017-08-31 17:24:51 -0700411
412/**
413 * Pass a request to another thread.
414 * This is used when one thread, A, wants another thread, B, to do something.
415 * A naive approach would be for A to set a flag and for B to clear it when done.
416 * But that creates a race condition. This technique avoids the race condition.
417 *
418 * Assumes only one requester and one acknowledger.
419 */
420class AtomicRequestor {
421public:
Phil Burk2d5ba532017-09-06 14:36:11 -0700422
423 __attribute__((no_sanitize("integer")))
Phil Burkbcc36742017-08-31 17:24:51 -0700424 void request() {
Phil Burkbcc36742017-08-31 17:24:51 -0700425 mRequested++;
426 }
427
Phil Burk2d5ba532017-09-06 14:36:11 -0700428 __attribute__((no_sanitize("integer")))
Phil Burkbcc36742017-08-31 17:24:51 -0700429 bool isRequested() {
Phil Burk2d5ba532017-09-06 14:36:11 -0700430 return (mRequested.load() - mAcknowledged.load()) > 0;
Phil Burkbcc36742017-08-31 17:24:51 -0700431 }
432
Phil Burk2d5ba532017-09-06 14:36:11 -0700433 __attribute__((no_sanitize("integer")))
Phil Burkbcc36742017-08-31 17:24:51 -0700434 void acknowledge() {
435 mAcknowledged++;
436 }
437
438private:
439 std::atomic<int> mRequested{0};
440 std::atomic<int> mAcknowledged{0};
441};
Phil Burk5ed503c2017-02-01 09:38:15 -0800442#endif //UTILITY_AAUDIO_UTILITIES_H