最近看到一篇关于音频的文章,忽然想起以前有个中国传媒大学的一位朋友,要我帮她设计一个可以实时播放输入音频的程序,我当时想到了要用DirectSound,可是对于这种从来没有碰过的东西,我内心是多少有些恐惧的,而且是用C#这样的语言来写这种相对来说比较底层的东西,所以这件事情最后就不了了之了,好在后来这位朋友顺利地完成了毕设。此时此刻,在Android上再次碰到这个问题,我就抱着试试看的决心,来学一学吧。主要代码如下:
package com.android.record2play; import java.util.LinkedList; import android.media.AudioFormat; import android.media.AudioManager; import android.media.AudioRecord; import android.media.AudioTrack; import android.media.MediaRecorder; import android.os.Bundle; import android.app.Activity; import android.view.Menu; import android.widget.Toast; public class MainActivity extends Activity { //写入缓冲区大小 private int m_Record_Size; //音频录制对象 private AudioRecord mAudioRecord; //音频写入存储字节数组 private byte[] m_Input_Bytes; //播放缓冲区大小 private int m_Play_Size; //音频播放对象 private AudioTrack mAudioTrack; //主线程 private Thread Record2Play_Thread; //标志变量 private boolean IsRecording=true; @SuppressWarnings("deprecation") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //获取用于录制的最小写入缓存区大小 m_Record_Size=AudioRecord.getMinBufferSize(44100, AudioFormat.CHANNEL_CONFIGURATION_MONO,AudioFormat.ENCODING_PCM_16BIT); //获取音频录制对象 mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, m_Record_Size); //获取用于播放的最小播放缓冲区大小 m_Play_Size = AudioTrack.getMinBufferSize(8000, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT); // 实例化播放音频对象 mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 8000, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, m_Play_Size, AudioTrack.MODE_STREAM); //初始化数组 m_Input_Bytes = new byte[m_Record_Size]; Record2Play_Thread=new Thread(new Record2Play()); Record2Play_Thread.start(); } class Record2Play implements Runnable { @Override public void run() { try { byte[] mBytes; // 开始录音 mAudioRecord.startRecording(); mAudioTrack.play(); while (IsRecording) { int BytesSize=mAudioRecord.read(m_Input_Bytes, 0, m_Record_Size); mBytes=new byte[BytesSize]; mBytes=m_Input_Bytes.clone(); mAudioTrack.write(mBytes, 0, mBytes.length); } mAudioRecord.stop(); mAudioTrack.stop(); } catch(Exception e) { Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show(); } } } }
这个和以前的基本思路是一样的,首先通过录音我们获取一个音频流写入缓冲区,然后再从缓冲区里取出来,交给播放设备去播放,可是我怎么感觉在Android这么简单呢?这个程序要想真正投入使用,需要解决的问题有:
1、录音降噪的问题
2、回音消除的问题
3、系统执行的问题