MicrophoneInputStream.java revision 3001a035439d8134a7d70d796376d1dfbff3cdcd
1/*---------------------------------------------------------------------------*
2 *  MicrophoneInputStream.java                                               *
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
21package android.speech.srec;
22
23import java.io.IOException;
24import java.io.InputStream;
25import java.lang.IllegalStateException;
26
27
28/**
29 * PCM input stream from the microphone, 16 bits per sample.
30 */
31public final class MicrophoneInputStream extends InputStream {
32    static {
33        System.loadLibrary("srec_jni");
34    }
35
36    private final static String TAG = "MicrophoneInputStream";
37    private int mAudioRecord = 0;
38    private byte[] mOneByte = new byte[1];
39
40    /**
41     * MicrophoneInputStream constructor.
42     * @param sampleRate sample rate of the microphone, typically 11025 or 8000.
43     * @param fifoDepth depth of the real time fifo, measured in sampleRate clock ticks.
44     * This determines how long an application may delay before losing data.
45     */
46    public MicrophoneInputStream(int sampleRate, int fifoDepth) throws IOException {
47        mAudioRecord = AudioRecordNew(sampleRate, fifoDepth);
48        if (mAudioRecord == 0) throw new IOException("AudioRecord constructor failed - busy?");
49        int status = AudioRecordStart(mAudioRecord);
50        if (status != 0) {
51            close();
52            throw new IOException("AudioRecord start failed: " + status);
53        }
54    }
55
56    @Override
57    public int read() throws IOException {
58        if (mAudioRecord == 0) throw new IllegalStateException("not open");
59        int rtn = AudioRecordRead(mAudioRecord, mOneByte, 0, 1);
60        return rtn == 1 ? ((int)mOneByte[0] & 0xff) : -1;
61    }
62
63    @Override
64    public int read(byte[] b) throws IOException {
65        if (mAudioRecord == 0) throw new IllegalStateException("not open");
66        return AudioRecordRead(mAudioRecord, b, 0, b.length);
67    }
68
69    @Override
70    public int read(byte[] b, int offset, int length) throws IOException {
71        if (mAudioRecord == 0) throw new IllegalStateException("not open");
72        // TODO: should we force all reads to be a multiple of the sample size?
73        return AudioRecordRead(mAudioRecord, b, offset, length);
74    }
75
76    /**
77     * Closes this stream.
78     */
79    @Override
80    public void close() throws IOException {
81        if (mAudioRecord != 0) {
82            try {
83                AudioRecordStop(mAudioRecord);
84            } finally {
85                try {
86                    AudioRecordDelete(mAudioRecord);
87                } finally {
88                    mAudioRecord = 0;
89                }
90            }
91        }
92    }
93
94    @Override
95    protected void finalize() throws Throwable {
96        if (mAudioRecord != 0) {
97            close();
98            throw new IOException("someone forgot to close MicrophoneInputStream");
99        }
100    }
101
102    //
103    // AudioRecord JNI interface
104    //
105    private static native int AudioRecordNew(int sampleRate, int fifoDepth);
106    private static native int AudioRecordStart(int audioRecord);
107    private static native int AudioRecordRead(int audioRecord, byte[] b, int offset, int length) throws IOException;
108    private static native void AudioRecordStop(int audioRecord) throws IOException;
109    private static native void AudioRecordDelete(int audioRecord) throws IOException;
110}
111