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