Home | History | Annotate | Download | only in examples
      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! */
     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 */
     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  */
    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 
    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