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
55 this simple example */
56 #define AUDIO_DATA_BUFFER_SIZE 4096/8
57
58 /* Checks for error. If any errors exit the application! */
CheckErr(SLresult res)59 void 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 */
72 typedef 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 */
80 SLint16 pcmData[AUDIO_DATA_STORAGE_SIZE];
81
82 /* Callback for Buffer Queue events */
BufferQueueCallback(SLBufferQueueItf queueItf,void * pContext)83 void 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 */
TestPlaySawtoothBufferQueue(SLObjectItf sl)105 void 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
main(int argc,char * const argv[])275 int main(int argc, char* const argv[])
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