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