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_EQ_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 TestEQPathFromFD( SLObjectItf sl, const char* path
     51 #ifdef ANDROID
     52     , SLAint64 offset, SLAint64 size
     53 #endif
     54     )
     55 {
     56     SLresult  result;
     57     SLEngineItf EngineItf;
     58 
     59     /* Objects this application uses: one player and an ouput mix */
     60     SLObjectItf  player, outputMix;
     61 
     62     /* Source of audio data to play */
     63     SLDataSource            audioSource;
     64 #ifdef ANDROID
     65     SLDataLocator_AndroidFD locatorFd;
     66 #else
     67     SLDataLocator_URI       locatorUri;
     68 #endif
     69     SLDataFormat_MIME       mime;
     70 
     71     /* Data sinks for the audio player */
     72     SLDataSink               audioSink;
     73     SLDataLocator_OutputMix  locator_outputmix;
     74 
     75     /* Play and PrefetchStatus interfaces for the audio player */
     76     SLPlayItf              playItf;
     77     SLPrefetchStatusItf    prefetchItf;
     78 
     79     /* Effect interface for the output mix */
     80     SLEqualizerItf         eqOutputItf;
     81 
     82     SLboolean required[MAX_NUMBER_INTERFACES];
     83     SLInterfaceID iidArray[MAX_NUMBER_INTERFACES];
     84 
     85     /* Get the SL Engine Interface which is implicit */
     86     result = (*sl)->GetInterface(sl, SL_IID_ENGINE, (void*)&EngineItf);
     87     ExitOnError(result);
     88 
     89     /* Initialize arrays required[] and iidArray[] */
     90     for (int i=0 ; i < MAX_NUMBER_INTERFACES ; i++) {
     91         required[i] = SL_BOOLEAN_FALSE;
     92         iidArray[i] = SL_IID_NULL;
     93     }
     94 
     95     /* ------------------------------------------------------ */
     96     /* Configuration of the output mix  */
     97 
     98     /* Set arrays required[] and iidArray[] for SLEqualizerItf interface */
     99     required[0] = SL_BOOLEAN_TRUE;
    100     iidArray[0] = SL_IID_EQUALIZER;
    101 
    102     /* Create Output Mix object to be used by the player */
    103      result = (*EngineItf)->CreateOutputMix(EngineItf, &outputMix, 1, iidArray, required);
    104      ExitOnError(result);
    105 
    106     /* Realize the Output Mix object in synchronous mode */
    107     result = (*outputMix)->Realize(outputMix, SL_BOOLEAN_FALSE);
    108     ExitOnError(result);
    109 
    110     /* Get the SLEqualizerItf interface */
    111     result = (*outputMix)->GetInterface(outputMix, SL_IID_EQUALIZER, (void*)&eqOutputItf);
    112 
    113     /* Setup the data sink structure */
    114     locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
    115     locator_outputmix.outputMix   = outputMix;
    116     audioSink.pLocator            = (void*)&locator_outputmix;
    117     audioSink.pFormat             = NULL;
    118 
    119     /* ------------------------------------------------------ */
    120     /* Configuration of the player  */
    121 
    122     /* Set arrays required[] and iidArray[] for SLPrefetchStatusItf interfaces */
    123     /*  (SLPlayItf is implicit) */
    124     required[0] = SL_BOOLEAN_TRUE;
    125     iidArray[0] = SL_IID_PREFETCHSTATUS;
    126 
    127     /* Setup the data source structure for the URI */
    128 #ifdef ANDROID
    129     locatorFd.locatorType = SL_DATALOCATOR_ANDROIDFD;
    130     int fd = open(path, O_RDONLY);
    131     if (fd == -1) {
    132         ExitOnError(SL_RESULT_RESOURCE_ERROR);
    133     }
    134     locatorFd.fd = (SLint32) fd;
    135     locatorFd.length = size;
    136     locatorFd.offset = offset;
    137 #else
    138     locatorUri.locatorType = SL_DATALOCATOR_URI;
    139     locatorUri.URI = (SLchar *) path;
    140 #endif
    141 
    142     mime.formatType = SL_DATAFORMAT_MIME;
    143     /*     this is how ignored mime information is specified, according to OpenSL ES spec
    144      *     in 9.1.6 SLDataFormat_MIME and 8.23 SLMetadataTraversalItf GetChildInfo */
    145     mime.mimeType      = (SLchar*)NULL;
    146     mime.containerType = SL_CONTAINERTYPE_UNSPECIFIED;
    147 
    148     audioSource.pFormat  = (void*)&mime;
    149 #ifdef ANDROID
    150     audioSource.pLocator = (void*)&locatorFd;
    151 #else
    152     audioSource.pLocator = (void*)&locatorUri;
    153 #endif
    154 
    155     /* Create the audio player */
    156     result = (*EngineItf)->CreateAudioPlayer(EngineItf, &player, &audioSource, &audioSink, 1,
    157             iidArray, required);
    158     ExitOnError(result);
    159 
    160     /* Realize the player in synchronous mode. */
    161     result = (*player)->Realize(player, SL_BOOLEAN_FALSE); ExitOnError(result);
    162     fprintf(stdout, "URI example: after Realize\n");
    163 
    164     /* Get the SLPlayItf, SLPrefetchStatusItf and SLAndroidStreamTypeItf interfaces for the player*/
    165     result = (*player)->GetInterface(player, SL_IID_PLAY, (void*)&playItf);
    166     ExitOnError(result);
    167 
    168     result = (*player)->GetInterface(player, SL_IID_PREFETCHSTATUS, (void*)&prefetchItf);
    169     ExitOnError(result);
    170 
    171     fprintf(stdout, "Player configured\n");
    172 
    173     /* ------------------------------------------------------ */
    174     /* Playback and test */
    175 
    176     /* Start the data prefetching by setting the player to the paused state */
    177     result = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PAUSED );
    178     ExitOnError(result);
    179 
    180     /* Wait until there's data to play */
    181     SLuint32 prefetchStatus = SL_PREFETCHSTATUS_UNDERFLOW;
    182     while (prefetchStatus != SL_PREFETCHSTATUS_SUFFICIENTDATA) {
    183         usleep(100 * 1000);
    184         (*prefetchItf)->GetPrefetchStatus(prefetchItf, &prefetchStatus);
    185         ExitOnError(result);
    186     }
    187 
    188     /* Get duration */
    189     SLmillisecond durationInMsec = SL_TIME_UNKNOWN;
    190     result = (*playItf)->GetDuration(playItf, &durationInMsec);
    191     ExitOnError(result);
    192     if (durationInMsec == SL_TIME_UNKNOWN) {
    193         durationInMsec = 5000;
    194     }
    195 
    196     /* Start playback */
    197     fprintf(stdout, "Starting to play\n");
    198     result = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PLAYING );
    199     ExitOnError(result);
    200 
    201     /* Configure EQ */
    202     SLuint16 nbPresets, preset, nbBands = 0;
    203     result = (*eqOutputItf)->GetNumberOfBands(eqOutputItf, &nbBands);
    204     ExitOnError(result);
    205     result = (*eqOutputItf)->GetNumberOfPresets(eqOutputItf, &nbPresets);
    206     ExitOnError(result);
    207     /*    Start from a preset  */
    208     preset = nbPresets > 2 ?  2 : 0;
    209     result = (*eqOutputItf)->UsePreset(eqOutputItf, preset);
    210 
    211     preset = 1977;
    212     result = (*eqOutputItf)->GetCurrentPreset(eqOutputItf, &preset);
    213     ExitOnError(result);
    214     if (SL_EQUALIZER_UNDEFINED == preset) {
    215         fprintf(stderr, "Using SL_EQUALIZER_UNDEFINED preset, unexpected here!\n");
    216     } else {
    217         fprintf(stdout, "Using preset %d\n", preset);
    218     }
    219 
    220     /*    Tweak it so it's obvious it gets turned on/off later */
    221     SLmillibel minLevel, maxLevel = 0;
    222     result = (*eqOutputItf)->GetBandLevelRange(eqOutputItf, &minLevel, &maxLevel);
    223     ExitOnError(result);
    224     fprintf(stdout, "Band level range = %dmB to %dmB\n", minLevel, maxLevel);
    225 
    226     SLuint16 b = 0;
    227     for(b = 0 ; b < nbBands/2 ; b++) {
    228         result = (*eqOutputItf)->SetBandLevel(eqOutputItf, b, minLevel);
    229         ExitOnError(result);
    230     }
    231     for(b = nbBands/2 ; b < nbBands ; b++) {
    232         result = (*eqOutputItf)->SetBandLevel(eqOutputItf, b, maxLevel);
    233         ExitOnError(result);
    234     }
    235 
    236     SLmillibel level = 0;
    237     for(b = 0 ; b < nbBands ; b++) {
    238         result = (*eqOutputItf)->GetBandLevel(eqOutputItf, b, &level);
    239         ExitOnError(result);
    240         fprintf(stdout, "Band %d level = %dmB\n", b, level);
    241     }
    242 
    243     /* Switch EQ on/off every TIME_S_BETWEEN_EQ_ON_OFF seconds */
    244     SLboolean enabled = SL_BOOLEAN_TRUE;
    245     result = (*eqOutputItf)->SetEnabled(eqOutputItf, enabled);
    246     ExitOnError(result);
    247     for(unsigned int j=0 ; j<(durationInMsec/(1000*TIME_S_BETWEEN_EQ_ON_OFF)) ; j++) {
    248         usleep(TIME_S_BETWEEN_EQ_ON_OFF * 1000 * 1000);
    249         result = (*eqOutputItf)->IsEnabled(eqOutputItf, &enabled);
    250         ExitOnError(result);
    251         enabled = enabled == SL_BOOLEAN_TRUE ? SL_BOOLEAN_FALSE : SL_BOOLEAN_TRUE;
    252         result = (*eqOutputItf)->SetEnabled(eqOutputItf, enabled);
    253         if (SL_BOOLEAN_TRUE == enabled) {
    254             fprintf(stdout, "EQ on\n");
    255         } else {
    256             fprintf(stdout, "EQ off\n");
    257         }
    258         ExitOnError(result);
    259     }
    260 
    261     /* Make sure player is stopped */
    262     fprintf(stdout, "Stopping playback\n");
    263     result = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED);
    264     ExitOnError(result);
    265 
    266     /* Destroy the player */
    267     (*player)->Destroy(player);
    268 
    269     /* Destroy Output Mix object */
    270     (*outputMix)->Destroy(outputMix);
    271 
    272 #ifdef ANDROID
    273     close(fd);
    274 #endif
    275 }
    276 
    277 //-----------------------------------------------------------------
    278 int main(int argc, char* const argv[])
    279 {
    280     SLresult    result;
    281     SLObjectItf sl;
    282 
    283     fprintf(stdout, "OpenSL ES test %s: exercises SLEqualizerItf ", argv[0]);
    284     fprintf(stdout, "on an OutputMix object\n");
    285     fprintf(stdout, "Plays the sound file designated by the given path, ");
    286     fprintf(stdout, "starting at the specified offset, and using the specified length.\n");
    287     fprintf(stdout, "Omit the length of the file for it to be computed by the system.\n");
    288     fprintf(stdout, "Every %d seconds, the EQ will be turned on and off.\n",
    289             TIME_S_BETWEEN_EQ_ON_OFF);
    290 
    291 #ifdef ANDROID
    292     if (argc < 3) {
    293         fprintf(stdout, "Usage: \t%s path offsetInBytes [sizeInBytes]\n", argv[0]);
    294         fprintf(stdout, "Example: \"%s /sdcard/my.mp3 0 344460\" \n", argv[0]);
    295         exit(EXIT_FAILURE);
    296     }
    297 #endif
    298 
    299     SLEngineOption EngineOption[] = {
    300             {(SLuint32) SL_ENGINEOPTION_THREADSAFE, (SLuint32) SL_BOOLEAN_TRUE}
    301     };
    302 
    303     result = slCreateEngine( &sl, 1, EngineOption, 0, NULL, NULL);
    304     ExitOnError(result);
    305 
    306     /* Realizing the SL Engine in synchronous mode. */
    307     result = (*sl)->Realize(sl, SL_BOOLEAN_FALSE);
    308     ExitOnError(result);
    309 
    310 #ifdef ANDROID
    311     if (argc == 3) {
    312         fprintf(stdout, "\nno file size given, using SL_DATALOCATOR_ANDROIDFD_USE_FILE_SIZE\n\n");
    313         TestEQPathFromFD(sl, argv[1], (SLAint64)atoi(argv[2]),
    314                 SL_DATALOCATOR_ANDROIDFD_USE_FILE_SIZE);
    315     } else {
    316         TestEQPathFromFD(sl, argv[1], (SLAint64)atoi(argv[2]), (SLAint64)atoi(argv[3]));
    317     }
    318 #else
    319     TestEQPathFromFD(sl, argv[1]);
    320 #endif
    321 
    322     /* Shutdown OpenSL ES */
    323     (*sl)->Destroy(sl);
    324 
    325     return EXIT_SUCCESS;
    326 }
    327