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 <system/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 aaudio_session_id_t to a value that is safe to pass to AudioFlinger.
42  * @param sessionId
43  * @return safe value
44  */
45 audio_session_t AAudioConvert_aaudioToAndroidSessionId(aaudio_session_id_t sessionId);
46 
47 /**
48  * 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  */
55 void AAudioConvert_floatToPcm16(const float *source,
56                                 int16_t *destination,
57                                 int32_t numSamples,
58                                 float amplitude);
59 
60 /**
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  */
73 void 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  */
97 void 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  */
115 void 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  */
135 void 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  */
155 void AAudio_linearRamp(const int16_t *source,
156                        int16_t *destination,
157                        int32_t numFrames,
158                        int32_t samplesPerFrame,
159                        float amplitude1,
160                        float amplitude2);
161 
162 class AAudioDataConverter {
163 public:
164 
165     struct FormattedData {
166 
FormattedDataFormattedData167         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 
183 private:
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 
197 /**
198  * Calculate the number of bytes and prevent numeric overflow.
199  * The *sizeInBytes will be set to zero if there is an error.
200  *
201  * @param numFrames frame count
202  * @param bytesPerFrame size of a frame in bytes
203  * @param sizeInBytes pointer to a variable to receive total size in bytes
204  * @return AAUDIO_OK or negative error, eg. AAUDIO_ERROR_OUT_OF_RANGE
205  */
206 int32_t AAudioConvert_framesToBytes(int32_t numFrames,
207                                     int32_t bytesPerFrame,
208                                     int32_t *sizeInBytes);
209 
210 audio_format_t AAudioConvert_aaudioToAndroidDataFormat(aaudio_format_t aaudio_format);
211 
212 aaudio_format_t AAudioConvert_androidToAAudioDataFormat(audio_format_t format);
213 
214 
215 /**
216  * Note that this function does not validate the passed in value.
217  * That is done somewhere else.
218  * @return internal value
219  */
220 
221 audio_usage_t AAudioConvert_usageToInternal(aaudio_usage_t usage);
222 
223 /**
224  * Note that this function does not validate the passed in value.
225  * That is done somewhere else.
226  * @return internal value
227  */
228 audio_content_type_t AAudioConvert_contentTypeToInternal(aaudio_content_type_t contentType);
229 
230 /**
231  * Note that this function does not validate the passed in value.
232  * That is done somewhere else.
233  * @return internal audio source
234  */
235 audio_source_t AAudioConvert_inputPresetToAudioSource(aaudio_input_preset_t preset);
236 
237 /**
238  * @return the size of a sample of the given format in bytes or AAUDIO_ERROR_ILLEGAL_ARGUMENT
239  */
240 int32_t AAudioConvert_formatToSizeInBytes(aaudio_format_t format);
241 
242 
243 // Note that this code may be replaced by Settings or by some other system configuration tool.
244 
245 #define AAUDIO_PROP_MMAP_POLICY           "aaudio.mmap_policy"
246 
247 /**
248  * Read system property.
249  * @return AAUDIO_UNSPECIFIED, AAUDIO_POLICY_NEVER or AAUDIO_POLICY_AUTO or AAUDIO_POLICY_ALWAYS
250  */
251 int32_t AAudioProperty_getMMapPolicy();
252 
253 #define AAUDIO_PROP_MMAP_EXCLUSIVE_POLICY "aaudio.mmap_exclusive_policy"
254 
255 /**
256  * Read system property.
257  * @return AAUDIO_UNSPECIFIED, AAUDIO_POLICY_NEVER or AAUDIO_POLICY_AUTO or AAUDIO_POLICY_ALWAYS
258  */
259 int32_t AAudioProperty_getMMapExclusivePolicy();
260 
261 #define AAUDIO_PROP_MIXER_BURSTS           "aaudio.mixer_bursts"
262 
263 /**
264  * Read system property.
265  * @return number of bursts per AAudio service mixer cycle
266  */
267 int32_t AAudioProperty_getMixerBursts();
268 
269 #define AAUDIO_PROP_HW_BURST_MIN_USEC      "aaudio.hw_burst_min_usec"
270 
271 /**
272  * Read a system property that specifies the number of extra microseconds that a thread
273  * should sleep when waiting for another thread to service a FIFO. This is used
274  * to avoid the waking thread from being overly optimistic about the other threads
275  * wakeup timing. This value should be set high enough to cover typical scheduling jitter
276  * for a real-time thread.
277  *
278  * @return number of microseconds to delay the wakeup.
279  */
280 int32_t AAudioProperty_getWakeupDelayMicros();
281 
282 #define AAUDIO_PROP_WAKEUP_DELAY_USEC      "aaudio.wakeup_delay_usec"
283 
284 /**
285  * Read a system property that specifies the minimum sleep time when polling the FIFO.
286  *
287  * @return minimum number of microseconds to sleep.
288  */
289 int32_t AAudioProperty_getMinimumSleepMicros();
290 
291 #define AAUDIO_PROP_MINIMUM_SLEEP_USEC      "aaudio.minimum_sleep_usec"
292 
293 /**
294  * Read system property.
295  * This is handy in case the DMA is bursting too quickly for the CPU to keep up.
296  * For example, there may be a DMA burst every 100 usec but you only
297  * want to feed the MMAP buffer every 2000 usec.
298  *
299  * This will affect the framesPerBurst for an MMAP stream.
300  *
301  * @return minimum number of microseconds for a MMAP HW burst
302  */
303 int32_t AAudioProperty_getHardwareBurstMinMicros();
304 
305 
306 /**
307  * Is flush allowed for the given state?
308  * @param state
309  * @return AAUDIO_OK if allowed or an error
310  */
311 aaudio_result_t AAudio_isFlushAllowed(aaudio_stream_state_t state);
312 
313 /**
314  * Try a function f until it returns true.
315  *
316  * The function is always called at least once.
317  *
318  * @param f the function to evaluate, which returns a bool.
319  * @param times the number of times to evaluate f.
320  * @param sleepMs the sleep time per check of f, if greater than 0.
321  * @return true if f() eventually returns true.
322  */
AAudio_tryUntilTrue(std::function<bool ()> f,int times,int sleepMs)323 static inline bool AAudio_tryUntilTrue(
324         std::function<bool()> f, int times, int sleepMs) {
325     static const useconds_t US_PER_MS = 1000;
326 
327     sleepMs = std::max(sleepMs, 0);
328     for (;;) {
329         if (f()) return true;
330         if (times <= 1) return false;
331         --times;
332         usleep(sleepMs * US_PER_MS);
333     }
334 }
335 
336 
337 /**
338  * Simple double buffer for a structure that can be written occasionally and read occasionally.
339  * This allows a SINGLE writer with multiple readers.
340  *
341  * It is OK if the FIFO overflows and we lose old values.
342  * It is also OK if we read an old value.
343  * Thread may return a non-atomic result if the other thread is rapidly writing
344  * new values on another core.
345  */
346 template <class T>
347 class SimpleDoubleBuffer {
348 public:
SimpleDoubleBuffer()349     SimpleDoubleBuffer()
350             : mValues() {}
351 
352     __attribute__((no_sanitize("integer")))
write(T value)353     void write(T value) {
354         int index = mCounter.load() & 1;
355         mValues[index] = value;
356         mCounter++; // Increment AFTER updating storage, OK if it wraps.
357     }
358 
359     /**
360      * This should only be called by the same thread that calls write() or when
361      * no other thread is calling write.
362      */
clear()363     void clear() {
364         mCounter.store(0);
365     }
366 
read()367     T read() const {
368         T result;
369         int before;
370         int after;
371         int timeout = 3;
372         do {
373             // Check to see if a write occurred while were reading.
374             before = mCounter.load();
375             int index = (before & 1) ^ 1;
376             result = mValues[index];
377             after = mCounter.load();
378         } while ((after != before) && (after > 0) && (--timeout > 0));
379         return result;
380     }
381 
382     /**
383      * @return true if at least one value has been written
384      */
isValid()385     bool isValid() const {
386         return mCounter.load() > 0;
387     }
388 
389 private:
390     T                    mValues[2];
391     std::atomic<int>     mCounter{0};
392 };
393 
394 class Timestamp {
395 public:
Timestamp()396     Timestamp()
397             : mPosition(0)
398             , mNanoseconds(0) {}
Timestamp(int64_t position,int64_t nanoseconds)399     Timestamp(int64_t position, int64_t nanoseconds)
400             : mPosition(position)
401             , mNanoseconds(nanoseconds) {}
402 
getPosition()403     int64_t getPosition() const { return mPosition; }
404 
getNanoseconds()405     int64_t getNanoseconds() const { return mNanoseconds; }
406 
407 private:
408     // These cannot be const because we need to implement the copy assignment operator.
409     int64_t mPosition;
410     int64_t mNanoseconds;
411 };
412 
413 
414 /**
415  * Pass a request to another thread.
416  * This is used when one thread, A, wants another thread, B, to do something.
417  * A naive approach would be for A to set a flag and for B to clear it when done.
418  * But that creates a race condition. This technique avoids the race condition.
419  *
420  * Assumes only one requester and one acknowledger.
421  */
422 class AtomicRequestor {
423 public:
424 
425     __attribute__((no_sanitize("integer")))
request()426     void request() {
427         mRequested++;
428     }
429 
430     __attribute__((no_sanitize("integer")))
isRequested()431     bool isRequested() {
432         return (mRequested.load() - mAcknowledged.load()) > 0;
433     }
434 
435     __attribute__((no_sanitize("integer")))
acknowledge()436     void acknowledge() {
437         mAcknowledged++;
438     }
439 
440 private:
441     std::atomic<int> mRequested{0};
442     std::atomic<int> mAcknowledged{0};
443 };
444 #endif //UTILITY_AAUDIO_UTILITIES_H
445