• 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 /* 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