Android 实时录音和回放,边录音边播放 (KTV回音效果)
上一篇介绍了如何使用Mediarecorder来录音,以及播放录音。不过并没有达到我的目的,一边录音一边播放。今天就讲解一下如何一边录音一边播放。使用AndioRecord录音和使用AudioTrack回放。参考了网上一位开发者的例子代码开发,最后会给出相关Demo。
(PS:新建的QQ群,有兴趣可以加入一起讨论:Android群:322599434)
1、AndioRecord类介绍
AndioRecord类的主要功能是让各种JAVA应用能够管理音频资源,以便它们通过此类能够录制平台的声音输入硬件所收集的声音。此功能的实现就是通过”pulling同步”(reading读取)AudioRecord对象的声音数据来完成的。在录音过程中,应用所需要做的就是通过后面三个类方法中的一个去及时地获取AudioRecord对象的录音数据. AudioRecord类提供的三个获取声音数据的方法分别是read(byte[], int, int), read(short[], int, int), read(ByteBuffer, int)。 无论选择使用那一个方法都必须事先设定方便用户的声音数据的存储格式。然后再使用AudioTrack实时回放声音即可。
下面是使用AudioRecord的过程中,可能会遇到的返回值,对于定位问题的原因很有用,解析很简单,我就不翻译了。

