Android音视频开发(五)AudioRecord录制音频
短信预约 -IT技能 免费直播动态提醒
简介
作者:GdinKing
AudioRecord是安卓多媒体框架中用于录制音频的工具。它支持录制原始音频数据,即PCM数据,PCM数据不能被播放器直接播放,需要编码压缩成常见音频格式才能被播放器识别。而原生api也提供了AudioTrack播放PCM数据。
谷歌Api文档
AudioRecord是通过read方式不断读取来自音源输入的数据流(字节流),进而把数据流保存成PCM数据。
开始录音的时候,AudioRecord需要创建一个缓冲区, 这个缓冲区主要是用来保存新的音频数据,它用于标识一个AudioRecord对象还没有被读取(同步)声音数据前能录多长的音(即一次可以录制的声音容量)。声音数据不断从音频硬件中被读出,每次读取的数据大小不超过初始化缓冲区的容量(录音数据的大小)。
流程如下:
下面使用Kotlin代码展示AudioRecord如何录制音频数据:
class AudioActivity : AppCompatActivity() {
//音频录制
private var audioRecord: AudioRecord? = null
//缓冲区大小,缓冲区用于保存音频数据流
private var bufferSize: Int = 0
//记录是否正在录制音频
@Volatile private var isRecording = false
//录音线程
private var recordThread: Thread? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_media)
initRecoder()
}
private fun initRecoder() {
bufferSize = AudioRecord.getMinBufferSize(
44100,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT
)
audioRecord = AudioRecord(
MediaRecorder.AudioSource.MIC,
44100,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT,
bufferSize * 2
)
}
fun startRecord(view: View) {
if (isRecording) {
return
}
isRecording = true
if (recordThread == null) {
recordThread = Thread(recordRunnable)
}
recordThread!!.start()
}
fun stopRecord(view: View) {
//置为false,表示线程循环就结束了,线程也执行完毕了
//也可以直接中断线程
isRecording = false
audioRecord?.stop()
audioRecord?.release()
audioRecord = null
recordThread = null
}
private val recordRunnable = Runnable {
//设置线程优先级
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO)
//创建文件
val tmpFile: File? = FileUtil.createFile("${System.currentTimeMillis()}.pcm")
//文件输出流
var fos: FileOutputStream = FileOutputStream(tmpFile?.getAbsoluteFile())
try {
if (audioRecord?.getState() !== AudioRecord.STATE_INITIALIZED) {
//没有初始化成功
return@Runnable
}
//开始录制
audioRecord?.startRecording()
var buffer = 0
val bytes = ByteArray(bufferSize)
//轮询读取数据
while (isRecording) {
if (audioRecord != null) {
buffer = audioRecord!!.read(bytes, 0, bufferSize)
if (buffer == AudioRecord.ERROR_INVALID_OPERATION || buffer == AudioRecord.ERROR_BAD_VALUE) {
continue
}
if (buffer == 0 || buffer == -1) {
break
}
//在此可以对录制音频的数据进行二次处理 如变声,压缩,降噪等操作
//也可以直接发送至服务器(实时语音传输) 对方可采用AudioTrack进行播放
//这里直接将pcm音频数据写入文件
fos.write(buffer)
}
}
} catch (e: Exception) {
Log.e("Test", "出错了", e)
} finally {
try {
fos?.close()
} catch (ex: IOException) {
}
}
}
}
作者:GdinKing
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341