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 
29 #define NUM_SECONDS           5
30 
main(int argc,char ** argv)31 int main(int argc, char **argv)
32 {
33     (void)argc; // unused
34     AAudioSimpleRecorder recorder;
35     PeakTrackerData_t myData = {0.0};
36     aaudio_result_t result;
37     aaudio_stream_state_t state;
38     const int displayRateHz = 20; // arbitrary
39     const int loopsNeeded = NUM_SECONDS * displayRateHz;
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\n", argv[0]);
45 
46     result = recorder.open(2, 48000, AAUDIO_FORMAT_PCM_I16,
47                        SimpleRecorderDataCallbackProc, SimpleRecorderErrorCallbackProc, &myData);
48     if (result != AAUDIO_OK) {
49         fprintf(stderr, "ERROR -  recorder.open() returned %d\n", result);
50         goto error;
51     }
52     printf("recorder.getFramesPerSecond() = %d\n", recorder.getFramesPerSecond());
53     printf("recorder.getSamplesPerFrame() = %d\n", recorder.getSamplesPerFrame());
54 
55     result = recorder.start();
56     if (result != AAUDIO_OK) {
57         fprintf(stderr, "ERROR -  recorder.start() returned %d\n", result);
58         goto error;
59     }
60 
61     printf("Sleep for %d seconds while audio record in a callback thread.\n", NUM_SECONDS);
62     for (int i = 0; i < loopsNeeded; i++)
63     {
64         const struct timespec request = { .tv_sec = 0,
65                 .tv_nsec = NANOS_PER_SECOND / displayRateHz };
66         (void) clock_nanosleep(CLOCK_MONOTONIC, 0 /*flags*/, &request, NULL /*remain*/);
67         printf("%08d: ", (int)recorder.getFramesRead());
68         displayPeakLevel(myData.peakLevel);
69 
70         result = AAudioStream_waitForStateChange(recorder.getStream(),
71                                                  AAUDIO_STREAM_STATE_CLOSED,
72                                                  &state,
73                                                  0);
74         if (result != AAUDIO_OK) {
75             fprintf(stderr, "ERROR - AAudioStream_waitForStateChange() returned %d\n", result);
76             goto error;
77         }
78         if (state != AAUDIO_STREAM_STATE_STARTING && state != AAUDIO_STREAM_STATE_STARTED) {
79             printf("Stream state is %d %s!\n", state, AAudio_convertStreamStateToText(state));
80             break;
81         }
82     }
83     printf("Woke up. Stop for a moment.\n");
84 
85     result = recorder.stop();
86     if (result != AAUDIO_OK) {
87         goto error;
88     }
89     usleep(2000 * 1000);
90     result = recorder.start();
91     if (result != AAUDIO_OK) {
92         fprintf(stderr, "ERROR -  recorder.start() returned %d\n", result);
93         goto error;
94     }
95 
96     printf("Sleep for %d seconds while audio records in a callback thread.\n", NUM_SECONDS);
97     for (int i = 0; i < loopsNeeded; i++)
98     {
99         const struct timespec request = { .tv_sec = 0,
100                 .tv_nsec = NANOS_PER_SECOND / displayRateHz };
101         (void) clock_nanosleep(CLOCK_MONOTONIC, 0 /*flags*/, &request, NULL /*remain*/);
102         printf("%08d: ", (int)recorder.getFramesRead());
103         displayPeakLevel(myData.peakLevel);
104 
105         state = AAudioStream_getState(recorder.getStream());
106         if (state != AAUDIO_STREAM_STATE_STARTING && state != AAUDIO_STREAM_STATE_STARTED) {
107             printf("Stream state is %d %s!\n", state, AAudio_convertStreamStateToText(state));
108             break;
109         }
110     }
111     printf("Woke up now.\n");
112 
113     result = recorder.stop();
114     if (result != AAUDIO_OK) {
115         goto error;
116     }
117     result = recorder.close();
118     if (result != AAUDIO_OK) {
119         goto error;
120     }
121 
122     printf("SUCCESS\n");
123     return EXIT_SUCCESS;
124 error:
125     recorder.close();
126     printf("exiting - AAudio result = %d = %s\n", result, AAudio_convertResultToText(result));
127     return EXIT_FAILURE;
128 }
129 
130