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