input_monitor.cpp revision a4eb0d86a29be2763be5fac51727858d5095794b
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#include <new> 20#include <assert.h> 21#include <stdio.h> 22#include <stdlib.h> 23#include <math.h> 24#include <aaudio/AAudio.h> 25 26#define SAMPLE_RATE 48000 27#define NUM_SECONDS 10 28#define NANOS_PER_MICROSECOND ((int64_t)1000) 29#define NANOS_PER_MILLISECOND (NANOS_PER_MICROSECOND * 1000) 30#define NANOS_PER_SECOND (NANOS_PER_MILLISECOND * 1000) 31 32#define DECAY_FACTOR 0.999 33#define MIN_FRAMES_TO_READ 48 /* arbitrary, 1 msec at 48000 Hz */ 34 35static const char *getSharingModeText(aaudio_sharing_mode_t mode) { 36 const char *modeText = "unknown"; 37 switch (mode) { 38 case AAUDIO_SHARING_MODE_EXCLUSIVE: 39 modeText = "EXCLUSIVE"; 40 break; 41 case AAUDIO_SHARING_MODE_SHARED: 42 modeText = "SHARED"; 43 break; 44 default: 45 break; 46 } 47 return modeText; 48} 49 50int main(int argc, char **argv) 51{ 52 (void)argc; // unused 53 54 aaudio_result_t result; 55 56 int actualSamplesPerFrame; 57 int actualSampleRate; 58 const aaudio_audio_format_t requestedDataFormat = AAUDIO_FORMAT_PCM_I16; 59 aaudio_audio_format_t actualDataFormat; 60 61 const aaudio_sharing_mode_t requestedSharingMode = AAUDIO_SHARING_MODE_SHARED; 62 aaudio_sharing_mode_t actualSharingMode; 63 64 AAudioStreamBuilder *aaudioBuilder = nullptr; 65 AAudioStream *aaudioStream = nullptr; 66 aaudio_stream_state_t state; 67 int32_t framesPerBurst = 0; 68 int32_t framesPerRead = 0; 69 int32_t framesToRecord = 0; 70 int32_t framesLeft = 0; 71 int32_t xRunCount = 0; 72 int16_t *data = nullptr; 73 float peakLevel = 0.0; 74 int loopCounter = 0; 75 76 // Make printf print immediately so that debug info is not stuck 77 // in a buffer if we hang or crash. 78 setvbuf(stdout, nullptr, _IONBF, (size_t) 0); 79 80 printf("%s - Monitor input level using AAudio\n", argv[0]); 81 82 // Use an AAudioStreamBuilder to contain requested parameters. 83 result = AAudio_createStreamBuilder(&aaudioBuilder); 84 if (result != AAUDIO_OK) { 85 goto finish; 86 } 87 88 // Request stream properties. 89 AAudioStreamBuilder_setDirection(aaudioBuilder, AAUDIO_DIRECTION_INPUT); 90 AAudioStreamBuilder_setFormat(aaudioBuilder, requestedDataFormat); 91 AAudioStreamBuilder_setSharingMode(aaudioBuilder, requestedSharingMode); 92 93 // Create an AAudioStream using the Builder. 94 result = AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream); 95 if (result != AAUDIO_OK) { 96 goto finish; 97 } 98 99 actualSamplesPerFrame = AAudioStream_getSamplesPerFrame(aaudioStream); 100 printf("SamplesPerFrame = %d\n", actualSamplesPerFrame); 101 actualSampleRate = AAudioStream_getSampleRate(aaudioStream); 102 printf("SamplesPerFrame = %d\n", actualSampleRate); 103 104 actualSharingMode = AAudioStream_getSharingMode(aaudioStream); 105 printf("SharingMode: requested = %s, actual = %s\n", 106 getSharingModeText(requestedSharingMode), 107 getSharingModeText(actualSharingMode)); 108 109 // This is the number of frames that are written in one chunk by a DMA controller 110 // or a DSP. 111 framesPerBurst = AAudioStream_getFramesPerBurst(aaudioStream); 112 printf("DataFormat: framesPerBurst = %d\n",framesPerBurst); 113 114 // Some DMA might use very short bursts of 16 frames. We don't need to read such small 115 // buffers. But it helps to use a multiple of the burst size for predictable scheduling. 116 framesPerRead = framesPerBurst; 117 while (framesPerRead < MIN_FRAMES_TO_READ) { 118 framesPerRead *= 2; 119 } 120 printf("DataFormat: framesPerRead = %d\n",framesPerRead); 121 122 actualDataFormat = AAudioStream_getFormat(aaudioStream); 123 printf("DataFormat: requested = %d, actual = %d\n", requestedDataFormat, actualDataFormat); 124 // TODO handle other data formats 125 assert(actualDataFormat == AAUDIO_FORMAT_PCM_I16); 126 127 // Allocate a buffer for the audio data. 128 data = new(std::nothrow) int16_t[framesPerRead * actualSamplesPerFrame]; 129 if (data == nullptr) { 130 fprintf(stderr, "ERROR - could not allocate data buffer\n"); 131 result = AAUDIO_ERROR_NO_MEMORY; 132 goto finish; 133 } 134 135 // Start the stream. 136 printf("call AAudioStream_requestStart()\n"); 137 result = AAudioStream_requestStart(aaudioStream); 138 if (result != AAUDIO_OK) { 139 fprintf(stderr, "ERROR - AAudioStream_requestStart() returned %d\n", result); 140 goto finish; 141 } 142 143 state = AAudioStream_getState(aaudioStream); 144 printf("after start, state = %s\n", AAudio_convertStreamStateToText(state)); 145 146 // Play for a while. 147 framesToRecord = actualSampleRate * NUM_SECONDS; 148 framesLeft = framesToRecord; 149 while (framesLeft > 0) { 150 // Read audio data from the stream. 151 int64_t timeoutNanos = 100 * NANOS_PER_MILLISECOND; 152 int minFrames = (framesToRecord < framesPerRead) ? framesToRecord : framesPerRead; 153 int actual = AAudioStream_read(aaudioStream, data, minFrames, timeoutNanos); 154 if (actual < 0) { 155 fprintf(stderr, "ERROR - AAudioStream_read() returned %zd\n", actual); 156 goto finish; 157 } else if (actual == 0) { 158 fprintf(stderr, "WARNING - AAudioStream_read() returned %zd\n", actual); 159 goto finish; 160 } 161 framesLeft -= actual; 162 163 // Peak follower. 164 for (int frameIndex = 0; frameIndex < actual; frameIndex++) { 165 float sample = data[frameIndex * actualSamplesPerFrame] * (1.0/32768); 166 peakLevel *= DECAY_FACTOR; 167 if (sample > peakLevel) { 168 peakLevel = sample; 169 } 170 } 171 172 // Display level as stars, eg. "******". 173 if ((loopCounter++ % 10) == 0) { 174 printf("%5.3f ", peakLevel); 175 int numStars = (int)(peakLevel * 50); 176 for (int i = 0; i < numStars; i++) { 177 printf("*"); 178 } 179 printf("\n"); 180 } 181 } 182 183 xRunCount = AAudioStream_getXRunCount(aaudioStream); 184 printf("AAudioStream_getXRunCount %d\n", xRunCount); 185 186finish: 187 delete[] data; 188 AAudioStream_close(aaudioStream); 189 AAudioStreamBuilder_delete(aaudioBuilder); 190 printf("exiting - AAudio result = %d = %s\n", result, AAudio_convertResultToText(result)); 191 return (result != AAUDIO_OK) ? EXIT_FAILURE : EXIT_SUCCESS; 192} 193 194