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