write_sine.cpp revision 3316d5e6d375a4f09c681205e9094d30a0bfc4a2
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 <stdio.h> 20#include <stdlib.h> 21#include <math.h> 22#include <aaudio/AAudioDefinitions.h> 23#include <aaudio/AAudio.h> 24#include "SineGenerator.h" 25 26#define SAMPLE_RATE 48000 27#define NUM_SECONDS 10 28#define NANOS_PER_MICROSECOND ((int64_t)1000) 29#define NANOS_PER_MILLISECOND (NANOS_PER_MICROSECOND * 1000) 30 31static const char *getSharingModeText(aaudio_sharing_mode_t mode) { 32 const char *modeText = "unknown"; 33 switch (mode) { 34 case AAUDIO_SHARING_MODE_EXCLUSIVE: 35 modeText = "EXCLUSIVE"; 36 break; 37 case AAUDIO_SHARING_MODE_SHARED: 38 modeText = "SHARED"; 39 break; 40 default: 41 break; 42 } 43 return modeText; 44} 45 46int main(int argc, char **argv) 47{ 48 (void)argc; // unused 49 50 aaudio_result_t result = AAUDIO_OK; 51 52 const int requestedSamplesPerFrame = 2; 53 int actualSamplesPerFrame = 0; 54 const int requestedSampleRate = SAMPLE_RATE; 55 int actualSampleRate = 0; 56 const aaudio_audio_format_t requestedDataFormat = AAUDIO_FORMAT_PCM_I16; 57 aaudio_audio_format_t actualDataFormat = AAUDIO_FORMAT_PCM_I16; 58 59 const aaudio_sharing_mode_t requestedSharingMode = AAUDIO_SHARING_MODE_EXCLUSIVE; 60 aaudio_sharing_mode_t actualSharingMode = AAUDIO_SHARING_MODE_SHARED; 61 62 AAudioStreamBuilder aaudioBuilder = nullptr; 63 AAudioStream aaudioStream = nullptr; 64 aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNINITIALIZED; 65 int32_t framesPerBurst = 0; 66 int32_t framesToPlay = 0; 67 int32_t framesLeft = 0; 68 int32_t xRunCount = 0; 69 int16_t *data = nullptr; 70 71 SineGenerator sineOsc1; 72 SineGenerator sineOsc2; 73 74 // Make printf print immediately so that debug info is not stuck 75 // in a buffer if we hang or crash. 76 setvbuf(stdout, nullptr, _IONBF, (size_t) 0); 77 78 printf("%s - Play a sine wave using AAudio\n", argv[0]); 79 80 // Use an AAudioStreamBuilder to contain requested parameters. 81 result = AAudio_createStreamBuilder(&aaudioBuilder); 82 if (result != AAUDIO_OK) { 83 goto finish; 84 } 85 86 // Request stream properties. 87 AAudioStreamBuilder_setSampleRate(aaudioBuilder, requestedSampleRate); 88 AAudioStreamBuilder_setSamplesPerFrame(aaudioBuilder, requestedSamplesPerFrame); 89 AAudioStreamBuilder_setFormat(aaudioBuilder, requestedDataFormat); 90 AAudioStreamBuilder_setSharingMode(aaudioBuilder, requestedSharingMode); 91 92 93 // Create an AAudioStream using the Builder. 94 result = AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream); 95 if (result != AAUDIO_OK) { 96 goto finish; 97 } 98 99 state = AAudioStream_getState(aaudioStream); 100 printf("after open, state = %s\n", AAudio_convertStreamStateToText(state)); 101 102 // Check to see what kind of stream we actually got. 103 actualSampleRate = AAudioStream_getSampleRate(aaudioStream); 104 printf("SampleRate: requested = %d, actual = %d\n", requestedSampleRate, actualSampleRate); 105 106 sineOsc1.setup(440.0, actualSampleRate); 107 sineOsc2.setup(660.0, actualSampleRate); 108 109 actualSamplesPerFrame = AAudioStream_getSamplesPerFrame(aaudioStream); 110 printf("SamplesPerFrame: requested = %d, actual = %d\n", 111 requestedSamplesPerFrame, actualSamplesPerFrame); 112 113 actualSharingMode = AAudioStream_getSharingMode(aaudioStream); 114 printf("SharingMode: requested = %s, actual = %s\n", 115 getSharingModeText(requestedSharingMode), 116 getSharingModeText(actualSharingMode)); 117 118 // This is the number of frames that are read in one chunk by a DMA controller 119 // or a DSP or a mixer. 120 framesPerBurst = AAudioStream_getFramesPerBurst(aaudioStream); 121 printf("DataFormat: original framesPerBurst = %d\n",framesPerBurst); 122 123 // Some DMA might use very short bursts of 16 frames. We don't need to write such small 124 // buffers. But it helps to use a multiple of the burst size for predictable scheduling. 125 while (framesPerBurst < 48) { 126 framesPerBurst *= 2; 127 } 128 printf("DataFormat: final framesPerBurst = %d\n",framesPerBurst); 129 130 actualDataFormat = AAudioStream_getFormat(aaudioStream); 131 printf("DataFormat: requested = %d, actual = %d\n", requestedDataFormat, actualDataFormat); 132 // TODO handle other data formats 133 134 // Allocate a buffer for the audio data. 135 data = new int16_t[framesPerBurst * actualSamplesPerFrame]; 136 if (data == nullptr) { 137 fprintf(stderr, "ERROR - could not allocate data buffer\n"); 138 result = AAUDIO_ERROR_NO_MEMORY; 139 goto finish; 140 } 141 142 // Start the stream. 143 printf("call AAudioStream_requestStart()\n"); 144 result = AAudioStream_requestStart(aaudioStream); 145 if (result != AAUDIO_OK) { 146 fprintf(stderr, "ERROR - AAudioStream_requestStart() returned %d\n", result); 147 goto finish; 148 } 149 150 state = AAudioStream_getState(aaudioStream); 151 printf("after start, state = %s\n", AAudio_convertStreamStateToText(state)); 152 153 // Play for a while. 154 framesToPlay = actualSampleRate * NUM_SECONDS; 155 framesLeft = framesToPlay; 156 while (framesLeft > 0) { 157 // Render sine waves to left and right channels. 158 sineOsc1.render(&data[0], actualSamplesPerFrame, framesPerBurst); 159 if (actualSamplesPerFrame > 1) { 160 sineOsc2.render(&data[1], actualSamplesPerFrame, framesPerBurst); 161 } 162 163 // Write audio data to the stream. 164 int64_t timeoutNanos = 100 * NANOS_PER_MILLISECOND; 165 int minFrames = (framesToPlay < framesPerBurst) ? framesToPlay : framesPerBurst; 166 int actual = AAudioStream_write(aaudioStream, data, minFrames, timeoutNanos); 167 if (actual < 0) { 168 fprintf(stderr, "ERROR - AAudioStream_write() returned %zd\n", actual); 169 goto finish; 170 } else if (actual == 0) { 171 fprintf(stderr, "WARNING - AAudioStream_write() returned %zd\n", actual); 172 goto finish; 173 } 174 framesLeft -= actual; 175 } 176 177 xRunCount = AAudioStream_getXRunCount(aaudioStream); 178 printf("AAudioStream_getXRunCount %d\n", xRunCount); 179 180finish: 181 delete[] data; 182 AAudioStream_close(aaudioStream); 183 AAudioStreamBuilder_delete(aaudioBuilder); 184 printf("exiting - AAudio result = %d = %s\n", result, AAudio_convertResultToText(result)); 185 return (result != AAUDIO_OK) ? EXIT_FAILURE : EXIT_SUCCESS; 186} 187 188