Home | History | Annotate | Download | only in sandbox
      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 // Demonstrate environmental reverb and preset reverb on an output mix and audio player
     18 
     19 #include <SLES/OpenSLES.h>
     20 #include <assert.h>
     21 #include <pthread.h>
     22 #include <string.h>
     23 #include <stdio.h>
     24 #include <stdlib.h>
     25 #include <unistd.h>
     26 
     27 #define bool int
     28 #define false 0
     29 #define true 1
     30 
     31 // Table of I3DL2 named environmental reverb settings
     32 
     33 typedef struct {
     34     const char *mName;
     35     SLEnvironmentalReverbSettings mSettings;
     36 } Pair;
     37 
     38 #define _(name) {#name, SL_I3DL2_ENVIRONMENT_PRESET_##name},
     39 
     40 Pair pairs[] = {
     41     _(DEFAULT)
     42     _(GENERIC)
     43     _(PADDEDCELL)
     44     _(ROOM)
     45     _(BATHROOM)
     46     _(LIVINGROOM)
     47     _(STONEROOM)
     48     _(AUDITORIUM)
     49     _(CONCERTHALL)
     50     _(CAVE)
     51     _(ARENA)
     52     _(HANGAR)
     53     _(CARPETEDHALLWAY)
     54     _(HALLWAY)
     55     _(STONECORRIDOR)
     56     _(ALLEY)
     57     _(FOREST)
     58     _(CITY)
     59     _(MOUNTAINS)
     60     _(QUARRY)
     61     _(PLAIN)
     62     _(PARKINGLOT)
     63     _(SEWERPIPE)
     64     _(UNDERWATER)
     65     _(SMALLROOM)
     66     _(MEDIUMROOM)
     67     _(LARGEROOM)
     68     _(MEDIUMHALL)
     69     _(LARGEHALL)
     70     _(PLATE)
     71 };
     72 
     73 // Parameters for preset reverb on output mix
     74 bool outputMixPresetItfRequested = false;
     75 SLuint16 outputMixPresetNumber = ~0;
     76 
     77 // Parameters for environmental reverb on output mix
     78 bool outputMixEnvironmentalItfRequested = false;
     79 char *outputMixEnvironmentalName = NULL;
     80 SLEnvironmentalReverbSettings outputMixEnvironmentalSettings;
     81 
     82 // Parameters for preset reverb on audio player (not supported)
     83 bool playerPresetItfRequested = false;
     84 SLuint16 playerPresetNumber = ~0;
     85 
     86 // Parameters for environmental reverb on audio player (not supported)
     87 bool playerEnvironmentalItfRequested = false;
     88 char *playerEnvironmentalName = NULL;
     89 SLEnvironmentalReverbSettings playerEnvironmentalSettings;
     90 
     91 // Compare two environmental reverb settings structures.
     92 // Returns true if the settings are identical, or false if they are different.
     93 
     94 bool slesutCompareEnvironmentalReverbSettings(
     95         const SLEnvironmentalReverbSettings *settings1,
     96         const SLEnvironmentalReverbSettings *settings2)
     97 {
     98     return
     99         (settings1->roomLevel == settings2->roomLevel) &&
    100         (settings1->roomHFLevel == settings2->roomHFLevel) &&
    101         (settings1->decayTime == settings2->decayTime) &&
    102         (settings1->decayHFRatio == settings2->decayHFRatio) &&
    103         (settings1->reflectionsLevel == settings2->reflectionsLevel) &&
    104         (settings1->reflectionsDelay == settings2->reflectionsDelay) &&
    105         (settings1->reverbLevel == settings2->reverbLevel) &&
    106         (settings1->reverbDelay == settings2->reverbDelay) &&
    107         (settings1->diffusion == settings2->diffusion) &&
    108         (settings1->density == settings2->density);
    109 }
    110 
    111 // Print an environmental reverb settings structure.
    112 
    113 void slesutPrintEnvironmentalReverbSettings(const SLEnvironmentalReverbSettings *settings)
    114 {
    115     printf("roomLevel: %d\n", settings->roomLevel);
    116     printf("roomHFLevel: %d\n", settings->roomHFLevel);
    117     printf("decayTime: %d\n", settings->decayTime);
    118     printf("decayHFRatio: %d\n", settings->decayHFRatio);
    119     printf("reflectionsLevel: %d\n", settings->reflectionsLevel);
    120     printf("reflectionsDelay: %d\n", settings->reflectionsDelay);
    121     printf("reverbLevel: %d\n", settings->reverbLevel);
    122     printf("reverbDelay: %d\n", settings->reverbDelay);
    123     printf("diffusion: %d\n", settings->diffusion);
    124     printf("density: %d\n", settings->density);
    125 }
    126 
    127 // Lookup environmental reverb settings by name
    128 
    129 const SLEnvironmentalReverbSettings *lookupEnvName(const char *name)
    130 {
    131     unsigned j;
    132     for (j = 0; j < sizeof(pairs) / sizeof(pairs[0]); ++j) {
    133         if (!strcasecmp(name, pairs[j].mName)) {
    134             return &pairs[j].mSettings;
    135         }
    136     }
    137     return NULL;
    138 }
    139 
    140 // Print all available environmental reverb names
    141 
    142 void printEnvNames(void)
    143 {
    144     unsigned j;
    145     bool needSpace = false;
    146     bool needNewline = false;
    147     unsigned lineLen = 0;
    148     for (j = 0; j < sizeof(pairs) / sizeof(pairs[0]); ++j) {
    149         const char *name = pairs[j].mName;
    150         unsigned nameLen = strlen(name);
    151         if (lineLen + (needSpace ? 1 : 0) + nameLen > 72) {
    152             putchar('\n');
    153             needSpace = false;
    154             needNewline = false;
    155             lineLen = 0;
    156         }
    157         if (needSpace) {
    158             putchar(' ');
    159             ++lineLen;
    160         }
    161         fputs(name, stdout);
    162         lineLen += nameLen;
    163         needSpace = true;
    164         needNewline = true;
    165     }
    166     if (needNewline) {
    167         putchar('\n');
    168     }
    169 }
    170 
    171 // These are extensions to OpenSL ES 1.0.1 values
    172 
    173 #define SL_PREFETCHSTATUS_UNKNOWN 0
    174 #define SL_PREFETCHSTATUS_ERROR   (-1)
    175 
    176 // Mutex and condition shared with main program to protect prefetch_status
    177 
    178 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
    179 static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
    180 SLuint32 prefetch_status = SL_PREFETCHSTATUS_UNKNOWN;
    181 
    182 /* used to detect errors likely to have occured when the OpenSL ES framework fails to open
    183  * a resource, for instance because a file URI is invalid, or an HTTP server doesn't respond.
    184  */
    185 #define PREFETCHEVENT_ERROR_CANDIDATE \
    186         (SL_PREFETCHEVENT_STATUSCHANGE | SL_PREFETCHEVENT_FILLLEVELCHANGE)
    187 
    188 // Prefetch status callback
    189 
    190 void prefetch_callback(SLPrefetchStatusItf caller, void *context, SLuint32 event)
    191 {
    192     SLresult result;
    193     assert(context == NULL);
    194     SLpermille level;
    195     result = (*caller)->GetFillLevel(caller, &level);
    196     assert(SL_RESULT_SUCCESS == result);
    197     SLuint32 status;
    198     result = (*caller)->GetPrefetchStatus(caller, &status);
    199     assert(SL_RESULT_SUCCESS == result);
    200     SLuint32 new_prefetch_status;
    201     if ((event & PREFETCHEVENT_ERROR_CANDIDATE) == PREFETCHEVENT_ERROR_CANDIDATE
    202             && level == 0 && status == SL_PREFETCHSTATUS_UNDERFLOW) {
    203         new_prefetch_status = SL_PREFETCHSTATUS_ERROR;
    204     } else if (event == SL_PREFETCHEVENT_STATUSCHANGE &&
    205             status == SL_PREFETCHSTATUS_SUFFICIENTDATA) {
    206         new_prefetch_status = status;
    207     } else {
    208         return;
    209     }
    210     int ok;
    211     ok = pthread_mutex_lock(&mutex);
    212     assert(ok == 0);
    213     prefetch_status = new_prefetch_status;
    214     ok = pthread_cond_signal(&cond);
    215     assert(ok == 0);
    216     ok = pthread_mutex_unlock(&mutex);
    217     assert(ok == 0);
    218 }
    219 
    220 // Main program
    221 
    222 int main(int argc, char **argv)
    223 {
    224     SLresult result;
    225     bool loop = false;
    226 
    227     // process command line parameters
    228     char *prog = argv[0];
    229     int i;
    230     for (i = 1; i < argc; ++i) {
    231         char *arg = argv[i];
    232         if (arg[0] != '-')
    233             break;
    234         bool bad = false;   // whether the option string is invalid
    235         if (!strncmp(arg, "--mix-preset", 12)) {
    236             if ('\0' == arg[12]) {
    237                 outputMixPresetItfRequested = true;
    238             } else if ('=' == arg[12]) {
    239                 outputMixPresetNumber = atoi(&arg[13]);
    240                 outputMixPresetItfRequested = true;
    241             } else {
    242                 bad = true;
    243             }
    244         } else if (!strncmp(arg, "--mix-name", 10)) {
    245             if ('\0' == arg[10]) {
    246                 outputMixEnvironmentalItfRequested = true;
    247             } else if ('=' == arg[10]) {
    248                 outputMixEnvironmentalName = &arg[11];
    249                 outputMixEnvironmentalItfRequested = true;
    250             } else {
    251                 bad = true;
    252             }
    253         } else if (!strncmp(arg, "--player-preset", 15)) {
    254             if ('\0' == arg[15]) {
    255                 playerPresetItfRequested = true;
    256             } else if ('=' == arg[15]) {
    257                 playerPresetNumber = atoi(&arg[16]);
    258                 playerPresetItfRequested = true;
    259             } else {
    260                 bad = true;
    261             }
    262         } else if (!strncmp(arg, "--player-name", 13)) {
    263             if ('\0' == arg[13]) {
    264                 playerEnvironmentalItfRequested = true;
    265             } else if ('=' == arg[13]) {
    266                 playerEnvironmentalName = &arg[14];
    267                 playerEnvironmentalItfRequested = true;
    268             } else {
    269                 bad = true;
    270             }
    271         } else if (!strcmp(arg, "--loop")) {
    272             loop = true;
    273         } else {
    274             bad = true;
    275         }
    276         if (bad) {
    277             fprintf(stderr, "%s: unknown option %s ignored\n", prog, arg);
    278         }
    279     }
    280     if (argc - i != 1) {
    281         fprintf(stderr, "usage: %s --mix-preset=# --mix-name=I3DL2 --player-preset=# "
    282                 "--player-name=I3DL2 --loop filename\n", prog);
    283         return EXIT_FAILURE;
    284     }
    285     char *pathname = argv[i];
    286 
    287     const SLEnvironmentalReverbSettings *envSettings;
    288     if (NULL != outputMixEnvironmentalName) {
    289         envSettings = lookupEnvName(outputMixEnvironmentalName);
    290         if (NULL == envSettings) {
    291             fprintf(stderr, "%s: output mix environmental reverb name %s not found, "
    292                     "available names are:\n", prog, outputMixEnvironmentalName);
    293             printEnvNames();
    294             return EXIT_FAILURE;
    295         }
    296         outputMixEnvironmentalSettings = *envSettings;
    297     }
    298     if (NULL != playerEnvironmentalName) {
    299         envSettings = lookupEnvName(playerEnvironmentalName);
    300         if (NULL == envSettings) {
    301             fprintf(stderr, "%s: player environmental reverb name %s not found, "
    302                     "available names are:\n", prog, playerEnvironmentalName);
    303             printEnvNames();
    304             return EXIT_FAILURE;
    305         }
    306         playerEnvironmentalSettings = *envSettings;
    307     }
    308 
    309     // create engine
    310     SLObjectItf engineObject;
    311     result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
    312     assert(SL_RESULT_SUCCESS == result);
    313     result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
    314     assert(SL_RESULT_SUCCESS == result);
    315     SLEngineItf engineEngine;
    316     result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
    317     assert(SL_RESULT_SUCCESS == result);
    318 
    319     // create output mix
    320     SLInterfaceID mix_ids[2];
    321     SLboolean mix_req[2];
    322     SLuint32 count = 0;
    323     if (outputMixPresetItfRequested) {
    324         mix_req[count] = SL_BOOLEAN_TRUE;
    325         mix_ids[count++] = SL_IID_PRESETREVERB;
    326     }
    327     if (outputMixEnvironmentalItfRequested) {
    328         mix_req[count] = SL_BOOLEAN_TRUE;
    329         mix_ids[count++] = SL_IID_ENVIRONMENTALREVERB;
    330     }
    331     SLObjectItf mixObject;
    332     result = (*engineEngine)->CreateOutputMix(engineEngine, &mixObject, count, mix_ids, mix_req);
    333     assert(SL_RESULT_SUCCESS == result);
    334     result = (*mixObject)->Realize(mixObject, SL_BOOLEAN_FALSE);
    335     assert(SL_RESULT_SUCCESS == result);
    336 
    337     // configure preset reverb on output mix
    338     SLPresetReverbItf outputMixPresetReverb;
    339     if (outputMixPresetItfRequested) {
    340         result = (*mixObject)->GetInterface(mixObject, SL_IID_PRESETREVERB, &outputMixPresetReverb);
    341         assert(SL_RESULT_SUCCESS == result);
    342         SLuint16 getPresetReverb = 12345;
    343         result = (*outputMixPresetReverb)->GetPreset(outputMixPresetReverb, &getPresetReverb);
    344         assert(SL_RESULT_SUCCESS == result);
    345         printf("Output mix default preset reverb number = %u\n", getPresetReverb);
    346         if (outputMixPresetNumber != ((SLuint16) ~0)) {
    347             result = (*outputMixPresetReverb)->SetPreset(outputMixPresetReverb,
    348                     outputMixPresetNumber);
    349             if (SL_RESULT_SUCCESS == result) {
    350                 result = (*outputMixPresetReverb)->GetPreset(outputMixPresetReverb,
    351                         &getPresetReverb);
    352                 assert(SL_RESULT_SUCCESS == result);
    353                 assert(getPresetReverb == outputMixPresetNumber);
    354                 printf("Output mix preset reverb successfully changed to %u\n",
    355                         outputMixPresetNumber);
    356             } else {
    357                 printf("Unable to set output mix preset reverb to %u, result=%u\n",
    358                         outputMixPresetNumber, result);
    359             }
    360         }
    361     }
    362 
    363     // configure environmental reverb on output mix
    364     SLEnvironmentalReverbItf outputMixEnvironmentalReverb;
    365     if (outputMixEnvironmentalItfRequested) {
    366         result = (*mixObject)->GetInterface(mixObject, SL_IID_ENVIRONMENTALREVERB,
    367                 &outputMixEnvironmentalReverb);
    368         assert(SL_RESULT_SUCCESS == result);
    369         SLEnvironmentalReverbSettings getSettings;
    370         result = (*outputMixEnvironmentalReverb)->GetEnvironmentalReverbProperties(
    371                 outputMixEnvironmentalReverb, &getSettings);
    372         assert(SL_RESULT_SUCCESS == result);
    373         printf("Output mix default environmental reverb settings\n");
    374         printf("------------------------------------------------\n");
    375         slesutPrintEnvironmentalReverbSettings(&getSettings);
    376         printf("\n");
    377         if (outputMixEnvironmentalName != NULL) {
    378             result = (*outputMixEnvironmentalReverb)->SetEnvironmentalReverbProperties(
    379                     outputMixEnvironmentalReverb, &outputMixEnvironmentalSettings);
    380             assert(SL_RESULT_SUCCESS == result);
    381             printf("Output mix new environmental reverb settings\n");
    382             printf("--------------------------------------------\n");
    383             slesutPrintEnvironmentalReverbSettings(&outputMixEnvironmentalSettings);
    384             printf("\n");
    385             result = (*outputMixEnvironmentalReverb)->GetEnvironmentalReverbProperties(
    386                     outputMixEnvironmentalReverb, &getSettings);
    387             assert(SL_RESULT_SUCCESS == result);
    388             printf("Output mix read environmental reverb settings\n");
    389             printf("--------------------------------------------\n");
    390             slesutPrintEnvironmentalReverbSettings(&getSettings);
    391             printf("\n");
    392             if (!slesutCompareEnvironmentalReverbSettings(&getSettings,
    393                     &outputMixEnvironmentalSettings)) {
    394                 printf("Warning: new and read are different; check details above\n");
    395             } else {
    396                 printf("New and read match, life is good\n");
    397             }
    398         }
    399     }
    400 
    401     // create audio player
    402     SLDataLocator_URI locURI = {SL_DATALOCATOR_URI, (SLchar *) pathname};
    403     SLDataFormat_MIME dfMIME = {SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED};
    404     SLDataSource audioSrc = {&locURI, &dfMIME};
    405     SLDataLocator_OutputMix locOutputMix = {SL_DATALOCATOR_OUTPUTMIX, mixObject};
    406     SLDataSink audioSnk = {&locOutputMix, NULL};
    407     SLInterfaceID player_ids[5];
    408     SLboolean player_req[5];
    409     count = 0;
    410     if (playerPresetItfRequested) {
    411         player_req[count] = SL_BOOLEAN_TRUE;
    412         player_ids[count++] = SL_IID_PRESETREVERB;
    413     }
    414     if (playerEnvironmentalItfRequested) {
    415         player_req[count] = SL_BOOLEAN_TRUE;
    416         player_ids[count++] = SL_IID_ENVIRONMENTALREVERB;
    417     }
    418     if (outputMixPresetItfRequested || outputMixEnvironmentalItfRequested) {
    419         player_req[count] = SL_BOOLEAN_TRUE;
    420         player_ids[count++] = SL_IID_EFFECTSEND;
    421     }
    422     if (loop) {
    423         player_req[count] = SL_BOOLEAN_TRUE;
    424         player_ids[count++] = SL_IID_SEEK;
    425     }
    426     player_req[count] = SL_BOOLEAN_TRUE;
    427     player_ids[count++] = SL_IID_PREFETCHSTATUS;
    428     SLObjectItf playerObject;
    429     result = (*engineEngine)->CreateAudioPlayer(engineEngine, &playerObject, &audioSrc,
    430         &audioSnk, count, player_ids, player_req);
    431     assert(SL_RESULT_SUCCESS == result);
    432 
    433     // realize audio player
    434     result = (*playerObject)->Realize(playerObject, SL_BOOLEAN_FALSE);
    435     assert(SL_RESULT_SUCCESS == result);
    436 
    437     // if reverb is on output mix (aux effect), then enable it for this player
    438     if (outputMixPresetItfRequested || outputMixEnvironmentalItfRequested) {
    439         SLEffectSendItf playerEffectSend;
    440         result = (*playerObject)->GetInterface(playerObject, SL_IID_EFFECTSEND, &playerEffectSend);
    441         assert(SL_RESULT_SUCCESS == result);
    442         SLboolean enabled;
    443         SLmillibel directLevel;
    444         SLmillibel sendLevel;
    445         if (outputMixPresetItfRequested) {
    446             result = (*playerEffectSend)->IsEnabled(playerEffectSend, outputMixPresetReverb,
    447                     &enabled);
    448             assert(SL_RESULT_SUCCESS == result);
    449             printf("Output mix preset reverb: player effect send default enabled = %s\n",
    450                     enabled ? "true" : "false");
    451             directLevel = 12345;
    452             result = (*playerEffectSend)->GetDirectLevel(playerEffectSend, &directLevel);
    453             assert(SL_RESULT_SUCCESS == result);
    454             printf("Output mix preset reverb: player effect send default direct level = %d\n",
    455                     directLevel);
    456             sendLevel = 12345;
    457             result = (*playerEffectSend)->GetSendLevel(playerEffectSend, outputMixPresetReverb,
    458                     &sendLevel);
    459             assert(SL_RESULT_SUCCESS == result);
    460             printf("Output mix preset reverb: player effect send default send level = %d\n",
    461                     sendLevel);
    462             if (outputMixPresetNumber != ((SLuint16) ~0)) {
    463                 result = (*playerEffectSend)->EnableEffectSend(playerEffectSend,
    464                         outputMixPresetReverb, SL_BOOLEAN_TRUE, (SLmillibel) 0);
    465                 assert(SL_RESULT_SUCCESS == result);
    466                 result = (*playerEffectSend)->IsEnabled(playerEffectSend, outputMixPresetReverb,
    467                         &enabled);
    468                 assert(SL_RESULT_SUCCESS == result);
    469                 directLevel = 12345;
    470                 result = (*playerEffectSend)->GetDirectLevel(playerEffectSend, &directLevel);
    471                 assert(SL_RESULT_SUCCESS == result);
    472                 sendLevel = 12345;
    473                 result = (*playerEffectSend)->GetSendLevel(playerEffectSend, outputMixPresetReverb,
    474                         &sendLevel);
    475                 assert(SL_RESULT_SUCCESS == result);
    476                 printf("Output mix preset reverb: player effect send new enabled = %s, direct level"
    477                     " = %d, send level = %d\n", enabled ? "true" : "false", directLevel, sendLevel);
    478             }
    479         }
    480         if (outputMixEnvironmentalItfRequested) {
    481             if (outputMixEnvironmentalName != NULL) {
    482                 result = (*playerEffectSend)->IsEnabled(playerEffectSend,
    483                         outputMixEnvironmentalReverb, &enabled);
    484                 assert(SL_RESULT_SUCCESS == result);
    485                 printf("Output mix environmental reverb: player effect send default enabled = %s\n",
    486                         enabled ? "true" : "false");
    487                 directLevel = 12345;
    488                 result = (*playerEffectSend)->GetDirectLevel(playerEffectSend, &directLevel);
    489                 assert(SL_RESULT_SUCCESS == result);
    490                 printf("Output mix environmental reverb: player effect send default direct level"
    491                         " = %d\n", directLevel);
    492                 sendLevel = 12345;
    493                 result = (*playerEffectSend)->GetSendLevel(playerEffectSend,
    494                         outputMixEnvironmentalReverb, &sendLevel);
    495                 assert(SL_RESULT_SUCCESS == result);
    496                 printf("Output mix environmental reverb: player effect send default send level"
    497                         " = %d\n", sendLevel);
    498                 result = (*playerEffectSend)->EnableEffectSend(playerEffectSend,
    499                         outputMixEnvironmentalReverb, SL_BOOLEAN_TRUE, (SLmillibel) 0);
    500                 assert(SL_RESULT_SUCCESS == result);
    501                 result = (*playerEffectSend)->IsEnabled(playerEffectSend,
    502                         outputMixEnvironmentalReverb, &enabled);
    503                 assert(SL_RESULT_SUCCESS == result);
    504                 directLevel = 12345;
    505                 result = (*playerEffectSend)->GetDirectLevel(playerEffectSend, &directLevel);
    506                 assert(SL_RESULT_SUCCESS == result);
    507                 sendLevel = 12345;
    508                 result = (*playerEffectSend)->GetSendLevel(playerEffectSend,
    509                         outputMixEnvironmentalReverb, &sendLevel);
    510                 assert(SL_RESULT_SUCCESS == result);
    511                 printf("Output mix environmental reverb: player effect send new enabled = %s, "
    512                     "direct level = %d, send level = %d\n", enabled ? "true" : "false",
    513                     directLevel, sendLevel);
    514             }
    515         }
    516     }
    517 
    518     // configure preset reverb on player
    519     SLPresetReverbItf playerPresetReverb;
    520     if (playerPresetItfRequested) {
    521         result = (*playerObject)->GetInterface(playerObject, SL_IID_PRESETREVERB,
    522                 &playerPresetReverb);
    523         assert(SL_RESULT_SUCCESS == result);
    524         SLuint16 getPresetReverb = 12345;
    525         result = (*playerPresetReverb)->GetPreset(playerPresetReverb, &getPresetReverb);
    526         if (SL_RESULT_SUCCESS == result) {
    527             printf("Player default preset reverb %u\n", getPresetReverb);
    528             if (playerPresetNumber != ((SLuint16) ~0)) {
    529                 result = (*playerPresetReverb)->SetPreset(playerPresetReverb, playerPresetNumber);
    530                 if (SL_RESULT_SUCCESS == result) {
    531                     result = (*playerPresetReverb)->GetPreset(playerPresetReverb, &getPresetReverb);
    532                     assert(SL_RESULT_SUCCESS == result);
    533                     assert(getPresetReverb == playerPresetNumber);
    534                     printf("Player preset reverb successfully changed to %u\n", playerPresetNumber);
    535                 } else {
    536                     printf("Unable to set player preset reverb to %u, result=%u\n",
    537                             playerPresetNumber, result);
    538                 }
    539             }
    540         } else {
    541             printf("Unable to get player default preset reverb, result=%u\n", result);
    542         }
    543     }
    544 
    545     // configure environmental reverb on player
    546     SLEnvironmentalReverbItf playerEnvironmentalReverb;
    547     if (playerEnvironmentalItfRequested) {
    548         result = (*playerObject)->GetInterface(playerObject, SL_IID_ENVIRONMENTALREVERB,
    549                 &playerEnvironmentalReverb);
    550         assert(SL_RESULT_SUCCESS == result);
    551         SLEnvironmentalReverbSettings getSettings;
    552         memset(&getSettings, 0, sizeof(getSettings));
    553         result = (*playerEnvironmentalReverb)->GetEnvironmentalReverbProperties(
    554                 playerEnvironmentalReverb, &getSettings);
    555         if (SL_RESULT_SUCCESS == result) {
    556             printf("Player default environmental reverb settings\n");
    557             printf("--------------------------------------------\n");
    558             slesutPrintEnvironmentalReverbSettings(&getSettings);
    559             printf("\n");
    560             if (playerEnvironmentalName != NULL) {
    561                 result = (*playerEnvironmentalReverb)->SetEnvironmentalReverbProperties(
    562                         playerEnvironmentalReverb, &playerEnvironmentalSettings);
    563                 assert(SL_RESULT_SUCCESS == result);
    564                 printf("Player new environmental reverb settings\n");
    565                 printf("----------------------------------------\n");
    566                 slesutPrintEnvironmentalReverbSettings(&playerEnvironmentalSettings);
    567                 printf("\n");
    568                 result = (*playerEnvironmentalReverb)->GetEnvironmentalReverbProperties(
    569                         playerEnvironmentalReverb, &getSettings);
    570                 assert(SL_RESULT_SUCCESS == result);
    571                 printf("Player read environmental reverb settings\n");
    572                 printf("-----------------------------------------\n");
    573                 slesutPrintEnvironmentalReverbSettings(&getSettings);
    574                 printf("\n");
    575                 if (!slesutCompareEnvironmentalReverbSettings(&getSettings,
    576                         &playerEnvironmentalSettings)) {
    577                     printf("Warning: new and read are different; check details above\n");
    578                 } else {
    579                     printf("New and read match, life is good\n");
    580                 }
    581             }
    582         } else {
    583             printf("Unable to get player default environmental reverb properties, result=%u\n",
    584                     result);
    585         }
    586     }
    587 
    588     // get the play interface
    589     SLPlayItf playerPlay;
    590     result = (*playerObject)->GetInterface(playerObject, SL_IID_PLAY, &playerPlay);
    591     assert(SL_RESULT_SUCCESS == result);
    592 
    593     // get the prefetch status interface
    594     SLPrefetchStatusItf playerPrefetchStatus;
    595     result = (*playerObject)->GetInterface(playerObject, SL_IID_PREFETCHSTATUS,
    596             &playerPrefetchStatus);
    597     assert(SL_RESULT_SUCCESS == result);
    598 
    599     // enable prefetch status callbacks
    600     result = (*playerPrefetchStatus)->RegisterCallback(playerPrefetchStatus, prefetch_callback,
    601             NULL);
    602     assert(SL_RESULT_SUCCESS == result);
    603     result = (*playerPrefetchStatus)->SetCallbackEventsMask(playerPrefetchStatus,
    604             SL_PREFETCHEVENT_STATUSCHANGE | SL_PREFETCHEVENT_FILLLEVELCHANGE);
    605     assert(SL_RESULT_SUCCESS == result);
    606 
    607     // set play state to paused to enable pre-fetch so we can get a more reliable duration
    608     result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PAUSED);
    609     assert(SL_RESULT_SUCCESS == result);
    610 
    611     // wait for prefetch status callback to indicate either sufficient data or error
    612     pthread_mutex_lock(&mutex);
    613     while (prefetch_status == SL_PREFETCHSTATUS_UNKNOWN) {
    614         pthread_cond_wait(&cond, &mutex);
    615     }
    616     pthread_mutex_unlock(&mutex);
    617     if (prefetch_status == SL_PREFETCHSTATUS_ERROR) {
    618         fprintf(stderr, "Error during prefetch, exiting\n");
    619         goto destroyRes;
    620     }
    621 
    622     // get the duration
    623     SLmillisecond duration;
    624     result = (*playerPlay)->GetDuration(playerPlay, &duration);
    625     assert(SL_RESULT_SUCCESS == result);
    626     if (SL_TIME_UNKNOWN == duration) {
    627         printf("duration: unknown\n");
    628     } else {
    629         printf("duration: %.1f seconds\n", duration / 1000.0);
    630     }
    631 
    632     // enable looping
    633     if (loop) {
    634         SLSeekItf playerSeek;
    635         result = (*playerObject)->GetInterface(playerObject, SL_IID_SEEK, &playerSeek);
    636         assert(SL_RESULT_SUCCESS == result);
    637         result = (*playerSeek)->SetLoop(playerSeek, SL_BOOLEAN_TRUE, (SLmillisecond) 0,
    638                 SL_TIME_UNKNOWN);
    639         assert(SL_RESULT_SUCCESS == result);
    640     }
    641 
    642     // start audio playing
    643     result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING);
    644     assert(SL_RESULT_SUCCESS == result);
    645 
    646     // wait for audio to finish playing
    647     SLuint32 state;
    648     for (;;) {
    649         result = (*playerPlay)->GetPlayState(playerPlay, &state);
    650         assert(SL_RESULT_SUCCESS == result);
    651         if (SL_PLAYSTATE_PLAYING != state)
    652             break;
    653         usleep(1000000);
    654      }
    655     assert(SL_PLAYSTATE_PAUSED == state);
    656 
    657 destroyRes:
    658     // cleanup objects
    659     (*playerObject)->Destroy(playerObject);
    660     (*mixObject)->Destroy(mixObject);
    661     (*engineObject)->Destroy(engineObject);
    662 
    663     return EXIT_SUCCESS;
    664 }
    665