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 /* This is a JNI example where we use native methods to play sounds
19 * using OpenSL ES. See the corresponding Java source file located at:
20 *
21 * src/com/example/nativeaudio/NativeAudio/NativeAudio.java
22 */
23
24 #include <assert.h>
25 #include <jni.h>
26 #include <string.h>
27
28 // for __android_log_print(ANDROID_LOG_INFO, "YourApp", "formatted message");
29 // #include <android/log.h>
30
31 // for native audio
32 #include <SLES/OpenSLES.h>
33 #include "SLES/OpenSLES_Android.h"
34
35 // for native asset manager
36 #include <sys/types.h>
37 #include <android/asset_manager.h>
38 #include <android/asset_manager_jni.h>
39
40 // pre-recorded sound clips, both are 8 kHz mono 16-bit signed little endian
41
42 static const char hello[] =
43 #include "hello_clip.h"
44 ;
45
46 static const char android[] =
47 #include "android_clip.h"
48 ;
49
50 // engine interfaces
51 static SLObjectItf engineObject = NULL;
52 static SLEngineItf engineEngine;
53
54 // output mix interfaces
55 static SLObjectItf outputMixObject = NULL;
56 static SLEnvironmentalReverbItf outputMixEnvironmentalReverb = NULL;
57
58 // buffer queue player interfaces
59 static SLObjectItf bqPlayerObject = NULL;
60 static SLPlayItf bqPlayerPlay;
61 static SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue;
62 static SLEffectSendItf bqPlayerEffectSend;
63
64 // aux effect on the output mix, used by the buffer queue player
65 static const SLEnvironmentalReverbSettings reverbSettings =
66 SL_I3DL2_ENVIRONMENT_PRESET_STONECORRIDOR;
67
68 // URI player interfaces
69 static SLObjectItf uriPlayerObject = NULL;
70 static SLPlayItf uriPlayerPlay;
71 static SLSeekItf uriPlayerSeek;
72
73 // file descriptor player interfaces
74 static SLObjectItf fdPlayerObject = NULL;
75 static SLPlayItf fdPlayerPlay;
76 static SLSeekItf fdPlayerSeek;
77
78 // recorder interfaces
79 static SLObjectItf recorderObject = NULL;
80 static SLRecordItf recorderRecord;
81 static SLAndroidSimpleBufferQueueItf recorderBufferQueue;
82
83 // synthesized sawtooth clip
84 #define SAWTOOTH_FRAMES 8000
85 static short sawtoothBuffer[SAWTOOTH_FRAMES];
86
87 // 5 seconds of recorded audio at 16 kHz mono, 16-bit signed little endian
88 #define RECORDER_FRAMES (16000 * 5)
89 static short recorderBuffer[RECORDER_FRAMES];
90 static unsigned recorderSize = 0;
91 static SLmilliHertz recorderSR;
92
93 // pointer and size of the next player buffer to enqueue, and number of remaining buffers
94 static short *nextBuffer;
95 static unsigned nextSize;
96 static int nextCount;
97
98
99 // synthesize a mono sawtooth wave and place it into a buffer (called automatically on load)
onDlOpen(void)100 __attribute__((constructor)) static void onDlOpen(void)
101 {
102 unsigned i;
103 for (i = 0; i < SAWTOOTH_FRAMES; ++i) {
104 sawtoothBuffer[i] = 32768 - ((i % 100) * 660);
105 }
106 }
107
108
109 // this callback handler is called every time a buffer finishes playing
bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq,void * context)110 void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context)
111 {
112 assert(bq == bqPlayerBufferQueue);
113 assert(NULL == context);
114 // for streaming playback, replace this test by logic to find and fill the next buffer
115 if (--nextCount > 0 && NULL != nextBuffer && 0 != nextSize) {
116 SLresult result;
117 // enqueue another buffer
118 result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, nextBuffer, nextSize);
119 // the most likely other result is SL_RESULT_BUFFER_INSUFFICIENT,
120 // which for this code example would indicate a programming error
121 assert(SL_RESULT_SUCCESS == result);
122 }
123 }
124
125
126 // this callback handler is called every time a buffer finishes recording
bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq,void * context)127 void bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void *context)
128 {
129 assert(bq == bqRecorderBufferQueue);
130 assert(NULL == context);
131 // for streaming recording, here we would call Enqueue to give recorder the next buffer to fill
132 // but instead, this is a one-time buffer so we stop recording
133 SLresult result;
134 result = (*recorderRecord)->SetRecordState(recorderRecord, SL_RECORDSTATE_STOPPED);
135 if (SL_RESULT_SUCCESS == result) {
136 recorderSize = RECORDER_FRAMES * sizeof(short);
137 recorderSR = SL_SAMPLINGRATE_16;
138 }
139 }
140
141
142 // create the engine and output mix objects
Java_com_example_nativeaudio_NativeAudio_createEngine(JNIEnv * env,jclass clazz)143 void Java_com_example_nativeaudio_NativeAudio_createEngine(JNIEnv* env, jclass clazz)
144 {
145 SLresult result;
146
147 // create engine
148 result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
149 assert(SL_RESULT_SUCCESS == result);
150
151 // realize the engine
152 result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
153 assert(SL_RESULT_SUCCESS == result);
154
155 // get the engine interface, which is needed in order to create other objects
156 result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
157 assert(SL_RESULT_SUCCESS == result);
158
159 // create output mix, with environmental reverb specified as a non-required interface
160 const SLInterfaceID ids[1] = {SL_IID_ENVIRONMENTALREVERB};
161 const SLboolean req[1] = {SL_BOOLEAN_FALSE};
162 result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 1, ids, req);
163 assert(SL_RESULT_SUCCESS == result);
164
165 // realize the output mix
166 result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
167 assert(SL_RESULT_SUCCESS == result);
168
169 // get the environmental reverb interface
170 // this could fail if the environmental reverb effect is not available,
171 // either because the feature is not present, excessive CPU load, or
172 // the required MODIFY_AUDIO_SETTINGS permission was not requested and granted
173 result = (*outputMixObject)->GetInterface(outputMixObject, SL_IID_ENVIRONMENTALREVERB,
174 &outputMixEnvironmentalReverb);
175 if (SL_RESULT_SUCCESS == result) {
176 result = (*outputMixEnvironmentalReverb)->SetEnvironmentalReverbProperties(
177 outputMixEnvironmentalReverb, &reverbSettings);
178 }
179 // ignore unsuccessful result codes for environmental reverb, as it is optional for this example
180
181 }
182
183
184 // create buffer queue audio player
Java_com_example_nativeaudio_NativeAudio_createBufferQueueAudioPlayer(JNIEnv * env,jclass clazz)185 void Java_com_example_nativeaudio_NativeAudio_createBufferQueueAudioPlayer(JNIEnv* env,
186 jclass clazz)
187 {
188 SLresult result;
189
190 // configure audio source
191 SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
192 SLDataFormat_PCM format_pcm = {SL_DATAFORMAT_PCM, 1, SL_SAMPLINGRATE_8,
193 SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16,
194 SL_SPEAKER_FRONT_CENTER, SL_BYTEORDER_LITTLEENDIAN};
195 SLDataSource audioSrc = {&loc_bufq, &format_pcm};
196
197 // configure audio sink
198 SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
199 SLDataSink audioSnk = {&loc_outmix, NULL};
200
201 // create audio player
202 const SLInterfaceID ids[2] = {SL_IID_BUFFERQUEUE, SL_IID_EFFECTSEND};
203 const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
204 result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk,
205 2, ids, req);
206 assert(SL_RESULT_SUCCESS == result);
207
208 // realize the player
209 result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE);
210 assert(SL_RESULT_SUCCESS == result);
211
212 // get the play interface
213 result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay);
214 assert(SL_RESULT_SUCCESS == result);
215
216 // get the buffer queue interface
217 result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE,
218 &bqPlayerBufferQueue);
219 assert(SL_RESULT_SUCCESS == result);
220
221 // register callback on the buffer queue
222 result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, NULL);
223 assert(SL_RESULT_SUCCESS == result);
224
225 // get the effect send interface
226 result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_EFFECTSEND,
227 &bqPlayerEffectSend);
228 assert(SL_RESULT_SUCCESS == result);
229
230 // set the player's state to playing
231 result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING);
232 assert(SL_RESULT_SUCCESS == result);
233
234 }
235
236
237 // create URI audio player
Java_com_example_nativeaudio_NativeAudio_createUriAudioPlayer(JNIEnv * env,jclass clazz,jstring uri)238 jboolean Java_com_example_nativeaudio_NativeAudio_createUriAudioPlayer(JNIEnv* env, jclass clazz,
239 jstring uri)
240 {
241 SLresult result;
242
243 // convert Java string to UTF-8
244 const jbyte *utf8 = (*env)->GetStringUTFChars(env, uri, NULL);
245 assert(NULL != utf8);
246
247 // configure audio source
248 // (requires the INTERNET permission depending on the uri parameter)
249 SLDataLocator_URI loc_uri = {SL_DATALOCATOR_URI, (SLchar *) utf8};
250 SLDataFormat_MIME format_mime = {SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED};
251 SLDataSource audioSrc = {&loc_uri, &format_mime};
252
253 // configure audio sink
254 SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
255 SLDataSink audioSnk = {&loc_outmix, NULL};
256
257 // create audio player
258 const SLInterfaceID ids[1] = {SL_IID_SEEK};
259 const SLboolean req[1] = {SL_BOOLEAN_TRUE};
260 result = (*engineEngine)->CreateAudioPlayer(engineEngine, &uriPlayerObject, &audioSrc,
261 &audioSnk, 1, ids, req);
262 // note that an invalid URI is not detected here, but during prepare/prefetch on Android,
263 // or possibly during Realize on other platforms
264 assert(SL_RESULT_SUCCESS == result);
265
266 // release the Java string and UTF-8
267 (*env)->ReleaseStringUTFChars(env, uri, utf8);
268
269 // realize the player
270 result = (*uriPlayerObject)->Realize(uriPlayerObject, SL_BOOLEAN_FALSE);
271 // this will always succeed on Android, but we check result for portability to other platforms
272 if (SL_RESULT_SUCCESS != result) {
273 (*uriPlayerObject)->Destroy(uriPlayerObject);
274 uriPlayerObject = NULL;
275 return JNI_FALSE;
276 }
277
278 // get the play interface
279 result = (*uriPlayerObject)->GetInterface(uriPlayerObject, SL_IID_PLAY, &uriPlayerPlay);
280 assert(SL_RESULT_SUCCESS == result);
281
282 // get the seek interface
283 result = (*uriPlayerObject)->GetInterface(uriPlayerObject, SL_IID_SEEK, &uriPlayerSeek);
284 assert(SL_RESULT_SUCCESS == result);
285
286 // enable whole file looping
287 result = (*uriPlayerSeek)->SetLoop(uriPlayerSeek, SL_BOOLEAN_TRUE, 0, SL_TIME_UNKNOWN);
288 assert(SL_RESULT_SUCCESS == result);
289
290 return JNI_TRUE;
291 }
292
293
294 // set the playing state for the URI audio player
Java_com_example_nativeaudio_NativeAudio_setPlayingUriAudioPlayer(JNIEnv * env,jclass clazz,jboolean isPlaying)295 void Java_com_example_nativeaudio_NativeAudio_setPlayingUriAudioPlayer(JNIEnv* env,
296 jclass clazz, jboolean isPlaying)
297 {
298 SLresult result;
299
300 // make sure the URI audio player was created
301 if (NULL != uriPlayerPlay) {
302
303 // set the player's state
304 result = (*uriPlayerPlay)->SetPlayState(uriPlayerPlay, isPlaying ?
305 SL_PLAYSTATE_PLAYING : SL_PLAYSTATE_PAUSED);
306 assert(SL_RESULT_SUCCESS == result);
307
308 }
309
310 }
311
312
313 // enable reverb on the buffer queue player
Java_com_example_nativeaudio_NativeAudio_enableReverb(JNIEnv * env,jclass clazz,jboolean enabled)314 jboolean Java_com_example_nativeaudio_NativeAudio_enableReverb(JNIEnv* env, jclass clazz,
315 jboolean enabled)
316 {
317 SLresult result;
318
319 // we might not have been able to add environmental reverb to the output mix
320 if (NULL == outputMixEnvironmentalReverb) {
321 return JNI_FALSE;
322 }
323
324 result = (*bqPlayerEffectSend)->EnableEffectSend(bqPlayerEffectSend,
325 outputMixEnvironmentalReverb, (SLboolean) enabled, (SLmillibel) 0);
326 // and even if environmental reverb was present, it might no longer be available
327 if (SL_RESULT_SUCCESS != result) {
328 return JNI_FALSE;
329 }
330
331 return JNI_TRUE;
332 }
333
334
335 // select the desired clip and play count, and enqueue the first buffer if idle
Java_com_example_nativeaudio_NativeAudio_selectClip(JNIEnv * env,jclass clazz,jint which,jint count)336 jboolean Java_com_example_nativeaudio_NativeAudio_selectClip(JNIEnv* env, jclass clazz, jint which,
337 jint count)
338 {
339 short *oldBuffer = nextBuffer;
340 switch (which) {
341 case 0: // CLIP_NONE
342 nextBuffer = (short *) NULL;
343 nextSize = 0;
344 break;
345 case 1: // CLIP_HELLO
346 nextBuffer = (short *) hello;
347 nextSize = sizeof(hello);
348 break;
349 case 2: // CLIP_ANDROID
350 nextBuffer = (short *) android;
351 nextSize = sizeof(android);
352 break;
353 case 3: // CLIP_SAWTOOTH
354 nextBuffer = sawtoothBuffer;
355 nextSize = sizeof(sawtoothBuffer);
356 break;
357 case 4: // CLIP_PLAYBACK
358 // we recorded at 16 kHz, but are playing buffers at 8 Khz, so do a primitive down-sample
359 if (recorderSR == SL_SAMPLINGRATE_16) {
360 unsigned i;
361 for (i = 0; i < recorderSize; i += 2 * sizeof(short)) {
362 recorderBuffer[i >> 2] = recorderBuffer[i >> 1];
363 }
364 recorderSR = SL_SAMPLINGRATE_8;
365 recorderSize >>= 1;
366 }
367 nextBuffer = recorderBuffer;
368 nextSize = recorderSize;
369 break;
370 default:
371 nextBuffer = NULL;
372 nextSize = 0;
373 break;
374 }
375 nextCount = count;
376 if (nextSize > 0) {
377 // here we only enqueue one buffer because it is a long clip,
378 // but for streaming playback we would typically enqueue at least 2 buffers to start
379 SLresult result;
380 result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, nextBuffer, nextSize);
381 if (SL_RESULT_SUCCESS != result) {
382 return JNI_FALSE;
383 }
384 }
385
386 return JNI_TRUE;
387 }
388
389
390 // create asset audio player
Java_com_example_nativeaudio_NativeAudio_createAssetAudioPlayer(JNIEnv * env,jclass clazz,jobject assetManager,jstring filename)391 jboolean Java_com_example_nativeaudio_NativeAudio_createAssetAudioPlayer(JNIEnv* env, jclass clazz,
392 jobject assetManager, jstring filename)
393 {
394 SLresult result;
395
396 // convert Java string to UTF-8
397 const jbyte *utf8 = (*env)->GetStringUTFChars(env, filename, NULL);
398 assert(NULL != utf8);
399
400 // use asset manager to open asset by filename
401 AAssetManager* mgr = AAssetManager_fromJava(env, assetManager);
402 assert(NULL != mgr);
403 AAsset* asset = AAssetManager_open(mgr, (const char *) utf8, AASSET_MODE_UNKNOWN);
404
405 // release the Java string and UTF-8
406 (*env)->ReleaseStringUTFChars(env, filename, utf8);
407
408 // the asset might not be found
409 if (NULL == asset) {
410 return JNI_FALSE;
411 }
412
413 // open asset as file descriptor
414 off_t start, length;
415 int fd = AAsset_openFileDescriptor(asset, &start, &length);
416 assert(0 <= fd);
417 AAsset_close(asset);
418
419 // configure audio source
420 SLDataLocator_AndroidFD loc_fd = {SL_DATALOCATOR_ANDROIDFD, fd, start, length};
421 SLDataFormat_MIME format_mime = {SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED};
422 SLDataSource audioSrc = {&loc_fd, &format_mime};
423
424 // configure audio sink
425 SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
426 SLDataSink audioSnk = {&loc_outmix, NULL};
427
428 // create audio player
429 const SLInterfaceID ids[1] = {SL_IID_SEEK};
430 const SLboolean req[1] = {SL_BOOLEAN_TRUE};
431 result = (*engineEngine)->CreateAudioPlayer(engineEngine, &fdPlayerObject, &audioSrc, &audioSnk,
432 1, ids, req);
433 assert(SL_RESULT_SUCCESS == result);
434
435 // realize the player
436 result = (*fdPlayerObject)->Realize(fdPlayerObject, SL_BOOLEAN_FALSE);
437 assert(SL_RESULT_SUCCESS == result);
438
439 // get the play interface
440 result = (*fdPlayerObject)->GetInterface(fdPlayerObject, SL_IID_PLAY, &fdPlayerPlay);
441 assert(SL_RESULT_SUCCESS == result);
442
443 // get the seek interface
444 result = (*fdPlayerObject)->GetInterface(fdPlayerObject, SL_IID_SEEK, &fdPlayerSeek);
445 assert(SL_RESULT_SUCCESS == result);
446
447 // enable whole file looping
448 result = (*fdPlayerSeek)->SetLoop(fdPlayerSeek, SL_BOOLEAN_TRUE, 0, SL_TIME_UNKNOWN);
449 assert(SL_RESULT_SUCCESS == result);
450
451 return JNI_TRUE;
452 }
453
454
455 // set the playing state for the asset audio player
Java_com_example_nativeaudio_NativeAudio_setPlayingAssetAudioPlayer(JNIEnv * env,jclass clazz,jboolean isPlaying)456 void Java_com_example_nativeaudio_NativeAudio_setPlayingAssetAudioPlayer(JNIEnv* env,
457 jclass clazz, jboolean isPlaying)
458 {
459 SLresult result;
460
461 // make sure the asset audio player was created
462 if (NULL != fdPlayerPlay) {
463
464 // set the player's state
465 result = (*fdPlayerPlay)->SetPlayState(fdPlayerPlay, isPlaying ?
466 SL_PLAYSTATE_PLAYING : SL_PLAYSTATE_PAUSED);
467 assert(SL_RESULT_SUCCESS == result);
468
469 }
470
471 }
472
473
474 // create audio recorder
Java_com_example_nativeaudio_NativeAudio_createAudioRecorder(JNIEnv * env,jclass clazz)475 jboolean Java_com_example_nativeaudio_NativeAudio_createAudioRecorder(JNIEnv* env, jclass clazz)
476 {
477 SLresult result;
478
479 // configure audio source
480 SLDataLocator_IODevice loc_dev = {SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT,
481 SL_DEFAULTDEVICEID_AUDIOINPUT, NULL};
482 SLDataSource audioSrc = {&loc_dev, NULL};
483
484 // configure audio sink
485 SLDataLocator_AndroidSimpleBufferQueue loc_bq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
486 SLDataFormat_PCM format_pcm = {SL_DATAFORMAT_PCM, 1, SL_SAMPLINGRATE_16,
487 SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16,
488 SL_SPEAKER_FRONT_CENTER, SL_BYTEORDER_LITTLEENDIAN};
489 SLDataSink audioSnk = {&loc_bq, &format_pcm};
490
491 // create audio recorder
492 // (requires the RECORD_AUDIO permission)
493 const SLInterfaceID id[1] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE};
494 const SLboolean req[1] = {SL_BOOLEAN_TRUE};
495 result = (*engineEngine)->CreateAudioRecorder(engineEngine, &recorderObject, &audioSrc,
496 &audioSnk, 1, id, req);
497 if (SL_RESULT_SUCCESS != result) {
498 return JNI_FALSE;
499 }
500
501 // realize the audio recorder
502 result = (*recorderObject)->Realize(recorderObject, SL_BOOLEAN_FALSE);
503 if (SL_RESULT_SUCCESS != result) {
504 return JNI_FALSE;
505 }
506
507 // get the record interface
508 result = (*recorderObject)->GetInterface(recorderObject, SL_IID_RECORD, &recorderRecord);
509 assert(SL_RESULT_SUCCESS == result);
510
511 // get the buffer queue interface
512 result = (*recorderObject)->GetInterface(recorderObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
513 &recorderBufferQueue);
514 assert(SL_RESULT_SUCCESS == result);
515
516 // register callback on the buffer queue
517 result = (*recorderBufferQueue)->RegisterCallback(recorderBufferQueue, bqRecorderCallback,
518 NULL);
519 assert(SL_RESULT_SUCCESS == result);
520
521 return JNI_TRUE;
522 }
523
524
525 // set the recording state for the audio recorder
Java_com_example_nativeaudio_NativeAudio_startRecording(JNIEnv * env,jclass clazz)526 void Java_com_example_nativeaudio_NativeAudio_startRecording(JNIEnv* env, jclass clazz)
527 {
528 SLresult result;
529
530 // in case already recording, stop recording and clear buffer queue
531 result = (*recorderRecord)->SetRecordState(recorderRecord, SL_RECORDSTATE_STOPPED);
532 assert(SL_RESULT_SUCCESS == result);
533 result = (*recorderBufferQueue)->Clear(recorderBufferQueue);
534 assert(SL_RESULT_SUCCESS == result);
535
536 // the buffer is not valid for playback yet
537 recorderSize = 0;
538
539 // enqueue an empty buffer to be filled by the recorder
540 // (for streaming recording, we would enqueue at least 2 empty buffers to start things off)
541 result = (*recorderBufferQueue)->Enqueue(recorderBufferQueue, recorderBuffer,
542 RECORDER_FRAMES * sizeof(short));
543 // the most likely other result is SL_RESULT_BUFFER_INSUFFICIENT,
544 // which for this code example would indicate a programming error
545 assert(SL_RESULT_SUCCESS == result);
546
547 // start recording
548 result = (*recorderRecord)->SetRecordState(recorderRecord, SL_RECORDSTATE_RECORDING);
549 assert(SL_RESULT_SUCCESS == result);
550
551 }
552
553
554 // shut down the native audio system
Java_com_example_nativeaudio_NativeAudio_shutdown(JNIEnv * env,jclass clazz)555 void Java_com_example_nativeaudio_NativeAudio_shutdown(JNIEnv* env, jclass clazz)
556 {
557
558 // destroy buffer queue audio player object, and invalidate all associated interfaces
559 if (bqPlayerObject != NULL) {
560 (*bqPlayerObject)->Destroy(bqPlayerObject);
561 bqPlayerObject = NULL;
562 bqPlayerPlay = NULL;
563 bqPlayerBufferQueue = NULL;
564 bqPlayerEffectSend = NULL;
565 }
566
567 // destroy file descriptor audio player object, and invalidate all associated interfaces
568 if (fdPlayerObject != NULL) {
569 (*fdPlayerObject)->Destroy(fdPlayerObject);
570 fdPlayerObject = NULL;
571 fdPlayerPlay = NULL;
572 fdPlayerSeek = NULL;
573 }
574
575 // destroy URI audio player object, and invalidate all associated interfaces
576 if (uriPlayerObject != NULL) {
577 (*uriPlayerObject)->Destroy(uriPlayerObject);
578 uriPlayerObject = NULL;
579 uriPlayerPlay = NULL;
580 uriPlayerSeek = NULL;
581 }
582
583 // destroy audio recorder object, and invalidate all associated interfaces
584 if (recorderObject != NULL) {
585 (*recorderObject)->Destroy(recorderObject);
586 recorderObject = NULL;
587 recorderRecord = NULL;
588 recorderBufferQueue = NULL;
589 }
590
591 // destroy output mix object, and invalidate all associated interfaces
592 if (outputMixObject != NULL) {
593 (*outputMixObject)->Destroy(outputMixObject);
594 outputMixObject = NULL;
595 outputMixEnvironmentalReverb = NULL;
596 }
597
598 // destroy engine object, and invalidate all associated interfaces
599 if (engineObject != NULL) {
600 (*engineObject)->Destroy(engineObject);
601 engineObject = NULL;
602 engineEngine = NULL;
603 }
604
605 }
606