版权声明:本文为原创文章,未经允许不得转载

博客地址:http://blog.csdn.net/kevindgk

GitHub地址:https://github.com/KevinDGK/MyAudioDemo

  • 一AudioRecord

    • 简介
    • 源码分析
  • 二AudioTrack类解析
    • 简介
    • 源码分析
      • 联系方式

一、AudioRecord

简介

在Java应用中,AudioRecord类管理着音频来源,使用平台的音频输入硬件来录音。然后,我们可以从AudioRecord类中将录音的数据“拉”出来。其中,我们获取数据的方法有三种:

- read(byte[],int, int)
- read(short[], int, int)
- sread(ByteBuffer, int)

至于选择哪个方法来获取数据,取决于我们需要的数据格式,需要哪种格式就使用哪种方法。

一旦我们创建成功了AudioRecord类并调用了read方法,它就会使用新的录音得到的数据来填充与之相关的音频缓冲区。缓冲区的大小是在构造方法中定义的,长度取决于不会使得有多余的音频没有录制到。

源码分析

  • 构造方法
/**构造方法- 由于一些无效的参数或者其他错误会抛出IllegalArgumentException,所以在你构造了一个AudioRecord实例之后,需要立刻调用 getState() 方法来判断这个实例的状态是否可以使用。参数:- audioSource:录音来源,查看MediaRecorder.AudioSource类对录音来源的定义。MediaRecorder.AudioSource.DEFAULT   默认音频来源MediaRecorder.AudioSource.MIC       麦克风MediaRecorder.AudioSource.VOICE_UPLINK  上行线路的声音来源...一般情况下,我们使用麦克风即可。- sampleRateInHz:采样率,单位Hz(赫兹)。44100Hz是目前唯一一个能够在所有的设备上使用的频率,但是一些其他的例如22050、16000、11025也能够在一部分设备上使用。- channelConfig:音频声道的配置(输入)AudioFormat.CHANNEL_IN_MONO:单声道AudioFormat.CHANNEL_IN_STEREO:立体声其中,CHANNEL_IN_MONO可以保证在所有设备上使用。- audioFormat:返回的音频数据的编码格式AudioFormat.ENCODING_INVALID:无效的编码格式AudioFormat.ENCODING_DEFAULT:默认的编码格式AudioFormat.ENCODING_PCM_16BIT:每份采样数据为PCM 16bit,保证所有设备支持AudioFormat.ENCODING_PCM_8BIT:样本数据格式为PCM 8bit,不保证所有设备支持AudioFormat.ENCODING_PCM_FLOAT:单精度浮点样本...- bufferSizeInBytes:在录音时期,音频数据写入的缓冲区的整体大小(单位字节),即缓冲区的大小。我们能够从这个缓冲区中读取到不超过缓冲区长度的整块数据。可以通过 getMinBufferSize(int, int, int) 这个方法来决定我们使用的AudioRecord实例所需要的最小的缓冲区的大小,如果我们使用的数值比这个还要小,则会导致AudioRecord实例初始化失败。
*/
public AudioRecord(int audioSource, int sampleRateInHz, int channelConfig, int audioFormat,int bufferSizeInBytes);
  • 初始化相关方法
/**获取我们要创建的AudioRecord实例所需要的缓冲区的最小长度该方法是AudioRecord类的静态方法哦~
*/
static public int getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat);/**获得AudioRecord实例的状态- 该方法在AudioRecord实例被创建之后调用来判断是否成功的初始化。确保获取(占用)到了合适的硬件资源。返回结果:STATE_INITIALIZED:1, 初始化成功,等待被使用;STATE_UNINITIALIZED:0, 初始化失败。
*/
public int getState();

小编看完构造方法和初始化相关的方法之后就无语了,参数很多,但是能够在所有的Android设备上使用的话,公共的参数都已经确定了,根据API获得了通用的使用麦克风录音的AudioRecord实例的方法:

//1. 获取最小的缓冲区大小
int recordBufferSize = AudioRecord.getMinBufferSize(44100, AudioFormat.CHANNEL_IN_MONO,AudioFormat.ENCODING_PCM_16BIT);//2. 创建AudioRecord实例
AudioRecord recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, 44100, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, recordBufferSize);
  • 录音相关方法
