思路:
1:根据java的Localsocket(FIFO)格式的原理 阻塞读入读出接受输出流和获取输出流
2:利用MediaRecorder (java)的录制类进行音频录制(单起线程写文件 -- 【注:如果这里是往网络发包也用这种方式只是把写文件的换成网络编程socket即可】)
注意:
1:当触发停止录制的时候可能写文件的现成还没有写完那么就必须得写成死循环只有当 FileinputStream.alailable()不存在了可读的字节了才停止这个循环确保读取完毕。
2:当全部读取完毕后记得要releaseall所有的localsocket和recorder
好了不废话了直接上代码:
/**
*
*/
package com.ubi.audioecoding;
/**
* @author Administrator
*
*/
import java.io.DataInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.BreakIterator;
import android.R.integer;
import android.app.Activity;
import android.media.MediaRecorder;
import android.net.LocalServerSocket;
import android.net.LocalSocket;
import android.net.LocalSocketAddress;
import android.os.Environment;
import android.util.Log;
import android.widget.Toast;
public class AmrAudioEncoder {
private static final String TAG = "ArmAudioEncoder";
private static AmrAudioEncoder amrAudioEncoder = null;
private Activity activity;
private MediaRecorder audioRecorder;
private LocalServerSocket lss;
private LocalSocket sender, receiver;
private AmrAudioEncoder() {
}
public static AmrAudioEncoder getArmAudioEncoderInstance() {
if (amrAudioEncoder == null) {
synchronized (AmrAudioEncoder.class) {
if (amrAudioEncoder == null) {
amrAudioEncoder = new AmrAudioEncoder();
}
}
}
return amrAudioEncoder;
}
public void initArmAudioEncoder(Activity activity) {
this.activity = activity;
}
public void start() {
if (activity == null) {
showToastText("现初始化调用的Activity 执行initArmAudioEncoder方法");
return;
}
if (!initLocalSocket()) {
showToastText("本地服务开启失败");
releaseAll();
return;
}
if (!initAudioRecorder()) {
showToastText("音频编码器初始化失败");
releaseAll();
return;
}
startAudioRecording();
}
private boolean initLocalSocket() {
boolean ret = true;
try {
releaseLocalSocket();
String serverName = "armAudioServer";
final int bufSize = 1024;
lss = new LocalServerSocket(serverName);
receiver = new LocalSocket();
receiver.connect(new LocalSocketAddress(serverName));
receiver.setReceiveBufferSize(bufSize);
receiver.setSendBufferSize(bufSize);
sender = lss.accept();
sender.setReceiveBufferSize(bufSize);
sender.setSendBufferSize(bufSize);
} catch (IOException e) {
ret = false;
}
return ret;
}
private boolean initAudioRecorder() {
if (audioRecorder != null) {
audioRecorder.reset();
audioRecorder.release();
}
audioRecorder = new MediaRecorder();
audioRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
audioRecorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR);
final int mono = 1;
audioRecorder.setAudioChannels(mono);
audioRecorder.setAudioSamplingRate(8000);
audioRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
audioRecorder.setOutputFile(sender.getFileDescriptor());
boolean ret = true;
try {
audioRecorder.prepare();
audioRecorder.start();
} catch (Exception e) {
releaseMediaRecorder();
showToastText("手机不支持录音此功能");
ret = false;
}
return ret;
}
private void startAudioRecording() {
new Thread(new AudioCaptureAndSendThread()).start();
}
public void stop() {
releaseAll();
}
private void releaseAll() {
releaseMediaRecorder();
releaseLocalSocket();
amrAudioEncoder = null;
}
public void releaseMediaRecorder() {
try {
if (audioRecorder == null) {
return;
}
audioRecorder.stop();
audioRecorder.reset();
audioRecorder.release();
audioRecorder = null;
} catch (Exception err) {
Log.d(TAG, err.toString());
}
}
public void releaseLocalSocket() {
try {
if (sender != null) {
sender.close();
}
if (receiver != null) {
receiver.close();
}
if (lss != null) {
lss.close();
}
} catch (IOException e) {
e.printStackTrace();
}
sender = null;
receiver = null;
lss = null;
}
private void showToastText(String msg) {
Toast.makeText(activity, msg, Toast.LENGTH_SHORT).show();
}
private class AudioCaptureAndSendThread implements Runnable {
FileOutputStream fileOutputStream;
File file;
{
String fileNameString = "test.amr";
String filePath = Environment.getDataDirectory().getPath()+"/shared/";
String filename = filePath + fileNameString;
file = new File(filename);
try {
fileOutputStream = new FileOutputStream(file , true);
} catch (Exception e) {
// TODO: handle exception
Log.e("instanceoutinstream" , e.getMessage());
}
}
public void run() {
try {
sendAmrAudio();
} catch (Exception e) {
Log.e(TAG, "sendAmrAudio() 出错");
}
}
private void sendAmrAudio() throws Exception {
DataInputStream dataInput = new DataInputStream(receiver.getInputStream());
writeAmrHead(dataInput);
final int SEND_FRAME_COUNT_ONE_TIME = 10;// 每次发送10帧的数据,1帧大约32B
// AMR格式见博客:http://blog.csdn.net/dinggo/article/details/1966444
final int BLOCK_SIZE[] = { 12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0 };
byte[] sendBuffer = new byte[1024];
boolean flag=false;
while (true)
{
int offset = 0;
for (int index = 0; index < SEND_FRAME_COUNT_ONE_TIME; ++index)
{
int available = dataInput.available();
if (available<=0) {
fileOutputStream.close();
dataInput.close();
releaseAll();
flag=true;
break;
}
dataInput.read(sendBuffer, offset, 1);
int blockIndex = (int) (sendBuffer[offset] >> 3) & 0x0F;
int frameLength = BLOCK_SIZE[blockIndex];
readSomeData(sendBuffer, offset + 1, frameLength, dataInput);
offset += frameLength + 1;
}
if (flag) {
break;
}
writeFile(sendBuffer , offset);
}
}
private void writeFile(byte[] bufferdata , int offset) throws IOException {
fileOutputStream.write(bufferdata, 0, offset);
fileOutputStream.flush();
}
private void writeAmrHead(DataInputStream dataInput) throws IOException {
final byte[] AMR_HEAD = new byte[] { 0x23, 0x21, 0x41, 0x4D, 0x52, 0x0A };
for (int i = 0; i < 6; i++) {
dataInput.readByte();
}
fileOutputStream.write(AMR_HEAD);
fileOutputStream.flush();
}
private void readSomeData(byte[] buffer, int offset, int length, DataInputStream dataInput) throws IOException {
// int available = dataInput.available();
// if (available<=0) {
// return;
// }
int numOfRead = -1;
while (true) {
try {
numOfRead = dataInput.read(buffer, offset, length);
if (numOfRead == -1) {
Log.d(TAG, "amr...no data get wait for data coming.....");
Thread.sleep(100);
} else {
//因为read的读取限制我们做了一次判断直到取出小于0才停止取出
offset += numOfRead;
length -= numOfRead;
if (length <= 0) {
break;
}
}
} catch (Exception e) {
//Log.e(TAG, "amr..error readSomeData");
Log.e("readSomeData->readTream", e.getMessage());
break;
}
}
}
}
}