• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.mobileer.oboetester;
18 
19 
20 import android.media.AudioFormat;
21 import android.media.AudioRecord;
22 import android.media.MediaRecorder;
23 
24 /**
25  * Abstract class for recording.
26  * Call processBuffer(buffer) when data is read.
27  */
28 class AudioRecordThread implements Runnable {
29     private static final String TAG = "AudioRecordThread";
30 
31     private final int mSampleRate;
32     private final int mChannelCount;
33     private Thread mThread;
34     protected boolean mGo;
35     private AudioRecord mRecorder;
36     private CircularCaptureBuffer mCaptureBuffer;
37     protected float[] mBuffer = new float[256];
38     private static int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_FLOAT;
39     private Runnable mTask;
40     private int mTaskCountdown;
41     private boolean mCaptureEnabled = true;
42 
AudioRecordThread(int frameRate, int channelCount, int maxFrames)43     public AudioRecordThread(int frameRate, int channelCount, int maxFrames) {
44         mSampleRate = frameRate;
45         mChannelCount = channelCount;
46         mCaptureBuffer = new CircularCaptureBuffer(maxFrames);
47     }
48 
createRecorder()49     private void createRecorder() {
50         int channelConfig = (mChannelCount == 1)
51                 ? AudioFormat.CHANNEL_IN_MONO : AudioFormat.CHANNEL_IN_STEREO;
52         int audioFormat = AudioFormat.ENCODING_PCM_FLOAT;
53         int minRecordBuffSizeInBytes = AudioRecord.getMinBufferSize(mSampleRate,
54                 channelConfig,
55                 audioFormat);
56         mRecorder = new AudioRecord(
57                 MediaRecorder.AudioSource.VOICE_RECOGNITION,
58                 mSampleRate,
59                 channelConfig,
60                 audioFormat,
61                 2 * minRecordBuffSizeInBytes);
62         if (mRecorder.getState() == AudioRecord.STATE_UNINITIALIZED) {
63             throw new RuntimeException("Could not make the AudioRecord - UNINITIALIZED");
64         }
65     }
66 
67     @Override
run()68     public void run() {
69         startAudioRecording();
70 
71         while (mGo) {
72             int result = handleAudioPeriod();
73             if (result < 0) {
74                 mGo = false;
75             }
76         }
77 
78         stopAudioRecording();
79     }
80 
startAudio()81     public void startAudio() {
82         if (mThread == null) {
83             mGo = true;
84             mThread = new Thread(this);
85             mThread.start();
86         }
87     }
88 
stopAudio()89     public void stopAudio() {
90         mGo = false;
91         if (mThread != null) {
92             try {
93                 mThread.join(1000);
94             } catch (InterruptedException e) {
95                 e.printStackTrace();
96             }
97             mThread = null;
98         }
99     }
100 
getSampleRate()101     public int getSampleRate() {
102         return mSampleRate;
103     }
104 
105     /**
106      * @return number of samples read or negative error
107      */
handleAudioPeriod()108     private int handleAudioPeriod() {
109         int numSamplesRead = mRecorder.read(mBuffer, 0, mBuffer.length,
110                 AudioRecord.READ_BLOCKING);
111         if (numSamplesRead <= 0) {
112             return numSamplesRead;
113         } else {
114             if (mTaskCountdown > 0) {
115                 mTaskCountdown -= numSamplesRead;
116                 if (mTaskCountdown <= 0) {
117                     mTaskCountdown = 0;
118                     new Thread(mTask).start(); // run asynchronously with audio thread
119                 }
120             }
121             if (mCaptureEnabled) {
122                 return mCaptureBuffer.write(mBuffer, 0, numSamplesRead);
123             } else {
124                 return numSamplesRead;
125             }
126         }
127     }
128 
startAudioRecording()129     private void startAudioRecording() {
130         stopAudioRecording();
131         createRecorder();
132         mRecorder.startRecording();
133     }
134 
stopAudioRecording()135     private void stopAudioRecording() {
136         if (mRecorder != null) {
137             mRecorder.stop();
138             mRecorder.release();
139             mRecorder = null;
140         }
141     }
142 
143     /**
144      * Schedule task to be run on its own thread when numSamples more samples have been recorded.
145      *
146      * @param numSamples
147      * @param task
148      */
scheduleTask(int numSamples, Runnable task)149     public void scheduleTask(int numSamples, Runnable task) {
150         mTask = task;
151         mTaskCountdown = numSamples;
152     }
153 
setCaptureEnabled(boolean captureEnabled)154     public void setCaptureEnabled(boolean captureEnabled) {
155         mCaptureEnabled = captureEnabled;
156     }
157 
readMostRecent(float[] buffer)158     public int readMostRecent(float[] buffer) {
159         return mCaptureBuffer.readMostRecent(buffer);
160     }
161 
162 }
163