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 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
main(int argc __unused,char * const argv[]__unused)272 int 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