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