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