首先添加录音权限
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
方式一:MediaRecorder
private MediaRecorder mediaRecorder;
private boolean isRecording;
设置存储路径
private final String FILE = Environment.getExternalStorageDirectory() + File.separator + "volomeDemo.aac";
初始化mediaRecorder
initMediaRecorder();
public void initMediaRecorder()
{
mediaRecorder = new MediaRecorder();
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mediaRecorder.setOutputFile(FILE);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
Log.w("madiarecorder","初始化成功");
try{
mediaRecorder.prepare();
mediaRecorder.start();
isRecording=true;
Log.w("madiarecorder","已启动");
}catch(Exception e)
{
Log.w("madiarecorder","异常");
}
}
利用
mediaRecorder.getMaxAmplitude();
得到当前某一时刻检测到的音量,这个数值通常可以上万
创建一个可视的绘图线程,一会儿实时将音量绘制出来
class Draw_thread extends Thread
{
@Override
public void run(){
while(true)
{
if (mediaRecorder == null) {
initMediaRecorder();
}
try{
myDraw();
Thread.sleep(30);
}
catch (Exception e) {
Log.w("线程", "异常");
}
}
}
}
initMediaRecorder();
}
try{
myDraw();
Thread.sleep(30);
}
catch (Exception e) {
Log.w("线程", "异常");
}
}
}
}
利用
isRecording
记录是否在监听中
重写销毁方法
protected void onDestroy() {
super.onDestroy();
if (mediaRecorder!=null&&isRecording) {
isRecording = false;
mediaRecorder.stop();
mediaRecorder.reset();
mediaRecorder.release();
mediaRecorder = null;
}
}
方法二:AudioRecord
声明变量
private AudioRecord audioRecord;
private int bufferSize;
private byte[] buffer;
初始化函数
public void initAudioRecord()
{
bufferSize = AudioRecord.getMinBufferSize(16000, AudioFormat.CHANNEL_IN_MONO , AudioFormat.ENCODING_PCM_16BIT);
audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, 16000,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT, bufferSize);
audioRecord.startRecording();
// 用于读取的 buffer
buffer= new byte[bufferSize];
}
在绘图线程中获取某一时刻音量,和mediaRecorder.getMaxAmplitude();作用差不多
try {
int r = audioRecord.read(buffer, 0, bufferSize);
int v = 0;
// 将 buffer 内容取出,进行平方和运算
for (int i = 0; i < buffer.length; i++) {
// 这里没有做运算的优化,为了更加清晰的展示代码
v += buffer[i] * buffer[i];
}
// 平方和除以数据总长度,得到音量大小。可以获取白噪声值,然后对实际采样进行标准化。
// 如果想利用这个数值进行操作,建议用 sendMessage 将其抛出,在 Handler 里进行处理。
double dB = 10*Math.log10(v/(double)r);
得到的db就是当前音量大小
但是这个数值基本只能用来判断有没有声音,
而分别不出来音量大小,所以建议使用第一种方式
绘图函数
canvas.drawColor(Color.BLACK);//背景
canvas.drawLine(200,250,200,250-6*(int)dB,paint);//子线程更新UI,如果是监听器等调用的函数,是属于主线程里的!!!
canvas.drawText(7*(int)dB+"",150,30,paint);
int maxa=mediaRecorder.getMaxAmplitude();
if(maxa<1600)
{
canvas.drawLine(100,250,100,250-maxa/8,paint);
}
else
{
canvas.drawLine(100,250,100,50,paint);
paint.setColor(Color.RED);
canvas.drawLine(150,250,150,250-maxa/100,paint);
paint.setColor(Color.GREEN);
}
canvas.drawText(maxa+"",30,30,paint);
mHandler.post(new Runnable() {
@Override
public void run() {
iv_audio.setImageBitmap(bitmap);
}
});
dB+"",150,30,paint);
int maxa=mediaRecorder.getMaxAmplitude();
if(maxa<1600)
{
canvas.drawLine(100,250,100,250-maxa/8,paint);
}
else
{
canvas.drawLine(100,250,100,50,paint);
paint.setColor(Color.RED);
canvas.drawLine(150,250,150,250-maxa/100,paint);
paint.setColor(Color.GREEN);
}
canvas.drawText(maxa+"",30,30,paint);
mHandler.post(new Runnable() {
@Override
public void run() {
iv_audio.setImageBitmap(bitmap);
}
});
用了draw和paint展示了一下两种方式的效果
我将第一种方法获得的音量用绿色(小数值时)+红色(大数值时)显示出来
这个绿色随着声音的增大,变化明显
而第二种方式,基本只要有点声音,绿色就满了
没声音时数值,还可能为负值
所以第一种好用