Home | History | Annotate | Download | only in srec_jni
      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 // Java uses an int to hold a raw pointer, which is already ugly.
     57 // But we need to hold an sp<>, which is of unknown size.
     58 // So we wrap the sp<> within a class, and give Java the int version of a pointer to this class.
     59 class AudioRecordWrapper {
     60 public:
     61     AudioRecordWrapper(AudioRecord *audioRecord) : mAudioRecord(audioRecord) { }
     62     ~AudioRecordWrapper() { }
     63     AudioRecord* get() const { return mAudioRecord.get(); }
     64 private:
     65     const sp<AudioRecord> mAudioRecord;
     66 };
     67 
     68 static JNIEXPORT jlong JNICALL Java_android_speech_srec_Recognizer_AudioRecordNew
     69         (JNIEnv *env, jclass clazz, jint sampleRate, jint fifoFrames) {
     70 
     71     AudioRecordWrapper *ar = new AudioRecordWrapper(new AudioRecord(
     72             AUDIO_SOURCE_VOICE_RECOGNITION, sampleRate,
     73             AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_MONO,
     74             fifoFrames));
     75     status_t s = ar->get()->initCheck();
     76     if (s != NO_ERROR) {
     77         delete ar;
     78         ar = NULL;
     79         ALOGE("initCheck error %d ", s);
     80     }
     81     return (jlong)ar;
     82 }
     83 
     84 static JNIEXPORT jint JNICALL Java_android_speech_srec_Recognizer_AudioRecordStart
     85         (JNIEnv *env, jclass clazz, jlong audioRecord) {
     86     return (jint)(((AudioRecordWrapper*)audioRecord)->get()->start());
     87 }
     88 
     89 static JNIEXPORT jint JNICALL Java_android_speech_srec_Recognizer_AudioRecordRead
     90         (JNIEnv *env, jclass clazz, jlong audioRecord, jbyteArray array, jint offset, jint length) {
     91     jbyte buffer[4096];
     92     if (length > (int)sizeof(buffer)) length = sizeof(buffer);
     93     length = ((AudioRecordWrapper*)audioRecord)->get()->read(buffer, length);
     94     if (length < 0) {
     95         throwException(env, "java/io/IOException", "AudioRecord::read failed %d", length);
     96         return -1;
     97     }
     98     env->SetByteArrayRegion(array, offset, length, buffer);
     99     return length;
    100 }
    101 
    102 static JNIEXPORT void JNICALL Java_android_speech_srec_Recognizer_AudioRecordStop
    103         (JNIEnv *env, jclass clazz, jlong audioRecord) {
    104     ((AudioRecordWrapper*)audioRecord)->get()->stop();
    105 }
    106 
    107 static JNIEXPORT void JNICALL Java_android_speech_srec_Recognizer_AudioRecordDelete
    108         (JNIEnv *env, jclass clazz, jlong audioRecord) {
    109     delete (AudioRecordWrapper*)audioRecord;
    110 }
    111 
    112 
    113 /*
    114  * Table of methods associated with a single class.
    115  */
    116 static JNINativeMethod gMethods[] = {
    117     /* name, signature, funcPtr */
    118     {"AudioRecordNew",    "(II)J",    (void*)Java_android_speech_srec_Recognizer_AudioRecordNew},
    119     {"AudioRecordStart",  "(J)I",     (void*)Java_android_speech_srec_Recognizer_AudioRecordStart},
    120     {"AudioRecordRead",   "(J[BII)I", (void*)Java_android_speech_srec_Recognizer_AudioRecordRead},
    121     {"AudioRecordStop",   "(J)V",     (void*)Java_android_speech_srec_Recognizer_AudioRecordStop},
    122     {"AudioRecordDelete", "(J)V",     (void*)Java_android_speech_srec_Recognizer_AudioRecordDelete},
    123 };
    124 
    125 /*
    126  * Set some test stuff up.
    127  *
    128  * Returns the JNI version on success, -1 on failure.
    129  */
    130 jint register_android_speech_srec_MicrophoneInputStream(JavaVM* vm, void* reserved)
    131 {
    132     JNIEnv* env = NULL;
    133     jclass clazz = NULL;
    134     const char* className = "android/speech/srec/MicrophoneInputStream";
    135 
    136     if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
    137         ALOGE("ERROR: GetEnv failed\n");
    138         return -1;
    139     }
    140     assert(env != NULL);
    141 
    142     clazz = env->FindClass(className);
    143     if (clazz == NULL) {
    144         ALOGE("Native registration unable to find class '%s'\n", className);
    145         return -1;
    146     }
    147     if (env->RegisterNatives(clazz, gMethods,
    148             sizeof(gMethods) / sizeof(gMethods[0])) < 0) {
    149         ALOGE("RegisterNatives failed for '%s'\n", className);
    150         return -1;
    151     }
    152 
    153     /* success -- return valid version number */
    154     return JNI_VERSION_1_4;;
    155 }
    156