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 33int 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 numActiveOscilators = 0; 51 float *floatData = nullptr; 52 int16_t *shortData = nullptr; 53 54 int testFd = -1; 55 56 // Make printf print immediately so that debug info is not stuck 57 // in a buffer if we hang or crash. 58 setvbuf(stdout, nullptr, _IONBF, (size_t) 0); 59 60 printf("%s - Play a sine wave using AAudio V0.1.3\n", argv[0]); 61 62 if (argParser.parseArgs(argc, argv)) { 63 return EXIT_FAILURE; 64 } 65 66 result = player.open(argParser); 67 if (result != AAUDIO_OK) { 68 fprintf(stderr, "ERROR - player.open() returned %d\n", result); 69 goto finish; 70 } 71 72 aaudioStream = player.getStream(); 73 74 argParser.compareWithStream(aaudioStream); 75 76 actualChannelCount = AAudioStream_getChannelCount(aaudioStream); 77 actualSampleRate = AAudioStream_getSampleRate(aaudioStream); 78 actualDataFormat = AAudioStream_getFormat(aaudioStream); 79 80 myData.sampleRate = actualSampleRate; 81 myData.setupSineSweeps(); 82 83 // Some DMA might use very short bursts of 16 frames. We don't need to write such small 84 // buffers. But it helps to use a multiple of the burst size for predictable scheduling. 85 framesPerBurst = AAudioStream_getFramesPerBurst(aaudioStream); 86 framesPerWrite = framesPerBurst; 87 while (framesPerWrite < 48) { 88 framesPerWrite *= 2; 89 } 90 printf("Buffer: framesPerBurst = %d\n",framesPerBurst); 91 printf("Buffer: framesPerWrite = %d\n",framesPerWrite); 92 93 // Allocate a buffer for the audio data. 94 if (actualDataFormat == AAUDIO_FORMAT_PCM_FLOAT) { 95 floatData = new float[framesPerWrite * actualChannelCount]; 96 } else if (actualDataFormat == AAUDIO_FORMAT_PCM_I16) { 97 shortData = new int16_t[framesPerWrite * actualChannelCount]; 98 } else { 99 printf("ERROR Unsupported data format!\n"); 100 goto finish; 101 } 102 103 testFd = open("/data/aaudio_temp.raw", O_CREAT | O_RDWR, S_IRWXU); 104 printf("testFd = %d, pid = %d\n", testFd, getpid()); 105 106 // Start the stream. 107 printf("call player.start()\n"); 108 result = player.start(); 109 if (result != AAUDIO_OK) { 110 fprintf(stderr, "ERROR - AAudioStream_requestStart() returned %d\n", result); 111 goto finish; 112 } 113 114 printf("after start, state = %s\n", 115 AAudio_convertStreamStateToText(AAudioStream_getState(aaudioStream))); 116 117 // Play for a while. 118 framesToPlay = actualSampleRate * argParser.getDurationSeconds(); 119 framesLeft = framesToPlay; 120 numActiveOscilators = (actualChannelCount > MAX_CHANNELS) ? MAX_CHANNELS : actualChannelCount; 121 while (framesLeft > 0) { 122 // Render as FLOAT or PCM 123 if (actualDataFormat == AAUDIO_FORMAT_PCM_FLOAT) { 124 for (int i = 0; i < numActiveOscilators; ++i) { 125 myData.sineOscillators[i].render(&floatData[i], actualChannelCount, 126 framesPerWrite); 127 } 128 } else if (actualDataFormat == AAUDIO_FORMAT_PCM_I16) { 129 for (int i = 0; i < numActiveOscilators; ++i) { 130 myData.sineOscillators[i].render(&shortData[i], actualChannelCount, 131 framesPerWrite); 132 } 133 } 134 135 // Write audio data to the stream. 136 int64_t timeoutNanos = 1000 * NANOS_PER_MILLISECOND; 137 int32_t minFrames = (framesToPlay < framesPerWrite) ? framesToPlay : framesPerWrite; 138 int32_t actual = 0; 139 if (actualDataFormat == AAUDIO_FORMAT_PCM_FLOAT) { 140 actual = AAudioStream_write(aaudioStream, floatData, minFrames, timeoutNanos); 141 } else if (actualDataFormat == AAUDIO_FORMAT_PCM_I16) { 142 actual = AAudioStream_write(aaudioStream, shortData, minFrames, timeoutNanos); 143 } 144 if (actual < 0) { 145 fprintf(stderr, "ERROR - AAudioStream_write() returned %d\n", actual); 146 goto finish; 147 } else if (actual == 0) { 148 fprintf(stderr, "WARNING - AAudioStream_write() returned %d\n", actual); 149 goto finish; 150 } 151 framesLeft -= actual; 152 153 // Use timestamp to estimate latency. 154 /* 155 { 156 int64_t presentationFrame; 157 int64_t presentationTime; 158 result = AAudioStream_getTimestamp(aaudioStream, 159 CLOCK_MONOTONIC, 160 &presentationFrame, 161 &presentationTime 162 ); 163 if (result == AAUDIO_OK) { 164 int64_t elapsedNanos = getNanoseconds() - presentationTime; 165 int64_t elapsedFrames = actualSampleRate * elapsedNanos / NANOS_PER_SECOND; 166 int64_t currentFrame = presentationFrame + elapsedFrames; 167 int64_t framesWritten = AAudioStream_getFramesWritten(aaudioStream); 168 int64_t estimatedLatencyFrames = framesWritten - currentFrame; 169 int64_t estimatedLatencyMillis = estimatedLatencyFrames * 1000 / actualSampleRate; 170 printf("estimatedLatencyMillis %d\n", (int)estimatedLatencyMillis); 171 } 172 } 173 */ 174 } 175 176 xRunCount = AAudioStream_getXRunCount(aaudioStream); 177 printf("AAudioStream_getXRunCount %d\n", xRunCount); 178 179 printf("call stop()\n"); 180 result = player.stop(); 181 if (result != AAUDIO_OK) { 182 goto finish; 183 } 184 185finish: 186 printf("testFd = %d, fcntl before aaudio close returns 0x%08X\n", 187 testFd, fcntl(testFd, F_GETFD)); 188 player.close(); 189 printf("testFd = %d, fcntl after aaudio close returns 0x%08X\n", 190 testFd, fcntl(testFd, F_GETFD)); 191 if (::close(testFd) != 0) { 192 printf("ERROR SharedMemoryParcelable::close() of testFd = %d, errno = %s\n", 193 testFd, strerror(errno)); 194 } 195 printf("testFd = %d, fcntl after close() returns 0x%08X\n", testFd, fcntl(testFd, F_GETFD)); 196 197 delete[] floatData; 198 delete[] shortData; 199 printf("exiting - AAudio result = %d = %s\n", result, AAudio_convertResultToText(result)); 200 return (result != AAUDIO_OK) ? EXIT_FAILURE : EXIT_SUCCESS; 201} 202 203