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 #include <stdlib.h>
     18 #include <stdio.h>
     19 #include <string.h>
     20 #include <unistd.h>
     21 #include <sys/time.h>
     22 #include <fcntl.h>
     23 
     24 #include "SLES/OpenSLES.h"
     25 #ifdef ANDROID
     26 #include "SLES/OpenSLES_Android.h"
     27 #endif
     28 
     29 
     30 #define MAX_NUMBER_INTERFACES 3
     31 
     32 #define TIME_S_BETWEEN_VIRT_ON_OFF 3
     33 
     34 //-----------------------------------------------------------------
     35 /* Exits the application if an error is encountered */
     36 #define ExitOnError(x) ExitOnErrorFunc(x,__LINE__)
     37 
     38 void ExitOnErrorFunc( SLresult result , int line)
     39 {
     40     if (SL_RESULT_SUCCESS != result) {
     41         fprintf(stderr, "%lu error code encountered at line %d, exiting\n", result, line);
     42         exit(EXIT_FAILURE);
     43     }
     44 }
     45 
     46 
     47 //-----------------------------------------------------------------
     48 
     49 /* Play an audio path by opening a file descriptor on that path  */
     50 void TestVirtualizerPathFromFD( SLObjectItf sl, const char* path, int16_t virtStrength)
     51 {
     52     SLresult  result;
     53     SLEngineItf EngineItf;
     54 
     55     /* Objects this application uses: one player and an ouput mix */
     56     SLObjectItf  player, outputMix;
     57 
     58     /* Source of audio data to play */
     59     SLDataSource            audioSource;
     60 #ifdef ANDROID
     61     SLDataLocator_AndroidFD locatorFd;
     62 #else
     63     SLDataLocator_URI       locatorUri;
     64 #endif
     65     SLDataFormat_MIME       mime;
     66 
     67     /* Data sinks for the audio player */
     68     SLDataSink               audioSink;
     69     SLDataLocator_OutputMix  locator_outputmix;
     70 
     71     /* Play and PrefetchStatus interfaces for the audio player */
     72     SLPlayItf              playItf;
     73     SLPrefetchStatusItf    prefetchItf;
     74     SLVirtualizerItf       virtItf;
     75 
     76     SLboolean required[MAX_NUMBER_INTERFACES];
     77     SLInterfaceID iidArray[MAX_NUMBER_INTERFACES];
     78 
     79     /* Get the SL Engine Interface which is implicit */
     80     result = (*sl)->GetInterface(sl, SL_IID_ENGINE, (void*)&EngineItf);
     81     ExitOnError(result);
     82 
     83     /* Initialize arrays required[] and iidArray[] */
     84     for (int i=0 ; i < MAX_NUMBER_INTERFACES ; i++) {
     85         required[i] = SL_BOOLEAN_FALSE;
     86         iidArray[i] = SL_IID_NULL;
     87     }
     88 
     89     /* ------------------------------------------------------ */
     90     /* Configuration of the output mix  */
     91 
     92     /* Create Output Mix object to be used by the player */
     93      result = (*EngineItf)->CreateOutputMix(EngineItf, &outputMix, 0, iidArray, required);
     94      ExitOnError(result);
     95 
     96     /* Realize the Output Mix object in synchronous mode */
     97     result = (*outputMix)->Realize(outputMix, SL_BOOLEAN_FALSE);
     98     ExitOnError(result);
     99 
    100     /* Setup the data sink structure */
    101     locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
    102     locator_outputmix.outputMix   = outputMix;
    103     audioSink.pLocator            = (void*)&locator_outputmix;
    104     audioSink.pFormat             = NULL;
    105 
    106     /* ------------------------------------------------------ */
    107     /* Configuration of the player  */
    108 
    109     /* Set arrays required[] and iidArray[] for SLPrefetchStatusItf interfaces */
    110     /*  (SLPlayItf is implicit) */
    111     required[0] = SL_BOOLEAN_TRUE;
    112     iidArray[0] = SL_IID_PREFETCHSTATUS;
    113     required[1] = SL_BOOLEAN_TRUE;
    114     iidArray[1] = SL_IID_VIRTUALIZER;
    115 
    116 #ifdef ANDROID
    117     /* Setup the data source structure for the URI */
    118     locatorFd.locatorType = SL_DATALOCATOR_ANDROIDFD;
    119     int fd = open(path, O_RDONLY);
    120     if (fd == -1) {
    121         ExitOnError(SL_RESULT_RESOURCE_ERROR);
    122     }
    123     locatorFd.fd = (SLint32) fd;
    124     locatorFd.length = SL_DATALOCATOR_ANDROIDFD_USE_FILE_SIZE;
    125     locatorFd.offset = 0;
    126 #else
    127     locatorUri.locatorType = SL_DATALOCATOR_URI;
    128     locatorUri.URI = (SLchar *) path;
    129 #endif
    130 
    131     mime.formatType = SL_DATAFORMAT_MIME;
    132     /*     this is how ignored mime information is specified, according to OpenSL ES spec
    133      *     in 9.1.6 SLDataFormat_MIME and 8.23 SLMetadataTraversalItf GetChildInfo */
    134     mime.mimeType      = (SLchar*)NULL;
    135     mime.containerType = SL_CONTAINERTYPE_UNSPECIFIED;
    136 
    137     audioSource.pFormat  = (void*)&mime;
    138 #ifdef ANDROID
    139     audioSource.pLocator = (void*)&locatorFd;
    140 #else
    141     audioSource.pLocator = (void*)&locatorUri;
    142 #endif
    143 
    144     /* Create the audio player */
    145     result = (*EngineItf)->CreateAudioPlayer(EngineItf, &player, &audioSource, &audioSink, 2,
    146             iidArray, required);
    147     ExitOnError(result);
    148 
    149     /* Realize the player in synchronous mode. */
    150     result = (*player)->Realize(player, SL_BOOLEAN_FALSE); ExitOnError(result);
    151     fprintf(stdout, "URI example: after Realize\n");
    152 
    153     /* Get the SLPlayItf, SLPrefetchStatusItf and SLAndroidStreamTypeItf interfaces for the player*/
    154     result = (*player)->GetInterface(player, SL_IID_PLAY, (void*)&playItf);
    155     ExitOnError(result);
    156 
    157     result = (*player)->GetInterface(player, SL_IID_PREFETCHSTATUS, (void*)&prefetchItf);
    158     ExitOnError(result);
    159 
    160     result = (*player)->GetInterface(player, SL_IID_VIRTUALIZER, (void*)&virtItf);
    161     ExitOnError(result);
    162 
    163     fprintf(stdout, "Player configured\n");
    164 
    165     /* ------------------------------------------------------ */
    166     /* Playback and test */
    167 
    168     /* Start the data prefetching by setting the player to the paused state */
    169     result = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PAUSED );
    170     ExitOnError(result);
    171 
    172     /* Wait until there's data to play */
    173     SLuint32 prefetchStatus = SL_PREFETCHSTATUS_UNDERFLOW;
    174     while (prefetchStatus != SL_PREFETCHSTATUS_SUFFICIENTDATA) {
    175         usleep(100 * 1000);
    176         (*prefetchItf)->GetPrefetchStatus(prefetchItf, &prefetchStatus);
    177         ExitOnError(result);
    178     }
    179 
    180     /* Get duration */
    181     SLmillisecond durationInMsec = SL_TIME_UNKNOWN;
    182     result = (*playItf)->GetDuration(playItf, &durationInMsec);
    183     ExitOnError(result);
    184     if (durationInMsec == SL_TIME_UNKNOWN) {
    185         durationInMsec = 5000;
    186     }
    187 
    188     /* Start playback */
    189     fprintf(stdout, "Starting to play\n");
    190     result = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PLAYING );
    191     ExitOnError(result);
    192 
    193     /* Configure Virtualizer */
    194     SLboolean strengthSupported = SL_BOOLEAN_FALSE;
    195     result = (*virtItf)->IsStrengthSupported(virtItf, &strengthSupported);
    196     ExitOnError(result);
    197     if (SL_BOOLEAN_FALSE == strengthSupported) {
    198         fprintf(stdout, "Virtualizer strength is not supported on this platform. Too bad!\n");
    199     } else {
    200         fprintf(stdout, "Virtualizer strength is supported, setting strength to %d\n",
    201                 virtStrength);
    202         result = (*virtItf)->SetStrength(virtItf, virtStrength);
    203         ExitOnError(result);
    204     }
    205 
    206     SLpermille strength = 0;
    207     result = (*virtItf)->GetRoundedStrength(virtItf, &strength);
    208     ExitOnError(result);
    209     fprintf(stdout, "Rounded strength of virt = %d\n", strength);
    210 
    211 
    212     /* Switch Virtualizer on/off every TIME_S_BETWEEN_VIRT_ON_OFF seconds */
    213     SLboolean enabled = SL_BOOLEAN_TRUE;
    214     result = (*virtItf)->SetEnabled(virtItf, enabled);
    215     ExitOnError(result);
    216     for(unsigned int j=0 ; j<(durationInMsec/(1000*TIME_S_BETWEEN_VIRT_ON_OFF)) ; j++) {
    217         usleep(TIME_S_BETWEEN_VIRT_ON_OFF * 1000 * 1000);
    218         result = (*virtItf)->IsEnabled(virtItf, &enabled);
    219         ExitOnError(result);
    220         enabled = enabled == SL_BOOLEAN_TRUE ? SL_BOOLEAN_FALSE : SL_BOOLEAN_TRUE;
    221         result = (*virtItf)->SetEnabled(virtItf, enabled);
    222         if (SL_BOOLEAN_TRUE == enabled) {
    223             fprintf(stdout, "Virtualizer on\n");
    224         } else {
    225             fprintf(stdout, "Virtualizer off\n");
    226         }
    227         ExitOnError(result);
    228     }
    229 
    230     /* Make sure player is stopped */
    231     fprintf(stdout, "Stopping playback\n");
    232     result = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED);
    233     ExitOnError(result);
    234 
    235     /* Destroy the player */
    236     (*player)->Destroy(player);
    237 
    238     /* Destroy Output Mix object */
    239     (*outputMix)->Destroy(outputMix);
    240 
    241 #ifdef ANDROID
    242     close(fd);
    243 #endif
    244 }
    245 
    246 //-----------------------------------------------------------------
    247 int main(int argc, char* const argv[])
    248 {
    249     SLresult    result;
    250     SLObjectItf sl;
    251 
    252     fprintf(stdout, "OpenSL ES test %s: exercises SLVirtualizerItf ", argv[0]);
    253     fprintf(stdout, "and AudioPlayer with SLDataLocator_AndroidFD source / OutputMix sink\n");
    254     fprintf(stdout, "Plays the sound file designated by the given path, ");
    255     fprintf(stdout, "and applies a virtualization effect of the specified strength,\n");
    256     fprintf(stdout, "where strength is an integer value between 0 and 1000.\n");
    257     fprintf(stdout, "Every %d seconds, the Virtualizer will be turned on and off.\n",
    258             TIME_S_BETWEEN_VIRT_ON_OFF);
    259 
    260     if (argc < 3) {
    261         fprintf(stdout, "Usage: \t%s path virtualization_strength\n", argv[0]);
    262         fprintf(stdout, "Example: \"%s /sdcard/my.mp3 1000\" \n", argv[0]);
    263         exit(EXIT_FAILURE);
    264     }
    265 
    266     SLEngineOption EngineOption[] = {
    267             {(SLuint32) SL_ENGINEOPTION_THREADSAFE, (SLuint32) SL_BOOLEAN_TRUE}
    268     };
    269 
    270     result = slCreateEngine( &sl, 1, EngineOption, 0, NULL, NULL);
    271     ExitOnError(result);
    272 
    273     /* Realizing the SL Engine in synchronous mode. */
    274     result = (*sl)->Realize(sl, SL_BOOLEAN_FALSE);
    275     ExitOnError(result);
    276 
    277     // intentionally not checking that argv[2], the virtualizer strength, is between 0 and 1000
    278     TestVirtualizerPathFromFD(sl, argv[1], (int16_t)atoi(argv[2]));
    279 
    280     /* Shutdown OpenSL ES */
    281     (*sl)->Destroy(sl);
    282 
    283     return EXIT_SUCCESS;
    284 }
    285