热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

Android实现语音数据实时采集、播放

这篇文章主要介绍了android实现语音数据实时采集、播放的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

最近做的项目是和语音实时采集并发送,对方实时接收并播放相关,下面记录下实现的核心代码。
很多Android开发者应该知道android有个MediaRecorder对象和MediaPlayer对象,用于录制和播放音频。这个弊端在于他们不能实时采集并发送出去,所以,我们只能使用AudioRecord和AudioTrack来实现。
记得申明权限:





一、AudioRecord实现核心代码介绍如下:

1、先申明相关录制配置参数

private AudioRecord audioRecord;// 录音对象
private int frequence = 8000;// 采样率 8000
private int channelInCOnfig= AudioFormat.CHANNEL_CONFIGURATION_MONO;// 定义采样通道
private int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;// 定义音频编码(16位)
private byte[] buffer = null;// 录制的缓冲数组


2、在开始录制前,我们需要初始化AudioRecord类。

// 根据定义好的几个配置,来获取合适的缓冲大小
// int bufferSize = 800;
int bufferSize = AudioRecord.getMinBufferSize(frequence,
    channelInConfig, audioEncoding);
// 实例化AudioRecord
audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
    frequence, channelInConfig, audioEncoding, bufferSize);
// 定义缓冲数组
buffer = new byte[bufferSize];

3、准备开始录制,使用循环不断读取数据。

audioRecord.startRecording();// 开始录制
isRecording = true;// 设置录制标记为true

// 开始录制
while (isRecording) {
// 录制的内容放置到了buffer中,result代表存储长度
int result = audioRecord.read(buffer, 0, buffer.length);
/*.....result为buffer中录制数据的长度(貌似基本上都是640)。
剩下就是处理buffer了,是发送出去还是直接播放,这个随便你。*/
}

//录制循环结束后,记得关闭录制!!
if (audioRecord != null) {
  audioRecord.stop();
}


二、AudioTrack代码实现介绍如下:

1、声明播放相关配置。

private AudioTrack track = null;// 录音文件播放对象
private int frequence = 8000;// 采样率 8000
private int channelInCOnfig= AudioFormat.CHANNEL_CONFIGURATION_MONO;// 定义采样通道
private int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;// 定义音频编码(16位)
private int bufferSize = -1;// 播放缓冲大小


2、初始化AudioTrack对象(初始化一次,该对象可重复使用)

// 获取缓冲 大小
bufferSize = AudioTrack.getMinBufferSize(frequence, channelInConfig,
    audioEncoding);
// 实例AudioTrack
track = new AudioTrack(AudioManager.STREAM_MUSIC, frequence,
    channelInConfig, audioEncoding, bufferSize,
    AudioTrack.MODE_STREAM);


3、使用AudioTrack播放语音数据。

//将语音数据写入即可。
track.write(dataArray, buffer, len);


问题一:

由于目前的项目是实时采集,实时发送,所以需要考虑到包的大小,经测试,我们使用160个byte作为一个包传递可以做到比较良好的播放效果(也就是将一份buffer拆分成四个发送)。处理代码如下:

// 将数据通过监听接口回调出去
if (audioRecordingCallback != null) {
  int offset = result % MAX_DATA_LENGTH > 0 ? 1 : 0;
  //将一个buffer拆分成几份小数据包 MAX_DATA_LENGTH 为包的最大byte数
  for (int i = 0; i  result) {
      length = result - i * MAX_DATA_LENGTH;
    }
  //写到回调接口
  audioRecordingCallback.onRecording(buffer, i
      * MAX_DATA_LENGTH, length);
  }
}


问题二:

