19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*---------------------------------------------------------------------------* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * MicrophoneInputStream.java * 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright 2007 Nuance Communciations, Inc. * 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * * 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the 'License'); * 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * * 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 * 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * * 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software * 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an 'AS IS' BASIS, * 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and * 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. * 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * * 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *---------------------------------------------------------------------------*/ 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.speech.srec; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.InputStream; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.IllegalStateException; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * PCM input stream from the microphone, 16 bits per sample. 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic final class MicrophoneInputStream extends InputStream { 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static { 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.loadLibrary("srec_jni"); 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final static String TAG = "MicrophoneInputStream"; 37bdebe1ad9573eec25f4acff89085530f490cc178Ashok Bhat private long mAudioRecord = 0; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private byte[] mOneByte = new byte[1]; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * MicrophoneInputStream constructor. 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param sampleRate sample rate of the microphone, typically 11025 or 8000. 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param fifoDepth depth of the real time fifo, measured in sampleRate clock ticks. 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This determines how long an application may delay before losing data. 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public MicrophoneInputStream(int sampleRate, int fifoDepth) throws IOException { 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAudioRecord = AudioRecordNew(sampleRate, fifoDepth); 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mAudioRecord == 0) throw new IOException("AudioRecord constructor failed - busy?"); 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int status = AudioRecordStart(mAudioRecord); 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (status != 0) { 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project close(); 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IOException("AudioRecord start failed: " + status); 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int read() throws IOException { 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mAudioRecord == 0) throw new IllegalStateException("not open"); 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int rtn = AudioRecordRead(mAudioRecord, mOneByte, 0, 1); 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return rtn == 1 ? ((int)mOneByte[0] & 0xff) : -1; 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int read(byte[] b) throws IOException { 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mAudioRecord == 0) throw new IllegalStateException("not open"); 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return AudioRecordRead(mAudioRecord, b, 0, b.length); 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int read(byte[] b, int offset, int length) throws IOException { 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mAudioRecord == 0) throw new IllegalStateException("not open"); 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // TODO: should we force all reads to be a multiple of the sample size? 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return AudioRecordRead(mAudioRecord, b, offset, length); 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Closes this stream. 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void close() throws IOException { 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mAudioRecord != 0) { 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AudioRecordStop(mAudioRecord); 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AudioRecordDelete(mAudioRecord); 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAudioRecord = 0; 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void finalize() throws Throwable { 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mAudioRecord != 0) { 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project close(); 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IOException("someone forgot to close MicrophoneInputStream"); 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // AudioRecord JNI interface 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // 105bdebe1ad9573eec25f4acff89085530f490cc178Ashok Bhat private static native long AudioRecordNew(int sampleRate, int fifoDepth); 106bdebe1ad9573eec25f4acff89085530f490cc178Ashok Bhat private static native int AudioRecordStart(long audioRecord); 107bdebe1ad9573eec25f4acff89085530f490cc178Ashok Bhat private static native int AudioRecordRead(long audioRecord, byte[] b, int offset, int length) throws IOException; 108bdebe1ad9573eec25f4acff89085530f490cc178Ashok Bhat private static native void AudioRecordStop(long audioRecord) throws IOException; 109bdebe1ad9573eec25f4acff89085530f490cc178Ashok Bhat private static native void AudioRecordDelete(long audioRecord) throws IOException; 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 111