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     */
76fcf9efd59e36759ee7df66fdfce4f8eedeb376e4Phil Burk    int32_t getChannelCount() {
77629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        if (mStream == nullptr) {
78629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            return AAUDIO_ERROR_INVALID_STATE;
79629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        }
802829428ff26be1e1a33d161a54e3f988a1299db9Glenn Kasten        return AAudioStream_getChannelCount(mStream);;
81629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    }
82fcf9efd59e36759ee7df66fdfce4f8eedeb376e4Phil Burk
83fcf9efd59e36759ee7df66fdfce4f8eedeb376e4Phil Burk    /**
84fcf9efd59e36759ee7df66fdfce4f8eedeb376e4Phil Burk     * @deprecated use getChannelCount()
85fcf9efd59e36759ee7df66fdfce4f8eedeb376e4Phil Burk     */
86fcf9efd59e36759ee7df66fdfce4f8eedeb376e4Phil Burk    int32_t getSamplesPerFrame() {
87fcf9efd59e36759ee7df66fdfce4f8eedeb376e4Phil Burk        return getChannelCount();
88fcf9efd59e36759ee7df66fdfce4f8eedeb376e4Phil Burk    }
89fcf9efd59e36759ee7df66fdfce4f8eedeb376e4Phil Burk
90629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    /**
91629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent     * Only call this after open() has been called.
92629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent     */
93629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    int64_t getFramesRead() {
94629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        if (mStream == nullptr) {
95629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            return AAUDIO_ERROR_INVALID_STATE;
96629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        }
97753c9f326b9505004576996091a64a43271634a0Phil Burk        return AAudioStream_getFramesRead(mStream);
98753c9f326b9505004576996091a64a43271634a0Phil Burk    }
99753c9f326b9505004576996091a64a43271634a0Phil Burk
100753c9f326b9505004576996091a64a43271634a0Phil Burk    aaudio_result_t open(const AAudioParameters &parameters,
101753c9f326b9505004576996091a64a43271634a0Phil Burk                         AAudioStream_dataCallback dataCallback = nullptr,
102753c9f326b9505004576996091a64a43271634a0Phil Burk                         AAudioStream_errorCallback errorCallback = nullptr,
103753c9f326b9505004576996091a64a43271634a0Phil Burk                         void *userContext = nullptr) {
104753c9f326b9505004576996091a64a43271634a0Phil Burk        aaudio_result_t result = AAUDIO_OK;
105753c9f326b9505004576996091a64a43271634a0Phil Burk
106753c9f326b9505004576996091a64a43271634a0Phil Burk        // Use an AAudioStreamBuilder to contain requested parameters.
107753c9f326b9505004576996091a64a43271634a0Phil Burk        AAudioStreamBuilder *builder = nullptr;
108753c9f326b9505004576996091a64a43271634a0Phil Burk        result = AAudio_createStreamBuilder(&builder);
109753c9f326b9505004576996091a64a43271634a0Phil Burk        if (result != AAUDIO_OK) return result;
110753c9f326b9505004576996091a64a43271634a0Phil Burk
111753c9f326b9505004576996091a64a43271634a0Phil Burk        parameters.applyParameters(builder); // apply args
112753c9f326b9505004576996091a64a43271634a0Phil Burk
113753c9f326b9505004576996091a64a43271634a0Phil Burk        AAudioStreamBuilder_setDirection(builder, AAUDIO_DIRECTION_INPUT);
114753c9f326b9505004576996091a64a43271634a0Phil Burk
115753c9f326b9505004576996091a64a43271634a0Phil Burk        if (dataCallback != nullptr) {
116753c9f326b9505004576996091a64a43271634a0Phil Burk            AAudioStreamBuilder_setDataCallback(builder, dataCallback, userContext);
117753c9f326b9505004576996091a64a43271634a0Phil Burk        }
118753c9f326b9505004576996091a64a43271634a0Phil Burk        if (errorCallback != nullptr) {
119753c9f326b9505004576996091a64a43271634a0Phil Burk            AAudioStreamBuilder_setErrorCallback(builder, errorCallback, userContext);
120753c9f326b9505004576996091a64a43271634a0Phil Burk        }
121753c9f326b9505004576996091a64a43271634a0Phil Burk
122753c9f326b9505004576996091a64a43271634a0Phil Burk        // Open an AAudioStream using the Builder.
123753c9f326b9505004576996091a64a43271634a0Phil Burk        result = AAudioStreamBuilder_openStream(builder, &mStream);
124753c9f326b9505004576996091a64a43271634a0Phil Burk        if (result != AAUDIO_OK) {
125753c9f326b9505004576996091a64a43271634a0Phil Burk            fprintf(stderr, "ERROR - AAudioStreamBuilder_openStream() returned %d %s\n",
126753c9f326b9505004576996091a64a43271634a0Phil Burk                    result, AAudio_convertResultToText(result));
127753c9f326b9505004576996091a64a43271634a0Phil Burk        }
128753c9f326b9505004576996091a64a43271634a0Phil Burk
129753c9f326b9505004576996091a64a43271634a0Phil Burk        if (result == AAUDIO_OK) {
130753c9f326b9505004576996091a64a43271634a0Phil Burk            int32_t sizeInBursts = parameters.getNumberOfBursts();
131753c9f326b9505004576996091a64a43271634a0Phil Burk            if (sizeInBursts > 0) {
132753c9f326b9505004576996091a64a43271634a0Phil Burk                int32_t framesPerBurst = AAudioStream_getFramesPerBurst(mStream);
133753c9f326b9505004576996091a64a43271634a0Phil Burk                AAudioStream_setBufferSizeInFrames(mStream, sizeInBursts * framesPerBurst);
134753c9f326b9505004576996091a64a43271634a0Phil Burk            }
135753c9f326b9505004576996091a64a43271634a0Phil Burk        }
136753c9f326b9505004576996091a64a43271634a0Phil Burk
137753c9f326b9505004576996091a64a43271634a0Phil Burk        AAudioStreamBuilder_delete(builder);
138753c9f326b9505004576996091a64a43271634a0Phil Burk        return result;
139629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    }
140629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
141629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    /**
142629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent     * Open a stream
143629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent     */
144629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    aaudio_result_t open(int channelCount, int sampSampleRate, aaudio_format_t format,
145753c9f326b9505004576996091a64a43271634a0Phil Burk                         AAudioStream_dataCallback dataProc,
146753c9f326b9505004576996091a64a43271634a0Phil Burk                         AAudioStream_errorCallback errorProc,
147629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent                         void *userContext) {
148629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        aaudio_result_t result = AAUDIO_OK;
149629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
150629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        // Use an AAudioStreamBuilder to contain requested parameters.
151753c9f326b9505004576996091a64a43271634a0Phil Burk        AAudioStreamBuilder *builder = nullptr;
152753c9f326b9505004576996091a64a43271634a0Phil Burk        result = AAudio_createStreamBuilder(&builder);
153629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        if (result != AAUDIO_OK) return result;
154629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
155753c9f326b9505004576996091a64a43271634a0Phil Burk        AAudioStreamBuilder_setDirection(builder, AAUDIO_DIRECTION_INPUT);
156753c9f326b9505004576996091a64a43271634a0Phil Burk        AAudioStreamBuilder_setPerformanceMode(builder, mRequestedPerformanceMode);
157753c9f326b9505004576996091a64a43271634a0Phil Burk        AAudioStreamBuilder_setSharingMode(builder, mRequestedSharingMode);
158629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        if (dataProc != nullptr) {
159753c9f326b9505004576996091a64a43271634a0Phil Burk            AAudioStreamBuilder_setDataCallback(builder, dataProc, userContext);
160629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        }
161629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        if (errorProc != nullptr) {
162753c9f326b9505004576996091a64a43271634a0Phil Burk            AAudioStreamBuilder_setErrorCallback(builder, errorProc, userContext);
163629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        }
164753c9f326b9505004576996091a64a43271634a0Phil Burk        AAudioStreamBuilder_setChannelCount(builder, channelCount);
165753c9f326b9505004576996091a64a43271634a0Phil Burk        AAudioStreamBuilder_setSampleRate(builder, sampSampleRate);
166753c9f326b9505004576996091a64a43271634a0Phil Burk        AAudioStreamBuilder_setFormat(builder, format);
167629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
168629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        // Open an AAudioStream using the Builder.
169753c9f326b9505004576996091a64a43271634a0Phil Burk        result = AAudioStreamBuilder_openStream(builder, &mStream);
170629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        if (result != AAUDIO_OK) {
171629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            fprintf(stderr, "ERROR - AAudioStreamBuilder_openStream() returned %d %s\n",
172629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent                    result, AAudio_convertResultToText(result));
173629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        }
174629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
175753c9f326b9505004576996091a64a43271634a0Phil Burk        AAudioStreamBuilder_delete(builder);
176629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        return result;
177629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    }
178629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
179629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    aaudio_result_t close() {
180629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        if (mStream != nullptr) {
181629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            AAudioStream_close(mStream);
182629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            mStream = nullptr;
183629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        }
184629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        return AAUDIO_OK;
185629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    }
186629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
187629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    // Write zero data to fill up the buffer and prevent underruns.
188629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    aaudio_result_t prime() {
1892829428ff26be1e1a33d161a54e3f988a1299db9Glenn Kasten        int32_t samplesPerFrame = AAudioStream_getChannelCount(mStream);
190629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        const int numFrames = 32; // arbitrary
191629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        float zeros[numFrames * samplesPerFrame];
192629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        memset(zeros, 0, sizeof(zeros));
193629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        aaudio_result_t result = numFrames;
194629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        while (result == numFrames) {
195629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            result = AAudioStream_write(mStream, zeros, numFrames, 0);
196629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        }
197629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        return result;
198629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    }
199629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
200629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    // Start the stream. AAudio will start calling your callback function.
201629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent     aaudio_result_t start() {
202629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        aaudio_result_t result = AAudioStream_requestStart(mStream);
203629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        if (result != AAUDIO_OK) {
204629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            fprintf(stderr, "ERROR - AAudioStream_requestStart() returned %d %s\n",
205629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent                    result, AAudio_convertResultToText(result));
206629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        }
207629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        return result;
208629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    }
209629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
210629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    // Stop the stream. AAudio will stop calling your callback function.
211629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    aaudio_result_t stop() {
212629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        aaudio_result_t result = AAudioStream_requestStop(mStream);
213629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        if (result != AAUDIO_OK) {
214629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            fprintf(stderr, "ERROR - AAudioStream_requestStop() returned %d %s\n",
215629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent                    result, AAudio_convertResultToText(result));
216629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        }
217629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        return result;
218629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    }
219629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
220629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    // Pause the stream. AAudio will stop calling your callback function.
221629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    aaudio_result_t pause() {
222629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        aaudio_result_t result = AAudioStream_requestPause(mStream);
223629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        if (result != AAUDIO_OK) {
224629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            fprintf(stderr, "ERROR - AAudioStream_requestPause() returned %d %s\n",
225629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent                    result, AAudio_convertResultToText(result));
226629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        }
227629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        return result;
228629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    }
229629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
230629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    AAudioStream *getStream() const {
231629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        return mStream;
232629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    }
233629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
234629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurentprivate:
235629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    AAudioStream             *mStream = nullptr;
236629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    aaudio_sharing_mode_t     mRequestedSharingMode = SHARING_MODE;
237629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    aaudio_performance_mode_t mRequestedPerformanceMode = PERFORMANCE_MODE;
238629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent};
239629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
240629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent// Application data that gets passed to the callback.
241629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurenttypedef struct PeakTrackerData {
242629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    float peakLevel;
243629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent} PeakTrackerData_t;
244629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
245629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent#define DECAY_FACTOR   0.999
246629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
247629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent// Callback function that fills the audio output buffer.
248629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurentaaudio_data_callback_result_t SimpleRecorderDataCallbackProc(
249629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        AAudioStream *stream,
250629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        void *userData,
251629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        void *audioData,
252629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        int32_t numFrames
253629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        ) {
254629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
255629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    // should not happen but just in case...
256629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    if (userData == nullptr) {
257629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        fprintf(stderr, "ERROR - SimpleRecorderDataCallbackProc needs userData\n");
258629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        return AAUDIO_CALLBACK_RESULT_STOP;
259629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    }
260629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    PeakTrackerData_t *data = (PeakTrackerData_t *) userData;
261629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    // printf("MyCallbackProc(): frameCount = %d\n", numFrames);
2622829428ff26be1e1a33d161a54e3f988a1299db9Glenn Kasten    int32_t samplesPerFrame = AAudioStream_getChannelCount(stream);
263629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    float sample;
264629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    // This code assume mono or stereo.
265629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    switch (AAudioStream_getFormat(stream)) {
266629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        case AAUDIO_FORMAT_PCM_I16: {
267629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            int16_t *audioBuffer = (int16_t *) audioData;
268629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            // Peak follower
269629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) {
270629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent                sample = audioBuffer[frameIndex * samplesPerFrame] * (1.0/32768);
271629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent                data->peakLevel *= DECAY_FACTOR;
272629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent                if (sample > data->peakLevel) {
273629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent                    data->peakLevel = sample;
274629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent                }
275629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            }
276629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        }
277629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        break;
278629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        case AAUDIO_FORMAT_PCM_FLOAT: {
279629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            float *audioBuffer = (float *) audioData;
280629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            // Peak follower
281629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) {
282629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent                sample = audioBuffer[frameIndex * samplesPerFrame];
283629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent                data->peakLevel *= DECAY_FACTOR;
284629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent                if (sample > data->peakLevel) {
285629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent                    data->peakLevel = sample;
286629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent                }
287629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            }
288629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        }
289629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        break;
290629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        default:
291629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent            return AAUDIO_CALLBACK_RESULT_STOP;
292629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    }
293629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
294629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    return AAUDIO_CALLBACK_RESULT_CONTINUE;
295629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent}
296629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
297629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurentvoid SimpleRecorderErrorCallbackProc(
298629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        AAudioStream *stream __unused,
299629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        void *userData __unused,
300629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent        aaudio_result_t error)
301629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent{
302629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    printf("Error Callback, error: %d\n",(int)error);
303629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent}
304629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent
305629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent#endif //AAUDIO_SIMPLE_RECORDER_H
306