1 package com.android.cts.verifier.audio;
2 
3 import android.media.AudioFormat;
4 import android.media.AudioManager;
5 import android.media.AudioRecord;
6 import android.media.AudioTrack;
7 import android.media.MediaRecorder;
8 import android.util.Log;
9 
10 import java.io.ByteArrayOutputStream;
11 import java.io.IOException;
12 
13 /**
14  * A wrapper on AudioRecord class.
15  */
16 public class AudioRecordHelper {
17 
18   private static final int[] SOURCE = {
19       MediaRecorder.AudioSource.MIC, MediaRecorder.AudioSource.VOICE_RECOGNITION};
20   private static final int[] SAMPLE_RATES_HZ = {
21     AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_MUSIC), 48000, 44100};
22 
23   private static final int CHANNEL = AudioFormat.CHANNEL_CONFIGURATION_MONO;
24   private static final int ENCODING = AudioFormat.ENCODING_PCM_16BIT;
25   private static final String TAG = "AudioRecordHelper";
26   private static AudioRecordHelper instance;
27   private final int bufferSize;
28   private final int sampleRate;
29   private final int source;
30   private ByteArrayOutputStream os;
31   private AudioRecord audioRecord;
32   private volatile boolean isRecording = false;
33 
AudioRecordHelper()34   private AudioRecordHelper() {
35     int tmpBufferSize = 0;
36     int tmpSampleRate = 0;
37     int tmpSource = 0;
38     initialization:
39     for (int source : SOURCE) {
40       for (int rate : SAMPLE_RATES_HZ) {
41         tmpBufferSize = AudioRecord.getMinBufferSize(rate, CHANNEL, ENCODING);
42         AudioRecord testAudioRecord = new AudioRecord(source, rate, CHANNEL, ENCODING,
43             tmpBufferSize);
44         if (testAudioRecord.getState() == AudioRecord.STATE_INITIALIZED) {
45           testAudioRecord.release();
46           tmpSampleRate = rate;
47           tmpSource = source;
48           break initialization;
49         }
50       }
51     }
52     if (tmpBufferSize == 0 || tmpSampleRate == 0) {
53       Log.e(TAG, "Failed to initialize");
54     }
55     bufferSize = tmpBufferSize;
56     sampleRate = tmpSampleRate;
57     source = tmpSource;
58     Log.d(TAG, "Sample rate = " + sampleRate + "Hz, Source = "
59         + source + " (VOICE_RECOGNITION = 6 , MIC = 1)");
60   }
61 
getInstance()62   public static AudioRecordHelper getInstance() {
63     if (instance == null) {
64       instance = new AudioRecordHelper();
65     }
66     return instance;
67   }
68 
69   /**
70    * Start recording.
71    */
start()72   public void start() {
73     if (!isRecording) {
74       isRecording = true;
75       os = new ByteArrayOutputStream();
76       audioRecord = new AudioRecord(source, sampleRate, CHANNEL, ENCODING, bufferSize);
77       audioRecord.startRecording();
78       startPullingData();
79     }
80   }
81 
82   /**
83    * Stop recording
84    */
stop()85   public void stop() {
86     if (isRecording) {
87       isRecording = false;
88       audioRecord.stop();
89       audioRecord.release();
90       audioRecord = null;
91       try {
92         os.close();
93       } catch (IOException e) {
94         e.printStackTrace();
95       }
96     }
97   }
98 
startPullingData()99   private void startPullingData() {
100     new Thread() {
101       @Override
102       public void run(){
103         byte data[] = new byte[bufferSize];
104         while (isRecording) {
105           int read = audioRecord.read(data, 0, bufferSize);
106           if (read > 0) {
107             os.write(data, 0, read);
108           }
109           if (read < 0) {
110             break;
111           }
112         }
113       }
114     }.start();
115   }
116 
117   /**
118    * Returns the sample rate for this recorder.
119    */
getSampleRate()120   public int getSampleRate() {
121     return sampleRate;
122   }
123 
124   /**
125    * Returns the audio source currently being used.
126    */
getAudioSource()127   public int getAudioSource() {
128     return source;
129   }
130 
131   /**
132    * Returns true if recorder is recording; False if not.
133    */
isRecording()134   public boolean isRecording() {
135     return isRecording;
136   }
137 
138   /**
139    * Returns the raw data.
140    */
getByte()141   public byte[] getByte() {
142     return os.toByteArray();
143   }
144 }
145