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