slesTestSawtoothBufferQueue.cpp revision 086a6f51a7b12880ed114962136972f89ed70da2
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#include <stdlib.h> 41#include <stdio.h> 42#include <string.h> 43#include <unistd.h> 44#include <sys/time.h> 45 46 47#include <SLES/OpenSLES.h> 48 49 50#define MAX_NUMBER_INTERFACES 3 51 52/* Local storage for Audio data in 16 bit words */ 53#define AUDIO_DATA_STORAGE_SIZE 4096 * 100 54/* Audio data buffer size in 16 bit words. 8 data segments are used in 55this simple example */ 56#define AUDIO_DATA_BUFFER_SIZE 4096/8 57 58/* Checks for error. If any errors exit the application! */ 59void CheckErr( SLresult res ) 60{ 61 if ( res != SL_RESULT_SUCCESS ) 62 { 63 fprintf(stdout, "%u SL failure, exiting\n", res); 64 exit(EXIT_FAILURE); 65 } 66 else { 67 //fprintf(stdout, "%d SL success, proceeding...\n", res); 68 } 69} 70 71/* Structure for passing information to callback function */ 72typedef struct CallbackCntxt_ { 73 SLPlayItf playItf; 74 SLint16* pDataBase; // Base adress of local audio data storage 75 SLint16* pData; // Current adress of local audio data storage 76 SLuint32 size; 77} CallbackCntxt; 78 79/* Local storage for Audio data */ 80SLint16 pcmData[AUDIO_DATA_STORAGE_SIZE]; 81 82/* Callback for Buffer Queue events */ 83void BufferQueueCallback( 84 SLBufferQueueItf queueItf, 85 void *pContext) 86{ 87 //fprintf(stdout, "BufferQueueCallback called\n"); 88 SLresult res; 89 //fprintf(stdout, " pContext=%p\n", pContext); 90 CallbackCntxt *pCntxt = (CallbackCntxt*)pContext; 91 92 if(pCntxt->pData < (pCntxt->pDataBase + pCntxt->size)) 93 { 94 //fprintf(stdout, "callback: before enqueue\n"); 95 res = (*queueItf)->Enqueue(queueItf, (void*) pCntxt->pData, 96 2 * AUDIO_DATA_BUFFER_SIZE); /* Size given in bytes. */ 97 CheckErr(res); 98 /* Increase data pointer by buffer size */ 99 pCntxt->pData += AUDIO_DATA_BUFFER_SIZE; 100 } 101 //fprintf(stdout, "end of BufferQueueCallback()\n"); 102} 103 104/* Play some audio from a buffer queue */ 105void TestPlaySawtoothBufferQueue( SLObjectItf sl ) 106{ 107 SLEngineItf EngineItf; 108 109 SLint32 numOutputs = 0; 110 SLuint32 deviceID = 0; 111 112 SLresult res; 113 114 SLDataSource audioSource; 115 SLDataLocator_BufferQueue bufferQueue; 116 SLDataFormat_PCM pcm; 117 118 SLDataSink audioSink; 119 SLDataLocator_OutputMix locator_outputmix; 120 121 SLObjectItf player; 122 SLPlayItf playItf; 123 SLBufferQueueItf bufferQueueItf; 124 SLBufferQueueState state; 125 126 SLObjectItf OutputMix; 127 SLVolumeItf volumeItf; 128 129 int i; 130 131 SLboolean required[MAX_NUMBER_INTERFACES]; 132 SLInterfaceID iidArray[MAX_NUMBER_INTERFACES]; 133 134 /* Callback context for the buffer queue callback function */ 135 CallbackCntxt cntxt; 136 137 /* Get the SL Engine Interface which is implicit */ 138 res = (*sl)->GetInterface(sl, SL_IID_ENGINE, (void*)&EngineItf); 139 CheckErr(res); 140 141 /* Initialize arrays required[] and iidArray[] */ 142 for (i=0;i<MAX_NUMBER_INTERFACES;i++) 143 { 144 required[i] = SL_BOOLEAN_FALSE; 145 iidArray[i] = SL_IID_NULL; 146 } 147 148 // Set arrays required[] and iidArray[] for VOLUME interface 149 required[0] = SL_BOOLEAN_TRUE; 150 iidArray[0] = SL_IID_VOLUME; 151 // Create Output Mix object to be used by player 152 res = (*EngineItf)->CreateOutputMix(EngineItf, &OutputMix, 0, 153 iidArray, required); CheckErr(res); 154 155 // Realizing the Output Mix object in synchronous mode. 156 res = (*OutputMix)->Realize(OutputMix, SL_BOOLEAN_FALSE); 157 CheckErr(res); 158 159#if 0 160 res = (*OutputMix)->GetInterface(OutputMix, SL_IID_VOLUME, 161 (void*)&volumeItf); CheckErr(res); 162#endif 163 164 /* Setup the data source structure for the buffer queue */ 165 bufferQueue.locatorType = SL_DATALOCATOR_BUFFERQUEUE; 166 bufferQueue.numBuffers = 4; /* Four buffers in our buffer queue */ 167 168 /* Setup the format of the content in the buffer queue */ 169 pcm.formatType = SL_DATAFORMAT_PCM; 170 pcm.numChannels = 1;//2; 171 pcm.samplesPerSec = SL_SAMPLINGRATE_44_1; 172 pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16; 173 pcm.containerSize = 16; 174 pcm.channelMask = SL_SPEAKER_FRONT_LEFT;// | SL_SPEAKER_FRONT_RIGHT; 175 pcm.endianness = SL_BYTEORDER_LITTLEENDIAN; 176 177 audioSource.pFormat = (void *)&pcm; 178 audioSource.pLocator = (void *)&bufferQueue; 179 180 /* Setup the data sink structure */ 181 locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX; 182 locator_outputmix.outputMix = OutputMix; 183 audioSink.pLocator = (void *)&locator_outputmix; 184 audioSink.pFormat = NULL; 185 186 /* Initialize the audio data to play */ 187 unsigned int j; 188 for (j = 0; j < sizeof(pcmData)/sizeof(pcmData[0]); ++j) { 189 pcmData[j] = j*(100 + j / 200);// % 1000; 190 } 191 192 /* Initialize the context for Buffer queue callbacks */ 193 cntxt.pDataBase = /*(void*)&*/pcmData; 194 cntxt.pData = cntxt.pDataBase; 195 cntxt.size = sizeof(pcmData) / 2; 196 197 /* Set arrays required[] and iidArray[] for SEEK interface 198 (PlayItf is implicit) */ 199 required[0] = SL_BOOLEAN_TRUE; 200 iidArray[0] = SL_IID_BUFFERQUEUE; 201 202 /* Create the music player */ 203 res = (*EngineItf)->CreateAudioPlayer(EngineItf, &player, 204 &audioSource, &audioSink, 1, iidArray, required); CheckErr(res); 205 fprintf(stdout, "bufferQueue example: after CreateAudioPlayer\n"); 206 207 /* Realizing the player in synchronous mode. */ 208 res = (*player)->Realize(player, SL_BOOLEAN_FALSE); CheckErr(res); 209 fprintf(stdout, "bufferQueue example: after Realize\n"); 210 211 /* Get seek and play interfaces */ 212 res = (*player)->GetInterface(player, SL_IID_PLAY, (void*)&playItf); 213 CheckErr(res); 214 fprintf(stdout, "bufferQueue example: after GetInterface(PLAY)\n"); 215 216 res = (*player)->GetInterface(player, SL_IID_BUFFERQUEUE, 217 (void*)&bufferQueueItf); CheckErr(res); 218 219 /* Setup to receive buffer queue event callbacks */ 220 res = (*bufferQueueItf)->RegisterCallback(bufferQueueItf, 221 BufferQueueCallback, &cntxt); CheckErr(res); 222 223#if 0 224 /* Before we start set volume to -3dB (-300mB) */ 225 res = (*volumeItf)->SetVolumeLevel(volumeItf, -300); CheckErr(res); 226#endif 227 228 /* Enqueue a few buffers to get the ball rolling */ 229 res = (*bufferQueueItf)->Enqueue(bufferQueueItf, cntxt.pData, 230 2 * AUDIO_DATA_BUFFER_SIZE); /* Size given in bytes. */ 231 CheckErr(res); 232 cntxt.pData += AUDIO_DATA_BUFFER_SIZE; 233 234 res = (*bufferQueueItf)->Enqueue(bufferQueueItf, cntxt.pData, 235 2 * AUDIO_DATA_BUFFER_SIZE); /* Size given in bytes. */ 236 CheckErr(res); 237 cntxt.pData += AUDIO_DATA_BUFFER_SIZE; 238 239 res = (*bufferQueueItf)->Enqueue(bufferQueueItf, cntxt.pData, 240 2 * AUDIO_DATA_BUFFER_SIZE); /* Size given in bytes. */ 241 CheckErr(res); 242 cntxt.pData += AUDIO_DATA_BUFFER_SIZE; 243 244 /* Play the PCM samples using a buffer queue */ 245 fprintf(stdout, "bufferQueue example: starting to play\n"); 246 res = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PLAYING ); 247 CheckErr(res); 248 249 /* Wait until the PCM data is done playing, the buffer queue callback 250 will continue to queue buffers until the entire PCM data has been 251 played. This is indicated by waiting for the count member of the 252 SLBufferQueueState to go to zero. 253 */ 254 res = (*bufferQueueItf)->GetState(bufferQueueItf, &state); 255 CheckErr(res); 256 257 // while (state.playIndex < 100) { 258 while (state.count) { 259 usleep(10000); 260 (*bufferQueueItf)->GetState(bufferQueueItf, &state); 261 } 262 263 /* Make sure player is stopped */ 264 res = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED); 265 CheckErr(res); 266 /* Destroy the player */ 267 (*player)->Destroy(player); 268 269 /* Destroy Output Mix object */ 270 (*OutputMix)->Destroy(OutputMix); 271} 272 273 274 275int main(int argc __unused, char* const argv[] __unused) 276{ 277 SLresult res; 278 SLObjectItf sl; 279 280 SLEngineOption EngineOption[] = { 281 {(SLuint32) SL_ENGINEOPTION_THREADSAFE, 282 (SLuint32) SL_BOOLEAN_TRUE}}; 283 284 res = slCreateEngine( &sl, 1, EngineOption, 0, NULL, NULL); 285 CheckErr(res); 286 /* Realizing the SL Engine in synchronous mode. */ 287 res = (*sl)->Realize(sl, SL_BOOLEAN_FALSE); CheckErr(res); 288 289 /* Run the test */ 290 TestPlaySawtoothBufferQueue(sl); 291 292 /* Shutdown OpenSL ES */ 293 (*sl)->Destroy(sl); 294 295 return EXIT_SUCCESS; 296} 297