• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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