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// Play silence and recover from dead servers or disconnected devices.
18
19#include <stdio.h>
20
21#include <aaudio/AAudio.h>
22
23
24#define DEFAULT_TIMEOUT_NANOS  ((int64_t)1000000000)
25
26int main(int argc, char **argv) {
27    (void) argc;
28    (void) argv;
29
30    aaudio_result_t result = AAUDIO_OK;
31
32    int32_t triesLeft = 3;
33    int32_t bufferCapacity;
34    int32_t framesPerBurst = 0;
35    float *buffer = nullptr;
36
37    int32_t actualChannelCount = 0;
38    int32_t actualSampleRate = 0;
39    aaudio_format_t actualDataFormat = AAUDIO_FORMAT_PCM_FLOAT;
40
41    AAudioStreamBuilder *aaudioBuilder = nullptr;
42    AAudioStream *aaudioStream = nullptr;
43
44    // Make printf print immediately so that debug info is not stuck
45    // in a buffer if we hang or crash.
46    setvbuf(stdout, nullptr, _IONBF, (size_t) 0);
47
48    printf("TestRecovery:\n");
49
50    // Use an AAudioStreamBuilder to contain requested parameters.
51    result = AAudio_createStreamBuilder(&aaudioBuilder);
52    if (result != AAUDIO_OK) {
53        printf("AAudio_createStreamBuilder returned %s",
54               AAudio_convertResultToText(result));
55        goto finish;
56    }
57
58    // Request stream properties.
59    AAudioStreamBuilder_setFormat(aaudioBuilder, AAUDIO_FORMAT_PCM_FLOAT);
60
61    while (triesLeft-- > 0) {
62        // Create an AAudioStream using the Builder.
63        result = AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream);
64        if (result != AAUDIO_OK) {
65            printf("AAudioStreamBuilder_openStream returned %s",
66                   AAudio_convertResultToText(result));
67            goto finish;
68        }
69
70        // Check to see what kind of stream we actually got.
71        actualSampleRate = AAudioStream_getSampleRate(aaudioStream);
72        actualChannelCount = AAudioStream_getChannelCount(aaudioStream);
73        actualDataFormat = AAudioStream_getFormat(aaudioStream);
74
75        printf("-------- chans = %3d, rate = %6d format = %d\n",
76                actualChannelCount, actualSampleRate, actualDataFormat);
77
78        // This is the number of frames that are read in one chunk by a DMA controller
79        // or a DSP or a mixer.
80        framesPerBurst = AAudioStream_getFramesPerBurst(aaudioStream);
81        bufferCapacity = AAudioStream_getBufferCapacityInFrames(aaudioStream);
82        printf("         bufferCapacity = %d, framesPerBurst = %d\n",
83        bufferCapacity, framesPerBurst);
84
85        int samplesPerBurst = framesPerBurst * actualChannelCount;
86        buffer = new float[samplesPerBurst];
87
88        result = AAudioStream_requestStart(aaudioStream);
89        if (result != AAUDIO_OK) {
90            printf("AAudioStream_requestStart returned %s",
91                   AAudio_convertResultToText(result));
92            goto finish;
93        }
94
95        // Play silence for awhile.
96        int32_t framesMax = actualSampleRate * 20;
97        int64_t framesTotal = 0;
98        int64_t printAt = actualSampleRate;
99        while (result == AAUDIO_OK && framesTotal < framesMax) {
100            int32_t framesWritten = AAudioStream_write(aaudioStream,
101                                                       buffer, framesPerBurst,
102                                                       DEFAULT_TIMEOUT_NANOS);
103            if (framesWritten < 0) {
104                result = framesWritten;
105                printf("write() returned %s, frames = %d\n",
106                       AAudio_convertResultToText(result), (int)framesTotal);
107                printf("  frames = %d\n", (int)framesTotal);
108            } else if (framesWritten != framesPerBurst) {
109                printf("write() returned %d, frames = %d\n", framesWritten, (int)framesTotal);
110                result = AAUDIO_ERROR_TIMEOUT;
111            } else {
112                framesTotal += framesWritten;
113                if (framesTotal >= printAt) {
114                    printf("frames = %d\n", (int)framesTotal);
115                    printAt += actualSampleRate;
116                }
117            }
118        }
119        result = AAudioStream_requestStop(aaudioStream);
120        if (result != AAUDIO_OK) {
121            printf("AAudioStream_requestStop returned %s\n",
122                   AAudio_convertResultToText(result));
123        }
124        result = AAudioStream_close(aaudioStream);
125        if (result != AAUDIO_OK) {
126            printf("AAudioStream_close returned %s\n",
127                   AAudio_convertResultToText(result));
128        }
129        aaudioStream = nullptr;
130    }
131
132finish:
133    if (aaudioStream != nullptr) {
134        AAudioStream_close(aaudioStream);
135    }
136    AAudioStreamBuilder_delete(aaudioBuilder);
137    delete[] buffer;
138    printf("          result = %d = %s\n", result, AAudio_convertResultToText(result));
139}
140