reverb.c revision 58432eb9cea995c69b4f905e68b38c1b8216edeb
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 32typedef struct { 33 const char *mName; 34 SLEnvironmentalReverbSettings mSettings; 35} Pair; 36 37#define _(name) {#name, SL_I3DL2_ENVIRONMENT_PRESET_##name}, 38 39Pair 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// Parameters for preset reverb on output mix 73bool outputMixPresetItfRequested = false; 74SLuint16 outputMixPresetNumber = ~0; 75 76// Parameters for environmental reverb on output mix 77bool outputMixEnvironmentalItfRequested = false; 78char *outputMixEnvironmentalName = NULL; 79SLEnvironmentalReverbSettings outputMixEnvironmentalSettings; 80 81// Parameters for preset reverb on audio player (not supported) 82bool playerPresetItfRequested = false; 83SLuint16 playerPresetNumber = ~0; 84 85// Parameters for environmental reverb on audio player (not supported) 86bool playerEnvironmentalItfRequested = false; 87char *playerEnvironmentalName = NULL; 88SLEnvironmentalReverbSettings playerEnvironmentalSettings; 89 90// Compare two environmental reverb settings structures. 91// Returns true if the settings are identical, or false if they are different. 92 93bool slesutCompareEnvironmentalReverbSettings( 94 const SLEnvironmentalReverbSettings *settings1, 95 const SLEnvironmentalReverbSettings *settings2) 96{ 97 return 98 (settings1->roomLevel == settings2->roomLevel) && 99 (settings1->roomHFLevel == settings2->roomHFLevel) && 100 (settings1->decayTime == settings2->decayTime) && 101 (settings1->decayHFRatio == settings2->decayHFRatio) && 102 (settings1->reflectionsLevel == settings2->reflectionsLevel) && 103 (settings1->reflectionsDelay == settings2->reflectionsDelay) && 104 (settings1->reverbLevel == settings2->reverbLevel) && 105 (settings1->reverbDelay == settings2->reverbDelay) && 106 (settings1->diffusion == settings2->diffusion) && 107 (settings1->density == settings2->density); 108} 109 110// Print an environmental reverb settings structure. 111 112void slesutPrintEnvironmentalReverbSettings(const SLEnvironmentalReverbSettings *settings) 113{ 114 printf("roomLevel: %d\n", settings->roomLevel); 115 printf("roomHFLevel: %d\n", settings->roomHFLevel); 116 printf("decayTime: %d\n", settings->decayTime); 117 printf("decayHFRatio: %d\n", settings->decayHFRatio); 118 printf("reflectionsLevel: %d\n", settings->reflectionsLevel); 119 printf("reflectionsDelay: %d\n", settings->reflectionsDelay); 120 printf("reverbLevel: %d\n", settings->reverbLevel); 121 printf("reverbDelay: %d\n", settings->reverbDelay); 122 printf("diffusion: %d\n", settings->diffusion); 123 printf("density: %d\n", settings->density); 124} 125 126// Lookup environmental reverb settings by name 127 128const SLEnvironmentalReverbSettings *lookupEnvName(const char *name) 129{ 130 unsigned j; 131 for (j = 0; j < sizeof(pairs) / sizeof(pairs[0]); ++j) { 132 if (!strcasecmp(name, pairs[j].mName)) { 133 return &pairs[j].mSettings; 134 } 135 } 136 return NULL; 137} 138 139// Print all available environmental reverb names 140 141void printEnvNames(void) 142{ 143 unsigned j; 144 bool needSpace = false; 145 bool needNewline = false; 146 unsigned lineLen = 0; 147 for (j = 0; j < sizeof(pairs) / sizeof(pairs[0]); ++j) { 148 const char *name = pairs[j].mName; 149 unsigned nameLen = strlen(name); 150 if (lineLen + (needSpace ? 1 : 0) + nameLen > 72) { 151 putchar('\n'); 152 needSpace = false; 153 needNewline = false; 154 lineLen = 0; 155 } 156 if (needSpace) { 157 putchar(' '); 158 ++lineLen; 159 } 160 fputs(name, stdout); 161 lineLen += nameLen; 162 needSpace = true; 163 needNewline = true; 164 } 165 if (needNewline) { 166 putchar('\n'); 167 } 168} 169 170// Main program 171 172int main(int argc, char **argv) 173{ 174 SLresult result; 175 176 // process command line parameters 177 char *prog = argv[0]; 178 int i; 179 for (i = 1; i < argc; ++i) { 180 char *arg = argv[i]; 181 if (arg[0] != '-') 182 break; 183 bool bad = false; // whether the option string is invalid 184 if (!strncmp(arg, "--mix-preset", 12)) { 185 if ('\0' == arg[12]) { 186 outputMixPresetItfRequested = true; 187 } else if ('=' == arg[12]) { 188 outputMixPresetNumber = atoi(&arg[13]); 189 outputMixPresetItfRequested = true; 190 } else { 191 bad = true; 192 } 193 } else if (!strncmp(arg, "--mix-name", 10)) { 194 if ('\0' == arg[10]) { 195 outputMixEnvironmentalItfRequested = true; 196 } else if ('=' == arg[10]) { 197 outputMixEnvironmentalName = &arg[11]; 198 outputMixEnvironmentalItfRequested = true; 199 } else { 200 bad = true; 201 } 202 } else if (!strncmp(arg, "--player-preset", 15)) { 203 if ('\0' == arg[15]) { 204 playerPresetItfRequested = true; 205 } else if ('=' == arg[15]) { 206 playerPresetNumber = atoi(&arg[16]); 207 playerPresetItfRequested = true; 208 } else { 209 bad = true; 210 } 211 } else if (!strncmp(arg, "--player-name", 13)) { 212 if ('\0' == arg[13]) { 213 playerEnvironmentalItfRequested = true; 214 } else if ('=' == arg[13]) { 215 playerEnvironmentalName = &arg[14]; 216 playerEnvironmentalItfRequested = true; 217 } else { 218 bad = true; 219 } 220 } else { 221 bad = true; 222 } 223 if (bad) { 224 fprintf(stderr, "%s: unknown option %s ignored\n", prog, arg); 225 } 226 } 227 if (argc - i != 1) { 228 fprintf(stderr, "usage: %s --mix-preset=# --mix-name=I3DL2 --player-preset=# " 229 "--player-name=I3DL2 filename\n", prog); 230 return EXIT_FAILURE; 231 } 232 char *pathname = argv[i]; 233 234 const SLEnvironmentalReverbSettings *envSettings; 235 if (NULL != outputMixEnvironmentalName) { 236 envSettings = lookupEnvName(outputMixEnvironmentalName); 237 if (NULL == envSettings) { 238 fprintf(stderr, "%s: output mix environmental reverb name %s not found, " 239 "available names are:\n", prog, outputMixEnvironmentalName); 240 printEnvNames(); 241 return EXIT_FAILURE; 242 } 243 outputMixEnvironmentalSettings = *envSettings; 244 } 245 if (NULL != playerEnvironmentalName) { 246 envSettings = lookupEnvName(playerEnvironmentalName); 247 if (NULL == envSettings) { 248 fprintf(stderr, "%s: player environmental reverb name %s not found, " 249 "available names are:\n", prog, playerEnvironmentalName); 250 printEnvNames(); 251 return EXIT_FAILURE; 252 } 253 playerEnvironmentalSettings = *envSettings; 254 } 255 256 // create engine 257 SLObjectItf engineObject; 258 result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); 259 assert(SL_RESULT_SUCCESS == result); 260 result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE); 261 assert(SL_RESULT_SUCCESS == result); 262 SLEngineItf engineEngine; 263 result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine); 264 assert(SL_RESULT_SUCCESS == result); 265 266 // create output mix 267 SLInterfaceID mix_ids[2]; 268 SLboolean mix_req[2]; 269 SLuint32 count = 0; 270 if (outputMixPresetItfRequested) { 271 mix_req[count] = SL_BOOLEAN_TRUE; 272 mix_ids[count++] = SL_IID_PRESETREVERB; 273 } 274 if (outputMixEnvironmentalItfRequested) { 275 mix_req[count] = SL_BOOLEAN_TRUE; 276 mix_ids[count++] = SL_IID_ENVIRONMENTALREVERB; 277 } 278 SLObjectItf mixObject; 279 result = (*engineEngine)->CreateOutputMix(engineEngine, &mixObject, count, mix_ids, mix_req); 280 assert(SL_RESULT_SUCCESS == result); 281 result = (*mixObject)->Realize(mixObject, SL_BOOLEAN_FALSE); 282 assert(SL_RESULT_SUCCESS == result); 283 284 // configure preset reverb on output mix 285 SLPresetReverbItf outputMixPresetReverb; 286 if (outputMixPresetItfRequested) { 287 result = (*mixObject)->GetInterface(mixObject, SL_IID_PRESETREVERB, &outputMixPresetReverb); 288 assert(SL_RESULT_SUCCESS == result); 289 SLuint16 getPresetReverb = 12345; 290 result = (*outputMixPresetReverb)->GetPreset(outputMixPresetReverb, &getPresetReverb); 291 assert(SL_RESULT_SUCCESS == result); 292 printf("Output mix default preset reverb number = %u\n", getPresetReverb); 293 if (outputMixPresetNumber != ((SLuint16) ~0)) { 294 result = (*outputMixPresetReverb)->SetPreset(outputMixPresetReverb, 295 outputMixPresetNumber); 296 if (SL_RESULT_SUCCESS == result) { 297 result = (*outputMixPresetReverb)->GetPreset(outputMixPresetReverb, 298 &getPresetReverb); 299 assert(SL_RESULT_SUCCESS == result); 300 assert(getPresetReverb == outputMixPresetNumber); 301 printf("Output mix preset reverb successfully changed to %u\n", 302 outputMixPresetNumber); 303 } else { 304 printf("Unable to set output mix preset reverb to %u, result=%u\n", 305 outputMixPresetNumber, result); 306 } 307 } 308 } 309 310 // configure environmental reverb on output mix 311 SLEnvironmentalReverbItf outputMixEnvironmentalReverb; 312 if (outputMixEnvironmentalItfRequested) { 313 result = (*mixObject)->GetInterface(mixObject, SL_IID_ENVIRONMENTALREVERB, 314 &outputMixEnvironmentalReverb); 315 assert(SL_RESULT_SUCCESS == result); 316 SLEnvironmentalReverbSettings getSettings; 317 result = (*outputMixEnvironmentalReverb)->GetEnvironmentalReverbProperties( 318 outputMixEnvironmentalReverb, &getSettings); 319 assert(SL_RESULT_SUCCESS == result); 320 printf("Output mix default environmental reverb settings\n"); 321 printf("------------------------------------------------\n"); 322 slesutPrintEnvironmentalReverbSettings(&getSettings); 323 printf("\n"); 324 if (outputMixEnvironmentalName != NULL) { 325 result = (*outputMixEnvironmentalReverb)->SetEnvironmentalReverbProperties( 326 outputMixEnvironmentalReverb, &outputMixEnvironmentalSettings); 327 assert(SL_RESULT_SUCCESS == result); 328 printf("Output mix new environmental reverb settings\n"); 329 printf("--------------------------------------------\n"); 330 slesutPrintEnvironmentalReverbSettings(&outputMixEnvironmentalSettings); 331 printf("\n"); 332 result = (*outputMixEnvironmentalReverb)->GetEnvironmentalReverbProperties( 333 outputMixEnvironmentalReverb, &getSettings); 334 assert(SL_RESULT_SUCCESS == result); 335 printf("Output mix read environmental reverb settings\n"); 336 printf("--------------------------------------------\n"); 337 slesutPrintEnvironmentalReverbSettings(&getSettings); 338 printf("\n"); 339 if (!slesutCompareEnvironmentalReverbSettings(&getSettings, 340 &outputMixEnvironmentalSettings)) { 341 printf("Warning: new and read are different; check details above\n"); 342 } else { 343 printf("New and read match, life is good\n"); 344 } 345 } 346 } 347 348 // create audio player 349 SLDataLocator_URI locURI = {SL_DATALOCATOR_URI, (SLchar *) pathname}; 350 SLDataFormat_MIME dfMIME = {SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED}; 351 SLDataSource audioSrc = {&locURI, &dfMIME}; 352 SLDataLocator_OutputMix locOutputMix = {SL_DATALOCATOR_OUTPUTMIX, mixObject}; 353 SLDataSink audioSnk = {&locOutputMix, NULL}; 354 SLInterfaceID player_ids[4]; 355 SLboolean player_req[4]; 356 count = 0; 357 if (playerPresetItfRequested) { 358 player_req[count] = SL_BOOLEAN_TRUE; 359 player_ids[count++] = SL_IID_PRESETREVERB; 360 } 361 if (playerEnvironmentalItfRequested) { 362 player_req[count] = SL_BOOLEAN_TRUE; 363 player_ids[count++] = SL_IID_ENVIRONMENTALREVERB; 364 } 365 if (outputMixPresetItfRequested || outputMixEnvironmentalItfRequested) { 366 player_req[count] = SL_BOOLEAN_TRUE; 367 player_ids[count++] = SL_IID_EFFECTSEND; 368 } 369 player_req[count] = SL_BOOLEAN_TRUE; 370 player_ids[count++] = SL_IID_PREFETCHSTATUS; 371 SLObjectItf playerObject; 372 result = (*engineEngine)->CreateAudioPlayer(engineEngine, &playerObject, &audioSrc, 373 &audioSnk, count, player_ids, player_req); 374 assert(SL_RESULT_SUCCESS == result); 375 376 // realize audio player 377 result = (*playerObject)->Realize(playerObject, SL_BOOLEAN_FALSE); 378 assert(SL_RESULT_SUCCESS == result); 379 380 // if reverb is on output mix (aux effect), then enable it for this player 381 if (outputMixPresetItfRequested || outputMixEnvironmentalItfRequested) { 382 SLEffectSendItf playerEffectSend; 383 result = (*playerObject)->GetInterface(playerObject, SL_IID_EFFECTSEND, &playerEffectSend); 384 assert(SL_RESULT_SUCCESS == result); 385 SLboolean enabled; 386 SLmillibel directLevel; 387 SLmillibel sendLevel; 388 if (outputMixPresetItfRequested) { 389 result = (*playerEffectSend)->IsEnabled(playerEffectSend, outputMixPresetReverb, 390 &enabled); 391 assert(SL_RESULT_SUCCESS == result); 392 printf("Output mix preset reverb: player effect send default enabled = %s\n", 393 enabled ? "true" : "false"); 394 directLevel = 12345; 395 result = (*playerEffectSend)->GetDirectLevel(playerEffectSend, &directLevel); 396 assert(SL_RESULT_SUCCESS == result); 397 printf("Output mix preset reverb: player effect send default direct level = %d\n", 398 directLevel); 399 sendLevel = 12345; 400 result = (*playerEffectSend)->GetSendLevel(playerEffectSend, outputMixPresetReverb, 401 &sendLevel); 402 assert(SL_RESULT_SUCCESS == result); 403 printf("Output mix preset reverb: player effect send default send level = %d\n", 404 sendLevel); 405 if (outputMixPresetNumber != ((SLuint16) ~0)) { 406 result = (*playerEffectSend)->EnableEffectSend(playerEffectSend, 407 outputMixPresetReverb, SL_BOOLEAN_TRUE, (SLmillibel) 0); 408 assert(SL_RESULT_SUCCESS == result); 409 result = (*playerEffectSend)->IsEnabled(playerEffectSend, outputMixPresetReverb, 410 &enabled); 411 assert(SL_RESULT_SUCCESS == result); 412 directLevel = 12345; 413 result = (*playerEffectSend)->GetDirectLevel(playerEffectSend, &directLevel); 414 assert(SL_RESULT_SUCCESS == result); 415 sendLevel = 12345; 416 result = (*playerEffectSend)->GetSendLevel(playerEffectSend, outputMixPresetReverb, 417 &sendLevel); 418 assert(SL_RESULT_SUCCESS == result); 419 printf("Output mix preset reverb: player effect send new enabled = %s, direct level" 420 " = %d, send level = %d\n", enabled ? "true" : "false", directLevel, sendLevel); 421 } 422 } 423 if (outputMixEnvironmentalItfRequested) { 424 if (outputMixEnvironmentalName != NULL) { 425 result = (*playerEffectSend)->IsEnabled(playerEffectSend, 426 outputMixEnvironmentalReverb, &enabled); 427 assert(SL_RESULT_SUCCESS == result); 428 printf("Output mix environmental reverb: player effect send default enabled = %s\n", 429 enabled ? "true" : "false"); 430 directLevel = 12345; 431 result = (*playerEffectSend)->GetDirectLevel(playerEffectSend, &directLevel); 432 assert(SL_RESULT_SUCCESS == result); 433 printf("Output mix environmental reverb: player effect send default direct level" 434 " = %d\n", directLevel); 435 sendLevel = 12345; 436 result = (*playerEffectSend)->GetSendLevel(playerEffectSend, 437 outputMixEnvironmentalReverb, &sendLevel); 438 assert(SL_RESULT_SUCCESS == result); 439 printf("Output mix environmental reverb: player effect send default send level" 440 " = %d\n", sendLevel); 441 result = (*playerEffectSend)->EnableEffectSend(playerEffectSend, 442 outputMixEnvironmentalReverb, SL_BOOLEAN_TRUE, (SLmillibel) 0); 443 assert(SL_RESULT_SUCCESS == result); 444 result = (*playerEffectSend)->IsEnabled(playerEffectSend, 445 outputMixEnvironmentalReverb, &enabled); 446 assert(SL_RESULT_SUCCESS == result); 447 directLevel = 12345; 448 result = (*playerEffectSend)->GetDirectLevel(playerEffectSend, &directLevel); 449 assert(SL_RESULT_SUCCESS == result); 450 sendLevel = 12345; 451 result = (*playerEffectSend)->GetSendLevel(playerEffectSend, 452 outputMixEnvironmentalReverb, &sendLevel); 453 assert(SL_RESULT_SUCCESS == result); 454 printf("Output mix environmental reverb: player effect send new enabled = %s, " 455 "direct level = %d, send level = %d\n", enabled ? "true" : "false", 456 directLevel, sendLevel); 457 } 458 } 459 } 460 461 // configure preset reverb on player 462 SLPresetReverbItf playerPresetReverb; 463 if (playerPresetItfRequested) { 464 result = (*playerObject)->GetInterface(playerObject, SL_IID_PRESETREVERB, 465 &playerPresetReverb); 466 assert(SL_RESULT_SUCCESS == result); 467 SLuint16 getPresetReverb = 12345; 468 result = (*playerPresetReverb)->GetPreset(playerPresetReverb, &getPresetReverb); 469 if (SL_RESULT_SUCCESS == result) { 470 printf("Player default preset reverb %u\n", getPresetReverb); 471 if (playerPresetNumber != ((SLuint16) ~0)) { 472 result = (*playerPresetReverb)->SetPreset(playerPresetReverb, playerPresetNumber); 473 if (SL_RESULT_SUCCESS == result) { 474 result = (*playerPresetReverb)->GetPreset(playerPresetReverb, &getPresetReverb); 475 assert(SL_RESULT_SUCCESS == result); 476 assert(getPresetReverb == playerPresetNumber); 477 printf("Player preset reverb successfully changed to %u\n", playerPresetNumber); 478 } else { 479 printf("Unable to set player preset reverb to %u, result=%u\n", 480 playerPresetNumber, result); 481 } 482 } 483 } else { 484 printf("Unable to get player default preset reverb, result=%u\n", result); 485 } 486 } 487 488 // configure environmental reverb on player 489 SLEnvironmentalReverbItf playerEnvironmentalReverb; 490 if (playerEnvironmentalItfRequested) { 491 result = (*playerObject)->GetInterface(playerObject, SL_IID_ENVIRONMENTALREVERB, 492 &playerEnvironmentalReverb); 493 assert(SL_RESULT_SUCCESS == result); 494 SLEnvironmentalReverbSettings getSettings; 495 memset(&getSettings, 0, sizeof(getSettings)); 496 result = (*playerEnvironmentalReverb)->GetEnvironmentalReverbProperties( 497 playerEnvironmentalReverb, &getSettings); 498 if (SL_RESULT_SUCCESS == result) { 499 printf("Player default environmental reverb settings\n"); 500 printf("--------------------------------------------\n"); 501 slesutPrintEnvironmentalReverbSettings(&getSettings); 502 printf("\n"); 503 if (playerEnvironmentalName != NULL) { 504 result = (*playerEnvironmentalReverb)->SetEnvironmentalReverbProperties( 505 playerEnvironmentalReverb, &playerEnvironmentalSettings); 506 assert(SL_RESULT_SUCCESS == result); 507 printf("Player new environmental reverb settings\n"); 508 printf("----------------------------------------\n"); 509 slesutPrintEnvironmentalReverbSettings(&playerEnvironmentalSettings); 510 printf("\n"); 511 result = (*playerEnvironmentalReverb)->GetEnvironmentalReverbProperties( 512 playerEnvironmentalReverb, &getSettings); 513 assert(SL_RESULT_SUCCESS == result); 514 printf("Player read environmental reverb settings\n"); 515 printf("-----------------------------------------\n"); 516 slesutPrintEnvironmentalReverbSettings(&getSettings); 517 printf("\n"); 518 if (!slesutCompareEnvironmentalReverbSettings(&getSettings, 519 &playerEnvironmentalSettings)) { 520 printf("Warning: new and read are different; check details above\n"); 521 } else { 522 printf("New and read match, life is good\n"); 523 } 524 } 525 } else { 526 printf("Unable to get player default environmental reverb properties, result=%u\n", 527 result); 528 } 529 } 530 531 // get the play interface 532 SLPlayItf playerPlay; 533 result = (*playerObject)->GetInterface(playerObject, SL_IID_PLAY, &playerPlay); 534 assert(SL_RESULT_SUCCESS == result); 535 536 // set play state to paused to enable pre-fetch so we can get a more reliable duration 537 result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PAUSED); 538 assert(SL_RESULT_SUCCESS == result); 539 540 // get the prefetch status interface 541 SLPrefetchStatusItf playerPrefetchStatus; 542 result = (*playerObject)->GetInterface(playerObject, SL_IID_PREFETCHSTATUS, 543 &playerPrefetchStatus); 544 assert(SL_RESULT_SUCCESS == result); 545 546 // poll prefetch status to detect when it completes 547 SLuint32 prefetchStatus = SL_PREFETCHSTATUS_UNDERFLOW; 548 SLuint32 timeOutIndex = 100; // 10s 549 while ((prefetchStatus != SL_PREFETCHSTATUS_SUFFICIENTDATA) && (timeOutIndex > 0)) { 550 usleep(100 * 1000); 551 (*playerPrefetchStatus)->GetPrefetchStatus(playerPrefetchStatus, &prefetchStatus); 552 timeOutIndex--; 553 } 554 if (timeOutIndex == 0) { 555 fprintf(stderr, "\nWe\'re done waiting, failed to prefetch data in time, exiting\n"); 556 goto destroyRes; 557 } 558 559 // get the duration 560 SLmillisecond duration; 561 result = (*playerPlay)->GetDuration(playerPlay, &duration); 562 assert(SL_RESULT_SUCCESS == result); 563 if (SL_TIME_UNKNOWN == duration) { 564 printf("duration: unknown\n"); 565 } else { 566 printf("duration: %.1f seconds\n", duration / 1000.0); 567 } 568 569 // start audio playing 570 result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING); 571 assert(SL_RESULT_SUCCESS == result); 572 573 // wait for audio to finish playing 574 SLuint32 state; 575 for (;;) { 576 result = (*playerPlay)->GetPlayState(playerPlay, &state); 577 assert(SL_RESULT_SUCCESS == result); 578 if (SL_PLAYSTATE_PLAYING != state) 579 break; 580 usleep(1000000); 581 } 582 assert(SL_PLAYSTATE_PAUSED == state); 583 584destroyRes: 585 // cleanup objects 586 (*playerObject)->Destroy(playerObject); 587 (*mixObject)->Destroy(mixObject); 588 (*engineObject)->Destroy(engineObject); 589 590 return EXIT_SUCCESS; 591} 592