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