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
slesutCompareEnvironmentalReverbSettings(const SLEnvironmentalReverbSettings * settings1,const SLEnvironmentalReverbSettings * settings2)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
slesutPrintEnvironmentalReverbSettings(const SLEnvironmentalReverbSettings * settings)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
lookupEnvName(const char * name)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
printEnvNames(void)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
prefetch_callback(SLPrefetchStatusItf caller,void * context,SLuint32 event)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
main(int argc,char ** argv)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