AAudioSimpleRecorder.h revision 629afae6135e6dc1e88ab4080f984fb30b3cdd7c
1/* 2 * Copyright (C) 2017 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// Record input using AAudio and display the peak amplitudes. 18 19#ifndef AAUDIO_SIMPLE_RECORDER_H 20#define AAUDIO_SIMPLE_RECORDER_H 21 22#include <aaudio/AAudio.h> 23 24//#define SHARING_MODE AAUDIO_SHARING_MODE_EXCLUSIVE 25#define SHARING_MODE AAUDIO_SHARING_MODE_SHARED 26#define PERFORMANCE_MODE AAUDIO_PERFORMANCE_MODE_NONE 27/** 28 * Simple wrapper for AAudio that opens an input stream either in callback or blocking read mode. 29 */ 30class AAudioSimpleRecorder { 31public: 32 AAudioSimpleRecorder() {} 33 ~AAudioSimpleRecorder() { 34 close(); 35 }; 36 37 /** 38 * Call this before calling open(). 39 * @param requestedSharingMode 40 */ 41 void setSharingMode(aaudio_sharing_mode_t requestedSharingMode) { 42 mRequestedSharingMode = requestedSharingMode; 43 } 44 45 /** 46 * Call this before calling open(). 47 * @param requestedPerformanceMode 48 */ 49 void setPerformanceMode(aaudio_performance_mode_t requestedPerformanceMode) { 50 mRequestedPerformanceMode = requestedPerformanceMode; 51 } 52 53 /** 54 * Also known as "sample rate" 55 * Only call this after open() has been called. 56 */ 57 int32_t getFramesPerSecond() { 58 if (mStream == nullptr) { 59 return AAUDIO_ERROR_INVALID_STATE; 60 } 61 return AAudioStream_getSampleRate(mStream);; 62 } 63 64 /** 65 * Only call this after open() has been called. 66 */ 67 int32_t getSamplesPerFrame() { 68 if (mStream == nullptr) { 69 return AAUDIO_ERROR_INVALID_STATE; 70 } 71 return AAudioStream_getSamplesPerFrame(mStream);; 72 } 73 /** 74 * Only call this after open() has been called. 75 */ 76 int64_t getFramesRead() { 77 if (mStream == nullptr) { 78 return AAUDIO_ERROR_INVALID_STATE; 79 } 80 return AAudioStream_getFramesRead(mStream);; 81 } 82 83 /** 84 * Open a stream 85 */ 86 aaudio_result_t open(int channelCount, int sampSampleRate, aaudio_format_t format, 87 AAudioStream_dataCallback dataProc, AAudioStream_errorCallback errorProc, 88 void *userContext) { 89 aaudio_result_t result = AAUDIO_OK; 90 91 // Use an AAudioStreamBuilder to contain requested parameters. 92 result = AAudio_createStreamBuilder(&mBuilder); 93 if (result != AAUDIO_OK) return result; 94 95 AAudioStreamBuilder_setDirection(mBuilder, AAUDIO_DIRECTION_INPUT); 96 AAudioStreamBuilder_setPerformanceMode(mBuilder, mRequestedPerformanceMode); 97 AAudioStreamBuilder_setSharingMode(mBuilder, mRequestedSharingMode); 98 if (dataProc != nullptr) { 99 AAudioStreamBuilder_setDataCallback(mBuilder, dataProc, userContext); 100 } 101 if (errorProc != nullptr) { 102 AAudioStreamBuilder_setErrorCallback(mBuilder, errorProc, userContext); 103 } 104 AAudioStreamBuilder_setChannelCount(mBuilder, channelCount); 105 AAudioStreamBuilder_setSampleRate(mBuilder, sampSampleRate); 106 AAudioStreamBuilder_setFormat(mBuilder, format); 107 108 // Open an AAudioStream using the Builder. 109 result = AAudioStreamBuilder_openStream(mBuilder, &mStream); 110 if (result != AAUDIO_OK) { 111 fprintf(stderr, "ERROR - AAudioStreamBuilder_openStream() returned %d %s\n", 112 result, AAudio_convertResultToText(result)); 113 goto finish1; 114 } 115 116 printf("AAudioStream_getFramesPerBurst() = %d\n", 117 AAudioStream_getFramesPerBurst(mStream)); 118 printf("AAudioStream_getBufferSizeInFrames() = %d\n", 119 AAudioStream_getBufferSizeInFrames(mStream)); 120 printf("AAudioStream_getBufferCapacityInFrames() = %d\n", 121 AAudioStream_getBufferCapacityInFrames(mStream)); 122 return result; 123 124 finish1: 125 AAudioStreamBuilder_delete(mBuilder); 126 mBuilder = nullptr; 127 return result; 128 } 129 130 aaudio_result_t close() { 131 if (mStream != nullptr) { 132 printf("call AAudioStream_close(%p)\n", mStream); fflush(stdout); 133 AAudioStream_close(mStream); 134 mStream = nullptr; 135 AAudioStreamBuilder_delete(mBuilder); 136 mBuilder = nullptr; 137 } 138 return AAUDIO_OK; 139 } 140 141 // Write zero data to fill up the buffer and prevent underruns. 142 aaudio_result_t prime() { 143 int32_t samplesPerFrame = AAudioStream_getSamplesPerFrame(mStream); 144 const int numFrames = 32; // arbitrary 145 float zeros[numFrames * samplesPerFrame]; 146 memset(zeros, 0, sizeof(zeros)); 147 aaudio_result_t result = numFrames; 148 while (result == numFrames) { 149 result = AAudioStream_write(mStream, zeros, numFrames, 0); 150 } 151 return result; 152 } 153 154 // Start the stream. AAudio will start calling your callback function. 155 aaudio_result_t start() { 156 aaudio_result_t result = AAudioStream_requestStart(mStream); 157 if (result != AAUDIO_OK) { 158 fprintf(stderr, "ERROR - AAudioStream_requestStart() returned %d %s\n", 159 result, AAudio_convertResultToText(result)); 160 } 161 return result; 162 } 163 164 // Stop the stream. AAudio will stop calling your callback function. 165 aaudio_result_t stop() { 166 aaudio_result_t result = AAudioStream_requestStop(mStream); 167 if (result != AAUDIO_OK) { 168 fprintf(stderr, "ERROR - AAudioStream_requestStop() returned %d %s\n", 169 result, AAudio_convertResultToText(result)); 170 } 171 return result; 172 } 173 174 // Pause the stream. AAudio will stop calling your callback function. 175 aaudio_result_t pause() { 176 aaudio_result_t result = AAudioStream_requestPause(mStream); 177 if (result != AAUDIO_OK) { 178 fprintf(stderr, "ERROR - AAudioStream_requestPause() returned %d %s\n", 179 result, AAudio_convertResultToText(result)); 180 } 181 return result; 182 } 183 184 AAudioStream *getStream() const { 185 return mStream; 186 } 187 188private: 189 AAudioStreamBuilder *mBuilder = nullptr; 190 AAudioStream *mStream = nullptr; 191 aaudio_sharing_mode_t mRequestedSharingMode = SHARING_MODE; 192 aaudio_performance_mode_t mRequestedPerformanceMode = PERFORMANCE_MODE; 193}; 194 195// Application data that gets passed to the callback. 196typedef struct PeakTrackerData { 197 float peakLevel; 198} PeakTrackerData_t; 199 200#define DECAY_FACTOR 0.999 201 202// Callback function that fills the audio output buffer. 203aaudio_data_callback_result_t SimpleRecorderDataCallbackProc( 204 AAudioStream *stream, 205 void *userData, 206 void *audioData, 207 int32_t numFrames 208 ) { 209 210 // should not happen but just in case... 211 if (userData == nullptr) { 212 fprintf(stderr, "ERROR - SimpleRecorderDataCallbackProc needs userData\n"); 213 return AAUDIO_CALLBACK_RESULT_STOP; 214 } 215 PeakTrackerData_t *data = (PeakTrackerData_t *) userData; 216 // printf("MyCallbackProc(): frameCount = %d\n", numFrames); 217 int32_t samplesPerFrame = AAudioStream_getSamplesPerFrame(stream); 218 float sample; 219 // This code assume mono or stereo. 220 switch (AAudioStream_getFormat(stream)) { 221 case AAUDIO_FORMAT_PCM_I16: { 222 int16_t *audioBuffer = (int16_t *) audioData; 223 // Peak follower 224 for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) { 225 sample = audioBuffer[frameIndex * samplesPerFrame] * (1.0/32768); 226 data->peakLevel *= DECAY_FACTOR; 227 if (sample > data->peakLevel) { 228 data->peakLevel = sample; 229 } 230 } 231 } 232 break; 233 case AAUDIO_FORMAT_PCM_FLOAT: { 234 float *audioBuffer = (float *) audioData; 235 // Peak follower 236 for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) { 237 sample = audioBuffer[frameIndex * samplesPerFrame]; 238 data->peakLevel *= DECAY_FACTOR; 239 if (sample > data->peakLevel) { 240 data->peakLevel = sample; 241 } 242 } 243 } 244 break; 245 default: 246 return AAUDIO_CALLBACK_RESULT_STOP; 247 } 248 249 return AAUDIO_CALLBACK_RESULT_CONTINUE; 250} 251 252void SimpleRecorderErrorCallbackProc( 253 AAudioStream *stream __unused, 254 void *userData __unused, 255 aaudio_result_t error) 256{ 257 printf("Error Callback, error: %d\n",(int)error); 258} 259 260#endif //AAUDIO_SIMPLE_RECORDER_H 261