• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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