1 /*
2 * Copyright (C) 2016 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 sine waves using AAudio.
18
19 #include <aaudio/AAudio.h>
20 #include <aaudio/AAudioTesting.h>
21 #include <asm/fcntl.h>
22 #include <fcntl.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26
27 #include "AAudioExampleUtils.h"
28 #include "AAudioSimplePlayer.h"
29 #include "AAudioArgsParser.h"
30
31 #define NUM_SECONDS 4
32
main(int argc,const char ** argv)33 int main(int argc, const char **argv)
34 {
35 AAudioArgsParser argParser;
36 AAudioSimplePlayer player;
37 SineThreadedData_t myData;
38 aaudio_result_t result = AAUDIO_OK;
39
40 int32_t actualChannelCount = 0;
41 int32_t actualSampleRate = 0;
42 aaudio_format_t actualDataFormat = AAUDIO_FORMAT_UNSPECIFIED;
43
44 AAudioStream *aaudioStream = nullptr;
45 int32_t framesPerBurst = 0;
46 int32_t framesPerWrite = 0;
47 int32_t framesToPlay = 0;
48 int32_t framesLeft = 0;
49 int32_t xRunCount = 0;
50 int numActiveOscillators = 0;
51 float *floatData = nullptr;
52 int16_t *shortData = nullptr;
53 int32_t *int32Data = nullptr;
54 uint8_t *byteData = nullptr;
55
56 int testFd = -1;
57
58 // Make printf print immediately so that debug info is not stuck
59 // in a buffer if we hang or crash.
60 setvbuf(stdout, nullptr, _IONBF, (size_t) 0);
61
62 printf("%s - Play a sine wave using AAudio V0.1.4\n", argv[0]);
63
64 if (argParser.parseArgs(argc, argv)) {
65 return EXIT_FAILURE;
66 }
67
68 result = player.open(argParser);
69 if (result != AAUDIO_OK) {
70 fprintf(stderr, "ERROR - player.open() returned %d\n", result);
71 goto finish;
72 }
73
74 aaudioStream = player.getStream();
75
76 argParser.compareWithStream(aaudioStream);
77
78 actualChannelCount = AAudioStream_getChannelCount(aaudioStream);
79 actualSampleRate = AAudioStream_getSampleRate(aaudioStream);
80 actualDataFormat = AAudioStream_getFormat(aaudioStream);
81
82 myData.sampleRate = actualSampleRate;
83 myData.setupSineSweeps();
84
85 // Some DMA might use very short bursts of 16 frames. We don't need to write such small
86 // buffers. But it helps to use a multiple of the burst size for predictable scheduling.
87 framesPerBurst = AAudioStream_getFramesPerBurst(aaudioStream);
88 framesPerWrite = framesPerBurst;
89 while (framesPerWrite < 48) {
90 framesPerWrite *= 2;
91 }
92 printf("Buffer: framesPerBurst = %d\n",framesPerBurst);
93 printf("Buffer: framesPerWrite = %d\n",framesPerWrite);
94
95 // Allocate a buffer for the audio data.
96 switch (actualDataFormat) {
97 case AAUDIO_FORMAT_PCM_FLOAT:
98 floatData = new float[framesPerWrite * actualChannelCount];
99 break;
100 case AAUDIO_FORMAT_PCM_I16:
101 shortData = new int16_t[framesPerWrite * actualChannelCount];
102 break;
103 case AAUDIO_FORMAT_PCM_I24_PACKED:
104 byteData = new uint8_t[framesPerWrite * actualChannelCount
105 * getBytesPerSample(AAUDIO_FORMAT_PCM_I24_PACKED)];
106 break;
107 case AAUDIO_FORMAT_PCM_I32:
108 int32Data = new int32_t[framesPerWrite * actualChannelCount];
109 break;
110 default:
111 printf("ERROR Unsupported data format!\n");
112 goto finish;
113 }
114
115 testFd = open("/data/aaudio_temp.raw", O_CREAT | O_RDWR, S_IRWXU);
116 printf("testFd = %d, pid = %d\n", testFd, getpid());
117
118 // Start the stream.
119 printf("call player.start()\n");
120 result = player.start();
121 if (result != AAUDIO_OK) {
122 fprintf(stderr, "ERROR - AAudioStream_requestStart() returned %d\n", result);
123 goto finish;
124 }
125
126 printf("after start, state = %s\n",
127 AAudio_convertStreamStateToText(AAudioStream_getState(aaudioStream)));
128
129 // Play for a while.
130 framesToPlay = actualSampleRate * argParser.getDurationSeconds();
131 framesLeft = framesToPlay;
132 numActiveOscillators = (actualChannelCount > MAX_CHANNELS) ? MAX_CHANNELS : actualChannelCount;
133 while (framesLeft > 0) {
134 // Render as FLOAT or PCM
135 switch (actualDataFormat) {
136 case AAUDIO_FORMAT_PCM_FLOAT:
137 for (int i = 0; i < numActiveOscillators; ++i) {
138 myData.sineOscillators[i].render(&floatData[i], actualChannelCount,
139 framesPerWrite);
140 }
141 break;
142 case AAUDIO_FORMAT_PCM_I16:
143 for (int i = 0; i < numActiveOscillators; ++i) {
144 myData.sineOscillators[i].render(&shortData[i], actualChannelCount,
145 framesPerWrite);
146 }
147 break;
148 case AAUDIO_FORMAT_PCM_I32:
149 for (int i = 0; i < numActiveOscillators; ++i) {
150 myData.sineOscillators[i].render(&int32Data[i], actualChannelCount,
151 framesPerWrite);
152 }
153 break;
154 case AAUDIO_FORMAT_PCM_I24_PACKED:
155 for (int i = 0; i < numActiveOscillators; ++i) {
156 static const int
157 bytesPerSample = getBytesPerSample(AAUDIO_FORMAT_PCM_I24_PACKED);
158 myData.sineOscillators[i].render24(&byteData[i * bytesPerSample],
159 actualChannelCount,
160 framesPerWrite);
161 }
162 break;
163 }
164
165 // Write audio data to the stream.
166 int64_t timeoutNanos = 1000 * NANOS_PER_MILLISECOND;
167 int32_t minFrames = (framesToPlay < framesPerWrite) ? framesToPlay : framesPerWrite;
168 int32_t actual = 0;
169 switch (actualDataFormat) {
170 case AAUDIO_FORMAT_PCM_FLOAT:
171 actual = AAudioStream_write(aaudioStream, floatData, minFrames, timeoutNanos);
172 break;
173 case AAUDIO_FORMAT_PCM_I16:
174 actual = AAudioStream_write(aaudioStream, shortData, minFrames, timeoutNanos);
175 break;
176 case AAUDIO_FORMAT_PCM_I32:
177 actual = AAudioStream_write(aaudioStream, int32Data, minFrames, timeoutNanos);
178 break;
179 case AAUDIO_FORMAT_PCM_I24_PACKED:
180 actual = AAudioStream_write(aaudioStream, byteData, minFrames, timeoutNanos);
181 break;
182 }
183 if (actual < 0) {
184 fprintf(stderr, "ERROR - AAudioStream_write() returned %d\n", actual);
185 goto finish;
186 } else if (actual == 0) {
187 fprintf(stderr, "WARNING - AAudioStream_write() returned %d\n", actual);
188 goto finish;
189 }
190 framesLeft -= actual;
191
192 // Use timestamp to estimate latency.
193 /*
194 {
195 int64_t presentationFrame;
196 int64_t presentationTime;
197 result = AAudioStream_getTimestamp(aaudioStream,
198 CLOCK_MONOTONIC,
199 &presentationFrame,
200 &presentationTime
201 );
202 if (result == AAUDIO_OK) {
203 int64_t elapsedNanos = getNanoseconds() - presentationTime;
204 int64_t elapsedFrames = actualSampleRate * elapsedNanos / NANOS_PER_SECOND;
205 int64_t currentFrame = presentationFrame + elapsedFrames;
206 int64_t framesWritten = AAudioStream_getFramesWritten(aaudioStream);
207 int64_t estimatedLatencyFrames = framesWritten - currentFrame;
208 int64_t estimatedLatencyMillis = estimatedLatencyFrames * 1000 / actualSampleRate;
209 printf("estimatedLatencyMillis %d\n", (int)estimatedLatencyMillis);
210 }
211 }
212 */
213 }
214
215 xRunCount = AAudioStream_getXRunCount(aaudioStream);
216 printf("AAudioStream_getXRunCount %d\n", xRunCount);
217
218 printf("call stop()\n");
219 result = player.stop();
220 if (result != AAUDIO_OK) {
221 goto finish;
222 }
223
224 finish:
225 printf("testFd = %d, fcntl before aaudio close returns 0x%08X\n",
226 testFd, fcntl(testFd, F_GETFD));
227 player.close();
228 printf("testFd = %d, fcntl after aaudio close returns 0x%08X\n",
229 testFd, fcntl(testFd, F_GETFD));
230 if (::close(testFd) != 0) {
231 printf("ERROR SharedMemoryParcelable::close() of testFd = %d, errno = %s\n",
232 testFd, strerror(errno));
233 }
234 printf("testFd = %d, fcntl after close() returns 0x%08X\n", testFd, fcntl(testFd, F_GETFD));
235
236 delete[] floatData;
237 delete[] shortData;
238 delete[] int32Data;
239 delete[] byteData;
240 printf("exiting - AAudio result = %d = %s\n", result, AAudio_convertResultToText(result));
241 return (result != AAUDIO_OK) ? EXIT_FAILURE : EXIT_SUCCESS;
242 }
243
244