slesTestSawtoothBufferQueue.cpp revision 527b7d2e606abdbde0e29fe75f7e9a67285629d2
1/* 2 * Copyright (C) 2010 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/* 18 * Copyright (c) 2009 The Khronos Group Inc. 19 * 20 * Permission is hereby granted, free of charge, to any person obtaining a copy of this 21 * software and /or associated documentation files (the "Materials "), to deal in the 22 * Materials without restriction, including without limitation the rights to use, copy, 23 * modify, merge, publish, distribute, sublicense, and/or sell copies of the Materials, 24 * and to permit persons to whom the Materials are furnished to do so, subject to 25 * the following conditions: 26 * 27 * The above copyright notice and this permission notice shall be included 28 * in all copies or substantial portions of the Materials. 29 * 30 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 31 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 32 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 33 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 34 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 35 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 36 * CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS IN THE 37 * MATERIALS. 38 */ 39 40#define LOG_NDEBUG 0 41#define LOG_TAG "Sawtooth" 42 43#ifdef ANDROID 44#include <utils/Log.h> 45#else 46#define LOGV printf 47#endif 48 49#include <getopt.h> 50#include <stdlib.h> 51#include <stdio.h> 52#include <string.h> 53#include <unistd.h> 54#include <sys/time.h> 55 56 57#include "SLES/OpenSLES.h" 58 59/*using namespace android;*/ 60 61#define SLEEP(x) /* Client system sleep function to sleep x milliseconds 62would replace SLEEP macro */ 63 64#define MAX_NUMBER_INTERFACES 3 65#define MAX_NUMBER_OUTPUT_DEVICES 6 66 67/* Local storage for Audio data in 16 bit words */ 68#define AUDIO_DATA_STORAGE_SIZE 4096 * 100 69/* Audio data buffer size in 16 bit words. 8 data segments are used in 70this simple example */ 71#define AUDIO_DATA_BUFFER_SIZE 4096/8 72 73/* Checks for error. If any errors exit the application! */ 74void CheckErr( SLresult res ) 75{ 76 if ( res != SL_RESULT_SUCCESS ) 77 { 78 fprintf(stdout, "%lu SL failure, exiting\n", res); 79 exit(1); 80 } 81 else { 82 //fprintf(stdout, "%d SL success, proceeding...\n", res); 83 } 84} 85 86/* Structure for passing information to callback function */ 87typedef struct CallbackCntxt_ { 88 SLPlayItf playItf; 89 SLint16* pDataBase; // Base adress of local audio data storage 90 SLint16* pData; // Current adress of local audio data storage 91 SLuint32 size; 92} CallbackCntxt; 93 94/* Local storage for Audio data */ 95SLint16 pcmData[AUDIO_DATA_STORAGE_SIZE]; 96 97/* Callback for Buffer Queue events */ 98void BufferQueueCallback( 99 SLBufferQueueItf queueItf, 100 void *pContext) 101{ 102 //fprintf(stdout, "BufferQueueCallback called\n"); 103 SLresult res; 104 //fprintf(stdout, " pContext=%p\n", pContext); 105 CallbackCntxt *pCntxt = (CallbackCntxt*)pContext; 106 107 if(pCntxt->pData < (pCntxt->pDataBase + pCntxt->size)) 108 { 109 //fprintf(stdout, "callback: before enqueue\n"); 110 res = (*queueItf)->Enqueue(queueItf, (void*) pCntxt->pData, 111 2 * AUDIO_DATA_BUFFER_SIZE); /* Size given in bytes. */ 112 CheckErr(res); 113 /* Increase data pointer by buffer size */ 114 pCntxt->pData += AUDIO_DATA_BUFFER_SIZE; 115 } 116 //fprintf(stdout, "end of BufferQueueCallback()\n"); 117} 118 119/* Play some audio from a buffer queue */ 120void TestPlaySawtoothBufferQueue( SLObjectItf sl ) 121{ 122 SLEngineItf EngineItf; 123 124 SLint32 numOutputs = 0; 125 SLuint32 deviceID = 0; 126 127 SLresult res; 128 129 SLDataSource audioSource; 130 SLDataLocator_BufferQueue bufferQueue; 131 SLDataFormat_PCM pcm; 132 133 SLDataSink audioSink; 134 SLDataLocator_OutputMix locator_outputmix; 135 136 SLObjectItf player; 137 SLPlayItf playItf; 138 SLBufferQueueItf bufferQueueItf; 139 SLBufferQueueState state; 140 141 SLObjectItf OutputMix; 142 SLVolumeItf volumeItf; 143 144 int i; 145 146 SLboolean required[MAX_NUMBER_INTERFACES]; 147 SLInterfaceID iidArray[MAX_NUMBER_INTERFACES]; 148 149 /* Callback context for the buffer queue callback function */ 150 CallbackCntxt cntxt; 151 152 /* Get the SL Engine Interface which is implicit */ 153 res = (*sl)->GetInterface(sl, SL_IID_ENGINE, (void*)&EngineItf); 154 CheckErr(res); 155 156 /* Initialize arrays required[] and iidArray[] */ 157 for (i=0;i<MAX_NUMBER_INTERFACES;i++) 158 { 159 required[i] = SL_BOOLEAN_FALSE; 160 iidArray[i] = SL_IID_NULL; 161 } 162 163 // Set arrays required[] and iidArray[] for VOLUME interface 164 required[0] = SL_BOOLEAN_TRUE; 165 iidArray[0] = SL_IID_VOLUME; 166 // Create Output Mix object to be used by player 167 res = (*EngineItf)->CreateOutputMix(EngineItf, &OutputMix, 1, 168 iidArray, required); CheckErr(res); 169 170 // Realizing the Output Mix object in synchronous mode. 171 res = (*OutputMix)->Realize(OutputMix, SL_BOOLEAN_FALSE); 172 CheckErr(res); 173 174 res = (*OutputMix)->GetInterface(OutputMix, SL_IID_VOLUME, 175 (void*)&volumeItf); CheckErr(res); 176 177 /* Setup the data source structure for the buffer queue */ 178 bufferQueue.locatorType = SL_DATALOCATOR_BUFFERQUEUE; 179 bufferQueue.numBuffers = 4; /* Four buffers in our buffer queue */ 180 181 /* Setup the format of the content in the buffer queue */ 182 pcm.formatType = SL_DATAFORMAT_PCM; 183 pcm.numChannels = 1;//2; 184 pcm.samplesPerSec = SL_SAMPLINGRATE_44_1; 185 pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16; 186 pcm.containerSize = 16; 187 pcm.channelMask = SL_SPEAKER_FRONT_LEFT;// | SL_SPEAKER_FRONT_RIGHT; 188 pcm.endianness = SL_BYTEORDER_LITTLEENDIAN; 189 190 audioSource.pFormat = (void *)&pcm; 191 audioSource.pLocator = (void *)&bufferQueue; 192 193 /* Setup the data sink structure */ 194 locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX; 195 locator_outputmix.outputMix = OutputMix; 196 audioSink.pLocator = (void *)&locator_outputmix; 197 audioSink.pFormat = NULL; 198 199 /* Initialize the audio data to play */ 200 unsigned int j; 201 for (j = 0; j < sizeof(pcmData)/sizeof(pcmData[0]); ++j) { 202 pcmData[j] = j*(100 + j / 200);// % 1000; 203 } 204 205 /* Initialize the context for Buffer queue callbacks */ 206 cntxt.pDataBase = /*(void*)&*/pcmData; 207 cntxt.pData = cntxt.pDataBase; 208 cntxt.size = sizeof(pcmData) / 2; 209 210 /* Set arrays required[] and iidArray[] for SEEK interface 211 (PlayItf is implicit) */ 212 required[0] = SL_BOOLEAN_TRUE; 213 iidArray[0] = SL_IID_BUFFERQUEUE; 214 215 /* Create the music player */ 216 res = (*EngineItf)->CreateAudioPlayer(EngineItf, &player, 217 &audioSource, &audioSink, 1, iidArray, required); CheckErr(res); 218 fprintf(stdout, "bufferQueue example: after CreateAudioPlayer\n"); 219 220 /* Realizing the player in synchronous mode. */ 221 res = (*player)->Realize(player, SL_BOOLEAN_FALSE); CheckErr(res); 222 fprintf(stdout, "bufferQueue example: after Realize\n"); 223 224 /* Get seek and play interfaces */ 225 res = (*player)->GetInterface(player, SL_IID_PLAY, (void*)&playItf); 226 CheckErr(res); 227 fprintf(stdout, "bufferQueue example: after GetInterface(PLAY)\n"); 228 229 res = (*player)->GetInterface(player, SL_IID_BUFFERQUEUE, 230 (void*)&bufferQueueItf); CheckErr(res); 231 232 /* Setup to receive buffer queue event callbacks */ 233 res = (*bufferQueueItf)->RegisterCallback(bufferQueueItf, 234 BufferQueueCallback, &cntxt); CheckErr(res); 235 236 /* Before we start set volume to -3dB (-300mB) */ 237 res = (*volumeItf)->SetVolumeLevel(volumeItf, -300); CheckErr(res); 238 239 /* Enqueue a few buffers to get the ball rolling */ 240 res = (*bufferQueueItf)->Enqueue(bufferQueueItf, cntxt.pData, 241 2 * AUDIO_DATA_BUFFER_SIZE); /* Size given in bytes. */ 242 CheckErr(res); 243 cntxt.pData += AUDIO_DATA_BUFFER_SIZE; 244 245 res = (*bufferQueueItf)->Enqueue(bufferQueueItf, cntxt.pData, 246 2 * AUDIO_DATA_BUFFER_SIZE); /* Size given in bytes. */ 247 CheckErr(res); 248 cntxt.pData += AUDIO_DATA_BUFFER_SIZE; 249 250 res = (*bufferQueueItf)->Enqueue(bufferQueueItf, cntxt.pData, 251 2 * AUDIO_DATA_BUFFER_SIZE); /* Size given in bytes. */ 252 CheckErr(res); 253 cntxt.pData += AUDIO_DATA_BUFFER_SIZE; 254 255 /* Play the PCM samples using a buffer queue */ 256 fprintf(stdout, "bufferQueue example: starting to play\n"); 257 res = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PLAYING ); 258 CheckErr(res); 259 260 /* Wait until the PCM data is done playing, the buffer queue callback 261 will continue to queue buffers until the entire PCM data has been 262 played. This is indicated by waiting for the count member of the 263 SLBufferQueueState to go to zero. 264 */ 265 res = (*bufferQueueItf)->GetState(bufferQueueItf, &state); 266 CheckErr(res); 267 268 // while (state.playIndex < 100) { 269 while (state.count) { 270 usleep(10000); 271 (*bufferQueueItf)->GetState(bufferQueueItf, &state); 272 } 273 274 /* Make sure player is stopped */ 275 res = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED); 276 CheckErr(res); 277 /* Destroy the player */ 278 (*player)->Destroy(player); 279 280 /* Destroy Output Mix object */ 281 (*OutputMix)->Destroy(OutputMix); 282} 283 284 285 286int main(int argc, char* const argv[]) 287{ 288 LOGV("Starting sawtoothPlayer\n"); 289 290 SLresult res; 291 SLObjectItf sl; 292 293 SLEngineOption EngineOption[] = { 294 {(SLuint32) SL_ENGINEOPTION_THREADSAFE, 295 (SLuint32) SL_BOOLEAN_TRUE}}; 296 297 res = slCreateEngine( &sl, 1, EngineOption, 0, NULL, NULL); 298 CheckErr(res); 299 /* Realizing the SL Engine in synchronous mode. */ 300 res = (*sl)->Realize(sl, SL_BOOLEAN_FALSE); CheckErr(res); 301 302 /* Run the test */ 303 TestPlaySawtoothBufferQueue(sl); 304 305 /* Shutdown OpenSL ES */ 306 (*sl)->Destroy(sl); 307 exit(0); 308 309 310 return 0; 311} 312