1 /*---------------------------------------------------------------------------*
2 * android_speech_srec_MicrophoneInputStream.cpp *
3 * *
4 * Copyright 2007 Nuance Communciations, Inc. *
5 * *
6 * Licensed under the Apache License, Version 2.0 (the 'License'); *
7 * you may not use this file except in compliance with the License. *
8 * *
9 * You may obtain a copy of the License at *
10 * http://www.apache.org/licenses/LICENSE-2.0 *
11 * *
12 * Unless required by applicable law or agreed to in writing, software *
13 * distributed under the License is distributed on an 'AS IS' BASIS, *
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
15 * See the License for the specific language governing permissions and *
16 * limitations under the License. *
17 * *
18 *---------------------------------------------------------------------------*/
19
20
21 #include <string.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24
25 #define LOG_TAG "srec_jni"
26 #include <utils/Log.h>
27
28 #include <media/AudioRecord.h>
29 #include <media/mediarecorder.h>
30
31 #include <system/audio.h>
32
33 #include <jni.h>
34
35 using namespace android;
36
37
38
39 //
40 // helper function to throw an exception
41 //
throwException(JNIEnv * env,const char * ex,const char * fmt,int data)42 static void throwException(JNIEnv *env, const char* ex, const char* fmt, int data) {
43 if (jclass cls = env->FindClass(ex)) {
44 char msg[1000];
45 sprintf(msg, fmt, data);
46 env->ThrowNew(cls, msg);
47 env->DeleteLocalRef(cls);
48 }
49 }
50
51
52 ///////////////////////////////////////////////////////////////////////////////
53 // MicrophoneInputStream JNI implememtations
54 ///////////////////////////////////////////////////////////////////////////////
55
Java_android_speech_srec_Recognizer_AudioRecordNew(JNIEnv * env,jclass clazz,jint sampleRate,jint fifoFrames)56 static JNIEXPORT jint JNICALL Java_android_speech_srec_Recognizer_AudioRecordNew
57 (JNIEnv *env, jclass clazz, jint sampleRate, jint fifoFrames) {
58
59 android::AudioRecord* ar = new android::AudioRecord(
60 AUDIO_SOURCE_VOICE_RECOGNITION, sampleRate,
61 AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_MONO,
62 fifoFrames, 0);
63 if (ar == NULL) {
64 LOGE("Error creating AudioRecord");
65 }
66 else {
67 status_t s = ar->initCheck();
68 if (s != NO_ERROR) {
69 delete ar;
70 ar = NULL;
71 LOGE("initCheck error %d ", s);
72 }
73 }
74 return (int)ar;
75 }
76
Java_android_speech_srec_Recognizer_AudioRecordStart(JNIEnv * env,jclass clazz,jint audioRecord)77 static JNIEXPORT int JNICALL Java_android_speech_srec_Recognizer_AudioRecordStart
78 (JNIEnv *env, jclass clazz, jint audioRecord) {
79 return (int)(((AudioRecord*)audioRecord)->start());
80 }
81
Java_android_speech_srec_Recognizer_AudioRecordRead(JNIEnv * env,jclass clazz,jint audioRecord,jbyteArray array,jint offset,jint length)82 static JNIEXPORT jint JNICALL Java_android_speech_srec_Recognizer_AudioRecordRead
83 (JNIEnv *env, jclass clazz, jint audioRecord, jbyteArray array, jint offset, jint length) {
84 jbyte buffer[4096];
85 if (length > (int)sizeof(buffer)) length = sizeof(buffer);
86 length = ((AudioRecord*)audioRecord)->read(buffer, length);
87 if (length < 0) {
88 throwException(env, "java/io/IOException", "AudioRecord::read failed %d", length);
89 return -1;
90 }
91 env->SetByteArrayRegion(array, offset, length, buffer);
92 return length;
93 }
94
Java_android_speech_srec_Recognizer_AudioRecordStop(JNIEnv * env,jclass clazz,jint audioRecord)95 static JNIEXPORT void JNICALL Java_android_speech_srec_Recognizer_AudioRecordStop
96 (JNIEnv *env, jclass clazz, jint audioRecord) {
97 if (int rtn = ((AudioRecord*)audioRecord)->stop()) {
98 throwException(env, "java/io/IOException", "AudioRecord::stop failed %d", rtn);
99 }
100 }
101
Java_android_speech_srec_Recognizer_AudioRecordDelete(JNIEnv * env,jclass clazz,jint audioRecord)102 static JNIEXPORT void JNICALL Java_android_speech_srec_Recognizer_AudioRecordDelete
103 (JNIEnv *env, jclass clazz, jint audioRecord) {
104 delete (AudioRecord*)audioRecord;
105 }
106
107
108 /*
109 * Table of methods associated with a single class.
110 */
111 static JNINativeMethod gMethods[] = {
112 /* name, signature, funcPtr */
113 {"AudioRecordNew", "(II)I", (void*)Java_android_speech_srec_Recognizer_AudioRecordNew},
114 {"AudioRecordStart", "(I)I", (void*)Java_android_speech_srec_Recognizer_AudioRecordStart},
115 {"AudioRecordRead", "(I[BII)I", (void*)Java_android_speech_srec_Recognizer_AudioRecordRead},
116 {"AudioRecordStop", "(I)V", (void*)Java_android_speech_srec_Recognizer_AudioRecordStop},
117 {"AudioRecordDelete", "(I)V", (void*)Java_android_speech_srec_Recognizer_AudioRecordDelete},
118 };
119
120 /*
121 * Set some test stuff up.
122 *
123 * Returns the JNI version on success, -1 on failure.
124 */
register_android_speech_srec_MicrophoneInputStream(JavaVM * vm,void * reserved)125 jint register_android_speech_srec_MicrophoneInputStream(JavaVM* vm, void* reserved)
126 {
127 JNIEnv* env = NULL;
128 jclass clazz = NULL;
129 const char* className = "android/speech/srec/MicrophoneInputStream";
130
131 if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
132 LOGE("ERROR: GetEnv failed\n");
133 return -1;
134 }
135 assert(env != NULL);
136
137 clazz = env->FindClass(className);
138 if (clazz == NULL) {
139 LOGE("Native registration unable to find class '%s'\n", className);
140 return -1;
141 }
142 if (env->RegisterNatives(clazz, gMethods,
143 sizeof(gMethods) / sizeof(gMethods[0])) < 0) {
144 LOGE("RegisterNatives failed for '%s'\n", className);
145 return -1;
146 }
147
148 /* success -- return valid version number */
149 return JNI_VERSION_1_4;;
150 }
151