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