slesTestSendToPresetReverb.cpp revision 2246c698482ab6860906672229f0ae6d886e6302
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#include <stdlib.h> 18#include <stdio.h> 19#include <string.h> 20#include <unistd.h> 21#include <sys/time.h> 22#include <fcntl.h> 23 24#include "SLES/OpenSLES.h" 25#ifdef ANDROID 26#include "SLES/OpenSLES_Android.h" 27#endif 28 29 30#define MAX_NUMBER_INTERFACES 3 31 32#define TIME_S_BETWEEN_SETTING_CHANGE 5 33 34//----------------------------------------------------------------- 35/* Exits the application if an error is encountered */ 36#define ExitOnError(x) ExitOnErrorFunc(x,__LINE__) 37 38void ExitOnErrorFunc( SLresult result , int line) 39{ 40 if (SL_RESULT_SUCCESS != result) { 41 fprintf(stderr, "%lu error code encountered at line %d, exiting\n", result, line); 42 exit(EXIT_FAILURE); 43 } 44} 45 46 47//----------------------------------------------------------------- 48 49/* Play an audio path and feed a global reverb */ 50void TestSendToPresetReverb( SLObjectItf sl, const char* path, int preset, SLmillibel directLevel, 51 SLmillibel sendLevel) 52{ 53 SLresult result; 54 SLEngineItf EngineItf; 55 56 /* Objects this application uses: one player and an ouput mix */ 57 SLObjectItf player, outputMix; 58 59 /* Source of audio data to play */ 60 SLDataSource audioSource; 61#ifdef ANDROID 62 SLDataLocator_AndroidFD locatorFd; 63#else 64 SLDataLocator_URI locatorUri; 65#endif 66 SLDataFormat_MIME mime; 67 68 /* Data sinks for the audio player */ 69 SLDataSink audioSink; 70 SLDataLocator_OutputMix locator_outputmix; 71 72 /* Interfaces for the audio player */ 73 SLPlayItf playItf; 74 SLEffectSendItf effectSendItf; 75 76 /* Interface for the output mix */ 77 SLPresetReverbItf reverbItf; 78 79 SLboolean required[MAX_NUMBER_INTERFACES]; 80 SLInterfaceID iidArray[MAX_NUMBER_INTERFACES]; 81 82 /* Get the SL Engine Interface which is implicit */ 83 result = (*sl)->GetInterface(sl, SL_IID_ENGINE, (void*)&EngineItf); 84 ExitOnError(result); 85 86 /* Initialize arrays required[] and iidArray[] */ 87 for (int i=0 ; i < MAX_NUMBER_INTERFACES ; i++) { 88 required[i] = SL_BOOLEAN_FALSE; 89 iidArray[i] = SL_IID_NULL; 90 } 91 92 /* ------------------------------------------------------ */ 93 /* Configuration of the output mix */ 94 95 /* Set arrays required[] and iidArray[] for required interfaces */ 96 required[0] = SL_BOOLEAN_TRUE; 97 iidArray[0] = SL_IID_PRESETREVERB; 98 99 /* Create Output Mix object to be used by the player */ 100 result = (*EngineItf)->CreateOutputMix(EngineItf, &outputMix, 1, iidArray, required); 101 ExitOnError(result); 102 103 /* Realize the Output Mix object in synchronous mode */ 104 result = (*outputMix)->Realize(outputMix, SL_BOOLEAN_FALSE); 105 ExitOnError(result); 106 107 /* Get the SLPresetReverbItf for the output mix */ 108 result = (*outputMix)->GetInterface(outputMix, SL_IID_PRESETREVERB, (void*)&reverbItf); 109 ExitOnError(result); 110 111 /* Setup the data sink structure */ 112 locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX; 113 locator_outputmix.outputMix = outputMix; 114 audioSink.pLocator = (void*)&locator_outputmix; 115 audioSink.pFormat = NULL; 116 117 /* Select the reverb preset */ 118 fprintf(stdout, "\nUsing preset "); 119 switch(preset) { 120 case SL_REVERBPRESET_NONE: 121 fprintf(stdout, "SL_REVERBPRESET_NONE, don't expect to hear reverb\n"); 122 break; 123 case SL_REVERBPRESET_SMALLROOM: fprintf(stdout, "SL_REVERBPRESET_SMALLROOM\n"); break; 124 case SL_REVERBPRESET_MEDIUMROOM: fprintf(stdout, "SL_REVERBPRESET_MEDIUMROOM\n"); break; 125 case SL_REVERBPRESET_LARGEROOM: fprintf(stdout, "SL_REVERBPRESET_LARGEROOM\n"); break; 126 case SL_REVERBPRESET_MEDIUMHALL: fprintf(stdout, "SL_REVERBPRESET_MEDIUMHALL\n"); break; 127 case SL_REVERBPRESET_LARGEHALL: fprintf(stdout, "SL_REVERBPRESET_LARGEHALL\n"); break; 128 case SL_REVERBPRESET_PLATE: fprintf(stdout, "SL_REVERBPRESET_PLATE\n"); break; 129 default: 130 fprintf(stdout, "unknown, use at your own risk\n"); break; 131 } 132 result = (*reverbItf)->SetPreset(reverbItf, preset); 133 ExitOnError(result); 134 135 /* ------------------------------------------------------ */ 136 /* Configuration of the player */ 137 138 /* Set arrays required[] and iidArray[] for required interfaces */ 139 /* (SLPlayItf is implicit) */ 140 required[0] = SL_BOOLEAN_TRUE; 141 iidArray[0] = SL_IID_PREFETCHSTATUS; 142 required[1] = SL_BOOLEAN_TRUE; 143 iidArray[1] = SL_IID_EFFECTSEND; 144 145#ifdef ANDROID 146 /* Setup the data source structure for the URI */ 147 locatorFd.locatorType = SL_DATALOCATOR_ANDROIDFD; 148 int fd = open(path, O_RDONLY); 149 if (fd == -1) { 150 ExitOnError(SL_RESULT_RESOURCE_ERROR); 151 } 152 locatorFd.fd = (SLint32) fd; 153 locatorFd.length = SL_DATALOCATOR_ANDROIDFD_USE_FILE_SIZE; 154 locatorFd.offset = 0; 155#else 156 locatorUri.locatorType = SL_DATALOCATOR_URI; 157 locatorUri.URI = (SLchar *) path; 158#endif 159 160 mime.formatType = SL_DATAFORMAT_MIME; 161 /* this is how ignored mime information is specified, according to OpenSL ES spec 162 * in 9.1.6 SLDataFormat_MIME and 8.23 SLMetadataTraversalItf GetChildInfo */ 163 mime.mimeType = (SLchar*)NULL; 164 mime.containerType = SL_CONTAINERTYPE_UNSPECIFIED; 165 166 audioSource.pFormat = (void*)&mime; 167#ifdef ANDROID 168 audioSource.pLocator = (void*)&locatorFd; 169#else 170 audioSource.pLocator = (void*)&locatorUri; 171#endif 172 173 /* Create the audio player */ 174 result = (*EngineItf)->CreateAudioPlayer(EngineItf, &player, &audioSource, &audioSink, 2, 175 iidArray, required); 176 ExitOnError(result); 177 178 /* Realize the player in synchronous mode. */ 179 result = (*player)->Realize(player, SL_BOOLEAN_FALSE); ExitOnError(result); 180 fprintf(stdout, "URI example: after Realize\n"); 181 182 /* Get the SLPlayItf, SLPrefetchStatusItf and SLEffectSendItf interfaces for the player*/ 183 result = (*player)->GetInterface(player, SL_IID_PLAY, (void*)&playItf); 184 ExitOnError(result); 185 186 result = (*player)->GetInterface(player, SL_IID_EFFECTSEND, (void*)&effectSendItf); 187 ExitOnError(result); 188 189 fprintf(stdout, "Player configured\n"); 190 191 /* ------------------------------------------------------ */ 192 /* Playback and test */ 193 194 /* Get duration */ 195 SLmillisecond durationInMsec = SL_TIME_UNKNOWN; 196 result = (*playItf)->GetDuration(playItf, &durationInMsec); 197 ExitOnError(result); 198 if (durationInMsec == SL_TIME_UNKNOWN) { 199 durationInMsec = 10000; 200 } 201 202 /* Feed the output mix' reverb from the audio player using the given send level */ 203 result = (*effectSendItf)->EnableEffectSend(effectSendItf, reverbItf, SL_BOOLEAN_TRUE, 204 sendLevel); 205 ExitOnError(result); 206 207 result = (*effectSendItf)->SetDirectLevel(effectSendItf, directLevel); 208 ExitOnError(result); 209 fprintf(stdout, "Set direct level to %dmB\n", directLevel); 210 211 result = (*effectSendItf)->SetSendLevel(effectSendItf, reverbItf, sendLevel); 212 ExitOnError(result); 213 fprintf(stdout, "Set send level to %dmB\n", sendLevel); 214 215 /* Start playback */ 216 result = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PLAYING ); 217 ExitOnError(result); 218 219 /* Disable preset reverb every TIME_S_BETWEEN_SETTING_CHANGE seconds */ 220 SLboolean enabled = SL_BOOLEAN_TRUE; 221 for(unsigned int j=0 ; j<(durationInMsec/(1000*TIME_S_BETWEEN_SETTING_CHANGE)) ; j++) { 222 enabled = !enabled; 223 result = (*reverbItf)->SetPreset(reverbItf, enabled ? preset : SL_REVERBPRESET_NONE); 224 if (enabled) { 225 fprintf(stdout, "Reverb on\n"); 226 } else { 227 fprintf(stdout, "Reverb off\n"); 228 } 229 ExitOnError(result); 230 usleep(TIME_S_BETWEEN_SETTING_CHANGE * 1000 * 1000); 231 } 232 233 /* Make sure player is stopped */ 234 fprintf(stdout, "Stopping playback\n"); 235 result = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED); 236 ExitOnError(result); 237 238 /* Destroy the player */ 239 (*player)->Destroy(player); 240 241 /* Destroy Output Mix object */ 242 (*outputMix)->Destroy(outputMix); 243 244#ifdef ANDROID 245 close(fd); 246#endif 247} 248 249//----------------------------------------------------------------- 250int main(int argc, char* const argv[]) 251{ 252 SLresult result; 253 SLObjectItf sl; 254 255 fprintf(stdout, "OpenSL ES test %s: exercises SLEffectSendItf ", argv[0]); 256 fprintf(stdout, "on AudioPlayer and SLPresetReverbItf on OutputMix.\n"); 257 fprintf(stdout, "Plays the sound file designated by the given path, "); 258 fprintf(stdout, "and sends a specified amount of energy to a global reverb\n"); 259 fprintf(stdout, "(sendLevel in mB), with a given direct level (in mB).\n"); 260 fprintf(stdout, "Every %d seconds, the reverb turned on and off.\n", 261 TIME_S_BETWEEN_SETTING_CHANGE); 262 263 if (argc < 5) { 264 fprintf(stdout, "Usage: \t%s path preset directLevel sendLevel\n", argv[0]); 265 fprintf(stdout, "Example: \"%s /sdcard/my.mp3 6 -2000 0\" \n", argv[0]); 266 exit(EXIT_FAILURE); 267 } 268 269 SLEngineOption EngineOption[] = { 270 {(SLuint32) SL_ENGINEOPTION_THREADSAFE, (SLuint32) SL_BOOLEAN_TRUE} 271 }; 272 273 result = slCreateEngine( &sl, 1, EngineOption, 0, NULL, NULL); 274 ExitOnError(result); 275 276 /* Realizing the SL Engine in synchronous mode. */ 277 result = (*sl)->Realize(sl, SL_BOOLEAN_FALSE); 278 ExitOnError(result); 279 280 // intentionally not checking that levels are of correct value 281 TestSendToPresetReverb(sl, argv[1], atoi(argv[2]), (SLmillibel)atoi(argv[3]), 282 (SLmillibel)atoi(argv[4])); 283 284 /* Shutdown OpenSL ES */ 285 (*sl)->Destroy(sl); 286 287 return EXIT_SUCCESS; 288} 289