转自:http://blog.youkuaiyun.com/zyfu0000/article/details/7513120#
http://www.huacong.net.cn/contents/12/307.html
一、MediaRecorder
使用MediaRecorder进行声音录制简单方便,不需要理会中间录制过程。结束录制后可以直接得到音频文件进行播放。
由于MediaRecorder较为简单,就不详细介绍,各位看官可自行搜索并试验。
简单的使用方式如下:
class SoundRecorder {
MediaRecorder mRecorder;
boolean isRecording;
public void startRecording() {
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mRecorder.setOutputFile(newFileName());
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
try {
mRecorder.prepare();
} catch (IOException e) {
Log.e(LOG_TAG, "prepare() failed");
}
mRecorder.start();
}
public void stopRecording() {
mRecorder.stop();
mRecorder.release();
mRecorder = null;
}
public String newFileName() {
String mFileName = Environment.getExternalStorageDirectory()
.getAbsolutePath();
String s = new SimpleDateFormat("yyyy-MM-dd hhmmss")
.format(new Date());
return mFileName += "/rcd_" + s + ".3gp";
}
}
可参考如下博客:
Android MediaRecorder录制音频:http://aina-hk55hk.iteye.com/blog/706793
Andriod MediaRecorder小结:http://www.cnblogs.com/shaobin0604/archive/2011/12/27/2303217.html
Android MediaRecorder框架介绍:http://forest606.blog.163.com/blog/static/13445008920102834914/
二、AudioRecorder
在声音录制过程中,有可能我们需要得到采集的声音数据并进行处理,比如降噪,合成等。MediaRecorder明显不能符合要求。而AudioRecorder恰能满足这种要求。过程为一段一段进行录制然后得到数据分别进行处理。
使用方式:
m_in_buf_size =AudioRecord.getMinBufferSize(8000,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT);
m_in_rec = new AudioRecord(MediaRecorder.AudioSource.MIC,
8000,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT,
m_in_buf_size) ;
AudioRecorder可以有2种处理方式:
1. 设置AudioRecorder的UpdateListener和NotificationPeriod
audioRecorder.setRecordPositionUpdateListener(updateListener);
audioRecorder.setPositionNotificationPeriod(framePeriod);
然后在UpdateListener中进行处理。
2.另外开启一线程得到录制数据然后进行处理
第一种方式简单明了,是在主线程中处理,可以很方便的进行其他操作,如更新UI。但实际使用过程中发现,即使没有进行其他操作也会造成程序崩溃,所以不推荐使用。
第二种方式较为麻烦,特别是需要在子线程中更新UI。但是效果很好。
2种方式示例代码如下:
1. UpdateListener
private AudioRecord.OnRecordPositionUpdateListener updateListener = new AudioRecord.OnRecordPositionUpdateListener()
{
private int x = 0;
public void onPeriodicNotification(AudioRecord recorder)
{
audioRecorder.read(buffer, 0, buffer.length); // Fill buffer
try
{
//randomAccessWriter.write(buffer); // Write buffer to file
//payloadSize += buffer.length;
if (bSamples == 16)
{
for (int i=0; i<buffer.length/2; i++)
{ // 16bit sample size
short curSample = ExtAudioRecorder.this.getShort(buffer[2*i], buffer[2*i+1]);
if (curSample > cAmplitude)
{ // Check amplitude
cAmplitude = curSample;
}
}
}
else
{ // 8bit sample size
for (int i=0; i<buffer.length; ++i)
{
if (buffer[i] > cAmplitude)
{ // Check amplitude
cAmplitude = buffer[i];
}
}
}
}
catch (Exception e)
{
Log.e(ExtAudioRecorder.class.getName(), "Error occured in updateListener, recording is aborted");
//stop();
}
if (x%4 == 0)
{
mDrawingView.getEditingLayer().addSquare(x/4, 19 - (int)((cAmplitude/65535.0f)*19));
mDrawingView.invalidate();
}
++x;
}
2. 子线程中处理:
class AudioRecordThread implements Runnable
{
public void run()
{
while (isRecording)
{
audioRecorder.read(buffer, 0, buffer.length);
cAmplitude = 0;
if (bSamples == 16)
{
for (int i=0; i<buffer.length/2; i++)
{
short curSample = ExtAudioRecorder.this.getShort(buffer[2*i], buffer[2*i+1]);
if (curSample > cAmplitude)
{
cAmplitude = curSample;
}
}
}
else
{
for (int i=0; i<buffer.length; ++i)
{
if (buffer[i] > cAmplitude)
{
cAmplitude = buffer[i];
}
}
}
Message message = Message.obtain();
message.obj = (Object)(new Integer(19 - (int)((cAmplitude/65535.0f)*19)));
messageHandler.sendMessage(message);
}
}
}
三、 电话录音
在MediaRecorder和AudioRecorder设置datasource为IN_CALL
因为Android不同厂商的定制原因有些手机不能进行电话录音。
有关电话录音的详细分析:http://wenku.baidu.com/view/71d3e008844769eae009ed00.html
四、声音播放
播放声音可以用MediaPlayer和AudioTrack,两者都提供了java API供应用开发者使用。虽然都可以播放声音,但两者还是有很大的区别的。
其中最大的区别是MediaPlayer可以播放多种格式的声音文件,例如MP3,AAC,WAV,OGG,MIDI等。MediaPlayer会在framework层创建对应的音频解码器。
而AudioTrack只能播放已经解码的PCM流,如果是文件的话只支持wav格式的音频文件,因为wav格式的音频文件大部分都是PCM流。AudioTrack不创建解码器,所以只能播放不需要解码的wav文件。
当然两者之间还是有紧密的联系的,MediaPlayer在framework层还是会创建AudioTrack,把解码后的PCM数流传递给AudioTrack,AudioTrack再传递给AudioFlinger进行混音,然后才传递给硬件播放。
所以是MediaPlayer包含了AudioTRack。
通过查看API可以知道,MediaPlayer提供了5个setDataSource方法,分为三类,一类是传递播放文件的字符串路径作为参数,例如直接取sd卡里mp3文件的路径,一类是传递播放文件的FileDescriptor文件描述符作为播放的id,例例如从db中查询的音频文件的id,就可以直接赋给MediaPlayer进行播放。还有一类是Uri类型的资源文件,用于播放content uri文件。
AudioTrack的初始化过程:
m_out_buf_size = android.media.AudioTrack.getMinBufferSize(8000,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT);
m_out_trk = new AudioTrack(AudioManager.STREAM_MUSIC, 8000,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT,
m_out_buf_size,
AudioTrack.MODE_STREAM);