2、AudioRecord初始化
//Edited by mythou
//http://www.cnblogs.com/mythou/
// AudioRecord 得到录制最小缓冲区的大小
m_in_buf_size = AudioRecord.getMinBufferSize(,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT);
// 实例化播放音频对象
m_in_rec = new AudioRecord(MediaRecorder.AudioSource.MIC, ,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT, m_in_buf_size);
AudioRecord的初始化参数比较多,需要注意设置。这几个参数都是标准的声音采集的参数,下面我针对这几个参数做个介绍,实际使用的时候,你可以根据你的情况设置。
AudioRecord(int audioSource, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes)
AudioRecord构造参数的参数解析,可以根据实际情况调整:
| audioSource | 音频源:指的是从哪里采集音频。这里我们是从麦克风采集音频,所以此参数的值为MIC。可以参考MediaRecorder.AudioSource类,查看其他音频源。 |
| sampleRateInHz | 采样率:音频的采样频率,每秒钟能够采样的次数,采样率越高,音质越高。给出的实例是44100、22050、11025但不限于这几个参数。例如要采集低质量的音频就可以使用4000、8000等低采样率。 |
| channelConfig | 声道设置:android支持双声道立体声和单声道。MONO单声道,STEREO立体声 |
| audioFormat | 编码制式和采样大小:采集来的数据当然使用PCM编码(脉冲代码调制编码,即PCM编码。PCM通过抽样、量化、编码三个步骤将连续变化的模拟信号转换为数字编码。) android支持的采样大小16bit 或者8bit。当然采样大小越大,那么信息量越多,音质也越高,现在主流的采样大小都是16bit,在低质量的语音传输的时候8bit 足够了。 |
| bufferSizeInBytes | 采集数据需要的缓冲区的大小,如果不知道最小需要的大小可以在getMinBufferSize()查看。 |
上面是针对AudioRecord的初始化参数做了详细阐述,这个对于使用AudioRecord十分重要,也影响了录音和后期播放的效果,所以在你使用AudioRecord进行录音前,请仔细熟悉上面参数。
3、录音
//Edited by mythou
//http://www.cnblogs.com/mythou/
// 录音线程
class recordSound implements Runnable
{
@Override
public void run()
{
Log.d(TAG, "........recordSound run()......");
byte[] bytes_pkg;
// 开始录音
m_in_rec.startRecording(); while (flag)
{
m_in_rec.read(m_in_bytes, , m_in_buf_size);
bytes_pkg = m_in_bytes.clone();
Log.i(TAG, "........recordSound bytes_pkg==" + bytes_pkg.length);
if (m_in_q.size() >= )
{
m_in_q.removeFirst();
}
m_in_q.add(bytes_pkg);
}
} }
这里录音使用的是read()方法来读取录音的数据,并且把录音放到一个独立线程执行,读取到的录音数据,放入到队列里面,供播放线程使用。下面我们看看播放线程:
4、播放录音
//Edited by mythou
//http://www.cnblogs.com/mythou/
//播放线程
class playRecord implements Runnable
{
@Override
public void run()
{
Log.d(TAG, "........playRecord run()......");
byte[] bytes_pkg = null;
// 开始播放
m_out_trk.play(); while (flag)
{
try
{
m_out_bytes = m_in_q.getFirst();
bytes_pkg = m_out_bytes.clone();
m_out_trk.write(bytes_pkg, , bytes_pkg.length);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
}
播放录音和录音过程大致一样,都是一个独立线程,这里需要注意的是,录音和播放都是开了独立的线程,而不是放在UI线程执行,至于原因不用我多说,大家应该都明白。
5、解决异常
下面把我调试过程中遇到的一个问题分享一下:
- ::25.032: E/AndroidRuntime(): FATAL EXCEPTION: Thread-
- ::25.032: E/AndroidRuntime(): java.lang.IllegalStateException: startRecording() called on an uninitialized AudioRecord.
- ::25.032: E/AndroidRuntime(): at android.media.AudioRecord.startRecording(AudioRecord.java:)
- ::25.032: E/AndroidRuntime(): at com.apical.AuxIn.AudioNowRecord$recordSound.run(AudioNowRecord.java:)
- ::25.032: E/AndroidRuntime(): at java.lang.Thread.run(Thread.java:)
出现上面问题的原因是录音的硬件资源被申请了,但是没有释放,然后你再次申请资源,导致初始化失败。这里需要注意的是不仅仅需要调用Release()方法。还需要把AudioRecord对象置为null,否则还是释放失败。下面是Android 开发网上面的一个对于AudioRecord的释放说明。
Releases the native AudioRecord resources. The object can no longer be used and the reference should be set to null after a call to release()。
6、结语
上面就是一边录音一边播放的大致代码流程,主要就是AudioRecord和AudioTrack的使用,实际使用的时候,你需要根据自己的实际情况,调试AudioRecord的音频采样参数和回放的参数,达到你想要的效果。另外这个功能也能实现KTV的回声效果。自己调试一下参数即可。
下面给出一个网络上的demo,是一位叫吴辰彪的开发者分享的,因为我是在CSDN下载的这个Demo,只从代码中看到作者名字。感谢这位开发者分享了这个录音回放的Demo。
录音回放Demo:RecordPlay2013-8-7.rar
相关文章:
Android 录音和播放
Edited by mythou
原创博文,转载请标明出处:http://www.cnblogs.com/mythou/p/3241925.html
Android 实时录音和回放,边录音边播放 (KTV回音效果)的更多相关文章
- Android开发--仿微信语音对讲录音
原文地址:http://www.2cto.com/kf/201502/378704.html 自微信出现以来取得了很好的成绩,语音对讲的实现更加方便了人与人之间的交流.今天来实践一下微信的语音对讲的录 ...
- Tiny6410声卡驱动——录音与回放
在Linux下,音频设备程序的实现与文件系统的操作密切相关.Linux将各种设备以文件的形式给出统一的接口,这样的设计使得对设备的编程与对文件的操作基本相同,对Linux内核的系统调用也基本一致,从而 ...
- Android开发手记(31) 使用MediaRecorder录音
使用Android手机的时候,有时我们会用到录音功能,本文简单的介绍了如何使用MediaRecorder通过手机自带麦克风进行录音. 首先,既然是录音,我们需要录音和写外存的权限: <uses- ...
- Android实时获取音量(单位:分贝)
基础知识 度量声音强度,大家最熟悉的单位就是分贝(decibel,缩写为dB).这是一个无纲量的相对单位,计算公式如下: 分子是测量值的声压,分母是参考值的声压(20微帕,人类所能听到的最小声压).因 ...
- [转] Android实时抓包分析 : 善用adb调试桥
Android实时抓包分析 : 善用adb调试桥 谈到android网络抓包,很多人都能想到牛逼轰轰的神器tcpdump.方法就是在android机器上面安装tcpdump,然后通过-w参数把抓包 ...
- Android实时监听网络状态
Android实时监听网络状态(1) 其实手机在网络方面的的监听也比较重要,有时候我们必须实时监控这个程序的实时网络状态,android在网络断开与连接的时候都会发出广播,我们通过接收系统的广播就 ...
- Android 使用NineOldAndroids实现绚丽的ListView左右滑动删除Item效果
本文出自xiaanming的博客(http://blog.csdn.net/xiaanming/article/details/18311877) 今天还是给大家带来自定义控件的编写,自定义一个Lis ...
- 【转】Android 使用Scroller实现绚丽的ListView左右滑动删除Item效果
原文网址:http://blog.csdn.net/xiaanming/article/details/17539199 转帖请注明本文出自xiaanming的博客(http://blog.csdn. ...
- Android较低版本(<5.2) 页面默认Select选择框效果的BUG解决
Bug描述: 使用低版本安卓(<5.2),在微信上打开网页,点击下拉框,会出现如下图所示的用来展示select选项的弹出框: 在选项较少的时候,可以向下滑动,将选项滑到底部 滑动前: 滑动后: ...
随机推荐
- Manjaro 初始配置----anaconda-pycharm-opencv-tensorflow
1.安装蟒蛇 1)安装 yaourt anaconda source /opt/anaconda/bin/active root 2)添加环境变量 在〜/ .bashrc中添加 export PATH ...
- GreenDao与ReactiveX的完美搭配
转载请注明出处:http://www.cnblogs.com/cnwutianhao/p/6719380.html 作为Android开发者,一定不会对 GreenDao 和 ReactiveX 陌生 ...
- 使用OutputStream向屏幕上输出内容
使用OutputStream向屏幕上输出内容 /** * 使用OutputStream向屏幕上输出内容 */ import java.io.*; class hello { public static ...
- BZOJ.4793.[CERC2016]Hangar Hurdles(Kruskal重构树 BFS)
题目链接 \(Description\) 有一个\(n\times n\)的正方形网格,上面有若干障碍点.\(q\)次询问,每次询问把一个正方形箱子从\((x1,y1)\)推到\((x2,y2)\) ...
- Python图形编程探索系列-09-tkinter与matplotlib结合案例
案例1 案例来自于:https://bbs.csdn.net/topics/390326088 代码示例: import matplotlib matplotlib.use('TkAgg') from ...
- doker学习笔记
1.获取镜像: docker pull mysql 2,查看已安装的镜像: docker image 3,运行: 查看docker运行:docker info(docker run ubuntu ec ...
- 2016年3月11日Android实习日记
1.明天删除orthodotics_design_animation_content_gif.gif文件.(已完成) 2. 如何检测内存泄露? A: 可以通过一些性能监测分析工具,如 JProfile ...
- 2018 OO第一次总结(作业1-3)
第一次作业1.程序分析 (1)OO度量 (2)类图: (3)分析与评价: 这次作业由于作业整体设计难度不大,因此按照去年暑假上的OO先导课老师讲的设计方法很容易实现一个还不错的面向对象式程序,类与类之 ...
- JDBC(2)—Statement
介绍: 获取到数据库连接之后,就可以对数据库进行一些增.删.改操作,但是却不能进行查询操作. 增删改操作是程序到数据库的一个操作过程,但是查询是程序到数据库--数据库返回到程序的一个过程. 步骤: 步 ...
- c#单元测试:使用Moq框架Mock对象
在.net中有几种mock框架可供选择,比如NMock,PhinoMocks,FakeItEasy和Moq.尽管Moq相对较新,但是它非常易用.不需要像传统的Record/Replay.并且使用Moq ...