Created
July 22, 2011 02:47
-
-
Save LCamel/1098784 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import java.io.OutputStream; | |
| import java.util.concurrent.atomic.AtomicBoolean; | |
| import android.media.AudioFormat; | |
| import android.media.AudioRecord; | |
| import android.media.MediaRecorder; | |
| import android.os.Handler; | |
| import android.util.Log; | |
| public class MyAudioRecord { | |
| private static final String TAG = MyAudioRecord.class.getName(); | |
| private static final int SAMPLE_RATE = QueuePlayer.SAMPLE_RATE; | |
| private static final int CHANNEL_CONFIG = AudioFormat.CHANNEL_IN_MONO; | |
| private static final int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT; // 看系統. 本來我們實驗的 Hero 最低只能 16 bit, 不能 8 bit | |
| private static final int MIN_BUFFER_SIZE = AudioRecord.getMinBufferSize( | |
| SAMPLE_RATE, CHANNEL_CONFIG, AUDIO_FORMAT); // on hero : 4096 bytes | |
| private static final int AUDIO_RECORD_BUFFER_SIZE = MIN_BUFFER_SIZE * 10; // 看原廠 AudioRecordTest 中有 * 10 | |
| private static final int OUR_16BIT_BUFFER_SIZE = MIN_BUFFER_SIZE * 2; | |
| //private static final int OUR_8BIT_BUFFER_SIZE = OUR_16BIT_BUFFER_SIZE / 2; | |
| private Thread t; | |
| private AtomicBoolean shouldStop = new AtomicBoolean(false); | |
| // non-blocking, 叫了就開始錄 | |
| // maxMillis 是最大錄製的秒數 (粗略的, 防止爆掉用的) | |
| // 外面記得要在 stopListener 裏面做事, 包含關閉 output stream | |
| public MyAudioRecord(final OutputStream os, final long maxMillis, final Handler handler, final Runnable stopListener) { | |
| Log.v(TAG, "SAMPLE_RATE: " + SAMPLE_RATE + " CHANNEL_CONFIG: " | |
| + CHANNEL_CONFIG + " AUDIO_FORMAT: " + AUDIO_FORMAT); | |
| Log.v(TAG, "MIN_BUFFER_SIZE: " + MIN_BUFFER_SIZE | |
| + " AUDIO_RECORD_BUFFER_SIZE: " + AUDIO_RECORD_BUFFER_SIZE | |
| + " OUR_16BIT_BUFFER_SIZE: " + OUR_16BIT_BUFFER_SIZE | |
| ); | |
| //+ " OUR_8BIT_BUFFER_SIZE: " + OUR_8BIT_BUFFER_SIZE); | |
| final byte[] our16BitBuffer = new byte[OUR_16BIT_BUFFER_SIZE]; | |
| //final byte[] our8BitBuffer = new byte[OUR_8BIT_BUFFER_SIZE]; | |
| final AudioRecord ar = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, SAMPLE_RATE, | |
| CHANNEL_CONFIG, AUDIO_FORMAT, AUDIO_RECORD_BUFFER_SIZE); | |
| t = new Thread() { | |
| public void run() { | |
| Log.v(TAG, "run() >>>>"); | |
| try { | |
| long stopNano = System.nanoTime() + maxMillis * 1000 * 1000; | |
| ar.startRecording(); | |
| while (true) { | |
| if (shouldStop.get() == true || System.nanoTime() >= stopNano) { | |
| ar.stop(); | |
| ar.release(); | |
| handler.post(stopListener); // TODO: 沒檢查傳回值, 放失敗就算了(?) | |
| break; | |
| } | |
| int bytesRead = ar.read(our16BitBuffer, 0, our16BitBuffer.length); | |
| //Log.v(TAG, "bytesRead: " + bytesRead); | |
| os.write(our16BitBuffer, 0, bytesRead); | |
| // // convert 16 to 8 | |
| // int j = 0; | |
| // for (int i = 1; i < bytesRead; i += 2, j += 1) { | |
| // our8BitBuffer[j] = our16BitBuffer[i]; | |
| // our8BitBuffer[j] ^= (1 << 7); | |
| // } | |
| // | |
| // os.write(our8BitBuffer, 0, j); | |
| } | |
| } catch (Exception e) { | |
| e.printStackTrace(); | |
| } | |
| Log.v(TAG, "run() <<<<"); | |
| } | |
| }; | |
| t.start(); | |
| } | |
| // non-blocking, return 時不見得真的停了, 該在傳進來的 listener 中作. | |
| public void stop() { | |
| shouldStop.set(true); | |
| // 在此就不 t.join 了 | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment