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