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_BB_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 TestBassBoostPathFromFD(SLObjectItf sl, const char* path, int16_t boostStrength, bool alwaysOn)
     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     /* Interfaces for the audio player */
     72     SLPlayItf              playItf;
     73     SLPrefetchStatusItf    prefetchItf;
     74     SLBassBoostItf         bbItf;
     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, 1, 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 required 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_BASSBOOST;
    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 SLBassBoostItf 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_BASSBOOST, (void*)&bbItf);
    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 BassBoost */
    194     SLboolean strengthSupported = SL_BOOLEAN_FALSE;
    195     result = (*bbItf)->IsStrengthSupported(bbItf, &strengthSupported);
    196     ExitOnError(result);
    197     if (SL_BOOLEAN_FALSE == strengthSupported) {
    198         fprintf(stdout, "BassBoost strength is not supported on this platform. Too bad!\n");
    199     } else {
    200         fprintf(stdout, "BassBoost strength is supported, setting strength to %d\n", boostStrength);
    201         result = (*bbItf)->SetStrength(bbItf, boostStrength);
    202         ExitOnError(result);
    203     }
    204 
    205     SLpermille strength = 0;
    206     result = (*bbItf)->GetRoundedStrength(bbItf, &strength);
    207     ExitOnError(result);
    208     fprintf(stdout, "Rounded strength of boost = %d\n", strength);
    209 
    210 
    211     /* Switch BassBoost on/off every TIME_S_BETWEEN_BB_ON_OFF seconds unless always on */
    212     SLboolean previousEnabled = SL_BOOLEAN_FALSE;
    213     for(unsigned int j=0 ; j<(durationInMsec/(1000*TIME_S_BETWEEN_BB_ON_OFF)) ; j++) {
    214         SLboolean enabled;
    215         result = (*bbItf)->IsEnabled(bbItf, &enabled);
    216         ExitOnError(result);
    217         enabled = alwaysOn || !enabled;
    218         if (enabled != previousEnabled) {
    219             result = (*bbItf)->SetEnabled(bbItf, enabled);
    220             ExitOnError(result);
    221             previousEnabled = enabled;
    222             if (SL_BOOLEAN_TRUE == enabled) {
    223                 fprintf(stdout, "BassBoost on\n");
    224             } else {
    225                 fprintf(stdout, "BassBoost off\n");
    226             }
    227         }
    228         usleep(TIME_S_BETWEEN_BB_ON_OFF * 1000 * 1000);
    229     }
    230 
    231     /* Make sure player is stopped */
    232     fprintf(stdout, "Stopping playback\n");
    233     result = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED);
    234     ExitOnError(result);
    235 
    236     /* Destroy the player */
    237     (*player)->Destroy(player);
    238 
    239     /* Destroy Output Mix object */
    240     (*outputMix)->Destroy(outputMix);
    241 
    242 #ifdef ANDROID
    243     close(fd);
    244 #endif
    245 }
    246 
    247 //-----------------------------------------------------------------
    248 int main(int argc, char* const argv[])
    249 {
    250     const char *programName = argv[0];
    251     SLresult    result;
    252     SLObjectItf sl;
    253 
    254     fprintf(stdout, "OpenSL ES test %s: exercises SLBassBoostItf ", programName);
    255     fprintf(stdout, "and AudioPlayer with SLDataLocator_AndroidFD source / OutputMix sink\n");
    256     fprintf(stdout, "Plays the sound file designated by the given path, ");
    257     fprintf(stdout, "and applies a bass boost effect of the specified strength,\n");
    258     fprintf(stdout, "where strength is a integer value between 0 and 1000.\n");
    259     fprintf(stdout, "Every %d seconds, the BassBoost will be turned on and off,\n",
    260             TIME_S_BETWEEN_BB_ON_OFF);
    261     fprintf(stdout, "unless the --always-on option is specified before the path.\n");
    262 
    263     bool alwaysOn = false;
    264     if (argc >= 2 && !strcmp(argv[1], "--always-on")) {
    265         alwaysOn = true;
    266         --argc;
    267         ++argv;
    268     }
    269 
    270     if (argc < 3) {
    271         fprintf(stdout, "Usage: \t%s [--always-on] path bass_boost_strength\n", programName);
    272         fprintf(stdout, "Example: \"%s /sdcard/my.mp3 1000\" \n", programName);
    273         exit(EXIT_FAILURE);
    274     }
    275 
    276     SLEngineOption EngineOption[] = {
    277             {(SLuint32) SL_ENGINEOPTION_THREADSAFE, (SLuint32) SL_BOOLEAN_TRUE}
    278     };
    279 
    280     result = slCreateEngine( &sl, 1, EngineOption, 0, NULL, NULL);
    281     ExitOnError(result);
    282 
    283     /* Realizing the SL Engine in synchronous mode. */
    284     result = (*sl)->Realize(sl, SL_BOOLEAN_FALSE);
    285     ExitOnError(result);
    286 
    287     // intentionally not checking that argv[2], the bassboost strength, is between 0 and 1000
    288     TestBassBoostPathFromFD(sl, argv[1], (int16_t)atoi(argv[2]), alwaysOn);
    289 
    290     /* Shutdown OpenSL ES */
    291     (*sl)->Destroy(sl);
    292 
    293     return EXIT_SUCCESS;
    294 }
    295