reverb.c revision c2303eb5497c488db786dcb2b8514db229452536
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// Table of I3DL2 named environmental reverb settings 27 28typedef struct { 29 const char *mName; 30 SLEnvironmentalReverbSettings mSettings; 31} Pair; 32 33#define _(name) {#name, SL_I3DL2_ENVIRONMENT_PRESET_##name}, 34 35Pair pairs[] = { 36 _(DEFAULT) 37 _(GENERIC) 38 _(PADDEDCELL) 39 _(ROOM) 40 _(BATHROOM) 41 _(LIVINGROOM) 42 _(STONEROOM) 43 _(AUDITORIUM) 44 _(CONCERTHALL) 45 _(CAVE) 46 _(ARENA) 47 _(HANGAR) 48 _(CARPETEDHALLWAY) 49 _(HALLWAY) 50 _(STONECORRIDOR) 51 _(ALLEY) 52 _(FOREST) 53 _(CITY) 54 _(MOUNTAINS) 55 _(QUARRY) 56 _(PLAIN) 57 _(PARKINGLOT) 58 _(SEWERPIPE) 59 _(UNDERWATER) 60 _(SMALLROOM) 61 _(MEDIUMROOM) 62 _(LARGEROOM) 63 _(MEDIUMHALL) 64 _(LARGEHALL) 65 _(PLATE) 66}; 67 68// Reverb parameters for output mix 69SLuint16 mixPresetNumber = ~0; 70char *mixEnvName = NULL; 71SLEnvironmentalReverbSettings mixEnvSettings; 72 73// Reverb parameters for audio player 74SLuint16 playerPreset = ~0; 75char *playerName = NULL; 76SLEnvironmentalReverbSettings playerSettings; 77 78// Compare two environmental reverb settings structures. 79// Returns true if the settings are identical, or false if they are different. 80 81#define bool int 82bool slesutCompareEnvronmentalReverbSettings( 83 const SLEnvironmentalReverbSettings *settings1, 84 const SLEnvironmentalReverbSettings *settings2) 85{ 86 return 87 (settings1->roomLevel == settings2->roomLevel) && 88 (settings1->roomHFLevel == settings2->roomHFLevel) && 89 (settings1->decayTime == settings2->decayTime) && 90 (settings1->decayHFRatio == settings2->decayHFRatio) && 91 (settings1->reflectionsLevel == settings2->reflectionsLevel) && 92 (settings1->reflectionsDelay == settings2->reflectionsDelay) && 93 (settings1->reverbLevel == settings2->reverbLevel) && 94 (settings1->reverbDelay == settings2->reverbDelay) && 95 (settings1->diffusion == settings2->diffusion) && 96 (settings1->density == settings2->density); 97} 98 99// Print an environmental reverb settings structure. 100 101void slesutPrintEnvironmentalReverbSettings( const SLEnvironmentalReverbSettings *settings) 102{ 103 printf("roomLevel: %u\n", settings->roomLevel); 104 printf("roomHFLevel: %u\n", settings->roomHFLevel); 105 printf("decayTime: %lu\n", settings->decayTime); 106 printf("decayHFRatio: %u\n", settings->decayHFRatio); 107 printf("reflectionsLevel: %u\n", settings->reflectionsLevel); 108 printf("reflectionsDelay: %lu\n", settings->reflectionsDelay); 109 printf("reverbLevel: %u\n", settings->reverbLevel); 110 printf("reverbDelay: %lu\n", settings->reverbDelay); 111 printf("diffusion: %u\n", settings->diffusion); 112 printf("density: %u\n", settings->density); 113} 114 115// Main program 116 117int main(int argc, char **argv) 118{ 119 SLresult result; 120 121 // process command line parameters 122 char *prog = argv[0]; 123 int i; 124 for (i = 1; i < argc; ++i) { 125 char *arg = argv[i]; 126 if (arg[0] != '-') 127 break; 128 if (!strncmp(arg, "--mix-preset=", 13)) { 129 mixPresetNumber = atoi(&arg[13]); 130 } else if (!strncmp(arg, "--mix-name=", 11)) { 131 mixEnvName = &arg[11]; 132 } else { 133 fprintf(stderr, "%s: unknown option %s ignored\n", prog, arg); 134 } 135 } 136 if (argc - i != 1) { 137 fprintf(stderr, "usage: %s --mix-preset=# --mix-name=name filename\n", prog); 138 exit(EXIT_FAILURE); 139 } 140 char *pathname = argv[i]; 141 142 if (NULL != mixEnvName) { 143 unsigned j; 144 for (j = 0; j < sizeof(pairs) / sizeof(pairs[0]); ++j) { 145 //printf("comparing %s %s\n", mixEnvName, pairs[j].mName); 146 if (!strcasecmp(mixEnvName, pairs[j].mName)) { 147 mixEnvSettings = pairs[j].mSettings; 148 goto found; 149 } 150 } 151 fprintf(stderr, "%s: reverb name %s not found\n", prog, mixEnvName); 152 exit(EXIT_FAILURE); 153found: 154 printf("Using reverb name %s\n", mixEnvName); 155 } 156 157 // create engine 158 SLObjectItf engineObject; 159 result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); 160 assert(SL_RESULT_SUCCESS == result); 161 result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE); 162 assert(SL_RESULT_SUCCESS == result); 163 SLEngineItf engineEngine; 164 result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine); 165 assert(SL_RESULT_SUCCESS == result); 166 167 // create output mix 168 SLInterfaceID mix_ids[2]; 169 SLboolean mix_req[2]; 170 SLuint32 count = 0; 171 if (mixPresetNumber != ((SLuint16) ~0)) { 172 mix_req[count] = SL_BOOLEAN_TRUE; 173 mix_ids[count++] = SL_IID_PRESETREVERB; 174 } 175 if (mixEnvName != NULL) { 176 mix_req[count] = SL_BOOLEAN_TRUE; 177 mix_ids[count++] = SL_IID_ENVIRONMENTALREVERB; 178 } 179 SLObjectItf mixObject; 180 result = (*engineEngine)->CreateOutputMix(engineEngine, &mixObject, count, mix_ids, mix_req); 181 assert(SL_RESULT_SUCCESS == result); 182 result = (*mixObject)->Realize(mixObject, SL_BOOLEAN_FALSE); 183 assert(SL_RESULT_SUCCESS == result); 184 185 // configure preset reverb on output mix 186 SLPresetReverbItf mixPresetReverb; 187 if (mixPresetNumber != ((SLuint16) ~0)) { 188 result = (*mixObject)->GetInterface(mixObject, SL_IID_PRESETREVERB, &mixPresetReverb); 189 assert(SL_RESULT_SUCCESS == result); 190 SLuint16 getPresetReverb = 12345; 191 result = (*mixPresetReverb)->GetPreset(mixPresetReverb, &getPresetReverb); 192 assert(SL_RESULT_SUCCESS == result); 193 printf("Output mix default preset reverb %u\n", getPresetReverb); 194 result = (*mixPresetReverb)->SetPreset(mixPresetReverb, mixPresetNumber); 195 if (SL_RESULT_SUCCESS == result) { 196 result = (*mixPresetReverb)->GetPreset(mixPresetReverb, &getPresetReverb); 197 assert(SL_RESULT_SUCCESS == result); 198 assert(getPresetReverb == mixPresetNumber); 199 printf("output mix preset reverb successfully changed to %u\n", mixPresetNumber); 200 } else 201 printf("Unable to set preset reverb to %u, result=%lu\n", mixPresetNumber, result); 202 } 203 204 // configure environmental reverb on output mix 205 SLEnvironmentalReverbItf mixEnvironmentalReverb; 206 if (mixEnvName != NULL) { 207 result = (*mixObject)->GetInterface(mixObject, SL_IID_ENVIRONMENTALREVERB, 208 &mixEnvironmentalReverb); 209 assert(SL_RESULT_SUCCESS == result); 210 SLEnvironmentalReverbSettings getSettings; 211 result = (*mixEnvironmentalReverb)->GetEnvironmentalReverbProperties(mixEnvironmentalReverb, 212 &getSettings); 213 assert(SL_RESULT_SUCCESS == result); 214 printf("Output mix default environmental reverb settings\n"); 215 printf("------------------------------------------------\n"); 216 slesutPrintEnvironmentalReverbSettings(&getSettings); 217 printf("\n"); 218 result = (*mixEnvironmentalReverb)->SetEnvironmentalReverbProperties(mixEnvironmentalReverb, 219 &mixEnvSettings); 220 assert(SL_RESULT_SUCCESS == result); 221 printf("Output mix new environmental reverb settings\n"); 222 printf("--------------------------------------------\n"); 223 slesutPrintEnvironmentalReverbSettings(&mixEnvSettings); 224 printf("\n"); 225 result = (*mixEnvironmentalReverb)->GetEnvironmentalReverbProperties(mixEnvironmentalReverb, 226 &getSettings); 227 assert(SL_RESULT_SUCCESS == result); 228 printf("Output mix read environmental reverb settings\n"); 229 printf("--------------------------------------------\n"); 230 slesutPrintEnvironmentalReverbSettings(&getSettings); 231 printf("\n"); 232 // assert(slesutCompareEnvronmentalReverbSettings(&getSettings, &mixEnvSettings)); 233 } 234 235 // create audio player 236 SLDataLocator_URI locURI = {SL_DATALOCATOR_URI, pathname}; 237 SLDataFormat_MIME dfMIME = {SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED}; 238 SLDataSource audioSrc = {&locURI, &dfMIME}; 239 SLDataLocator_OutputMix locOutputMix = {SL_DATALOCATOR_OUTPUTMIX, mixObject}; 240 SLDataSink audioSnk = {&locOutputMix, NULL}; 241 SLInterfaceID player_ids[3]; 242 SLboolean player_req[3]; 243 count = 0; 244 if (playerPreset != ((SLuint16) ~0)) { 245 player_req[count] = SL_BOOLEAN_TRUE; 246 player_ids[count++] = SL_IID_PRESETREVERB; 247 } 248 if (playerName != NULL) { 249 player_req[count] = SL_BOOLEAN_TRUE; 250 player_ids[count++] = SL_IID_ENVIRONMENTALREVERB; 251 } 252 if (mixPresetNumber != ((SLuint16) ~0) || mixEnvName != NULL) { 253 player_req[count] = SL_BOOLEAN_TRUE; 254 player_ids[count++] = SL_IID_EFFECTSEND; 255 } 256 SLObjectItf playerObject; 257 result = (*engineEngine)->CreateAudioPlayer(engineEngine, &playerObject, &audioSrc, 258 &audioSnk, count, player_ids, player_req); 259 assert(SL_RESULT_SUCCESS == result); 260 result = (*playerObject)->Realize(playerObject, SL_BOOLEAN_FALSE); 261 SLPlayItf playerPlay; 262 result = (*playerObject)->GetInterface(playerObject, SL_IID_PLAY, &playerPlay); 263 assert(SL_RESULT_SUCCESS == result); 264 265 // get duration 266 SLmillisecond duration; 267 result = (*playerPlay)->GetDuration(playerPlay, &duration); 268 assert(SL_RESULT_SUCCESS == result); 269 if (SL_TIME_UNKNOWN == duration) 270 printf("first attempt at duration: unknown\n"); 271 else 272 printf("first attempt at duration: %.1f seconds\n", duration / 1000.0); 273 274 // set play state to paused to enable pre-fetch so we can get a more reliable duration 275 result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PAUSED); 276 assert(SL_RESULT_SUCCESS == result); 277 usleep(1000000); 278 result = (*playerPlay)->GetDuration(playerPlay, &duration); 279 assert(SL_RESULT_SUCCESS == result); 280 if (SL_TIME_UNKNOWN == duration) 281 printf("second attempt at duration: unknown\n"); 282 else 283 printf("second attempt at duration: %.1f seconds\n", duration / 1000.0); 284 285 // if reverb is on output mix (aux effect), then enable it 286 if (mixPresetNumber != ((SLuint16) ~0) || mixEnvName != NULL) { 287 SLEffectSendItf playerEffectSend; 288 result = (*playerObject)->GetInterface(playerObject, SL_IID_EFFECTSEND, &playerEffectSend); 289 assert(SL_RESULT_SUCCESS == result); 290 if (mixPresetNumber != ((SLuint16) ~0)) { 291 result = (*playerEffectSend)->EnableEffectSend(playerEffectSend, mixPresetReverb, 292 SL_BOOLEAN_TRUE, (SLmillibel) 0); 293 assert(SL_RESULT_SUCCESS == result); 294 } 295 if (mixEnvName != NULL) { 296 result = (*playerEffectSend)->EnableEffectSend(playerEffectSend, mixEnvironmentalReverb, 297 SL_BOOLEAN_TRUE, (SLmillibel) 0); 298 assert(SL_RESULT_SUCCESS == result); 299 } 300 } 301 302 // start audio playing 303 result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING); 304 assert(SL_RESULT_SUCCESS == result); 305 306 // wait for audio to finish playing 307 SLuint32 state; 308 for (;;) { 309 result = (*playerPlay)->GetPlayState(playerPlay, &state); 310 assert(SL_RESULT_SUCCESS == result); 311 if (SL_PLAYSTATE_PLAYING != state) 312 break; 313 usleep(5000000); 314 } 315 assert(SL_PLAYSTATE_PAUSED == state); 316 317 return EXIT_SUCCESS; 318} 319