/**获得AudioRecord实例的录音状态返回结果:RECORDSTATE_STOPPED:1,录音停止,表示没有在录音;RECORDSTATE_RECORDING:3, 正在录音。
*/
public int getRecordingState();/**开始录音- 调用该方法后,会调用本地方法,使得录音设备开始录音。如果当前AudioRecord实例没有初始化成功,则此时会抛出违法状态异常。录音的过程中添加了同步锁,即同一时间只能有一个设备在使用麦克风。在该方法中就会获得该锁,然后修改当前的录音状态为正在录音,并开始录制声音。这个时候,我们初始化的时候使用的录音设备就会将录制到的音频的数据写入到我们定义的缓冲区中。
*/
public void startRecording();/**获取录音数据- 从录音硬件设备中读取录音数据,放入到字节数组中。具体我们使用那个方法来获取数据,根据我们设置的AudioRecord录制返回的音频数据的编码格式来定。由于ENCODING_PCM_16BIT是所有设备都支持的,所以我们也使用这个参数对应的read方法来获取录制的音频数据。参数:- audioData:需要写入音频数据的数组,即AudioRecord实例会将缓冲区中的数据根据指定的长度取出来放到这个给定的数组中,由于我们构造实例的时候设置的返回数据的格式是16bit,所以我们这里的audioData的格式为short[]- offsetInxxx:在audioData数组中写入数据的起始索引- sizeInShorts:请求的数据的大小- readMode:read模式READ_BLOCKING:获取数据会阻塞,直到所有的请求的数据被获得;READ_NON_BLOCKING:获取尽可能多的录音数据后会立刻返回,不会造成阻塞。该参数需要高版本的sdk,>=android.os.Build.VERSION_CODES.M (23),所以可以不设置。
*/
public int read(byte[] audioData, int offsetInBytes, int sizeInBytes);      //8BIT
public int read(byte[] audioData, int offsetInBytes, int sizeInBytes,int readMode);public int read(short[] audioData, int offsetInShorts, int sizeInShorts);//16BIT,用这个
public int read(short[] audioData, int offsetInShorts, int sizeInShorts,int readMode);public int read(float[] audioData, int offsetInFloats, int sizeInFloats,int readMode);//FLOATpublic int read(ByteBuffer audioBuffer, int sizeInBytes);   // ByteBuffer
public int read(ByteBuffer audioBuffer, int sizeInBytes, @ReadMode int readMode) /**停止录音- 调用本地方法会使得硬件设备停止录音,设置当前录音状态为停止录音。
*/
public void stop();/**释放资源- 释放本地的AudioRecord资源,AudioRecord实例就不能够使用了,在调用完该方法之后,引用应该被置为null。
*/
public void release();

二、AudioTrack类解析

简介

声道/音轨,该类为Java应用管理和播放一个单声道资源。它可以使用音频接收器来回放PCM格式的音频缓冲流。我们通过AudioTrack实例的write方法将数据写入进去,就可以达到回放的效果。

源码分析

  • 构造方法
/**构造方法- streamType:音频流的类型AudioManager.STREAM_VOICE_CALL:电话的音频流AudioManager.STREAM_SYSTEM:系统的音频流AudioManager.STREAM_RING:闹钟AudioManager.STREAM_MUSIC:音乐AudioManager.STREAM_ALARM:警告声AudioManager.STREAM_NOTIFICATION:通知- sampleRateInHz:来源的音频的采样频率,单位Hz- channelConfig:音频声道的配置AudioFormat.CHANNEL_OUT_MONO:单声道输出(左)AudioFormat.CHANNEL_OUT_STEREO:立体声输出(左和右)- audioFormat:音频格式AudioFormat.ENCODING_INVALID:无效的编码格式AudioFormat.ENCODING_DEFAULT:默认的编码格式AudioFormat.ENCODING_PCM_16BIT:每份采样数据为PCM 16bit,保证所有设备支持AudioFormat.ENCODING_PCM_8BIT:样本数据格式为PCM 8bit,不保证所有设备支持AudioFormat.ENCODING_PCM_FLOAT:单精度浮点样本...- bufferSizeInBytes:缓冲区的大小该缓冲区是为了存放需要回放的音频流数据,单位为字节。AudioTrack实例不断的从该缓冲区内读取写入的音频流数据,然后播放出来。它的大小应该是框架层尺寸的数倍。如果该声轨的创建模式是"AudioTrack.MODE_STATIC",- mode:流或者是静态缓存AudioTrack.MODE_STATIC:创建模式-在音频开始播放之前,音频数据仅仅只会从Java层写入到本地层中一次。即开始播放前一次性写入音频数据。AudioTrack.MODE_STREAM:创建模式-在音频播放的时候,音频数据会同时会以流的形式写入到本地层中。即一边播放,一边写入数据。(很明显,如果实现一边录音一边播放的话,用这个模式创建声轨)- */
public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat,int bufferSizeInBytes, int mode);
  • 初始化相关方法
