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     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 
    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