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 <string.h>
     22 #include <stdio.h>
     23 #include <stdlib.h>
     24 #include <unistd.h>
     25 
     26 #define bool int
     27 #define false 0
     28 #define true 1
     29 
     30 // Table of I3DL2 named environmental reverb settings
     31 
     32 typedef struct {
     33     const char *mName;
     34     SLEnvironmentalReverbSettings mSettings;
     35 } Pair;
     36 
     37 #define _(name) {#name, SL_I3DL2_ENVIRONMENT_PRESET_##name},
     38 
     39 Pair pairs[] = {
     40     _(DEFAULT)
     41     _(GENERIC)
     42     _(PADDEDCELL)
     43     _(ROOM)
     44     _(BATHROOM)
     45     _(LIVINGROOM)
     46     _(STONEROOM)
     47     _(AUDITORIUM)
     48     _(CONCERTHALL)
     49     _(CAVE)
     50     _(ARENA)
     51     _(HANGAR)
     52     _(CARPETEDHALLWAY)
     53     _(HALLWAY)
     54     _(STONECORRIDOR)
     55     _(ALLEY)
     56     _(FOREST)
     57     _(CITY)
     58     _(MOUNTAINS)
     59     _(QUARRY)
     60     _(PLAIN)
     61     _(PARKINGLOT)
     62     _(SEWERPIPE)
     63     _(UNDERWATER)
     64     _(SMALLROOM)
     65     _(MEDIUMROOM)
     66     _(LARGEROOM)
     67     _(MEDIUMHALL)
     68     _(LARGEHALL)
     69     _(PLATE)
     70 };
     71 
     72 // Reverb parameters for output mix
     73 SLuint16 mixPresetNumber = ~0;
     74 char *mixEnvName = NULL;
     75 SLEnvironmentalReverbSettings mixEnvSettings;
     76 
     77 // Reverb parameters for audio player
     78 SLuint16 playerPresetNumber = ~0;
     79 char *playerEnvName = NULL;
     80 SLEnvironmentalReverbSettings playerEnvSettings;
     81 
     82 // Compare two environmental reverb settings structures.
     83 // Returns true if the settings are identical, or false if they are different.
     84 
     85 bool slesutCompareEnvronmentalReverbSettings(
     86         const SLEnvironmentalReverbSettings *settings1,
     87         const SLEnvironmentalReverbSettings *settings2)
     88 {
     89     return
     90         (settings1->roomLevel == settings2->roomLevel) &&
     91         (settings1->roomHFLevel == settings2->roomHFLevel) &&
     92         (settings1->decayTime == settings2->decayTime) &&
     93         (settings1->decayHFRatio == settings2->decayHFRatio) &&
     94         (settings1->reflectionsLevel == settings2->reflectionsLevel) &&
     95         (settings1->reflectionsDelay == settings2->reflectionsDelay) &&
     96         (settings1->reverbLevel == settings2->reverbLevel) &&
     97         (settings1->reverbDelay == settings2->reverbDelay) &&
     98         (settings1->diffusion == settings2->diffusion) &&
     99         (settings1->density == settings2->density);
    100 }
    101 
    102 // Print an environmental reverb settings structure.
    103 
    104 void slesutPrintEnvironmentalReverbSettings(const SLEnvironmentalReverbSettings *settings)
    105 {
    106     printf("roomLevel: %u\n", settings->roomLevel);
    107     printf("roomHFLevel: %u\n", settings->roomHFLevel);
    108     printf("decayTime: %lu\n", settings->decayTime);
    109     printf("decayHFRatio: %u\n", settings->decayHFRatio);
    110     printf("reflectionsLevel: %u\n", settings->reflectionsLevel);
    111     printf("reflectionsDelay: %lu\n", settings->reflectionsDelay);
    112     printf("reverbLevel: %u\n", settings->reverbLevel);
    113     printf("reverbDelay: %lu\n", settings->reverbDelay);
    114     printf("diffusion: %u\n", settings->diffusion);
    115     printf("density: %u\n", settings->density);
    116 }
    117 
    118 // Lookup environmental reverb settings by name
    119 
    120 const SLEnvironmentalReverbSettings *lookupEnvName(const char *name)
    121 {
    122     unsigned j;
    123     for (j = 0; j < sizeof(pairs) / sizeof(pairs[0]); ++j) {
    124         if (!strcasecmp(name, pairs[j].mName)) {
    125             return &pairs[j].mSettings;
    126         }
    127     }
    128     return NULL;
    129 }
    130 
    131 // Print all available environmental reverb names
    132 
    133 void printEnvNames(void)
    134 {
    135     unsigned j;
    136     bool needSpace = false;
    137     bool needNewline = false;
    138     unsigned lineLen = 0;
    139     for (j = 0; j < sizeof(pairs) / sizeof(pairs[0]); ++j) {
    140         const char *name = pairs[j].mName;
    141         unsigned nameLen = strlen(name);
    142         if (lineLen + (needSpace ? 1 : 0) + nameLen > 72) {
    143             putchar('\n');
    144             needSpace = false;
    145             needNewline = false;
    146             lineLen = 0;
    147         }
    148         if (needSpace) {
    149             putchar(' ');
    150             ++lineLen;
    151         }
    152         fputs(name, stdout);
    153         lineLen += nameLen;
    154         needSpace = true;
    155         needNewline = true;
    156     }
    157     if (needNewline) {
    158         putchar('\n');
    159     }
    160 }
    161 
    162 // Main program
    163 
    164 int main(int argc, char **argv)
    165 {
    166     SLresult result;
    167 
    168     // process command line parameters
    169     char *prog = argv[0];
    170     int i;
    171     for (i = 1; i < argc; ++i) {
    172         char *arg = argv[i];
    173         if (arg[0] != '-')
    174             break;
    175         if (!strncmp(arg, "--mix-preset=", 13)) {
    176             mixPresetNumber = atoi(&arg[13]);
    177         } else if (!strncmp(arg, "--mix-name=", 11)) {
    178             mixEnvName = &arg[11];
    179         } else if (!strncmp(arg, "--player-preset=", 16)) {
    180             playerPresetNumber = atoi(&arg[16]);
    181         } else if (!strncmp(arg, "--player-name=", 14)) {
    182             playerEnvName = &arg[14];
    183         } else {
    184             fprintf(stderr, "%s: unknown option %s ignored\n", prog, arg);
    185         }
    186     }
    187     if (argc - i != 1) {
    188         fprintf(stderr, "usage: %s --mix-preset=# --mix-name=I3DL2 --player-preset=# "
    189                 "--player-name=I3DL2 filename\n", prog);
    190         return EXIT_FAILURE;
    191     }
    192     char *pathname = argv[i];
    193 
    194     const SLEnvironmentalReverbSettings *envSettings;
    195     if (NULL != mixEnvName) {
    196         envSettings = lookupEnvName(mixEnvName);
    197         if (NULL == envSettings) {
    198             fprintf(stderr, "%s: mix environmental reverb name %s not found, "
    199                     "available names are:\n", prog, mixEnvName);
    200             printEnvNames();
    201             return EXIT_FAILURE;
    202         }
    203         mixEnvSettings = *envSettings;
    204     }
    205     if (NULL != playerEnvName) {
    206         envSettings = lookupEnvName(playerEnvName);
    207         if (NULL == envSettings) {
    208             fprintf(stderr, "%s: player environmental reverb name %s not found, "
    209                     "available names are:\n", prog, playerEnvName);
    210             printEnvNames();
    211             return EXIT_FAILURE;
    212         }
    213         playerEnvSettings = *envSettings;
    214     }
    215 
    216     // create engine
    217     SLObjectItf engineObject;
    218     result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
    219     assert(SL_RESULT_SUCCESS == result);
    220     result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
    221     assert(SL_RESULT_SUCCESS == result);
    222     SLEngineItf engineEngine;
    223     result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
    224     assert(SL_RESULT_SUCCESS == result);
    225 
    226     // create output mix
    227     SLInterfaceID mix_ids[2];
    228     SLboolean mix_req[2];
    229     SLuint32 count = 0;
    230     if (mixPresetNumber != ((SLuint16) ~0)) {
    231         mix_req[count] = SL_BOOLEAN_TRUE;
    232         mix_ids[count++] = SL_IID_PRESETREVERB;
    233     }
    234     if (mixEnvName != NULL) {
    235         mix_req[count] = SL_BOOLEAN_TRUE;
    236         mix_ids[count++] = SL_IID_ENVIRONMENTALREVERB;
    237     }
    238     SLObjectItf mixObject;
    239     result = (*engineEngine)->CreateOutputMix(engineEngine, &mixObject, count, mix_ids, mix_req);
    240     assert(SL_RESULT_SUCCESS == result);
    241     result = (*mixObject)->Realize(mixObject, SL_BOOLEAN_FALSE);
    242     assert(SL_RESULT_SUCCESS == result);
    243 
    244     // configure preset reverb on output mix
    245     SLPresetReverbItf mixPresetReverb;
    246     if (mixPresetNumber != ((SLuint16) ~0)) {
    247         result = (*mixObject)->GetInterface(mixObject, SL_IID_PRESETREVERB, &mixPresetReverb);
    248         assert(SL_RESULT_SUCCESS == result);
    249         SLuint16 getPresetReverb = 12345;
    250         result = (*mixPresetReverb)->GetPreset(mixPresetReverb, &getPresetReverb);
    251         assert(SL_RESULT_SUCCESS == result);
    252         printf("Output mix default preset reverb %u\n", getPresetReverb);
    253         result = (*mixPresetReverb)->SetPreset(mixPresetReverb, mixPresetNumber);
    254         if (SL_RESULT_SUCCESS == result) {
    255             result = (*mixPresetReverb)->GetPreset(mixPresetReverb, &getPresetReverb);
    256             assert(SL_RESULT_SUCCESS == result);
    257             assert(getPresetReverb == mixPresetNumber);
    258             printf("Output mix preset reverb successfully changed to %u\n", mixPresetNumber);
    259         } else
    260             printf("Unable to set output mix preset reverb to %u, result=%lu\n", mixPresetNumber,
    261                     result);
    262     }
    263 
    264     // configure environmental reverb on output mix
    265     SLEnvironmentalReverbItf mixEnvironmentalReverb;
    266     if (mixEnvName != NULL) {
    267         result = (*mixObject)->GetInterface(mixObject, SL_IID_ENVIRONMENTALREVERB,
    268                 &mixEnvironmentalReverb);
    269         assert(SL_RESULT_SUCCESS == result);
    270         SLEnvironmentalReverbSettings getSettings;
    271         result = (*mixEnvironmentalReverb)->GetEnvironmentalReverbProperties(mixEnvironmentalReverb,
    272                 &getSettings);
    273         assert(SL_RESULT_SUCCESS == result);
    274         printf("Output mix default environmental reverb settings\n");
    275         printf("------------------------------------------------\n");
    276         slesutPrintEnvironmentalReverbSettings(&getSettings);
    277         printf("\n");
    278         result = (*mixEnvironmentalReverb)->SetEnvironmentalReverbProperties(mixEnvironmentalReverb,
    279                 &mixEnvSettings);
    280         assert(SL_RESULT_SUCCESS == result);
    281         printf("Output mix new environmental reverb settings\n");
    282         printf("--------------------------------------------\n");
    283         slesutPrintEnvironmentalReverbSettings(&mixEnvSettings);
    284         printf("\n");
    285         result = (*mixEnvironmentalReverb)->GetEnvironmentalReverbProperties(mixEnvironmentalReverb,
    286                 &getSettings);
    287         assert(SL_RESULT_SUCCESS == result);
    288         printf("Output mix read environmental reverb settings\n");
    289         printf("--------------------------------------------\n");
    290         slesutPrintEnvironmentalReverbSettings(&getSettings);
    291         printf("\n");
    292         if (!slesutCompareEnvronmentalReverbSettings(&getSettings, &mixEnvSettings)) {
    293             printf("Warning: new and read are different; check details above\n");
    294         } else {
    295             printf("New and read match, life is good\n");
    296         }
    297     }
    298 
    299     // create audio player
    300     SLDataLocator_URI locURI = {SL_DATALOCATOR_URI, (SLchar *) pathname};
    301     SLDataFormat_MIME dfMIME = {SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED};
    302     SLDataSource audioSrc = {&locURI, &dfMIME};
    303     SLDataLocator_OutputMix locOutputMix = {SL_DATALOCATOR_OUTPUTMIX, mixObject};
    304     SLDataSink audioSnk = {&locOutputMix, NULL};
    305     SLInterfaceID player_ids[4];
    306     SLboolean player_req[4];
    307     count = 0;
    308     if (playerPresetNumber != ((SLuint16) ~0)) {
    309         player_req[count] = SL_BOOLEAN_TRUE;
    310         player_ids[count++] = SL_IID_PRESETREVERB;
    311     }
    312     if (playerEnvName != NULL) {
    313         player_req[count] = SL_BOOLEAN_TRUE;
    314         player_ids[count++] = SL_IID_ENVIRONMENTALREVERB;
    315     }
    316     if (mixPresetNumber != ((SLuint16) ~0) || mixEnvName != NULL) {
    317         player_req[count] = SL_BOOLEAN_TRUE;
    318         player_ids[count++] = SL_IID_EFFECTSEND;
    319     }
    320     player_req[count] = SL_BOOLEAN_TRUE;
    321     player_ids[count++] = SL_IID_PREFETCHSTATUS;
    322     SLObjectItf playerObject;
    323     result = (*engineEngine)->CreateAudioPlayer(engineEngine, &playerObject, &audioSrc,
    324         &audioSnk, count, player_ids, player_req);
    325     assert(SL_RESULT_SUCCESS == result);
    326 
    327     // realize audio player
    328     result = (*playerObject)->Realize(playerObject, SL_BOOLEAN_FALSE);
    329     assert(SL_RESULT_SUCCESS == result);
    330 
    331     // if reverb is on output mix (aux effect), then enable it for this player
    332     if (mixPresetNumber != ((SLuint16) ~0) || mixEnvName != NULL) {
    333         SLEffectSendItf playerEffectSend;
    334         result = (*playerObject)->GetInterface(playerObject, SL_IID_EFFECTSEND, &playerEffectSend);
    335         assert(SL_RESULT_SUCCESS == result);
    336         if (mixPresetNumber != ((SLuint16) ~0)) {
    337             result = (*playerEffectSend)->EnableEffectSend(playerEffectSend, mixPresetReverb,
    338                     SL_BOOLEAN_TRUE, (SLmillibel) 0);
    339             assert(SL_RESULT_SUCCESS == result);
    340         }
    341         if (mixEnvName != NULL) {
    342             result = (*playerEffectSend)->EnableEffectSend(playerEffectSend, mixEnvironmentalReverb,
    343                     SL_BOOLEAN_TRUE, (SLmillibel) 0);
    344             assert(SL_RESULT_SUCCESS == result);
    345         }
    346     }
    347 
    348     // configure preset reverb on player
    349     SLPresetReverbItf playerPresetReverb;
    350     if (playerPresetNumber != ((SLuint16) ~0)) {
    351         result = (*playerObject)->GetInterface(playerObject, SL_IID_PRESETREVERB,
    352                 &playerPresetReverb);
    353         assert(SL_RESULT_SUCCESS == result);
    354         SLuint16 getPresetReverb = 12345;
    355         result = (*playerPresetReverb)->GetPreset(playerPresetReverb, &getPresetReverb);
    356         assert(SL_RESULT_SUCCESS == result);
    357         printf("Player default preset reverb %u\n", getPresetReverb);
    358         result = (*playerPresetReverb)->SetPreset(playerPresetReverb, playerPresetNumber);
    359         if (SL_RESULT_SUCCESS == result) {
    360             result = (*playerPresetReverb)->GetPreset(playerPresetReverb, &getPresetReverb);
    361             assert(SL_RESULT_SUCCESS == result);
    362             assert(getPresetReverb == playerPresetNumber);
    363             printf("Player preset reverb successfully changed to %u\n", playerPresetNumber);
    364         } else
    365             printf("Unable to set player preset reverb to %u, result=%lu\n", playerPresetNumber,
    366                     result);
    367     }
    368 
    369     // configure environmental reverb on player
    370     SLEnvironmentalReverbItf playerEnvironmentalReverb;
    371     if (playerEnvName != NULL) {
    372         result = (*playerObject)->GetInterface(playerObject, SL_IID_ENVIRONMENTALREVERB,
    373                 &playerEnvironmentalReverb);
    374         assert(SL_RESULT_SUCCESS == result);
    375         SLEnvironmentalReverbSettings getSettings;
    376         memset(&getSettings, 0, sizeof(getSettings));
    377         result = (*playerEnvironmentalReverb)->GetEnvironmentalReverbProperties(
    378                 playerEnvironmentalReverb, &getSettings);
    379         assert(SL_RESULT_SUCCESS == result);
    380         printf("Player default environmental reverb settings\n");
    381         printf("--------------------------------------------\n");
    382         slesutPrintEnvironmentalReverbSettings(&getSettings);
    383         printf("\n");
    384         result = (*playerEnvironmentalReverb)->SetEnvironmentalReverbProperties(
    385                 playerEnvironmentalReverb, &playerEnvSettings);
    386         assert(SL_RESULT_SUCCESS == result);
    387         printf("Player new environmental reverb settings\n");
    388         printf("----------------------------------------\n");
    389         slesutPrintEnvironmentalReverbSettings(&playerEnvSettings);
    390         printf("\n");
    391         result = (*playerEnvironmentalReverb)->GetEnvironmentalReverbProperties(
    392                 playerEnvironmentalReverb, &getSettings);
    393         assert(SL_RESULT_SUCCESS == result);
    394         printf("Player read environmental reverb settings\n");
    395         printf("-----------------------------------------\n");
    396         slesutPrintEnvironmentalReverbSettings(&getSettings);
    397         printf("\n");
    398         if (!slesutCompareEnvronmentalReverbSettings(&getSettings, &playerEnvSettings)) {
    399             printf("Warning: new and read are different; check details above\n");
    400         } else {
    401             printf("New and read match, life is good\n");
    402         }
    403     }
    404 
    405     // get the play interface
    406     SLPlayItf playerPlay;
    407     result = (*playerObject)->GetInterface(playerObject, SL_IID_PLAY, &playerPlay);
    408     assert(SL_RESULT_SUCCESS == result);
    409 
    410     // set play state to paused to enable pre-fetch so we can get a more reliable duration
    411     result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PAUSED);
    412     assert(SL_RESULT_SUCCESS == result);
    413 
    414     // get the prefetch status interface
    415     SLPrefetchStatusItf playerPrefetchStatus;
    416     result = (*playerObject)->GetInterface(playerObject, SL_IID_PREFETCHSTATUS,
    417             &playerPrefetchStatus);
    418     assert(SL_RESULT_SUCCESS == result);
    419 
    420     // poll prefetch status to detect when it completes
    421     SLuint32 prefetchStatus = SL_PREFETCHSTATUS_UNDERFLOW;
    422     SLuint32 timeOutIndex = 100; // 10s
    423     while ((prefetchStatus != SL_PREFETCHSTATUS_SUFFICIENTDATA) && (timeOutIndex > 0)) {
    424         usleep(100 * 1000);
    425         (*playerPrefetchStatus)->GetPrefetchStatus(playerPrefetchStatus, &prefetchStatus);
    426         timeOutIndex--;
    427     }
    428     if (timeOutIndex == 0) {
    429         fprintf(stderr, "\nWe\'re done waiting, failed to prefetch data in time, exiting\n");
    430         goto destroyRes;
    431     }
    432 
    433     // get the duration
    434     SLmillisecond duration;
    435     result = (*playerPlay)->GetDuration(playerPlay, &duration);
    436     assert(SL_RESULT_SUCCESS == result);
    437     if (SL_TIME_UNKNOWN == duration) {
    438         printf("duration: unknown\n");
    439     } else {
    440         printf("duration: %.1f seconds\n", duration / 1000.0);
    441     }
    442 
    443     // start audio playing
    444     result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING);
    445     assert(SL_RESULT_SUCCESS == result);
    446 
    447     // wait for audio to finish playing
    448     SLuint32 state;
    449     for (;;) {
    450         result = (*playerPlay)->GetPlayState(playerPlay, &state);
    451         assert(SL_RESULT_SUCCESS == result);
    452         if (SL_PLAYSTATE_PLAYING != state)
    453             break;
    454         usleep(1000000);
    455      }
    456     assert(SL_PLAYSTATE_PAUSED == state);
    457 
    458 destroyRes:
    459     // cleanup objects
    460     (*playerObject)->Destroy(playerObject);
    461     (*mixObject)->Destroy(mixObject);
    462     (*engineObject)->Destroy(engineObject);
    463 
    464     return EXIT_SUCCESS;
    465 }
    466