/**获取缓冲区大小返回使用音频流模式创建声轨的实例时所需要的最小的缓冲区的大小。注意,该尺寸并不会保证在加载音频数据的时候能够平滑的播放数据,应该根据预期的频率来选择更高的缓冲区大小,可以被填充额外的数据。例如,如果你想要动态地提高回放的采样频率,那么也要确保配置比之前设置的缓冲区尺寸更高。简单讲,就是如果提高音频的频率,那么就得相应的提高缓冲区的大小。- sampleRateInHz:采样频率- channelConfig:声轨的配置- audioFormat:音频的格式返回值:AudioTrack.ERROR_BAD_VALUE:有无效的参数 -2AudioTrack.ERROR:不能够查询音频输出的性能 -1最小的缓冲区的尺寸,单位为Hz
*/
static public int getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat);/**返回AudioTrack实例的状态该方法十分有用,可以在创建完AudioTrack实例之后来检查该实例是否初始化成功,来确保获得了合适的硬件资源。返回值如下:AudioTrack.STATE_UNINITIALIZED:没有初始化成功AudioTrack.STATE_INITIALIZED:初始化成功AudioTrack实例,等待被使用AudioTrack.STATE_NO_STATIC_DATA:初始化成功一个使用静态数据的AudioTrack实例,但是该实例还没有获取到任何的数据呢。*/
public int getState();
  • 播放音频相关方法
/**获取AudioTrack实例的回放状态AudioTrack.PLAYSTATE_STOPPED:停止 1AudioTrack.PLAYSTATE_PAUSED:暂停  2AudioTrack.PLAYSTATE_PLAYING:正在播放   3
*/
public int getPlayState();/**启动回放的实例,开始播放写入的音频数据如果AudioTrack的创建模式是"MODE_STATIC",即播放静态资源模式,必须在调用该方法之前调用写入数据的方法,一次性写入音频数据;如果AudioTrack的创建模式是"MODE_STREAM",即音频流模式,你可以随意的在调用play()方法之前,通过向缓冲区写入数据来填充音轨数据。
*/
public void play();/**停止播放音频数据当使用音频流模式创建的AudioTrack实例来播放音频数据的时候,该实例会在播放完上一个写入的音频缓冲数据之后停止播放。如果想要立刻马上停止播放,请见下面的方法。
*/
public void stop();/**暂停音频数据的回放。立刻马上瞬间暂停,此时,未播放的数据不会被丢弃掉,如果重新调用play()方法,会继续之前的数据进行播放。如果想要丢弃剩下未播放的音频数据,应该在调用该方法之后调用flush()方法。
*/
public void pause();/**立刻刷新已经排队等待回放的音频数据所有被写入的,但是还没有被播放的数据都会被丢弃。
*/
public void flush();/**释放本地AudioTrack资源
*/
public void release();

联系方式

邮箱:815852777@qq.com

微信:

