14a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/*---------------------------------------------------------------------------*
24a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  android_speech_srec_MicrophoneInputStream.cpp                            *
34a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                           *
44a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  Copyright 2007 Nuance Communciations, Inc.                               *
54a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                           *
64a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  Licensed under the Apache License, Version 2.0 (the 'License');          *
74a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  you may not use this file except in compliance with the License.         *
84a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                           *
94a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  You may obtain a copy of the License at                                  *
104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0                           *
114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                           *
124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  Unless required by applicable law or agreed to in writing, software      *
134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  distributed under the License is distributed on an 'AS IS' BASIS,        *
144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  See the License for the specific language governing permissions and      *
164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  limitations under the License.                                           *
174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                           *
184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *---------------------------------------------------------------------------*/
194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include <string.h>
224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include <stdio.h>
234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include <stdlib.h>
244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define LOG_TAG "srec_jni"
264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include <utils/Log.h>
274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include <media/AudioRecord.h>
2985d4a2a8fe7c306f0e0cfd30f51e9015566c021dEric Laurent#include <media/mediarecorder.h>
304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
31570be96f35b570ee31c86a602cc6c050e03a1f3dDima Zavin#include <system/audio.h>
321b229941e91e25f6fa787b20cd6f53c818b2eb7fDima Zavin
334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include <jni.h>
344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectusing namespace android;
364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//
404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// helper function to throw an exception
414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//
424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic void throwException(JNIEnv *env, const char* ex, const char* fmt, int data) {
434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (jclass cls = env->FindClass(ex)) {
444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        char msg[1000];
454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        sprintf(msg, fmt, data);
464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        env->ThrowNew(cls, msg);
474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        env->DeleteLocalRef(cls);
484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// MicrophoneInputStream JNI implememtations
544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
562706e1ca0c118cb78fbbbc977e4e95e14fdedebcGlenn Kasten// Java uses an int to hold a raw pointer, which is already ugly.
572706e1ca0c118cb78fbbbc977e4e95e14fdedebcGlenn Kasten// But we need to hold an sp<>, which is of unknown size.
582706e1ca0c118cb78fbbbc977e4e95e14fdedebcGlenn Kasten// So we wrap the sp<> within a class, and give Java the int version of a pointer to this class.
592706e1ca0c118cb78fbbbc977e4e95e14fdedebcGlenn Kastenclass AudioRecordWrapper {
602706e1ca0c118cb78fbbbc977e4e95e14fdedebcGlenn Kastenpublic:
612706e1ca0c118cb78fbbbc977e4e95e14fdedebcGlenn Kasten    AudioRecordWrapper(AudioRecord *audioRecord) : mAudioRecord(audioRecord) { }
622706e1ca0c118cb78fbbbc977e4e95e14fdedebcGlenn Kasten    ~AudioRecordWrapper() { }
632706e1ca0c118cb78fbbbc977e4e95e14fdedebcGlenn Kasten    AudioRecord* get() const { return mAudioRecord.get(); }
642706e1ca0c118cb78fbbbc977e4e95e14fdedebcGlenn Kastenprivate:
652706e1ca0c118cb78fbbbc977e4e95e14fdedebcGlenn Kasten    const sp<AudioRecord> mAudioRecord;
662706e1ca0c118cb78fbbbc977e4e95e14fdedebcGlenn Kasten};
672706e1ca0c118cb78fbbbc977e4e95e14fdedebcGlenn Kasten
68b3adea6f471d03c5bd728725adc7ca1cea89edfdMarcus Oaklandstatic JNIEXPORT jlong JNICALL Java_android_speech_srec_Recognizer_AudioRecordNew
694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        (JNIEnv *env, jclass clazz, jint sampleRate, jint fifoFrames) {
704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
712706e1ca0c118cb78fbbbc977e4e95e14fdedebcGlenn Kasten    AudioRecordWrapper *ar = new AudioRecordWrapper(new AudioRecord(
721b229941e91e25f6fa787b20cd6f53c818b2eb7fDima Zavin            AUDIO_SOURCE_VOICE_RECOGNITION, sampleRate,
731b229941e91e25f6fa787b20cd6f53c818b2eb7fDima Zavin            AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_MONO,
742706e1ca0c118cb78fbbbc977e4e95e14fdedebcGlenn Kasten            fifoFrames));
752706e1ca0c118cb78fbbbc977e4e95e14fdedebcGlenn Kasten    status_t s = ar->get()->initCheck();
762706e1ca0c118cb78fbbbc977e4e95e14fdedebcGlenn Kasten    if (s != NO_ERROR) {
772706e1ca0c118cb78fbbbc977e4e95e14fdedebcGlenn Kasten        delete ar;
782706e1ca0c118cb78fbbbc977e4e95e14fdedebcGlenn Kasten        ar = NULL;
792706e1ca0c118cb78fbbbc977e4e95e14fdedebcGlenn Kasten        ALOGE("initCheck error %d ", s);
804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
81b3adea6f471d03c5bd728725adc7ca1cea89edfdMarcus Oakland    return (jlong)ar;
824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
84b3adea6f471d03c5bd728725adc7ca1cea89edfdMarcus Oaklandstatic JNIEXPORT jint JNICALL Java_android_speech_srec_Recognizer_AudioRecordStart
85b3adea6f471d03c5bd728725adc7ca1cea89edfdMarcus Oakland        (JNIEnv *env, jclass clazz, jlong audioRecord) {
86b3adea6f471d03c5bd728725adc7ca1cea89edfdMarcus Oakland    return (jint)(((AudioRecordWrapper*)audioRecord)->get()->start());
874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic JNIEXPORT jint JNICALL Java_android_speech_srec_Recognizer_AudioRecordRead
90b3adea6f471d03c5bd728725adc7ca1cea89edfdMarcus Oakland        (JNIEnv *env, jclass clazz, jlong audioRecord, jbyteArray array, jint offset, jint length) {
914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    jbyte buffer[4096];
924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (length > (int)sizeof(buffer)) length = sizeof(buffer);
932706e1ca0c118cb78fbbbc977e4e95e14fdedebcGlenn Kasten    length = ((AudioRecordWrapper*)audioRecord)->get()->read(buffer, length);
944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (length < 0) {
954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        throwException(env, "java/io/IOException", "AudioRecord::read failed %d", length);
964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        return -1;
974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    env->SetByteArrayRegion(array, offset, length, buffer);
994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return length;
1004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
1014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic JNIEXPORT void JNICALL Java_android_speech_srec_Recognizer_AudioRecordStop
103b3adea6f471d03c5bd728725adc7ca1cea89edfdMarcus Oakland        (JNIEnv *env, jclass clazz, jlong audioRecord) {
1042706e1ca0c118cb78fbbbc977e4e95e14fdedebcGlenn Kasten    ((AudioRecordWrapper*)audioRecord)->get()->stop();
1054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
1064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic JNIEXPORT void JNICALL Java_android_speech_srec_Recognizer_AudioRecordDelete
108b3adea6f471d03c5bd728725adc7ca1cea89edfdMarcus Oakland        (JNIEnv *env, jclass clazz, jlong audioRecord) {
1092706e1ca0c118cb78fbbbc977e4e95e14fdedebcGlenn Kasten    delete (AudioRecordWrapper*)audioRecord;
1104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
1114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/*
1144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * Table of methods associated with a single class.
1154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project */
1164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic JNINativeMethod gMethods[] = {
1174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /* name, signature, funcPtr */
118b3adea6f471d03c5bd728725adc7ca1cea89edfdMarcus Oakland    {"AudioRecordNew",    "(II)J",    (void*)Java_android_speech_srec_Recognizer_AudioRecordNew},
119b3adea6f471d03c5bd728725adc7ca1cea89edfdMarcus Oakland    {"AudioRecordStart",  "(J)I",     (void*)Java_android_speech_srec_Recognizer_AudioRecordStart},
120b3adea6f471d03c5bd728725adc7ca1cea89edfdMarcus Oakland    {"AudioRecordRead",   "(J[BII)I", (void*)Java_android_speech_srec_Recognizer_AudioRecordRead},
121b3adea6f471d03c5bd728725adc7ca1cea89edfdMarcus Oakland    {"AudioRecordStop",   "(J)V",     (void*)Java_android_speech_srec_Recognizer_AudioRecordStop},
122b3adea6f471d03c5bd728725adc7ca1cea89edfdMarcus Oakland    {"AudioRecordDelete", "(J)V",     (void*)Java_android_speech_srec_Recognizer_AudioRecordDelete},
1234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project};
1244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/*
1264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * Set some test stuff up.
1274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *
1284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * Returns the JNI version on success, -1 on failure.
1294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project */
1304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectjint register_android_speech_srec_MicrophoneInputStream(JavaVM* vm, void* reserved)
1314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
1324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    JNIEnv* env = NULL;
1334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    jclass clazz = NULL;
1344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    const char* className = "android/speech/srec/MicrophoneInputStream";
1354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
137040dcc36996cded4371cc59dfc3a9e53247a61f5Steve Block        ALOGE("ERROR: GetEnv failed\n");
1384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        return -1;
1394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
1404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    assert(env != NULL);
1414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    clazz = env->FindClass(className);
1434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (clazz == NULL) {
144040dcc36996cded4371cc59dfc3a9e53247a61f5Steve Block        ALOGE("Native registration unable to find class '%s'\n", className);
1454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        return -1;
1464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
1474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (env->RegisterNatives(clazz, gMethods,
1484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            sizeof(gMethods) / sizeof(gMethods[0])) < 0) {
149040dcc36996cded4371cc59dfc3a9e53247a61f5Steve Block        ALOGE("RegisterNatives failed for '%s'\n", className);
1504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        return -1;
1514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
1524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /* success -- return valid version number */
1544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return JNI_VERSION_1_4;;
1554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
156