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 SLresult res; 110 111 SLDataSource audioSource; 112 SLDataLocator_BufferQueue bufferQueue; 113 SLDataFormat_PCM pcm; 114 115 SLDataSink audioSink; 116 SLDataLocator_OutputMix locator_outputmix; 117 118 SLObjectItf player; 119 SLPlayItf playItf; 120 SLBufferQueueItf bufferQueueItf; 121 SLBufferQueueState state; 122 123 SLObjectItf OutputMix; 124 //SLVolumeItf volumeItf; 125 126 int i; 127 128 SLboolean required[MAX_NUMBER_INTERFACES]; 129 SLInterfaceID iidArray[MAX_NUMBER_INTERFACES]; 130 131 /* Callback context for the buffer queue callback function */ 132 CallbackCntxt cntxt; 133 134 /* Get the SL Engine Interface which is implicit */ 135 res = (*sl)->GetInterface(sl, SL_IID_ENGINE, (void*)&EngineItf); 136 CheckErr(res); 137 138 /* Initialize arrays required[] and iidArray[] */ 139 for (i=0;i<MAX_NUMBER_INTERFACES;i++) 140 { 141 required[i] = SL_BOOLEAN_FALSE; 142 iidArray[i] = SL_IID_NULL; 143 } 144 145 // Set arrays required[] and iidArray[] for VOLUME interface 146 required[0] = SL_BOOLEAN_TRUE; 147 iidArray[0] = SL_IID_VOLUME; 148 // Create Output Mix object to be used by player 149 res = (*EngineItf)->CreateOutputMix(EngineItf, &OutputMix, 0, 150 iidArray, required); CheckErr(res); 151 152 // Realizing the Output Mix object in synchronous mode. 153 res = (*OutputMix)->Realize(OutputMix, SL_BOOLEAN_FALSE); 154 CheckErr(res); 155 156#if 0 157 res = (*OutputMix)->GetInterface(OutputMix, SL_IID_VOLUME, 158 (void*)&volumeItf); CheckErr(res); 159#endif 160 161 /* Setup the data source structure for the buffer queue */ 162 bufferQueue.locatorType = SL_DATALOCATOR_BUFFERQUEUE; 163 bufferQueue.numBuffers = 4; /* Four buffers in our buffer queue */ 164 165 /* Setup the format of the content in the buffer queue */ 166 pcm.formatType = SL_DATAFORMAT_PCM; 167 pcm.numChannels = 1;//2; 168 pcm.samplesPerSec = SL_SAMPLINGRATE_44_1; 169 pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16; 170 pcm.containerSize = 16; 171 pcm.channelMask = SL_SPEAKER_FRONT_LEFT;// | SL_SPEAKER_FRONT_RIGHT; 172 pcm.endianness = SL_BYTEORDER_LITTLEENDIAN; 173 174 audioSource.pFormat = (void *)&pcm; 175 audioSource.pLocator = (void *)&bufferQueue; 176 177 /* Setup the data sink structure */ 178 locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX; 179 locator_outputmix.outputMix = OutputMix; 180 audioSink.pLocator = (void *)&locator_outputmix; 181 audioSink.pFormat = NULL; 182 183 /* Initialize the audio data to play */ 184 unsigned int j; 185 for (j = 0; j < sizeof(pcmData)/sizeof(pcmData[0]); ++j) { 186 pcmData[j] = j*(100 + j / 200);// % 1000; 187 } 188 189 /* Initialize the context for Buffer queue callbacks */ 190 cntxt.pDataBase = /*(void*)&*/pcmData; 191 cntxt.pData = cntxt.pDataBase; 192 cntxt.size = sizeof(pcmData) / 2; 193 194 /* Set arrays required[] and iidArray[] for SEEK interface 195 (PlayItf is implicit) */ 196 required[0] = SL_BOOLEAN_TRUE; 197 iidArray[0] = SL_IID_BUFFERQUEUE; 198 199 /* Create the music player */ 200 res = (*EngineItf)->CreateAudioPlayer(EngineItf, &player, 201 &audioSource, &audioSink, 1, iidArray, required); CheckErr(res); 202 fprintf(stdout, "bufferQueue example: after CreateAudioPlayer\n"); 203 204 /* Realizing the player in synchronous mode. */ 205 res = (*player)->Realize(player, SL_BOOLEAN_FALSE); CheckErr(res); 206 fprintf(stdout, "bufferQueue example: after Realize\n"); 207 208 /* Get seek and play interfaces */ 209 res = (*player)->GetInterface(player, SL_IID_PLAY, (void*)&playItf); 210 CheckErr(res); 211 fprintf(stdout, "bufferQueue example: after GetInterface(PLAY)\n"); 212 213 res = (*player)->GetInterface(player, SL_IID_BUFFERQUEUE, 214 (void*)&bufferQueueItf); CheckErr(res); 215 216 /* Setup to receive buffer queue event callbacks */ 217 res = (*bufferQueueItf)->RegisterCallback(bufferQueueItf, 218 BufferQueueCallback, &cntxt); CheckErr(res); 219 220#if 0 221 /* Before we start set volume to -3dB (-300mB) */ 222 res = (*volumeItf)->SetVolumeLevel(volumeItf, -300); CheckErr(res); 223#endif 224 225 /* Enqueue a few buffers to get the ball rolling */ 226 res = (*bufferQueueItf)->Enqueue(bufferQueueItf, cntxt.pData, 227 2 * AUDIO_DATA_BUFFER_SIZE); /* Size given in bytes. */ 228 CheckErr(res); 229 cntxt.pData += AUDIO_DATA_BUFFER_SIZE; 230 231 res = (*bufferQueueItf)->Enqueue(bufferQueueItf, cntxt.pData, 232 2 * AUDIO_DATA_BUFFER_SIZE); /* Size given in bytes. */ 233 CheckErr(res); 234 cntxt.pData += AUDIO_DATA_BUFFER_SIZE; 235 236 res = (*bufferQueueItf)->Enqueue(bufferQueueItf, cntxt.pData, 237 2 * AUDIO_DATA_BUFFER_SIZE); /* Size given in bytes. */ 238 CheckErr(res); 239 cntxt.pData += AUDIO_DATA_BUFFER_SIZE; 240 241 /* Play the PCM samples using a buffer queue */ 242 fprintf(stdout, "bufferQueue example: starting to play\n"); 243 res = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PLAYING ); 244 CheckErr(res); 245 246 /* Wait until the PCM data is done playing, the buffer queue callback 247 will continue to queue buffers until the entire PCM data has been 248 played. This is indicated by waiting for the count member of the 249 SLBufferQueueState to go to zero. 250 */ 251 res = (*bufferQueueItf)->GetState(bufferQueueItf, &state); 252 CheckErr(res); 253 254 // while (state.playIndex < 100) { 255 while (state.count) { 256 usleep(10000); 257 (*bufferQueueItf)->GetState(bufferQueueItf, &state); 258 } 259 260 /* Make sure player is stopped */ 261 res = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED); 262 CheckErr(res); 263 /* Destroy the player */ 264 (*player)->Destroy(player); 265 266 /* Destroy Output Mix object */ 267 (*OutputMix)->Destroy(OutputMix); 268} 269 270 271 272int main(int argc __unused, char* const argv[] __unused) 273{ 274 SLresult res; 275 SLObjectItf sl; 276 277 SLEngineOption EngineOption[] = { 278 {(SLuint32) SL_ENGINEOPTION_THREADSAFE, 279 (SLuint32) SL_BOOLEAN_TRUE}}; 280 281 res = slCreateEngine( &sl, 1, EngineOption, 0, NULL, NULL); 282 CheckErr(res); 283 /* Realizing the SL Engine in synchronous mode. */ 284 res = (*sl)->Realize(sl, SL_BOOLEAN_FALSE); CheckErr(res); 285 286 /* Run the test */ 287 TestPlaySawtoothBufferQueue(sl); 288 289 /* Shutdown OpenSL ES */ 290 (*sl)->Destroy(sl); 291 292 return EXIT_SUCCESS; 293} 294