Home | History | Annotate | Download | only in src
      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 
     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, V0.1.2\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