音频(二) - AudioRecordAudioTrack相关推荐

  1. Android 录音机小米商业项目开源代码 AudioRecord录音暂停 播放 Wav格式(音频二)

    Android MediaRecorder录音录像 暂停 继续录音 播放 ARM格式(音频一) https://blog.csdn.net/WHB20081815/article/details/88 ...

  2. 分析wav音频结构实现音频截取、音频二倍速播放、倒播和音频合并(C#实现)

    通过文件流读取wav文件放入byte数组,其中byte数组的前44位是存储wav音频文件头信息,如编码格式.声道数和样本速率等信息,网上也有比较多的相关博文,可以参考: WAV文件头分析 https: ...

  3. 音频(二)——I2S 协议

    I2S 协议详解 信号线定义 各个信号线的功能及描述见下表 信号线 描述 MCLK 主时钟,也叫系统时钟(Sys Clock),为了使系统间能够更好的同步,MCLK的频率=256fs 或384fs(f ...

  4. audiotrack java_Android音视频之AudioTrack播放音频(二)

    前一篇讲了如何录制wav音频文件,本篇就来讲讲如何播放wav文件,这里就是使用AudioTrack来播放音频,确切的说是播放pcm格式数据,使用AudioTrack播放也没什么难度,主要就是将数据写入 ...

  5. 深入剖析Android音频(二)AudioSystem

    原址 AudioSystem是AudioPolicyService和AudioFlinger对外提供接口类.

  6. 【音频处理】Melodyne 网络缩放功能 ( 音符分离线 | 片段分离线 | 窗口滚动条 | 网格缩放 | 修改图像显示位置 | 显示五线谱 )

    文章目录 一.Melodyne 音符分离线 | 片段分离线 二.窗口滚动条 三.网格缩放 四.修改图像显示位置 五.显示五线谱 一.Melodyne 音符分离线 | 片段分离线 音符分离线 : 每个音 ...

  7. 卖二手书的多抓鱼是如何逆袭上位的!

    实体书店越来越难做,并非是因为疫情的原因.此事可以追溯至2011年,那时候中国近一半独立书店倒闭,所谓的坚守与情怀,极可能让一家书店沦为沙滩上被拍死的虾米.不往远了讲,就最近几年倒下了不少情怀书店. ...

  8. 图片二维码,如何将图片制作成二维码

    想要将图片做成二维码? 其实很简单. 你只需要一个二维码生成器就能做到. 比如,这个业界小有名声的二维彩虹二维码生成器. 比如企业活动中,要展示多张图片:比如你想要将喜欢的插画作品保存并分享:比如你要 ...

  9. 出版图书二维码,要如何制作呢?

    在出版图书中使用二维码已经非常普遍.且印刷在图书上的二维码类型也更加多样化.出版社可以通过一个简单的二维码,来向读者传递更加有趣的和丰富的内容,同时更加方便和读者进行互动沟通,还能实现私域引流的目的. ...

最新文章

  1. firefox不激活新标签页
  2. UA MATH564 概率论 公式与定理总结
  3. linux oracle 01157,Oracle数据库启动时出现ORA-01157和ORA-01110问题
  4. docker二进制安装mysql_Docker搭建MySQL读写分离主从模式 分布式数据库中间件Mycat分库分表应用...
  5. 使用vs2010自带的数据库的方法
  6. 2021年福建高考省检成绩查询,福建省教育考试院:2021年福建高考查分入口、查分系统...
  7. .net反编译工具reflector5.0 的介绍及使用
  8. css的语义---Cascading Style Sheet
  9. [生存志] 第101节 九歌道尽楚芳华
  10. risc-v vector扩展1.0版本解读(riscv-v-spec-1.0)
  11. HttpUrlConnection与HttpClient的认识(六) -实际应用之刷网络流量
  12. 解决iphone 微信H5自动播放音乐问题
  13. JS中的批量替换---.replace(/\/g,@);
  14. 如何用php显示图标,显示桌面图标不见了如何恢复
  15. STC89C52RC 按键控制LED
  16. Intel HD Graphics 3000/4000核心显卡可玩游戏列表
  17. 办公室可以挂画吗?挂什么样的画好?
  18. 无人机航测行业中常见名词解释,你都知道吗?
  19. opencv双目测距实现
  20. Qt操作至少需要一个处于启用状态的有效资料档案库

热门文章

  1. 百度百科全站爬取教程
  2. Win10远程桌面黑屏详细解决办法
  3. 微信浏览器 苹果 ios 网页跳转没反应
  4. 仿QQ通信(一)绘制客户端界面
  5. Atcoder 4142 Xor Sum (双指针)
  6. Redis思维导图笔记——服务器
  7. Java根据生日得出是十二星座的哪一个星座属相
  8. 前端框架OnsenUI学习之初识OnsenUI
  9. 支付宝(网商银行)提前批一面
  10. 【开源项目】股票配资系统开发与设计(二)