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 */
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 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 */
48 void 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 */
66 void 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 */
90 void 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 */
108 void 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 */
128 void 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 */
148 void 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 */
162 int32_t AAudioConvert_framesToBytes(int32_t numFrames,
163 int32_t bytesPerFrame,
164 int32_t *sizeInBytes);
165
166 audio_format_t AAudioConvert_aaudioToAndroidDataFormat(aaudio_format_t aaudio_format);
167
168 aaudio_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 */
173 int32_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 */
184 int32_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 */
192 int32_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 */
200 int32_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 */
213 int32_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 */
222 int32_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 */
236 int32_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 */
AAudio_tryUntilTrue(std::function<bool ()> f,int times,int sleepMs)248 static 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 */
271 template <class T>
272 class SimpleDoubleBuffer {
273 public:
SimpleDoubleBuffer()274 SimpleDoubleBuffer()
275 : mValues() {}
276
277 __attribute__((no_sanitize("integer")))
write(T value)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 */
clear()288 void clear() {
289 mCounter.store(0);
290 }
291
read()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 */
isValid()310 bool isValid() const {
311 return mCounter.load() > 0;
312 }
313
314 private:
315 T mValues[2];
316 std::atomic<int> mCounter{0};
317 };
318
319 class Timestamp {
320 public:
Timestamp()321 Timestamp()
322 : mPosition(0)
323 , mNanoseconds(0) {}
Timestamp(int64_t position,int64_t nanoseconds)324 Timestamp(int64_t position, int64_t nanoseconds)
325 : mPosition(position)
326 , mNanoseconds(nanoseconds) {}
327
getPosition()328 int64_t getPosition() const { return mPosition; }
329
getNanoseconds()330 int64_t getNanoseconds() const { return mNanoseconds; }
331
332 private:
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 */
347 class AtomicRequestor {
348 public:
349
350 __attribute__((no_sanitize("integer")))
request()351 void request() {
352 mRequested++;
353 }
354
355 __attribute__((no_sanitize("integer")))
isRequested()356 bool isRequested() {
357 return (mRequested.load() - mAcknowledged.load()) > 0;
358 }
359
360 __attribute__((no_sanitize("integer")))
acknowledge()361 void acknowledge() {
362 mAcknowledged++;
363 }
364
365 private:
366 std::atomic<int> mRequested{0};
367 std::atomic<int> mAcknowledged{0};
368 };
369 #endif //UTILITY_AAUDIO_UTILITIES_H
370