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 */
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
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 */
45audio_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 */
55void 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 */
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);
161
162class 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
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 */
206int32_t AAudioConvert_framesToBytes(int32_t numFrames,
207                                    int32_t bytesPerFrame,
208                                    int32_t *sizeInBytes);
209
210audio_format_t AAudioConvert_aaudioToAndroidDataFormat(aaudio_format_t aaudio_format);
211
212aaudio_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
221audio_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 */
228audio_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 */
235audio_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 */
240int32_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 */
251int32_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 */
259int32_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 */
267int32_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 */
280int32_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 */
289int32_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 */
303int32_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 */
311aaudio_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 */
323static 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 */
346template <class T>
347class SimpleDoubleBuffer {
348public:
349    SimpleDoubleBuffer()
350            : mValues() {}
351
352    __attribute__((no_sanitize("integer")))
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     */
363    void clear() {
364        mCounter.store(0);
365    }
366
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     */
385    bool isValid() const {
386        return mCounter.load() > 0;
387    }
388
389private:
390    T                    mValues[2];
391    std::atomic<int>     mCounter{0};
392};
393
394class Timestamp {
395public:
396    Timestamp()
397            : mPosition(0)
398            , mNanoseconds(0) {}
399    Timestamp(int64_t position, int64_t nanoseconds)
400            : mPosition(position)
401            , mNanoseconds(nanoseconds) {}
402
403    int64_t getPosition() const { return mPosition; }
404
405    int64_t getNanoseconds() const { return mNanoseconds; }
406
407private:
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 */
422class AtomicRequestor {
423public:
424
425    __attribute__((no_sanitize("integer")))
426    void request() {
427        mRequested++;
428    }
429
430    __attribute__((no_sanitize("integer")))
431    bool isRequested() {
432        return (mRequested.load() - mAcknowledged.load()) > 0;
433    }
434
435    __attribute__((no_sanitize("integer")))
436    void acknowledge() {
437        mAcknowledged++;
438    }
439
440private:
441    std::atomic<int> mRequested{0};
442    std::atomic<int> mAcknowledged{0};
443};
444#endif //UTILITY_AAUDIO_UTILITIES_H
445