package com.Javen;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import android.app.Activity;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnPreparedListener;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class AudioRecordActivity extends Activity {
private static final String TAG = "AudioRecordActivity";
private Button startButton, stopButton, playButton;
private int bufferSizeInBytes = 0;//缓冲区大小
//音频获取来源
private int audioSource = MediaRecorder.AudioSource.MIC;
//设置音频的采样率,44100是目前的标准,但是某些设备仍然支持22050,16000,11025
private static int sampleRateInHz = 44100;
//设置音频的录制声道,CHANNEL_IN_STEREO为双声道,CHANNEL_CONFIGURATION_MONO为单声道
private static int channelConfig = AudioFormat.CHANNEL_IN_STEREO;
//设置音频数据格式:PCM 16位每个样本,保证设备支持。PCM 8位每个样本,不一定能得到设备的支持。
private static int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
//AudioName裸音频数据文件
private static final String AudioName = "/sdcard/love.raw";
//NewAudioName可播放的音频文件
private static final String NewAudioName = "/sdcard/new.wav";
private AudioRecord audioRecord;
//播放音频
private MediaPlayer mediaPlayer;
private boolean isRecord = false;//设置录制状态
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
init();
}
private void init()
{
startButton = (Button)findViewById(R.id.startButton);
stopButton = (Button)findViewById(R.id.stopButton);
playButton = (Button)findViewById(R.id.playButton);
creatAudioRecord();
startButton.setOnClickListener(new AudioRecordLinstener());
stopButton.setOnClickListener(new AudioRecordLinstener());
playButton.setOnClickListener(new AudioRecordLinstener());
}
private void creatAudioRecord()
{
//根据AudioRecord的音频采样率、音频录制声道、音频数据格式获取缓冲区大小
bufferSizeInBytes = AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat);
Log.d(TAG, "creatAudioRecord-->bufferSizeInBytes="+bufferSizeInBytes);
//根据音频获取来源、音频采用率、音频录制声道、音频数据格式和缓冲区大小来创建AudioRecord对象
audioRecord = new AudioRecord(audioSource, sampleRateInHz, channelConfig, audioFormat, bufferSizeInBytes);
//创建播放实例
mediaPlayer = new MediaPlayer();
}
class AudioRecordLinstener implements OnClickListener
{
@Override
public void onClick(View v)
{
if(v == startButton)
{
startAudioRecord();
}
if(v == stopButton)
{
stopAudioRecord();
}
if(v == playButton)
{
playMusic();
}
}
}
private final class PrepareListener implements OnPreparedListener
{
@Override
public void onPrepared(MediaPlayer mp)
{
// TODO Auto-generated method stub
mediaPlayer.start();//开始播放
}
}
/**
* 播放录制的音频
*/
private void playMusic()
{
File file = new File(NewAudioName);
if(file.exists())
{
try
{
mediaPlayer.reset();
mediaPlayer.setDataSource(NewAudioName);
mediaPlayer.prepare();//进行数据缓冲
mediaPlayer.setOnPreparedListener(new PrepareListener());
} catch (IllegalArgumentException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* 开始录制音频
*/
private void startAudioRecord()
{
audioRecord.startRecording();//开始录制
isRecord = true;
new AudioRecordThread().start();//开启线程来把录制的音频数据保留下来
}
/**
* 停止录制音频
*/
private void stopAudioRecord()
{
close();
}
private void close()
{
if (audioRecord != null)
{
System.out.println("stopRecord");
isRecord = false;//停止文件写入
audioRecord.stop();
audioRecord.release();//释放资源
audioRecord = null;
}
}
/**
* 音频数据写入线程
* @author Administrator
*
*/
class AudioRecordThread extends Thread
{
@Override
public void run()
{
super.run();
writeDataToFile();//把录制的音频裸数据写入到文件中去
copyWaveFile(AudioName, NewAudioName);//给裸数据加上头文件
}
}
/**
* 把录制的音频裸数据写入到文件中去
* 这里将数据写入文件,但是并不能播放,因为AudioRecord获得的音频是原始的裸音频,
* 如果需要播放就必须加入一些格式或者编码的头信息。但是这样的好处就是你可以对音频的 裸数据进行处理,比如你要做一个爱说话的TOM
* 猫在这里就进行音频的处理,然后重新封装 所以说这样得到的音频比较容易做一些音频的处理。
*/
private void writeDataToFile()
{
// new一个byte数组用来存一些字节数据,大小为缓冲区大小
byte[] audioData = new byte[bufferSizeInBytes];
int readSize = 0;
FileOutputStream fos = null;
File file = new File(AudioName);
if(file.exists())
file.delete();
try
{
fos = new FileOutputStream(file);//获取一个文件的输出流
} catch (FileNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
while(isRecord == true)
{
readSize = audioRecord.read(audioData, 0, bufferSizeInBytes);
Log.d(TAG, "readSize ="+readSize);
if(AudioRecord.ERROR_INVALID_OPERATION != readSize)
{
try
{
fos.write(audioData);
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
try
{
fos.close();
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void copyWaveFile(String inFileName, String outFileName)
{
FileInputStream in = null;
FileOutputStream out = null;
long totalAudioLen = 0;
long totalDataLen = totalAudioLen + 36;
long longSampleRate = sampleRateInHz;
int channels = 2;
long byteRate = 16 * sampleRateInHz * channels / 8;
byte[] data = new byte[bufferSizeInBytes];
try
{
in = new FileInputStream(inFileName);
out = new FileOutputStream(outFileName);
totalAudioLen = in.getChannel().size();
totalDataLen = totalAudioLen + 36;
WriteWaveFileHeader(out, totalAudioLen, totalDataLen, longSampleRate, channels, byteRate);
while(in.read(data) != -1)
{
out.write(data);
}
in.close();
out.close();
} catch (FileNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 这里提供一个头信息。插入这些信息就可以得到可以播放的文件。
* 为我为啥插入这44个字节,这个还真没深入研究,不过你随便打开一个wav
* 音频的文件,可以发现前面的头文件可以说基本一样哦。每种格式的文件都有
* 自己特有的头文件。
*/
private void WriteWaveFileHeader(FileOutputStream out, long totalAudioLen,
long totalDataLen, long longSampleRate, int channels, long byteRate)
throws IOException {
- 1
- 2
前往页