Android-使用mediarecorder类获取当前麦克风音量值

获取当前麦克风音量

2014年12月22日

0:21

首先是界面:

 

 

检测麦克风当前音量主要是用Android自己的类MediaRecorder来实现的,很多函数都是可以直接使用的,所以实现检测麦克风音量其实不是很难,只要注意一下使用的方法就可以了。

start:是开始监测

end:结束检测

大概思路就是用麦克风录音,用MediaRecorder.getMaxAmplitude()函数来获取麦克风当前的音量值

 

 

getMaxAmplitude()返回值就是从上一次调用getMaxAmplitude( )的时刻到这一次调用getMaxAmplitude( )时刻之间的音频振幅绝对值的最大值,如果控制两个getMaxAmplitude()调用的间隔比较小的话,就可以实时得到当前的音频的振幅的绝对值了。

 

值得一说的是,getMaxAmplitude()方法不能在android的主线程循环调用,否则程序会闪退(哈,试过好几次了,都不知道是什么原因,后来才发现是大概因为Android的主线程会使用比较多的资源来调用这个方法,然后系统九崩溃了,就造成了闪退。解决的方法就是把getMaxAmplitude()函数的调用放在一个线程里,通过控制线程的启动时间间隔来减少使用的资源以保证程序稳定不会闪退)

以下是MainActivity.java里的代码:(含注释)

package com.example.rec;

import java.io.File;
import java.io.IOException;

import java.util.Timer;
import java.util.TimerTask;


import android.support.v7.app.ActionBarActivity;
import android.annotation.SuppressLint;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;