有时候传输的过来播放声音会一卡一卡的,为了解决这样的问题,暂时使用了语音双缓冲机制来解决,问题优化很明显。代码和示意图如下:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • 本文深入探讨了 iOS 开发中 `int`、`NSInteger`、`NSUInteger` 和 `NSNumber` 的应用与区别。首先,我们将详细介绍 `NSNumber` 类型,该类用于封装基本数据类型,如整数、浮点数等,使其能够在 Objective-C 的集合类中使用。通过分析这些类型的特性和应用场景,帮助开发者更好地理解和选择合适的数据类型,提高代码的健壮性和可维护性。苹果官方文档提供了更多详细信息,可供进一步参考。 ... [详细]
  • 在执行 Vim/VM 命令时遇到错误提示:检测到名为
    在使用 Docker 时,通过 Vim 编辑 Dockerfile 文件时遇到了错误提示:“检测到名为 .dockerfile.swp 的交换文件”。这一问题通常是因为上次编辑该文件时意外中断,导致系统生成了临时的交换文件。为了解决这个问题,可以手动删除该交换文件或使用 Vim 的恢复功能来恢复未保存的更改。 ... [详细]
  • 当前,众多初创企业对全栈工程师的需求日益增长,但市场中却存在大量所谓的“伪全栈工程师”,尤其是那些仅掌握了Node.js技能的前端开发人员。本文旨在深入探讨全栈工程师在现代技术生态中的真实角色与价值,澄清对这一角色的误解,并强调真正的全栈工程师应具备全面的技术栈和综合解决问题的能力。 ... [详细]
  • 全面解析:Hadoop技术栈中的Linux操作系统概览
    全面解析:Hadoop技术栈中的Linux操作系统概览 ... [详细]
  • 题目描述:小K不幸被LL邪教洗脑,洗脑程度之深使他决定彻底脱离这个邪教。在最终离开前,他计划再进行一次亚瑟王游戏。作为最后一战,他希望这次游戏能够尽善尽美。众所周知,亚瑟王游戏的结果很大程度上取决于运气,但通过合理的策略和算法优化,可以提高获胜的概率。本文将详细解析洛谷P3239 [HNOI2015] 亚瑟王问题,并提供具体的算法实现方法,帮助读者更好地理解和应用相关技术。 ... [详细]
  • 基于Node.js的高性能实时消息推送系统通过集成Socket.IO和Express框架,实现了高效的高并发消息转发功能。该系统能够支持大量用户同时在线,并确保消息的实时性和可靠性,适用于需要即时通信的应用场景。 ... [详细]
  • [TyvjP1050] 动态规划求解最长公共子序列问题
    在解决最长公共子序列问题时,动态规划是一种高效的方法。具体而言,我们使用二维数组 `dp[i][j]` 来表示第一个字符串匹配到第 `i` 位,第二个字符串匹配到第 `j` 位时的最长公共子序列长度。状态转移方程为:当两个字符相等时,`dp[i][j] = dp[i-1][j-1] + 1`;否则,`dp[i][j] = max(dp[i-1][j], dp[i][j-1])`。通过这种方法,我们可以有效地计算出两个字符串的最长公共子序列。 ... [详细]
  • BZOJ4240 Gym 102082G:贪心算法与树状数组的综合应用
    BZOJ4240 Gym 102082G 题目 "有趣的家庭菜园" 结合了贪心算法和树状数组的应用,旨在解决在有限时间和内存限制下高效处理复杂数据结构的问题。通过巧妙地运用贪心策略和树状数组,该题目能够在 10 秒的时间限制和 256MB 的内存限制内,有效处理大量输入数据,实现高性能的解决方案。提交次数为 756 次,成功解决次数为 349 次,体现了该题目的挑战性和实际应用价值。 ... [详细]
  • iOS 应用未集成系统账号注册功能,仅支持第三方登录,如何顺利通过苹果审核? ... [详细]
  • 使用cpphttplib构建HTTP服务器以处理带有查询参数的URL请求 ... [详细]
  • U盘安装操作系统详细指南及常见问题解决方法 ... [详细]
  • 作为140字符的开创者,Twitter看似简单却异常复杂。其简洁之处在于仅用140个字符就能实现信息的高效传播,甚至在多次全球性事件中超越传统媒体的速度。然而,为了支持2亿用户的高效使用,其背后的技术架构和系统设计则极为复杂,涉及高并发处理、数据存储和实时传输等多个技术挑战。 ... [详细]
  • Laravel 与 Vue 实现前后端分离时的跨域解决方案探析
    Laravel 与 Vue 实现前后端分离时的跨域解决方案探析 ... [详细]
  • 【小程序开发】iOS平台时间显示异常问题解析与优化方案
    在iOS平台上,小程序的时间显示出现异常的问题主要源于iOS系统对特定日期格式的支持不足。具体而言,iOS无法正确解析“2019-12-23”这种标准的日期格式,需要将其转换为“20191223”这种连续的数字格式。本文详细分析了这一问题的成因,并提出了一系列优化方案,以确保小程序在iOS平台上的时间显示功能正常运行。此外,我们还探讨了在小程序编辑功能中如何高效地进行日期格式的转换,以提升用户体验。 ... [详细]
  • 在稀疏直接法视觉里程计中,通过优化特征点并采用基于光度误差最小化的灰度图像线性插值技术,提高了定位精度。该方法通过对空间点的非齐次和齐次表示进行处理,利用RGB-D传感器获取的3D坐标信息,在两帧图像之间实现精确匹配,有效减少了光度误差,提升了系统的鲁棒性和稳定性。 ... [详细]
author-avatar
阿莱沃_132
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有