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/* Audio Record Test 18 19First run the program from shell: 20 % adb shell slesTest_recBuffQueue /sdcard/myrec.wav 21 22These use adb on host to retrive the file: 23 % adb pull /sdcard/myrec.wav 24 25*/ 26 27 28#include <stdlib.h> 29#include <stdio.h> 30#include <string.h> 31#include <unistd.h> 32#include <sys/time.h> 33#include <fcntl.h> 34#include <system/audio.h> 35#include <audio_utils/primitives.h> 36#include <audio_utils/sndfile.h> 37 38#include <SLES/OpenSLES.h> 39#include <SLES/OpenSLES_Android.h> 40 41audio_format_t transferFormat = AUDIO_FORMAT_DEFAULT; 42uint32_t sampleRate = 48000; 43int channelCount = 1; 44bool useIndexChannelMask = false; 45size_t frameSize; 46uint32_t performanceMode = SL_ANDROID_PERFORMANCE_LATENCY; 47bool aec = false; 48bool agc = false; 49bool ns = false; 50 51/* Preset number to use for recording */ 52SLuint32 presetValue = SL_ANDROID_RECORDING_PRESET_NONE; 53 54/* Explicitly requesting SL_IID_ANDROIDSIMPLEBUFFERQUEUE and SL_IID_ANDROIDCONFIGURATION 55 * on the AudioRecorder object */ 56#define NUM_EXPLICIT_INTERFACES_FOR_RECORDER 2 57 58/* Size of the recording buffer queue */ 59#define NB_BUFFERS_IN_QUEUE 1 60/* Size of each buffer in the queue */ 61#define BUFFER_SIZE_IN_BYTES 2048 62 63/* Local storage for Audio data */ 64int8_t pcmData[NB_BUFFERS_IN_QUEUE * BUFFER_SIZE_IN_BYTES]; 65 66/* destination for recorded data */ 67SNDFILE *sndfile; 68 69//----------------------------------------------------------------- 70/* Exits the application if an error is encountered */ 71#define ExitOnError(x) ExitOnErrorFunc(x,__LINE__) 72 73void ExitOnErrorFunc( SLresult result , int line) 74{ 75 if (SL_RESULT_SUCCESS != result) { 76 fprintf(stderr, "%u error code encountered at line %d, exiting\n", result, line); 77 exit(EXIT_FAILURE); 78 } 79} 80 81//----------------------------------------------------------------- 82/* Structure for passing information to callback function */ 83typedef struct CallbackCntxt_ { 84 SLPlayItf playItf; 85 SLuint32 size; 86 SLint8* pDataBase; // Base address of local audio data storage 87 SLint8* pData; // Current address of local audio data storage 88} CallbackCntxt; 89 90 91//----------------------------------------------------------------- 92/* Callback for recording buffer queue events */ 93void RecCallback( 94 SLRecordItf caller, 95 void *pContext __unused, 96 SLuint32 event) 97{ 98 if (SL_RECORDEVENT_HEADATNEWPOS & event) { 99 SLmillisecond pMsec = 0; 100 (*caller)->GetPosition(caller, &pMsec); 101 printf("SL_RECORDEVENT_HEADATNEWPOS current position=%ums\n", pMsec); 102 } 103 104 if (SL_RECORDEVENT_HEADATMARKER & event) { 105 SLmillisecond pMsec = 0; 106 (*caller)->GetPosition(caller, &pMsec); 107 printf("SL_RECORDEVENT_HEADATMARKER current position=%ums\n", pMsec); 108 } 109} 110 111//----------------------------------------------------------------- 112/* Callback for recording buffer queue events */ 113void RecBufferQueueCallback( 114 SLAndroidSimpleBufferQueueItf queueItf, 115 void *pContext) 116{ 117 //printf("RecBufferQueueCallback called\n"); 118 119 CallbackCntxt *pCntxt = (CallbackCntxt*)pContext; 120 121 /* Save the recorded data */ 122 sf_count_t frameCount = BUFFER_SIZE_IN_BYTES / frameSize; 123 switch (transferFormat) { 124 case AUDIO_FORMAT_PCM_8_BIT: { 125 short temp[BUFFER_SIZE_IN_BYTES]; 126 memcpy_to_i16_from_u8(temp, (const unsigned char *) pCntxt->pDataBase, BUFFER_SIZE_IN_BYTES); 127 (void) sf_writef_short(sndfile, (const short *) temp, frameCount); 128 } break; 129 case AUDIO_FORMAT_PCM_16_BIT: 130 (void) sf_writef_short(sndfile, (const short *) pCntxt->pDataBase, frameCount); 131 break; 132 case AUDIO_FORMAT_PCM_32_BIT: 133 (void) sf_writef_int(sndfile, (const int *) pCntxt->pDataBase, frameCount); 134 break; 135 case AUDIO_FORMAT_PCM_FLOAT: 136 (void) sf_writef_float(sndfile, (const float *) pCntxt->pDataBase, frameCount); 137 break; 138 default: 139 fprintf(stderr, "Unsupported transfer format %d\n", transferFormat); 140 exit(EXIT_FAILURE); 141 } 142 143 /* Increase data pointer by buffer size */ 144 pCntxt->pData += BUFFER_SIZE_IN_BYTES; 145 146 if (pCntxt->pData >= pCntxt->pDataBase + (NB_BUFFERS_IN_QUEUE * BUFFER_SIZE_IN_BYTES)) { 147 pCntxt->pData = pCntxt->pDataBase; 148 } 149 150 ExitOnError( (*queueItf)->Enqueue(queueItf, pCntxt->pDataBase, BUFFER_SIZE_IN_BYTES) ); 151 152 SLAndroidSimpleBufferQueueState recQueueState; 153 ExitOnError( (*queueItf)->GetState(queueItf, &recQueueState) ); 154 155 /*fprintf(stderr, "\tRecBufferQueueCallback now has pCntxt->pData=%p queue: " 156 "count=%u playIndex=%u\n", 157 pCntxt->pData, recQueueState.count, recQueueState.index);*/ 158 //printf("RecBufferQueueCallback returned\n"); 159} 160 161//----------------------------------------------------------------- 162 163/* Record to an audio path by opening a file descriptor on that path */ 164void TestRecToBuffQueue( SLObjectItf sl, const char* path, SLAint64 durationInSeconds) 165{ 166 SF_INFO info; 167 info.frames = 0; 168 info.samplerate = sampleRate; 169 info.channels = channelCount; 170 switch (transferFormat) { 171 case AUDIO_FORMAT_PCM_8_BIT: 172 info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_U8; 173 break; 174 case AUDIO_FORMAT_PCM_16_BIT: 175 info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16; 176 break; 177 case AUDIO_FORMAT_PCM_32_BIT: 178 info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_32; 179 break; 180 case AUDIO_FORMAT_PCM_FLOAT: 181 info.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT; 182 break; 183 default: 184 fprintf(stderr, "Unsupported transfer format %d\n", transferFormat); 185 exit(EXIT_FAILURE); 186 } 187 sndfile = sf_open(path, SFM_WRITE, &info); 188 if (sndfile == NULL) { 189 ExitOnError(SL_RESULT_RESOURCE_ERROR); 190 } 191 192 SLresult result; 193 SLEngineItf EngineItf; 194 195 /* Objects this application uses: one audio recorder */ 196 SLObjectItf recorder; 197 198 /* Interfaces for the audio recorder */ 199 SLAndroidSimpleBufferQueueItf recBuffQueueItf; 200 SLRecordItf recordItf; 201 SLAndroidConfigurationItf configItf; 202 203 /* Source of audio data for the recording */ 204 SLDataSource recSource; 205 SLDataLocator_IODevice ioDevice; 206 207 /* Data sink for recorded audio */ 208 SLDataSink recDest; 209 SLDataLocator_AndroidSimpleBufferQueue recBuffQueue; 210 /* As mentioned in the Android extension API documentation this is identical to 211 * OpenSL ES 1.1 SLDataFormat_PCM_EX, and can be used for an instance of SLDataFormat_PCM. 212 */ 213 SLAndroidDataFormat_PCM_EX pcm; 214 215 int numInterfaces = NUM_EXPLICIT_INTERFACES_FOR_RECORDER; 216 if (aec) numInterfaces++; 217 if (agc) numInterfaces++; 218 if (ns) numInterfaces++; 219 220 SLboolean required[numInterfaces]; 221 SLInterfaceID iidArray[numInterfaces]; 222 223 /* Get the SL Engine Interface which is implicit */ 224 result = (*sl)->GetInterface(sl, SL_IID_ENGINE, (void*)&EngineItf); 225 ExitOnError(result); 226 227 /* Initialize arrays required[] and iidArray[] */ 228 for (int i=0 ; i < numInterfaces ; i++) { 229 required[i] = SL_BOOLEAN_FALSE; 230 iidArray[i] = SL_IID_NULL; 231 } 232 233 234 /* ------------------------------------------------------ */ 235 /* Configuration of the recorder */ 236 237 /* Request the AndroidSimpleBufferQueue and AndroidConfiguration interfaces */ 238 int index = 0; 239 required[index] = SL_BOOLEAN_TRUE; 240 iidArray[index++] = SL_IID_ANDROIDSIMPLEBUFFERQUEUE; 241 required[index] = SL_BOOLEAN_TRUE; 242 iidArray[index++] = SL_IID_ANDROIDCONFIGURATION; 243 if (aec) { 244 iidArray[index++] = SL_IID_ANDROIDACOUSTICECHOCANCELLATION; 245 } 246 if (agc) { 247 iidArray[index++] = SL_IID_ANDROIDAUTOMATICGAINCONTROL; 248 } 249 if (ns) { 250 iidArray[index++] = SL_IID_ANDROIDNOISESUPPRESSION; 251 } 252 253 /* Setup the data source */ 254 ioDevice.locatorType = SL_DATALOCATOR_IODEVICE; 255 ioDevice.deviceType = SL_IODEVICE_AUDIOINPUT; 256 ioDevice.deviceID = SL_DEFAULTDEVICEID_AUDIOINPUT; 257 ioDevice.device = NULL; 258 recSource.pLocator = (void *) &ioDevice; 259 recSource.pFormat = NULL; 260 261 /* Setup the data sink */ 262 recBuffQueue.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE; 263 recBuffQueue.numBuffers = NB_BUFFERS_IN_QUEUE; 264 /* set up the format of the data in the buffer queue */ 265 pcm.formatType = transferFormat == AUDIO_FORMAT_PCM_FLOAT || 266 transferFormat == AUDIO_FORMAT_PCM_8_BIT ? 267 SL_ANDROID_DATAFORMAT_PCM_EX : SL_DATAFORMAT_PCM; 268 pcm.numChannels = channelCount; 269 pcm.sampleRate = sampleRate * 1000; // milliHz 270 pcm.representation = SL_ANDROID_PCM_REPRESENTATION_SIGNED_INT; 271 switch (transferFormat) { 272 case AUDIO_FORMAT_PCM_16_BIT: 273 pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16; 274 pcm.containerSize = 16; 275 break; 276 case AUDIO_FORMAT_PCM_32_BIT: 277 pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_32; 278 pcm.containerSize = 32; 279 break; 280 case AUDIO_FORMAT_PCM_8_BIT: 281 pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_8; 282 pcm.containerSize = 8; 283 pcm.representation = SL_ANDROID_PCM_REPRESENTATION_UNSIGNED_INT; 284 break; 285 case AUDIO_FORMAT_PCM_FLOAT: 286 pcm.bitsPerSample = 32; 287 pcm.containerSize = 32; 288 pcm.representation = SL_ANDROID_PCM_REPRESENTATION_FLOAT; 289 break; 290 default: 291 fprintf(stderr, "Unsupported transfer format %d\n", transferFormat); 292 exit(EXIT_FAILURE); 293 } 294 if (useIndexChannelMask) { 295 pcm.channelMask = (1 << channelCount) - 1; 296 } else { 297 switch (channelCount) { 298 case 1: 299 pcm.channelMask = SL_SPEAKER_FRONT_LEFT; 300 break; 301 case 2: 302 pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; 303 break; 304 default: 305 fprintf(stderr, "Unsupported channel count %d\n", channelCount); 306 exit(EXIT_FAILURE); 307 } 308 } 309 pcm.endianness = SL_BYTEORDER_LITTLEENDIAN; 310 311 recDest.pLocator = (void *) &recBuffQueue; 312 recDest.pFormat = (void * ) &pcm; 313 314 /* Create the audio recorder */ 315 result = (*EngineItf)->CreateAudioRecorder(EngineItf, &recorder, &recSource, &recDest, 316 numInterfaces, iidArray, required); 317 ExitOnError(result); 318 printf("Recorder created\n"); 319 320 /* Get the Android configuration interface which is explicit */ 321 result = (*recorder)->GetInterface(recorder, SL_IID_ANDROIDCONFIGURATION, (void*)&configItf); 322 ExitOnError(result); 323 324 /* Use the configuration interface to configure the recorder before it's realized */ 325 if (presetValue != SL_ANDROID_RECORDING_PRESET_NONE) { 326 result = (*configItf)->SetConfiguration(configItf, SL_ANDROID_KEY_RECORDING_PRESET, 327 &presetValue, sizeof(SLuint32)); 328 ExitOnError(result); 329 printf("Recorder configured with preset %u\n", presetValue); 330 } else { 331 printf("Using default record preset\n"); 332 } 333 334 if (performanceMode != SL_ANDROID_PERFORMANCE_LATENCY) { 335 result = (*configItf)->SetConfiguration(configItf, SL_ANDROID_KEY_PERFORMANCE_MODE, 336 &performanceMode, sizeof(SLuint32)); 337 ExitOnError(result); 338 printf("Recorder configured with performance mode %u\n", performanceMode); 339 } else { 340 printf("Using default performance mode\n"); 341 } 342 343 SLuint32 presetRetrieved = SL_ANDROID_RECORDING_PRESET_NONE; 344 SLuint32 presetSize = 2*sizeof(SLuint32); // intentionally too big 345 result = (*configItf)->GetConfiguration(configItf, SL_ANDROID_KEY_RECORDING_PRESET, 346 &presetSize, (void*)&presetRetrieved); 347 ExitOnError(result); 348 if (presetValue == SL_ANDROID_RECORDING_PRESET_NONE) { 349 printf("The default record preset appears to be %u\n", presetRetrieved); 350 } else if (presetValue != presetRetrieved) { 351 fprintf(stderr, "Error retrieving recording preset as %u instead of %u\n", presetRetrieved, 352 presetValue); 353 ExitOnError(SL_RESULT_INTERNAL_ERROR); 354 } 355 356 /* Realize the recorder in synchronous mode. */ 357 result = (*recorder)->Realize(recorder, SL_BOOLEAN_FALSE); 358 ExitOnError(result); 359 printf("Recorder realized\n"); 360 361 /* Check actual performance mode granted*/ 362 SLuint32 modeRetrieved = SL_ANDROID_PERFORMANCE_NONE; 363 SLuint32 modeSize = sizeof(SLuint32); 364 result = (*configItf)->GetConfiguration(configItf, SL_ANDROID_KEY_PERFORMANCE_MODE, 365 &modeSize, (void*)&modeRetrieved); 366 ExitOnError(result); 367 printf("Actual performance mode is %u\n", modeRetrieved); 368 369 /* Get the record interface which is implicit */ 370 result = (*recorder)->GetInterface(recorder, SL_IID_RECORD, (void*)&recordItf); 371 ExitOnError(result); 372 373 /* Set up the recorder callback to get events during the recording */ 374 result = (*recordItf)->SetMarkerPosition(recordItf, 2000); 375 ExitOnError(result); 376 result = (*recordItf)->SetPositionUpdatePeriod(recordItf, 500); 377 ExitOnError(result); 378 result = (*recordItf)->SetCallbackEventsMask(recordItf, 379 SL_RECORDEVENT_HEADATMARKER | SL_RECORDEVENT_HEADATNEWPOS); 380 ExitOnError(result); 381 result = (*recordItf)->RegisterCallback(recordItf, RecCallback, NULL); 382 ExitOnError(result); 383 printf("Recorder callback registered\n"); 384 385 /* Enable AEC if requested */ 386 if (aec) { 387 SLAndroidAcousticEchoCancellationItf aecItf; 388 result = (*recorder)->GetInterface( 389 recorder, SL_IID_ANDROIDACOUSTICECHOCANCELLATION, (void*)&aecItf); 390 printf("AEC is %savailable\n", SL_RESULT_SUCCESS == result ? "" : "not "); 391 if (SL_RESULT_SUCCESS == result) { 392 result = (*aecItf)->SetEnabled(aecItf, true); 393 ExitOnError(result); 394 SLboolean enabled; 395 result = (*aecItf)->IsEnabled(aecItf, &enabled); 396 ExitOnError(result); 397 printf("AEC is %s\n", enabled ? "enabled" : "not enabled"); 398 } 399 } 400 401 /* Enable AGC if requested */ 402 if (agc) { 403 SLAndroidAutomaticGainControlItf agcItf; 404 result = (*recorder)->GetInterface( 405 recorder, SL_IID_ANDROIDAUTOMATICGAINCONTROL, (void*)&agcItf); 406 printf("AGC is %savailable\n", SL_RESULT_SUCCESS == result ? "" : "not "); 407 if (SL_RESULT_SUCCESS == result) { 408 result = (*agcItf)->SetEnabled(agcItf, true); 409 ExitOnError(result); 410 SLboolean enabled; 411 result = (*agcItf)->IsEnabled(agcItf, &enabled); 412 ExitOnError(result); 413 printf("AGC is %s\n", enabled ? "enabled" : "not enabled"); 414 } 415 } 416 417 /* Enable NS if requested */ 418 if (ns) { 419 SLAndroidNoiseSuppressionItf nsItf; 420 result = (*recorder)->GetInterface( 421 recorder, SL_IID_ANDROIDNOISESUPPRESSION, (void*)&nsItf); 422 printf("NS is %savailable\n", SL_RESULT_SUCCESS == result ? "" : "not "); 423 if (SL_RESULT_SUCCESS == result) { 424 result = (*nsItf)->SetEnabled(nsItf, true); 425 ExitOnError(result); 426 SLboolean enabled; 427 result = (*nsItf)->IsEnabled(nsItf, &enabled); 428 ExitOnError(result); 429 printf("NS is %s\n", enabled ? "enabled" : "not enabled"); 430 } 431 } 432 433 /* Get the buffer queue interface which was explicitly requested */ 434 result = (*recorder)->GetInterface(recorder, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, 435 (void*)&recBuffQueueItf); 436 ExitOnError(result); 437 438 /* ------------------------------------------------------ */ 439 /* Initialize the callback and its context for the recording buffer queue */ 440 CallbackCntxt cntxt; 441 cntxt.pDataBase = (int8_t*)&pcmData; 442 cntxt.pData = cntxt.pDataBase; 443 cntxt.size = sizeof(pcmData); 444 result = (*recBuffQueueItf)->RegisterCallback(recBuffQueueItf, RecBufferQueueCallback, &cntxt); 445 ExitOnError(result); 446 447 /* Enqueue buffers to map the region of memory allocated to store the recorded data */ 448 printf("Enqueueing buffer "); 449 for(int i = 0 ; i < NB_BUFFERS_IN_QUEUE ; i++) { 450 printf("%d ", i); 451 result = (*recBuffQueueItf)->Enqueue(recBuffQueueItf, cntxt.pData, BUFFER_SIZE_IN_BYTES); 452 ExitOnError(result); 453 cntxt.pData += BUFFER_SIZE_IN_BYTES; 454 } 455 printf("\n"); 456 cntxt.pData = cntxt.pDataBase; 457 458 /* ------------------------------------------------------ */ 459 /* Start recording */ 460 result = (*recordItf)->SetRecordState(recordItf, SL_RECORDSTATE_RECORDING); 461 ExitOnError(result); 462 printf("Starting to record\n"); 463 464 /* Record for at least a second */ 465 if (durationInSeconds < 1) { 466 durationInSeconds = 1; 467 } 468 usleep(durationInSeconds * 1000 * 1000); 469 470 /* ------------------------------------------------------ */ 471 /* End of recording */ 472 473 /* Stop recording */ 474 result = (*recordItf)->SetRecordState(recordItf, SL_RECORDSTATE_STOPPED); 475 ExitOnError(result); 476 printf("Stopped recording\n"); 477 478 /* Destroy the AudioRecorder object */ 479 (*recorder)->Destroy(recorder); 480 481 sf_close(sndfile); 482} 483 484//----------------------------------------------------------------- 485int main(int argc, char* const argv[]) 486{ 487 int durationInSeconds = 10; 488 SLresult result; 489 SLObjectItf sl; 490 491 const char *prog = argv[0]; 492 printf("OpenSL ES test %s: exercises SLRecordItf and SLAndroidSimpleBufferQueueItf ", 493 prog); 494 printf("on an AudioRecorder object\n"); 495 496 int i; 497 for (i = 1; i < argc; ++i) { 498 const char *arg = argv[i]; 499 if (arg[0] != '-') { 500 break; 501 } 502 switch (arg[1]) { 503 case 'c': // channel count 504 channelCount = atoi(&arg[2]); 505 break; 506 case 'd': // duration in seconds 507 durationInSeconds = atoi(&arg[2]); 508 break; 509 case 'f': 510 transferFormat = AUDIO_FORMAT_PCM_FLOAT; 511 break; 512 case 'i': 513 useIndexChannelMask = true; 514 break; 515 case 'p': // preset number 516 presetValue = atoi(&arg[2]); 517 break; 518 case 'r': 519 sampleRate = atoi(&arg[2]); 520 break; 521 case '1': 522 transferFormat = AUDIO_FORMAT_PCM_8_BIT; 523 break; 524 case '2': 525 transferFormat = AUDIO_FORMAT_PCM_16_BIT; 526 break; 527 case '4': 528 transferFormat = AUDIO_FORMAT_PCM_32_BIT; 529 break; 530 case 'm': 531 performanceMode = atoi(&arg[2]); 532 break; 533 case 'x': 534 if (strstr(arg, "e") != NULL) { 535 aec = true; 536 } 537 if (strstr(arg, "a") != NULL) { 538 agc = true; 539 } 540 if (strstr(arg, "n") != NULL) { 541 ns = true; 542 } 543 break; 544 default: 545 fprintf(stderr, "%s: unknown option %s\n", prog, arg); 546 break; 547 } 548 } 549 550 if (transferFormat == AUDIO_FORMAT_DEFAULT) { 551 transferFormat = AUDIO_FORMAT_PCM_16_BIT; 552 } 553 frameSize = audio_bytes_per_sample(transferFormat) * channelCount; 554 555 if (argc-i != 1) { 556 printf("Usage: \t%s [-c#] [-d#] [-i] [-p#] [-r#] [-1/2/4/f] destination_file\n", prog); 557 printf(" -c# channel count, defaults to 1\n"); 558 printf(" -d# duration in seconds, default to 10\n"); 559 printf(" -i index channel mask, not yet implemented\n"); 560 printf(" -p# is the preset value which defaults to SL_ANDROID_RECORDING_PRESET_NONE\n"); 561 printf(" possible values are:\n"); 562 printf(" -p%d SL_ANDROID_RECORDING_PRESET_NONE\n", 563 SL_ANDROID_RECORDING_PRESET_NONE); 564 printf(" -p%d SL_ANDROID_RECORDING_PRESET_GENERIC\n", 565 SL_ANDROID_RECORDING_PRESET_GENERIC); 566 printf(" -p%d SL_ANDROID_RECORDING_PRESET_CAMCORDER\n", 567 SL_ANDROID_RECORDING_PRESET_CAMCORDER); 568 printf(" -p%d SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION\n", 569 SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION); 570 printf(" -p%d SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION\n", 571 SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION); 572 printf(" -r# sample rate in Hz, defaults to 48000\n"); 573 printf(" -[1/2/4/f] sample format: 8-bit unsigned, 16-bit signed, 32-bit signed, float, " 574 "defaults to 16-bit signed\n"); 575 printf(" -m# is the performance mode value which defaults to" 576 " SL_ANDROID_PERFORMANCE_LATENCY\n"); 577 printf(" possible values are:\n"); 578 printf(" -m%d SL_ANDROID_PERFORMANCE_NONE\n", 579 SL_ANDROID_PERFORMANCE_NONE); 580 printf(" -m%d SL_ANDROID_PERFORMANCE_LATENCY\n", 581 SL_ANDROID_PERFORMANCE_LATENCY); 582 printf(" -m%d SL_ANDROID_PERFORMANCE_LATENCY_EFFECTS\n", 583 SL_ANDROID_PERFORMANCE_LATENCY_EFFECTS); 584 printf(" -m%d SL_ANDROID_PERFORMANCE_POWER_SAVING\n", 585 SL_ANDROID_PERFORMANCE_POWER_SAVING); 586 printf(" -x[e][a][n] for pre processing:\n" 587 " - e: Echo canceler\n" 588 " - a: Automatic Gain Control\n" 589 " - n: Noise Suppression\n"); 590 printf("Example: \"%s /sdcard/myrec.wav\" \n", prog); 591 exit(EXIT_FAILURE); 592 } 593 594 SLEngineOption EngineOption[] = { 595 {(SLuint32) SL_ENGINEOPTION_THREADSAFE, (SLuint32) SL_BOOLEAN_TRUE} 596 }; 597 598 result = slCreateEngine( &sl, 1, EngineOption, 0, NULL, NULL); 599 ExitOnError(result); 600 601 /* Realizing the SL Engine in synchronous mode. */ 602 result = (*sl)->Realize(sl, SL_BOOLEAN_FALSE); 603 ExitOnError(result); 604 605 TestRecToBuffQueue(sl, argv[i], durationInSeconds); 606 607 /* Shutdown OpenSL ES */ 608 (*sl)->Destroy(sl); 609 610 return EXIT_SUCCESS; 611} 612