@SuppressLint("ShowToast")
public class MainActivity extends ActionBarActivity {
	private MediaRecorder mp;
	private TextView txt1;
	private int value=0;
	private TimerTask  task=null;
	private Timer timer=null;
	private int maxx=0;
	private TextView maxtext;
	File soundFile=null;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		txt1=(TextView) findViewById(R.id.voise);
		maxtext=(TextView)findViewById(R.id.maxxvalue);
		
	}


	public void deal_with(View v){                     //这是按钮按下去触发的函数,然后再执行对于的实现方法
		switch(v.getId()){
		case R.id.startbt:                                 //开始按钮
			startrec(); 
			break; 
		case R.id.endbt:                                  //结束按钮
			endrec();                                     
			break;
			
		}
	}    
	private void startrec(){                                                                                                                 //开始监测,先准备好用麦克风录音,
		if(mp==null){
			File dir=new File(Environment.getExternalStorageDirectory(),"sound");    //指定录音输出文件的文件夹(最后会删除录音文件的)
			if(!dir.exists()){                                                                                                        //文件夹路径不存在就创建一个
				dir.mkdirs();
			}
			soundFile=new File(dir,System.currentTimeMillis()+".amr");                      //创建输出文件
			if(!soundFile.exists()){
				try {
					soundFile.createNewFile();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			mp=new MediaRecorder();                                                                                //程序中操作的MediaRecorder类
			
			
			mp.setAudioSource(MediaRecorder.AudioSource.MIC);                            //MediaRecorder类的初始化(注意顺序不能反
			mp.setOutputFormat(MediaRecorder.OutputFormat.AMR_WB);
			mp.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_WB);
			mp.setOutputFile(soundFile.getAbsolutePath());                       //MediaRecorder和文件绑定,MediaRecorder录制的内容将自动保存在soundFile文件中
			try {
				mp.prepare();
				mp.start();                                                                                                //开始录音
			} catch (IllegalStateException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			Toast.makeText(MainActivity.this,"开始录音...", Toast.LENGTH_LONG).show(); //标签提示一下
			starttorec();                                                                                                          //调用线程来实现获取当前音频振幅 (start to record)
			
		}
		
	}
	private Handler mHandler =new Handler(){
			public void handleMessage(Message msg){                                            
				txt1.setText(""+msg.arg1);                                                                //把Handle 中获得的信息在主线程使用,更新txt1的显示内容
				if(maxx<msg.arg1){                                                                              //(注意在setText()中要加"",否则又会跪(使用是跪了几次才发现= =)
					maxx=msg.arg1;                                                                       //显示最大值
					maxtext.setText(""+maxx);
				}
				starttorec();                                                                                          //重新调用检测的线程
			}
	};

	public  void starttorec(){
		
		timer=new Timer();
		task=new TimerTask(){                                                                                              //设置线程抽象类中的run(),这里更新value的值
			@Override                                                                                                        //把value的值放到用于线程之间交流数据的Handler的message里
			public void run() {
				value=mp.getMaxAmplitude();
				Message message=mHandler.obtainMessage();
				message.arg1=value;
				mHandler.sendMessage(message);                                                 //Handler类发出信息
			}
			
		};
		timer.schedule(task, 100);                                                                                      //timer,设置为100毫秒后执行task线程(会自动调用task的start()函数)
		                                                                                                                                     //timer是计时器,作用就是在设定时间后启动规定的线程。这用来限制
		                                                            //getMaxAmplitude()的调用频率,减少资源的使用(时间调太短,也会闪退)                                                                              //
	}

	private void endrec(){
		if(mp!=null){
			Toast.makeText(MainActivity.this,"录音结束...", Toast.LENGTH_SHORT).show();          //提示
			timer.cancel();;                                                                                                                               //取消计时器(线程将不会被启动)
			mp.stop();                                                                                                                                        //停止录音
			mp.release();                                                                                                                                   //释放资源(mp不再绑定soundFile文件)
			soundFile.delete();                                                                                                                         //删除刚才录下的文件节约空间(也可以不删拿出来听一听~)
			mp=null;                                                                                                                                           //习惯性赋空值
		}
	}
}



 

 

 

MainActivity.java文件就是这样,在AndroidManifest.xml中声明写入sd卡,和打开麦克风的权限

 

 


 

 

还有的是同时刻,同场合不同机器所测出来的音频最大振幅值相差比较大,应该是硬件个体性差异的缘故。

 

 

好的,针对你的问题,我可以给出以下方案: 1. 写音频文件 使用AudioRecord录制音频数据后,可以将数据写入音频文件中,可以通过以下步骤实现: 1)创建一个FileOutputStream对象,用于指定音频文件的存储路径和名称; 2)创建一个byte数组,用于存储录音数据; 3)在AudioRecord的回调函数中,将录音数据写入byte数组; 4)将byte数组写入FileOutputStream中。 示例代码如下: ``` //设置音频源(麦克风) int audioSource = MediaRecorder.AudioSource.MIC; //设置采样率 int sampleRate = 44100; //设置音频通道(单声道) int channelConfig = AudioFormat.CHANNEL_IN_MONO; //设置音频编码(PCM编码) int audioFormat = AudioFormat.ENCODING_PCM_16BIT; //计算缓冲区大小 int bufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat); //创建AudioRecord对象 AudioRecord audioRecord = new AudioRecord(audioSource, sampleRate, channelConfig, audioFormat, bufferSize); //创建一个byte数组,用于存储录音数据 byte[] buffer = new byte[bufferSize]; //创建一个FileOutputStream对象,用于指定音频文件的存储路径和名称 FileOutputStream fos = new FileOutputStream(new File(Environment.getExternalStorageDirectory(), "audio.pcm")); //开始录音 audioRecord.startRecording(); //循环读取录音数据并写入文件 while (isRecording) { int len = audioRecord.read(buffer, 0, bufferSize); fos.write(buffer, 0, len); } //停止录音 audioRecord.stop(); //关闭FileOutputStream fos.close(); ``` 2. 获取实时麦克风音量大小 使用AudioRecord录制音频数据后,可以通过计算音量大小来获取麦克风的实时音量大小,可以通过以下步骤实现: 1)定义一个计算音量大小的方法getVolumeLevel(),用于计算音量大小; 2)在AudioRecord的回调函数中,调用getVolumeLevel()方法获取实时音量大小。 示例代码如下: ``` //定义一个计算音量大小的方法 public int getVolumeLevel(byte[] audioData) { int sum = 0; //将byte数组转换为short数组 short[] shorts = new short[audioData.length / 2]; ByteBuffer.wrap(audioData).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(shorts); //计算音量大小 for (short s : shorts) { sum += Math.abs(s); } return sum / shorts.length; } //创建一个byte数组,用于存储录音数据 byte[] buffer = new byte[bufferSize]; //开始录音 audioRecord.startRecording(); //循环读取录音数据并计算音量大小 while (isRecording) { int len = audioRecord.read(buffer, 0, bufferSize); int volumeLevel = getVolumeLevel(buffer); } //停止录音 audioRecord.stop(); ``` 以上就是实现Android AudioRecord写音频文件和获取实时麦克风音量大小的方法,希望可以帮助到你。如果有任何问题或不足之处,欢迎指出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值