android手机的Mic对声音的感知

如下是转载的文章,前段时间我也在作mic录音方面的东东,等整理出来再总结一下。。 java


这段时间作了个有关android手机利用mic捕获外界环境音量的小东东,多方查询,各类研究,如今把这些东西跟童鞋们分享一下,若有不足或者差错,还望大牛们多给意见。 android

        android提供能够实现录音功能的有AudioRecord和MediaRecorder,其中AudioRecord是读取Mic的音频流,能够边录音边分析流的数据;而MediaRecorder则可以直接把Mic的数据存到文件,而且可以进行编码(如AMR,MP3等)。 api

        首先,要将你的应用加入权限(不管你是使用AudioRecord仍是MediaRecorder): 数组

                 <uses-permission android:name="android.permission.RECORD_AUDIO" /> dom

        而后,分开介绍二者的用法。 函数

        《!--AudioRecord--》 测试

        一、新建录音采样类,实现接口: 编码

             public class MicSensor implements AudioRecord.OnRecordPositionUpdateListener spa

        二、关于AudioRecord的初始化: .net

             public AudioRecord (int audioSource, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes)

             audioSource:              录音源(例如:MediaRecorder.AudioSource.MIC    指定Mic为录音源)

             sampleRateInHz:        默认的采样频率,单位为Hz。(经常使用的如44100Hz、22050Hz、16000Hz、11025Hz、8000Hz,有人说44100Hz是目前保证在全部厂商的android手机上都能使用的采样频率,可是我的在三星i9000上使用却否则,经测试8000Hz彷佛更为靠谱)  

            channelConfig:           描述音频通道设置。(在此我使用了AudioFormat.CHANNEL_CONFIGURATION_MONO)

            audioFormat:              音频数据支持格式。(这个好像跟声道有关,16bit的脉码调制录音应该是所谓的双声道,而8bit脉码调制录音是单声道。AudioFormat.ENCODING_PCM_16BIT、AudioFormat.ENCODING_PCM_8BIT

           bufferSizeInBytes:        在录制过程当中,音频数据写入缓冲区的总数(字节)。 从缓冲区读取的新音频数据总会小于此值。 getMinBufferSize(int, int, int)返回AudioRecord 实例建立成功后的最小缓冲区。 设置的值比getMinBufferSize()还小则会致使初始化失败。

       三、初始化成功后则可启动录音    audioRecord.startRecording()

       四、编写线程类将录音数据读入缓冲区,进行分析

             short[] buffer = new short[bufferSize];              //short类型对应16bit音频数据格式,byte类型对应于8bit
             audioRecord.read(buffer, 0, bufferSize);            //返回值是个int类型的数据长度值

      五、在此须要对buffer中的数据进行一些说明:

           这样读取的数据是在时域下的数据,直接用于计算没有任何实际意义。须要将时域下的数据转化为频域下的数据,才能诉诸于计算。

           频域(frequency domain)是指在对函数或信号进行分析时,分析其和频率有关部份,而不是和时间有关的部份。

           函数或信号能够透过一对数学的运算子在时域及频域之间转换。例如傅里叶变换能够将一个时域信号转换成在不一样频率下对应的振幅及相位,其频谱就是时域信号在频域下的表现,而反傅里叶变换能够将频谱再转换回时域的信号。

           信号在时域下的图形能够显示信号如何随着时间变化,而信号在频域下的图形(通常称为频谱)能够显示信号分布在哪些频率及其比例。频域的表示法除了有各个频率下的大小外,也会有各个频率的相位,利用大小及相位的资讯能够将各频率的弦波给予不一样的大小及相位,相加之后能够还原成原始的信号。

           经傅立叶变化后获得的复数数组是个二维数组,实部和虚部的平方和取对数后乘以10就大体等于咱们一般表示音量的分贝了。

       《!--MediaRecorder--》

         相对于AudioRecord,MediaRecorder提供了更为简单的api。

[java]  view plain copy
  1.               mediaRecorder = new MediaRecorder();  
  2. mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);  
  3. mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);  
  4. mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);  
  5. mediaRecorder.setOutputFile("/dev/null");    

         设置好mediaRecorder的各个属性,而后经过线程调用方法  mediaRecorder.getMaxAmplitude();

            获得的是瞬时的最大振幅,直接取对数而后乘以10就能够表征分贝了。

            最后须要说明一下,android手机厂商定制的硬件不尽相同,因此mic获取的值也只能“表征”,而不能拿过来当真正的依据。它们虽是智能手机,但也仍是手机,机器人不是人!呵呵。。。

            对了,每一个手机mic在声信号和电信号进行转换时都有作过电容保护,为了其不因外界环境的过于嘈杂而易受到损坏。因此超声波和次声波,咱们人不容易接受的声音,手机也不会入耳的。

相关文章
相关标签/搜索