AAudioSimpleRecorder.h revision 753c9f326b9505004576996091a64a43271634a0
1629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent/*
2629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent * Copyright (C) 2017 The Android Open Source Project
3629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent *
4629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent * Licensed under the Apache License, Version 2.0 (the "License");
5629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent * you may not use this file except in compliance with the License.
6629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent * You may obtain a copy of the License at
7629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent *
8629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent *      http://www.apache.org/licenses/LICENSE-2.0
9629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent *
10629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent * Unless required by applicable law or agreed to in writing, software
11629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent * distributed under the License is distributed on an "AS IS" BASIS,
12629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent * See the License for the specific language governing permissions and
14629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent * limitations under the License.
15629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent */
16629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
17629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent// Record input using AAudio and display the peak amplitudes.
18629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
19629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent#ifndef AAUDIO_SIMPLE_RECORDER_H
20629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent#define AAUDIO_SIMPLE_RECORDER_H
21629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
22629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent#include <aaudio/AAudio.h>
23753c9f326b9505004576996091a64a43271634a0Phil Burk#include "AAudioArgsParser.h"
24629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
25629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent//#define SHARING_MODE  AAUDIO_SHARING_MODE_EXCLUSIVE
26629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent#define SHARING_MODE  AAUDIO_SHARING_MODE_SHARED
27629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent#define PERFORMANCE_MODE AAUDIO_PERFORMANCE_MODE_NONE
28753c9f326b9505004576996091a64a43271634a0Phil Burk
29629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent/**
30629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent * Simple wrapper for AAudio that opens an input stream either in callback or blocking read mode.
31629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent */
32629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurentclass AAudioSimpleRecorder {
33629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurentpublic:
34629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    AAudioSimpleRecorder() {}
35629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    ~AAudioSimpleRecorder() {
36629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        close();
37629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    };
38629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
39629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    /**
40629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent     * Call this before calling open().
41629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent     * @param requestedSharingMode
42629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent     */
43629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    void setSharingMode(aaudio_sharing_mode_t requestedSharingMode) {
44629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        mRequestedSharingMode = requestedSharingMode;
45629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    }
46629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
47629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    /**
48629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent     * Call this before calling open().
49629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent     * @param requestedPerformanceMode
50629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent     */
51629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    void setPerformanceMode(aaudio_performance_mode_t requestedPerformanceMode) {
52629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        mRequestedPerformanceMode = requestedPerformanceMode;
53629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    }
54629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
55629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    /**
56629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent     * Also known as "sample rate"
57629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent     * Only call this after open() has been called.
58629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent     */
59753c9f326b9505004576996091a64a43271634a0Phil Burk    int32_t getFramesPerSecond() const {
60753c9f326b9505004576996091a64a43271634a0Phil Burk        return getSampleRate(); // alias
61753c9f326b9505004576996091a64a43271634a0Phil Burk    }
62753c9f326b9505004576996091a64a43271634a0Phil Burk
63753c9f326b9505004576996091a64a43271634a0Phil Burk    /**
64753c9f326b9505004576996091a64a43271634a0Phil Burk     * Only call this after open() has been called.
65753c9f326b9505004576996091a64a43271634a0Phil Burk     */
66753c9f326b9505004576996091a64a43271634a0Phil Burk    int32_t getSampleRate() const {
67629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        if (mStream == nullptr) {
68629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            return AAUDIO_ERROR_INVALID_STATE;
69629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        }
70753c9f326b9505004576996091a64a43271634a0Phil Burk        return AAudioStream_getSampleRate(mStream);
71629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    }
72629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
73629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    /**
74629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent     * Only call this after open() has been called.
75629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent     */
76629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    int32_t getSamplesPerFrame() {
77629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        if (mStream == nullptr) {
78629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            return AAUDIO_ERROR_INVALID_STATE;
79629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        }
802829428ff26be1e1a33d161a54e3f988a1299db9Glenn Kasten        return AAudioStream_getChannelCount(mStream);;
81629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    }
82629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    /**
83629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent     * Only call this after open() has been called.
84629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent     */
85629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    int64_t getFramesRead() {
86629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        if (mStream == nullptr) {
87629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            return AAUDIO_ERROR_INVALID_STATE;
88629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        }
89753c9f326b9505004576996091a64a43271634a0Phil Burk        return AAudioStream_getFramesRead(mStream);
90753c9f326b9505004576996091a64a43271634a0Phil Burk    }
91753c9f326b9505004576996091a64a43271634a0Phil Burk
92753c9f326b9505004576996091a64a43271634a0Phil Burk    aaudio_result_t open(const AAudioParameters &parameters,
93753c9f326b9505004576996091a64a43271634a0Phil Burk                         AAudioStream_dataCallback dataCallback = nullptr,
94753c9f326b9505004576996091a64a43271634a0Phil Burk                         AAudioStream_errorCallback errorCallback = nullptr,
95753c9f326b9505004576996091a64a43271634a0Phil Burk                         void *userContext = nullptr) {
96753c9f326b9505004576996091a64a43271634a0Phil Burk        aaudio_result_t result = AAUDIO_OK;
97753c9f326b9505004576996091a64a43271634a0Phil Burk
98753c9f326b9505004576996091a64a43271634a0Phil Burk        // Use an AAudioStreamBuilder to contain requested parameters.
99753c9f326b9505004576996091a64a43271634a0Phil Burk        AAudioStreamBuilder *builder = nullptr;
100753c9f326b9505004576996091a64a43271634a0Phil Burk        result = AAudio_createStreamBuilder(&builder);
101753c9f326b9505004576996091a64a43271634a0Phil Burk        if (result != AAUDIO_OK) return result;
102753c9f326b9505004576996091a64a43271634a0Phil Burk
103753c9f326b9505004576996091a64a43271634a0Phil Burk        parameters.applyParameters(builder); // apply args
104753c9f326b9505004576996091a64a43271634a0Phil Burk
105753c9f326b9505004576996091a64a43271634a0Phil Burk        AAudioStreamBuilder_setDirection(builder, AAUDIO_DIRECTION_INPUT);
106753c9f326b9505004576996091a64a43271634a0Phil Burk
107753c9f326b9505004576996091a64a43271634a0Phil Burk        if (dataCallback != nullptr) {
108753c9f326b9505004576996091a64a43271634a0Phil Burk            AAudioStreamBuilder_setDataCallback(builder, dataCallback, userContext);
109753c9f326b9505004576996091a64a43271634a0Phil Burk        }
110753c9f326b9505004576996091a64a43271634a0Phil Burk        if (errorCallback != nullptr) {
111753c9f326b9505004576996091a64a43271634a0Phil Burk            AAudioStreamBuilder_setErrorCallback(builder, errorCallback, userContext);
112753c9f326b9505004576996091a64a43271634a0Phil Burk        }
113753c9f326b9505004576996091a64a43271634a0Phil Burk
114753c9f326b9505004576996091a64a43271634a0Phil Burk        // Open an AAudioStream using the Builder.
115753c9f326b9505004576996091a64a43271634a0Phil Burk        result = AAudioStreamBuilder_openStream(builder, &mStream);
116753c9f326b9505004576996091a64a43271634a0Phil Burk        if (result != AAUDIO_OK) {
117753c9f326b9505004576996091a64a43271634a0Phil Burk            fprintf(stderr, "ERROR - AAudioStreamBuilder_openStream() returned %d %s\n",
118753c9f326b9505004576996091a64a43271634a0Phil Burk                    result, AAudio_convertResultToText(result));
119753c9f326b9505004576996091a64a43271634a0Phil Burk        }
120753c9f326b9505004576996091a64a43271634a0Phil Burk
121753c9f326b9505004576996091a64a43271634a0Phil Burk        if (result == AAUDIO_OK) {
122753c9f326b9505004576996091a64a43271634a0Phil Burk            int32_t sizeInBursts = parameters.getNumberOfBursts();
123753c9f326b9505004576996091a64a43271634a0Phil Burk            if (sizeInBursts > 0) {
124753c9f326b9505004576996091a64a43271634a0Phil Burk                int32_t framesPerBurst = AAudioStream_getFramesPerBurst(mStream);
125753c9f326b9505004576996091a64a43271634a0Phil Burk                AAudioStream_setBufferSizeInFrames(mStream, sizeInBursts * framesPerBurst);
126753c9f326b9505004576996091a64a43271634a0Phil Burk            }
127753c9f326b9505004576996091a64a43271634a0Phil Burk        }
128753c9f326b9505004576996091a64a43271634a0Phil Burk
129753c9f326b9505004576996091a64a43271634a0Phil Burk        AAudioStreamBuilder_delete(builder);
130753c9f326b9505004576996091a64a43271634a0Phil Burk        return result;
131629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    }
132629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
133629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    /**
134629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent     * Open a stream
135629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent     */
136629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    aaudio_result_t open(int channelCount, int sampSampleRate, aaudio_format_t format,
137753c9f326b9505004576996091a64a43271634a0Phil Burk                         AAudioStream_dataCallback dataProc,
138753c9f326b9505004576996091a64a43271634a0Phil Burk                         AAudioStream_errorCallback errorProc,
139629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent                         void *userContext) {
140629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        aaudio_result_t result = AAUDIO_OK;
141629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
142629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        // Use an AAudioStreamBuilder to contain requested parameters.
143753c9f326b9505004576996091a64a43271634a0Phil Burk        AAudioStreamBuilder *builder = nullptr;
144753c9f326b9505004576996091a64a43271634a0Phil Burk        result = AAudio_createStreamBuilder(&builder);
145629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        if (result != AAUDIO_OK) return result;
146629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
147753c9f326b9505004576996091a64a43271634a0Phil Burk        AAudioStreamBuilder_setDirection(builder, AAUDIO_DIRECTION_INPUT);
148753c9f326b9505004576996091a64a43271634a0Phil Burk        AAudioStreamBuilder_setPerformanceMode(builder, mRequestedPerformanceMode);
149753c9f326b9505004576996091a64a43271634a0Phil Burk        AAudioStreamBuilder_setSharingMode(builder, mRequestedSharingMode);
150629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        if (dataProc != nullptr) {
151753c9f326b9505004576996091a64a43271634a0Phil Burk            AAudioStreamBuilder_setDataCallback(builder, dataProc, userContext);
152629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        }
153629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        if (errorProc != nullptr) {
154753c9f326b9505004576996091a64a43271634a0Phil Burk            AAudioStreamBuilder_setErrorCallback(builder, errorProc, userContext);
155629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        }
156753c9f326b9505004576996091a64a43271634a0Phil Burk        AAudioStreamBuilder_setChannelCount(builder, channelCount);
157753c9f326b9505004576996091a64a43271634a0Phil Burk        AAudioStreamBuilder_setSampleRate(builder, sampSampleRate);
158753c9f326b9505004576996091a64a43271634a0Phil Burk        AAudioStreamBuilder_setFormat(builder, format);
159629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
160629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        // Open an AAudioStream using the Builder.
161753c9f326b9505004576996091a64a43271634a0Phil Burk        result = AAudioStreamBuilder_openStream(builder, &mStream);
162629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        if (result != AAUDIO_OK) {
163629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            fprintf(stderr, "ERROR - AAudioStreamBuilder_openStream() returned %d %s\n",
164629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent                    result, AAudio_convertResultToText(result));
165629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        }
166629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
167753c9f326b9505004576996091a64a43271634a0Phil Burk        AAudioStreamBuilder_delete(builder);
168629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        return result;
169629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    }
170629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
171629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    aaudio_result_t close() {
172629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        if (mStream != nullptr) {
173629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            printf("call AAudioStream_close(%p)\n", mStream);  fflush(stdout);
174629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            AAudioStream_close(mStream);
175629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            mStream = nullptr;
176629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        }
177629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        return AAUDIO_OK;
178629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    }
179629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
180629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    // Write zero data to fill up the buffer and prevent underruns.
181629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    aaudio_result_t prime() {
1822829428ff26be1e1a33d161a54e3f988a1299db9Glenn Kasten        int32_t samplesPerFrame = AAudioStream_getChannelCount(mStream);
183629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        const int numFrames = 32; // arbitrary
184629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        float zeros[numFrames * samplesPerFrame];
185629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        memset(zeros, 0, sizeof(zeros));
186629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        aaudio_result_t result = numFrames;
187629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        while (result == numFrames) {
188629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            result = AAudioStream_write(mStream, zeros, numFrames, 0);
189629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        }
190629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        return result;
191629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    }
192629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
193629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    // Start the stream. AAudio will start calling your callback function.
194629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent     aaudio_result_t start() {
195629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        aaudio_result_t result = AAudioStream_requestStart(mStream);
196629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        if (result != AAUDIO_OK) {
197629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            fprintf(stderr, "ERROR - AAudioStream_requestStart() returned %d %s\n",
198629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent                    result, AAudio_convertResultToText(result));
199629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        }
200629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        return result;
201629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    }
202629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
203629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    // Stop the stream. AAudio will stop calling your callback function.
204629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    aaudio_result_t stop() {
205629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        aaudio_result_t result = AAudioStream_requestStop(mStream);
206629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        if (result != AAUDIO_OK) {
207629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            fprintf(stderr, "ERROR - AAudioStream_requestStop() returned %d %s\n",
208629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent                    result, AAudio_convertResultToText(result));
209629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        }
210629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        return result;
211629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    }
212629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
213629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    // Pause the stream. AAudio will stop calling your callback function.
214629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    aaudio_result_t pause() {
215629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        aaudio_result_t result = AAudioStream_requestPause(mStream);
216629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        if (result != AAUDIO_OK) {
217629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            fprintf(stderr, "ERROR - AAudioStream_requestPause() returned %d %s\n",
218629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent                    result, AAudio_convertResultToText(result));
219629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        }
220629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        return result;
221629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    }
222629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
223629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    AAudioStream *getStream() const {
224629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        return mStream;
225629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    }
226629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
227629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurentprivate:
228629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    AAudioStream             *mStream = nullptr;
229629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    aaudio_sharing_mode_t     mRequestedSharingMode = SHARING_MODE;
230629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    aaudio_performance_mode_t mRequestedPerformanceMode = PERFORMANCE_MODE;
231629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent};
232629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
233629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent// Application data that gets passed to the callback.
234629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurenttypedef struct PeakTrackerData {
235629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    float peakLevel;
236629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent} PeakTrackerData_t;
237629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
238629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent#define DECAY_FACTOR   0.999
239629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
240629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent// Callback function that fills the audio output buffer.
241629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurentaaudio_data_callback_result_t SimpleRecorderDataCallbackProc(
242629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        AAudioStream *stream,
243629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        void *userData,
244629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        void *audioData,
245629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        int32_t numFrames
246629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        ) {
247629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
248629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    // should not happen but just in case...
249629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    if (userData == nullptr) {
250629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        fprintf(stderr, "ERROR - SimpleRecorderDataCallbackProc needs userData\n");
251629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        return AAUDIO_CALLBACK_RESULT_STOP;
252629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    }
253629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    PeakTrackerData_t *data = (PeakTrackerData_t *) userData;
254629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    // printf("MyCallbackProc(): frameCount = %d\n", numFrames);
2552829428ff26be1e1a33d161a54e3f988a1299db9Glenn Kasten    int32_t samplesPerFrame = AAudioStream_getChannelCount(stream);
256629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    float sample;
257629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    // This code assume mono or stereo.
258629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    switch (AAudioStream_getFormat(stream)) {
259629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        case AAUDIO_FORMAT_PCM_I16: {
260629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            int16_t *audioBuffer = (int16_t *) audioData;
261629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            // Peak follower
262629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) {
263629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent                sample = audioBuffer[frameIndex * samplesPerFrame] * (1.0/32768);
264629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent                data->peakLevel *= DECAY_FACTOR;
265629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent                if (sample > data->peakLevel) {
266629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent                    data->peakLevel = sample;
267629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent                }
268629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            }
269629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        }
270629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        break;
271629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        case AAUDIO_FORMAT_PCM_FLOAT: {
272629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            float *audioBuffer = (float *) audioData;
273629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            // Peak follower
274629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) {
275629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent                sample = audioBuffer[frameIndex * samplesPerFrame];
276629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent                data->peakLevel *= DECAY_FACTOR;
277629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent                if (sample > data->peakLevel) {
278629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent                    data->peakLevel = sample;
279629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent                }
280629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            }
281629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        }
282629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        break;
283629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        default:
284629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            return AAUDIO_CALLBACK_RESULT_STOP;
285629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    }
286629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
287629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    return AAUDIO_CALLBACK_RESULT_CONTINUE;
288629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent}
289629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
290629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurentvoid SimpleRecorderErrorCallbackProc(
291629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        AAudioStream *stream __unused,
292629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        void *userData __unused,
293629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        aaudio_result_t error)
294629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent{
295629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    printf("Error Callback, error: %d\n",(int)error);
296629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent}
297629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
298629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent#endif //AAUDIO_SIMPLE_RECORDER_H
299