• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
18 #include "sles_allinclusive.h"
19 #include "android_prompts.h"
20 
21 // use this flag to dump all recorded audio into a file
22 //#define MONITOR_RECORDING
23 #ifdef MONITOR_RECORDING
24 #define MONITOR_TARGET "/sdcard/monitor.raw"
25 #include <stdio.h>
26 static FILE* gMonitorFp = NULL;
27 #endif
28 
29 
30 #define KEY_RECORDING_SOURCE_PARAMSIZE  sizeof(SLuint32)
31 #define KEY_RECORDING_PRESET_PARAMSIZE  sizeof(SLuint32)
32 
33 //-----------------------------------------------------------------------------
34 // Internal utility functions
35 //----------------------------
36 
audioRecorder_setPreset(CAudioRecorder * ar,SLuint32 recordPreset)37 SLresult audioRecorder_setPreset(CAudioRecorder* ar, SLuint32 recordPreset) {
38     SLresult result = SL_RESULT_SUCCESS;
39 
40     int newRecordSource = android::AUDIO_SOURCE_DEFAULT;
41     switch (recordPreset) {
42     case SL_ANDROID_RECORDING_PRESET_GENERIC:
43         newRecordSource = android::AUDIO_SOURCE_DEFAULT;
44         break;
45     case SL_ANDROID_RECORDING_PRESET_CAMCORDER:
46         newRecordSource = android::AUDIO_SOURCE_CAMCORDER;
47         break;
48     case SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION:
49         newRecordSource = android::AUDIO_SOURCE_VOICE_RECOGNITION;
50         break;
51     case SL_ANDROID_RECORDING_PRESET_NONE:
52         // it is an error to set preset "none"
53     default:
54         SL_LOGE(ERROR_RECORDERPRESET_SET_UNKNOWN_PRESET);
55         result = SL_RESULT_PARAMETER_INVALID;
56     }
57 
58     // recording preset needs to be set before the object is realized
59     // (ap->mAudioRecord is supposed to be NULL until then)
60     if (SL_OBJECT_STATE_UNREALIZED != ar->mObject.mState) {
61         SL_LOGE(ERROR_RECORDERPRESET_REALIZED);
62         result = SL_RESULT_PRECONDITIONS_VIOLATED;
63     } else {
64         ar->mRecordSource = newRecordSource;
65     }
66 
67     return result;
68 }
69 
70 
audioRecorder_getPreset(CAudioRecorder * ar,SLuint32 * pPreset)71 SLresult audioRecorder_getPreset(CAudioRecorder* ar, SLuint32* pPreset) {
72     SLresult result = SL_RESULT_SUCCESS;
73 
74     switch (ar->mRecordSource) {
75     case android::AUDIO_SOURCE_DEFAULT:
76     case android::AUDIO_SOURCE_MIC:
77         *pPreset = SL_ANDROID_RECORDING_PRESET_GENERIC;
78         break;
79     case android::AUDIO_SOURCE_VOICE_UPLINK:
80     case android::AUDIO_SOURCE_VOICE_DOWNLINK:
81     case android::AUDIO_SOURCE_VOICE_CALL:
82         *pPreset = SL_ANDROID_RECORDING_PRESET_NONE;
83         break;
84     case android::AUDIO_SOURCE_VOICE_RECOGNITION:
85         *pPreset = SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION;
86         break;
87     case android::AUDIO_SOURCE_CAMCORDER:
88         *pPreset = SL_ANDROID_RECORDING_PRESET_CAMCORDER;
89         break;
90     default:
91         *pPreset = SL_ANDROID_RECORDING_PRESET_NONE;
92         result = SL_RESULT_INTERNAL_ERROR;
93         break;
94     }
95 
96     return result;
97 }
98 
99 
audioRecorder_handleNewPos_lockRecord(CAudioRecorder * ar)100 void audioRecorder_handleNewPos_lockRecord(CAudioRecorder* ar) {
101     //SL_LOGV("received event EVENT_NEW_POS from AudioRecord");
102     slRecordCallback callback = NULL;
103     void* callbackPContext = NULL;
104 
105     interface_lock_shared(&ar->mRecord);
106     callback = ar->mRecord.mCallback;
107     callbackPContext = ar->mRecord.mContext;
108     interface_unlock_shared(&ar->mRecord);
109 
110     if (NULL != callback) {
111         // getting this event implies SL_RECORDEVENT_HEADATNEWPOS was set in the event mask
112         (*callback)(&ar->mRecord.mItf, callbackPContext, SL_RECORDEVENT_HEADATNEWPOS);
113     }
114 }
115 
116 
audioRecorder_handleMarker_lockRecord(CAudioRecorder * ar)117 void audioRecorder_handleMarker_lockRecord(CAudioRecorder* ar) {
118     //SL_LOGV("received event EVENT_MARKER from AudioRecord");
119     slRecordCallback callback = NULL;
120     void* callbackPContext = NULL;
121 
122     interface_lock_shared(&ar->mRecord);
123     callback = ar->mRecord.mCallback;
124     callbackPContext = ar->mRecord.mContext;
125     interface_unlock_shared(&ar->mRecord);
126 
127     if (NULL != callback) {
128         // getting this event implies SL_RECORDEVENT_HEADATMARKER was set in the event mask
129         (*callback)(&ar->mRecord.mItf, callbackPContext, SL_RECORDEVENT_HEADATMARKER);
130     }
131 }
132 
133 
audioRecorder_handleOverrun_lockRecord(CAudioRecorder * ar)134 void audioRecorder_handleOverrun_lockRecord(CAudioRecorder* ar) {
135     //SL_LOGV("received event EVENT_OVERRUN from AudioRecord");
136     slRecordCallback callback = NULL;
137     void* callbackPContext = NULL;
138 
139     interface_lock_shared(&ar->mRecord);
140     if (ar->mRecord.mCallbackEventsMask & SL_RECORDEVENT_HEADSTALLED) {
141         callback = ar->mRecord.mCallback;
142         callbackPContext = ar->mRecord.mContext;
143     }
144     interface_unlock_shared(&ar->mRecord);
145 
146     if (NULL != callback) {
147         (*callback)(&ar->mRecord.mItf, callbackPContext, SL_RECORDEVENT_HEADSTALLED);
148     }
149 }
150 
151 //-----------------------------------------------------------------------------
android_audioRecorder_checkSourceSinkSupport(CAudioRecorder * ar)152 SLresult android_audioRecorder_checkSourceSinkSupport(CAudioRecorder* ar) {
153 
154     const SLDataSource *pAudioSrc = &ar->mDataSource.u.mSource;
155     const SLDataSink   *pAudioSnk = &ar->mDataSink.u.mSink;
156 
157     // Sink check:
158     // only buffer queue sinks are supported, regardless of the data source
159     if (SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE != *(SLuint32 *)pAudioSnk->pLocator) {
160         SL_LOGE(ERROR_RECORDER_SINK_MUST_BE_ANDROIDSIMPLEBUFFERQUEUE);
161         return SL_RESULT_PARAMETER_INVALID;
162     } else {
163         // only PCM buffer queues are supported
164         SLuint32 formatType = *(SLuint32 *)pAudioSnk->pFormat;
165         if (SL_DATAFORMAT_PCM == formatType) {
166             SLDataFormat_PCM *df_pcm = (SLDataFormat_PCM *)ar->mDataSink.u.mSink.pFormat;
167             ar->mSampleRateMilliHz = df_pcm->samplesPerSec;
168             ar->mNumChannels = df_pcm->numChannels;
169             SL_LOGV("AudioRecorder requested sample rate = %lumHz, %u channel(s)",
170                     ar->mSampleRateMilliHz, ar->mNumChannels);
171         }
172         else {
173             SL_LOGE(ERROR_RECORDER_SINK_FORMAT_MUST_BE_PCM);
174             return SL_RESULT_PARAMETER_INVALID;
175         }
176     }
177 
178     // Source check:
179     // only input device sources are supported
180     // check it's an IO device
181     if (SL_DATALOCATOR_IODEVICE != *(SLuint32 *)pAudioSrc->pLocator) {
182         SL_LOGE(ERROR_RECORDER_SOURCE_MUST_BE_IODEVICE);
183         return SL_RESULT_PARAMETER_INVALID;
184     } else {
185 
186         // check it's an input device
187         SLDataLocator_IODevice *dl_iod =  (SLDataLocator_IODevice *) pAudioSrc->pLocator;
188         if (SL_IODEVICE_AUDIOINPUT != dl_iod->deviceType) {
189             SL_LOGE(ERROR_RECORDER_IODEVICE_MUST_BE_AUDIOINPUT);
190             return SL_RESULT_PARAMETER_INVALID;
191         }
192 
193         // check it's the default input device, others aren't supported here
194         if (SL_DEFAULTDEVICEID_AUDIOINPUT != dl_iod->deviceID) {
195             SL_LOGE(ERROR_RECORDER_INPUT_ID_MUST_BE_DEFAULT);
196             return SL_RESULT_PARAMETER_INVALID;
197         }
198     }
199 
200     return SL_RESULT_SUCCESS;
201 }
202 //-----------------------------------------------------------------------------
audioRecorder_callback(int event,void * user,void * info)203 static void audioRecorder_callback(int event, void* user, void *info) {
204     //SL_LOGV("audioRecorder_callback(%d, %p, %p) entering", event, user, info);
205 
206     CAudioRecorder *ar = (CAudioRecorder *)user;
207     void * callbackPContext = NULL;
208 
209     switch(event) {
210     case android::AudioRecord::EVENT_MORE_DATA: {
211         slBufferQueueCallback callback = NULL;
212         android::AudioRecord::Buffer* pBuff = (android::AudioRecord::Buffer*)info;
213 
214         // push data to the buffer queue
215         interface_lock_exclusive(&ar->mBufferQueue);
216 
217         if (ar->mBufferQueue.mState.count != 0) {
218             assert(ar->mBufferQueue.mFront != ar->mBufferQueue.mRear);
219 
220             BufferHeader *oldFront = ar->mBufferQueue.mFront;
221             BufferHeader *newFront = &oldFront[1];
222 
223             // FIXME handle 8bit based on buffer format
224             short *pDest = (short*)((char *)oldFront->mBuffer + ar->mBufferQueue.mSizeConsumed);
225             if (ar->mBufferQueue.mSizeConsumed + pBuff->size < oldFront->mSize) {
226                 // can't consume the whole or rest of the buffer in one shot
227                 ar->mBufferQueue.mSizeConsumed += pBuff->size;
228                 // leave pBuff->size untouched
229                 // consume data
230                 // FIXME can we avoid holding the lock during the copy?
231                 memcpy (pDest, pBuff->i16, pBuff->size);
232 #ifdef MONITOR_RECORDING
233                 if (NULL != gMonitorFp) { fwrite(pBuff->i16, pBuff->size, 1, gMonitorFp); }
234 #endif
235             } else {
236                 // finish pushing the buffer or push the buffer in one shot
237                 pBuff->size = oldFront->mSize - ar->mBufferQueue.mSizeConsumed;
238                 ar->mBufferQueue.mSizeConsumed = 0;
239                 if (newFront ==  &ar->mBufferQueue.mArray[ar->mBufferQueue.mNumBuffers + 1]) {
240                     newFront = ar->mBufferQueue.mArray;
241                 }
242                 ar->mBufferQueue.mFront = newFront;
243 
244                 ar->mBufferQueue.mState.count--;
245                 ar->mBufferQueue.mState.playIndex++;
246                 // consume data
247                 // FIXME can we avoid holding the lock during the copy?
248                 memcpy (pDest, pBuff->i16, pBuff->size);
249 #ifdef MONITOR_RECORDING
250                 if (NULL != gMonitorFp) { fwrite(pBuff->i16, pBuff->size, 1, gMonitorFp); }
251 #endif
252                 // data has been copied to the buffer, and the buffer queue state has been updated
253                 // we will notify the client if applicable
254                 callback = ar->mBufferQueue.mCallback;
255                 // save callback data
256                 callbackPContext = ar->mBufferQueue.mContext;
257             }
258         } else {
259             // no destination to push the data
260             pBuff->size = 0;
261         }
262 
263         interface_unlock_exclusive(&ar->mBufferQueue);
264         // notify client
265         if (NULL != callback) {
266             (*callback)(&ar->mBufferQueue.mItf, callbackPContext);
267         }
268         }
269         break;
270 
271     case android::AudioRecord::EVENT_OVERRUN:
272         audioRecorder_handleOverrun_lockRecord(ar);
273         break;
274 
275     case android::AudioRecord::EVENT_MARKER:
276         audioRecorder_handleMarker_lockRecord(ar);
277         break;
278 
279     case android::AudioRecord::EVENT_NEW_POS:
280         audioRecorder_handleNewPos_lockRecord(ar);
281         break;
282 
283     }
284 }
285 
286 
287 //-----------------------------------------------------------------------------
android_audioRecorder_create(CAudioRecorder * ar)288 SLresult android_audioRecorder_create(CAudioRecorder* ar) {
289     SL_LOGV("android_audioRecorder_create(%p) entering", ar);
290 
291     SLresult result = SL_RESULT_SUCCESS;
292 
293     //  the following platform-independent fields have been initialized in CreateAudioRecorder()
294     //    ar->mNumChannels
295     //    ar->mSampleRateMilliHz
296 
297     ar->mAudioRecord = NULL;
298     ar->mRecordSource = android::AUDIO_SOURCE_DEFAULT;
299 
300     return result;
301 }
302 
303 
304 //-----------------------------------------------------------------------------
android_audioRecorder_setConfig(CAudioRecorder * ar,const SLchar * configKey,const void * pConfigValue,SLuint32 valueSize)305 SLresult android_audioRecorder_setConfig(CAudioRecorder* ar, const SLchar *configKey,
306         const void *pConfigValue, SLuint32 valueSize) {
307 
308     SLresult result = SL_RESULT_SUCCESS;
309 
310     if (NULL == ar) {
311         result = SL_RESULT_INTERNAL_ERROR;
312     } else if (NULL == pConfigValue) {
313         SL_LOGE(ERROR_CONFIG_NULL_PARAM);
314         result = SL_RESULT_PARAMETER_INVALID;
315 
316     } else if(strcmp((const char*)configKey, (const char*)SL_ANDROID_KEY_RECORDING_PRESET) == 0) {
317 
318         // recording preset
319         if (KEY_RECORDING_PRESET_PARAMSIZE > valueSize) {
320             SL_LOGE(ERROR_CONFIG_VALUESIZE_TOO_LOW);
321             result = SL_RESULT_PARAMETER_INVALID;
322         } else {
323             result = audioRecorder_setPreset(ar, *(SLuint32*)pConfigValue);
324         }
325 
326     } else {
327         SL_LOGE(ERROR_CONFIG_UNKNOWN_KEY);
328         result = SL_RESULT_PARAMETER_INVALID;
329     }
330 
331     return result;
332 }
333 
334 
335 //-----------------------------------------------------------------------------
android_audioRecorder_getConfig(CAudioRecorder * ar,const SLchar * configKey,SLuint32 * pValueSize,void * pConfigValue)336 SLresult android_audioRecorder_getConfig(CAudioRecorder* ar, const SLchar *configKey,
337         SLuint32* pValueSize, void *pConfigValue) {
338 
339     SLresult result = SL_RESULT_SUCCESS;
340 
341     if (NULL == ar) {
342         return SL_RESULT_INTERNAL_ERROR;
343     } else if (NULL == pValueSize) {
344         SL_LOGE(ERROR_CONFIG_NULL_PARAM);
345         result = SL_RESULT_PARAMETER_INVALID;
346 
347     } else if(strcmp((const char*)configKey, (const char*)SL_ANDROID_KEY_RECORDING_PRESET) == 0) {
348 
349         // recording preset
350         if (KEY_RECORDING_PRESET_PARAMSIZE > *pValueSize) {
351             SL_LOGE(ERROR_CONFIG_VALUESIZE_TOO_LOW);
352             result = SL_RESULT_PARAMETER_INVALID;
353         } else {
354             *pValueSize = KEY_RECORDING_PRESET_PARAMSIZE;
355             if (NULL != pConfigValue) {
356                 result = audioRecorder_getPreset(ar, (SLuint32*)pConfigValue);
357             }
358         }
359 
360     } else {
361         SL_LOGE(ERROR_CONFIG_UNKNOWN_KEY);
362         result = SL_RESULT_PARAMETER_INVALID;
363     }
364 
365     return result;
366 }
367 
368 
369 //-----------------------------------------------------------------------------
android_audioRecorder_realize(CAudioRecorder * ar,SLboolean async)370 SLresult android_audioRecorder_realize(CAudioRecorder* ar, SLboolean async) {
371     SL_LOGV("android_audioRecorder_realize(%p) entering", ar);
372 
373     SLresult result = SL_RESULT_SUCCESS;
374 
375     // initialize platform-independent CAudioRecorder fields
376     if (SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE != ar->mDataSink.mLocator.mLocatorType) {
377         SL_LOGE(ERROR_RECORDER_SINK_MUST_BE_ANDROIDSIMPLEBUFFERQUEUE);
378         return SL_RESULT_CONTENT_UNSUPPORTED;
379     }
380     //  the following platform-independent fields have been initialized in CreateAudioRecorder()
381     //    ar->mNumChannels
382     //    ar->mSampleRateMilliHz
383 
384     SL_LOGV("new AudioRecord %u channels, %lu mHz", ar->mNumChannels, ar->mSampleRateMilliHz);
385 
386     // initialize platform-specific CAudioRecorder fields
387     ar->mAudioRecord = new android::AudioRecord();
388     ar->mAudioRecord->set(ar->mRecordSource, // source
389             sles_to_android_sampleRate(ar->mSampleRateMilliHz), // sample rate in Hertz
390             android::AudioSystem::PCM_16_BIT,   //FIXME use format from buffer queue sink
391             sles_to_android_channelMaskIn(ar->mNumChannels, 0 /*no channel mask*/),
392                                    // channel config
393             0,                     //frameCount min
394             0,                     // flags
395             audioRecorder_callback,// callback_t
396             (void*)ar,             // user, callback data, here the AudioRecorder
397             0,                     // notificationFrames
398             false);                // threadCanCallJava, note: this will prevent direct Java
399                                    //   callbacks, but we don't want them in the recording loop
400 
401     if (android::NO_ERROR != ar->mAudioRecord->initCheck()) {
402         SL_LOGE("android_audioRecorder_realize(%p) error creating AudioRecord object", ar);
403         result = SL_RESULT_CONTENT_UNSUPPORTED;
404     }
405 
406 #ifdef MONITOR_RECORDING
407     gMonitorFp = fopen(MONITOR_TARGET, "w");
408     if (NULL == gMonitorFp) { SL_LOGE("error opening %s", MONITOR_TARGET); }
409     else { SL_LOGE("recording to %s", MONITOR_TARGET); } // SL_LOGE so it's always displayed
410 #endif
411 
412     return result;
413 }
414 
415 
416 //-----------------------------------------------------------------------------
android_audioRecorder_destroy(CAudioRecorder * ar)417 void android_audioRecorder_destroy(CAudioRecorder* ar) {
418     SL_LOGV("android_audioRecorder_destroy(%p) entering", ar);
419 
420     if (NULL != ar->mAudioRecord) {
421         ar->mAudioRecord->stop();
422         delete ar->mAudioRecord;
423         ar->mAudioRecord = NULL;
424     }
425 
426 #ifdef MONITOR_RECORDING
427     if (NULL != gMonitorFp) {
428         fclose(gMonitorFp);
429         gMonitorFp = NULL;
430     }
431 #endif
432 }
433 
434 
435 //-----------------------------------------------------------------------------
android_audioRecorder_setRecordState(CAudioRecorder * ar,SLuint32 state)436 void android_audioRecorder_setRecordState(CAudioRecorder* ar, SLuint32 state) {
437     SL_LOGV("android_audioRecorder_setRecordState(%p, %lu) entering", ar, state);
438 
439     if (NULL == ar->mAudioRecord) {
440         return;
441     }
442 
443     switch (state) {
444      case SL_RECORDSTATE_STOPPED:
445          ar->mAudioRecord->stop();
446          break;
447      case SL_RECORDSTATE_PAUSED:
448          // Note that pausing is treated like stop as this implementation only records to a buffer
449          //  queue, so there is no notion of destination being "opened" or "closed" (See description
450          //  of SL_RECORDSTATE in specification)
451          ar->mAudioRecord->stop();
452          break;
453      case SL_RECORDSTATE_RECORDING:
454          ar->mAudioRecord->start();
455          break;
456      default:
457          break;
458      }
459 
460 }
461 
462 
463 //-----------------------------------------------------------------------------
android_audioRecorder_useEventMask(CAudioRecorder * ar)464 void android_audioRecorder_useEventMask(CAudioRecorder *ar) {
465     IRecord *pRecordItf = &ar->mRecord;
466     SLuint32 eventFlags = pRecordItf->mCallbackEventsMask;
467 
468     if (NULL == ar->mAudioRecord) {
469         return;
470     }
471 
472     if ((eventFlags & SL_RECORDEVENT_HEADATMARKER) && (pRecordItf->mMarkerPosition != 0)) {
473         ar->mAudioRecord->setMarkerPosition((uint32_t)((((int64_t)pRecordItf->mMarkerPosition
474                 * sles_to_android_sampleRate(ar->mSampleRateMilliHz)))/1000));
475     } else {
476         // clear marker
477         ar->mAudioRecord->setMarkerPosition(0);
478     }
479 
480     if (eventFlags & SL_RECORDEVENT_HEADATNEWPOS) {
481         SL_LOGV("pos update period %ld", pRecordItf->mPositionUpdatePeriod);
482          ar->mAudioRecord->setPositionUpdatePeriod(
483                 (uint32_t)((((int64_t)pRecordItf->mPositionUpdatePeriod
484                 * sles_to_android_sampleRate(ar->mSampleRateMilliHz)))/1000));
485     } else {
486         // clear periodic update
487         ar->mAudioRecord->setPositionUpdatePeriod(0);
488     }
489 
490     if (eventFlags & SL_RECORDEVENT_HEADATLIMIT) {
491         // FIXME support SL_RECORDEVENT_HEADATLIMIT
492         SL_LOGD("[ FIXME: IRecord_SetCallbackEventsMask(SL_RECORDEVENT_HEADATLIMIT) on an "
493                     "SL_OBJECTID_AUDIORECORDER to be implemented ]");
494     }
495 
496     if (eventFlags & SL_RECORDEVENT_HEADMOVING) {
497         // FIXME support SL_RECORDEVENT_HEADMOVING
498         SL_LOGD("[ FIXME: IRecord_SetCallbackEventsMask(SL_RECORDEVENT_HEADMOVING) on an "
499                 "SL_OBJECTID_AUDIORECORDER to be implemented ]");
500     }
501 
502     if (eventFlags & SL_RECORDEVENT_BUFFER_FULL) {
503         // nothing to do for SL_RECORDEVENT_BUFFER_FULL since this will not be encountered on
504         // recording to buffer queues
505     }
506 
507     if (eventFlags & SL_RECORDEVENT_HEADSTALLED) {
508         // nothing to do for SL_RECORDEVENT_HEADSTALLED, callback event will be checked against mask
509         // when AudioRecord::EVENT_OVERRUN is encountered
510 
511     }
512 
513 }
514 
515 
516 //-----------------------------------------------------------------------------
android_audioRecorder_getPosition(CAudioRecorder * ar,SLmillisecond * pPosMsec)517 void android_audioRecorder_getPosition(CAudioRecorder *ar, SLmillisecond *pPosMsec) {
518     if ((NULL == ar) || (NULL == ar->mAudioRecord)) {
519         *pPosMsec = 0;
520     } else {
521         uint32_t positionInFrames;
522         ar->mAudioRecord->getPosition(&positionInFrames);
523         if (ar->mSampleRateMilliHz == 0) {
524             *pPosMsec = 0;
525         } else {
526             *pPosMsec = ((int64_t)positionInFrames * 1000) /
527                     sles_to_android_sampleRate(ar->mSampleRateMilliHz);
528         }
529     }
530 }
531