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 <assert.h>
20 #include <unistd.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <math.h>
24 #include <time.h>
25 #include <aaudio/AAudio.h>
26 #include "AAudioExampleUtils.h"
27 #include "AAudioSimpleRecorder.h"
28
main(int argc,const char ** argv)29 int main(int argc, const char **argv)
30 {
31 AAudioArgsParser argParser;
32 AAudioSimpleRecorder recorder;
33 PeakTrackerData_t myData = {0.0};
34 AAudioStream *aaudioStream = nullptr;
35 aaudio_result_t result;
36 aaudio_stream_state_t state;
37
38 int loopsNeeded = 0;
39 const int displayRateHz = 20; // arbitrary
40
41 // Make printf print immediately so that debug info is not stuck
42 // in a buffer if we hang or crash.
43 setvbuf(stdout, nullptr, _IONBF, (size_t) 0);
44 printf("%s - Display audio input using an AAudio callback, V0.1.3\n", argv[0]);
45
46 if (argParser.parseArgs(argc, argv)) {
47 return EXIT_FAILURE;
48 }
49
50 result = recorder.open(argParser,
51 SimpleRecorderDataCallbackProc,
52 SimpleRecorderErrorCallbackProc,
53 &myData);
54 if (result != AAUDIO_OK) {
55 fprintf(stderr, "ERROR - recorder.open() returned %d\n", result);
56 printf("IMPORTANT - Did you remember to enter: adb root\n");
57 goto error;
58 }
59 aaudioStream = recorder.getStream();
60 argParser.compareWithStream(aaudioStream);
61
62 printf("recorder.getFramesPerSecond() = %d\n", recorder.getFramesPerSecond());
63 printf("recorder.getSamplesPerFrame() = %d\n", recorder.getSamplesPerFrame());
64
65 result = recorder.start();
66 if (result != AAUDIO_OK) {
67 fprintf(stderr, "ERROR - recorder.start() returned %d\n", result);
68 goto error;
69 }
70
71 printf("Sleep for %d seconds while audio record in a callback thread.\n",
72 argParser.getDurationSeconds());
73 loopsNeeded = argParser.getDurationSeconds() * displayRateHz;
74 for (int i = 0; i < loopsNeeded; i++)
75 {
76 const struct timespec request = { .tv_sec = 0,
77 .tv_nsec = NANOS_PER_SECOND / displayRateHz };
78 (void) clock_nanosleep(CLOCK_MONOTONIC, 0 /*flags*/, &request, NULL /*remain*/);
79 printf("%08d: ", (int)recorder.getFramesRead());
80 displayPeakLevel(myData.peakLevel);
81
82 result = AAudioStream_waitForStateChange(aaudioStream,
83 AAUDIO_STREAM_STATE_CLOSED,
84 &state,
85 0);
86 if (result != AAUDIO_OK) {
87 fprintf(stderr, "ERROR - AAudioStream_waitForStateChange() returned %d\n", result);
88 goto error;
89 }
90 if (state != AAUDIO_STREAM_STATE_STARTING && state != AAUDIO_STREAM_STATE_STARTED) {
91 printf("Stream state is %d %s!\n", state, AAudio_convertStreamStateToText(state));
92 break;
93 }
94 }
95 printf("Woke up. Stop for a moment.\n");
96
97 result = recorder.stop();
98 if (result != AAUDIO_OK) {
99 goto error;
100 }
101 usleep(2000 * 1000);
102 result = recorder.start();
103 if (result != AAUDIO_OK) {
104 fprintf(stderr, "ERROR - recorder.start() returned %d\n", result);
105 goto error;
106 }
107
108 printf("Sleep for %d seconds while audio records in a callback thread.\n",
109 argParser.getDurationSeconds());
110 for (int i = 0; i < loopsNeeded; i++)
111 {
112 const struct timespec request = { .tv_sec = 0,
113 .tv_nsec = NANOS_PER_SECOND / displayRateHz };
114 (void) clock_nanosleep(CLOCK_MONOTONIC, 0 /*flags*/, &request, NULL /*remain*/);
115 printf("%08d: ", (int)recorder.getFramesRead());
116 displayPeakLevel(myData.peakLevel);
117
118 state = AAudioStream_getState(aaudioStream);
119 if (state != AAUDIO_STREAM_STATE_STARTING && state != AAUDIO_STREAM_STATE_STARTED) {
120 printf("Stream state is %d %s!\n", state, AAudio_convertStreamStateToText(state));
121 break;
122 }
123 }
124 printf("Woke up now.\n");
125 argParser.compareWithStream(aaudioStream);
126
127 result = recorder.stop();
128 if (result != AAUDIO_OK) {
129 goto error;
130 }
131 result = recorder.close();
132 if (result != AAUDIO_OK) {
133 goto error;
134 }
135
136 printf("SUCCESS\n");
137 return EXIT_SUCCESS;
138 error:
139 recorder.close();
140 printf("exiting - AAudio result = %d = %s\n", result, AAudio_convertResultToText(result));
141 return EXIT_FAILURE;
142 }
143
144