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
slesutCompareEnvronmentalReverbSettings(const SLEnvironmentalReverbSettings * settings1,const SLEnvironmentalReverbSettings * settings2)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
slesutPrintEnvironmentalReverbSettings(const SLEnvironmentalReverbSettings * settings)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
lookupEnvName(const char * name)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
printEnvNames(void)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
main(int argc,char ** argv)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