• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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