Android多媒体(一) 音轨合成 我用双手成就你的梦想

近期需要做音轨合成这样一个功能,何为音轨合成,说白了就是N个音频文件合成一个,同时播放N个声音。然而网上各种找代码,并没有一个能用的,最后终于找到一个外国大神写的合音工具类,稍加修改便成了自己的东西,现在分享出来,方便大家使用。


模拟器没办法录音,所以这里先只提供一张效果图


我这里做的效果是点击开始录音开始录制声音,停止后将该录音文件存储在sd卡,并在中间的ListViw显示名字,点击item选中多条后,即可开始合音

先来说一下步骤,

1.录音并将录音文件存储在sd卡下

2.解码

3.合音

从大的方向来讲,要实现这里的效果只需以上三步


我这里使用的MediaRecorder录音,首先,点击按钮后开始录音:

MediaRecorder mRecorder = new MediaRecorder();
mRecorder.reset();
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); // 设置声音来源
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);// 设置所录制的音视频文件的格式
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);// 设置所录制的声音的编码格式
mRecorder.setAudioEncodingBitRate(96000);// 比特率
mRecorder.setAudioChannels(2);// 通道
mRecorder.setAudioSamplingRate(44100);// 采样率
mRecorder.setOutputFile(recordFile.getAbsolutePath() + "/record"+ count + ".mp4");// 设置录制的音频文件的保存位置
try {mRecorder.prepare();
} catch (IOException e) {e.printStackTrace();
}
mRecorder.start();


这里需要注意的是:

1.要合音的文件格式必须相同,比如必须都是MP4或都是MP3,否则合出来的音会像卡带了一样

2.采样率、通道、精度必须相同,有一个参数不同都会影响到合出来的效果

3.做的时候还遇到一个问题,设置采样率、通道、比特率的代码必须放在setOutputFormat后面,如果放在setOutputFormat前面,合出来的音也是有问题的。至于这个为什么, 我暂时也没有找到答案,当时因为这个问题困扰了很久,无意间放到setOutputFormat后面才意外成功


录音结束后,将文件名字添加到List中,来充当ListView的数据

mRecorder.stop();
mRecorder = null;
RecordBean bean = new RecordBean();
bean.setId(count);
bean.setName(count + ".mp4");
bean.setState(0);
bean.setPath(recordFile.getAbsolutePath() + "/record" + count + ".mp4");
list.add(bean);
adapter.setList(list);

接下来,就是选择录音的文件并进行解码,将解码后的文件存在sd卡,合音时,将解码后的文件进行合音。

解码:

/*** 解码* */class DecodeTask extends AsyncTask<Void, Double, Boolean> {private String fileUrl;private int position;DecodeTask(String url, int p) {fileUrl = url;position = p;}@Overrideprotected Boolean doInBackground(Void... params) {try {// 解码后的路径String decodeFilePath = decodeFile.getAbsolutePath()+ "/decode" + MD5Util.getMD5Str(fileUrl);// 将解码后的路径保存在list中,方便后面取值list.get(position).setDecodePath(decodeFilePath);// 解码AudioDecoder audioDec = AudioDecoder.createDefualtDecoder(fileUrl);fileUrl = decodeFilePath;audioDec.decodeToFile(decodeFilePath);return true;} catch (IOException e) {e.printStackTrace();return false;}}@Overrideprotected void onPostExecute(Boolean result) {super.onPostExecute(result);dialog.cancel();}}


合音:

/*** 合音* */class MixTask extends AsyncTask<Void, Double, Boolean> {private int size;MixTask(int num) {size = num;}@Overrideprotected Boolean doInBackground(Void... params) {String rawAudioFile = null;// 将需要合音的音频解码后的文件放到数组里File[] rawAudioFiles = new File[size];StringBuilder sbMix = new StringBuilder();int index = 0;for (int i = 0; i < list.size(); i++) {if (1 == list.get(i).getState()) {rawAudioFiles[index++] = new File(list.get(i).getDecodePath());sbMix.append(i + "");}}// 最终合音的路径final String mixFilePath = mixFile.getAbsolutePath() + "/mix"+ MD5Util.getMD5Str(sbMix.toString());// 下面的都是合音的代码try {MultiAudioMixer audioMixer = MultiAudioMixer.createAudioMixer();audioMixer.setOnAudioMixListener(new OnAudioMixListener() {FileOutputStream fosRawMixAudio = new FileOutputStream(mixFilePath);@Overridepublic void onMixing(byte[] mixBytes) throws IOException {fosRawMixAudio.write(mixBytes);}@Overridepublic void onMixError(int errorCode) {try {if (fosRawMixAudio != null)fosRawMixAudio.close();} catch (IOException e) {e.printStackTrace();}}@Overridepublic void onMixComplete() {try {if (fosRawMixAudio != null)fosRawMixAudio.close();} catch (IOException e) {e.printStackTrace();}}});audioMixer.mixAudios(rawAudioFiles);rawAudioFile = mixFilePath;} catch (FileNotFoundException e) {e.printStackTrace();}AudioEncoder accEncoder = AudioEncoder.createAccEncoder(rawAudioFile);String finalMixPath = mixFile.getAbsolutePath() + "/finalMix.aac";accEncoder.encodeToFile(finalMixPath);return true;}@Overrideprotected void onPostExecute(Boolean result) {super.onPostExecute(result);Toast.makeText(getApplicationContext(), "合音成功", Toast.LENGTH_SHORT).show();dialog.cancel();}}


最后合成的声音,可以在sdcard/merge/mix/中找到,叫finalMix.aac,可以点击播放试一下

Demo中只是实现该操作,有些东西没有加,如判断sd卡、判断权限是否关闭等,这些实际操作中切勿忘记自行加上



由于所需要的类还是比较多的,这里不能贴上全部代码,有需要的可自行下载Demo:http://download.csdn.net/detail/qq_18612815/9529622

Demo中重要的地方我都加了注释,基本都能看得懂

本篇讲的是音轨合成,接下来的几篇会增加音轨拼接、音轨与视频合成,有需要的加个关注,方便get


刚刚发现了一个bug,Demo中  RecordWithRecordActivity  199行应改为 new MixTask(num).execute();,之前写demo时候测试把num写成2固定死了,所以如果选择超过2个文件就会崩...


转载请注明来自http://blog.csdn.net/qq_18612815



本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/1380107.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

FFMpeg 实现从视频中提取音轨

近期由于项目需要&#xff0c;要实现以下功能&#xff1a;将视频中的音轨提取出来&#xff0c;也就是只保留音频部分&#xff0c;以便于后期对于声音的处理。 我选择的工具是 FFMpeg &#xff0c;环境&#xff1a;win7 首先&#xff0c;从官网上下载FFMpeg的文件包&#xff0c;…

html5音轨的提取,(图文)mkv音轨提取软件 如何提取mkv中的音轨

很多人都知道&#xff0c;MKV是个“组合”和“封装”的格式&#xff0c;换句话说就是一种容器格式。最大的特点就是能容纳多种不同类型编码的视频、音频及字幕流。现在流行的高清电影一般都是MKV格式&#xff0c;里面可能包含有多个音轨&#xff0c;方便我们在播放视频时选择需…

html5音轨字幕,(图解)如何修改mkv默认音轨和字幕

平常有下载一些MKV双语电影在家里看,一般播放时电影默认播放外语加中文字幕,不过家里老爸老妈听不懂外语,所以每次看片时我还要手动切换音轨变成国语的。要是可以修改mkv的默认音轨或字幕就好了,于是我就找出了以下修改mkv默认音轨和字幕的解决方案,顺便分享一下,也许能帮…

前后端分离------后端创建笔记(上)

本文章转载于【SpringBootVue】全网最简单但实用的前后端分离项目实战笔记 - 前端_大菜007的博客-CSDN博客 仅用于学习和讨论&#xff0c;如有侵权请联系 源码&#xff1a;https://gitee.com/green_vegetables/x-admin-project.git 素材&#xff1a;https://pan.baidu.com/s/…

提取视频多音轨: 魔力玄(Medlexo) V9.7 (2023-01-31更新)

软件名称 (Windows) 魔力玄(Medlexo) 一句简介 假如一个视频144mb&#xff0c;改后缀等于没转换。如果真正提取音轨&#xff0c;就能得到没转换过的原音轨&#xff0c;大小可能才4mb。 这是一个ffmpeg 以及 yt-dlp 图形化软件&#xff0c;这个工具大小3mb&#xff0c;可以一…

yama搜集的超超…全的下载音效的网站,持续更新

yama有时间就会更新搜集的音效下载网站&#xff0c;哼唧~ 1.Find Sounds.com 一个免费网站&#xff0c;用于在网上查找声音效果。它是一个网络搜索引擎。提供强大的功能&#xff0c;简单易用&#xff0c;我们平时找音频资源的时候就可以到这个网站找你需要的资源&#xff0c;…

RTT(RT-Thread)线程间同步(保姆级)

目录 线程间同步 信号量 信号量结构体 信号量的使用和管理 动态创建信号量 实例 静态创建信号量 初始化和脱离信号量 获取信号量 信号量的互斥操作 获取信号量函数 释放信号量 信号量同步实例 互斥量&#xff08;互斥锁&#xff09; 互斥量的使用和管理 动态创…

【网络编程·网络层】IP协议

目录 一、IP协议的概念 二、IP协议的报头 1、四位首部长度 2、16位总长度&#xff08;解包&#xff09; 3、8位协议&#xff08;分用&#xff09; 4、16位首部校验和 5、8位生存时间 6、32位源IP和32位目的IP 7、4位版本/8位服务类型 8、16位标识 9、3位标志 10、1…

无涯教程-Perl - lock函数

描述 此函数将咨询锁放在共享变量或THING中包含的引用对象上,直到该锁超出范围。 lock()是一个"弱关键字":这意味着,如果您在调用该函数之前已通过该名称定义了该函数,则将改为调用该函数。 语法 以下是此函数的简单语法- lock THING返回值 此函数不返回任何值…

Python接口自动化测试之UnitTest详解

基本概念 UnitTest单元测试框架是受到JUnit的启发&#xff0c;与其他语言中的主流单元测试框架有着相似的风格。其支持测试自动化&#xff0c;配置共享和关机代码测试。支持将测试样例聚合到测试集中&#xff0c;并将测试与报告框架独立。 它分为四个部分test fixture、TestC…

武汉大学计算机学院2010情景剧,武汉大学金秋情景剧大赛精彩落幕(组图)

作为金秋艺术节的“重头戏”&#xff0c;留香行板--情景剧大赛决赛于11月5日在信息学部大学生活动中心隆重开演。15个学院先后表演了精心编排的情景剧&#xff0c;最终经过激烈的角逐&#xff0c;新闻与传播学院凭借《方向》成功蝉联&#xff0c;与经济管理学院的《爱的礼赞》一…

快来带您了解中秋节的前世今生

中秋节是中国传统的节日&#xff0c;落在农历八月十五&#xff0c;一般是公历九月或十月上旬。 按中国古代历法的解释&#xff0c;八月是秋季的第二个月&#xff0c;称“仲秋”&#xff0c;八月十五又在仲秋之中&#xff0c;所以叫“中秋”。2022年&#xff0c;中秋节落在9月10…

MySQL数据库 *实验16 变量表达式和函数

只要你有想去的地方&#xff0c;全世界都会为你让路~ 1.定义一个变量x存放以下字符串 刘王张赵李钱朱何孙曾陈吴黄刘邓周毛江胡’&#xff1b; 2.定义一个变量len1存放x字符串的长度&#xff1b; 3.定义一个变量m1存放以下字符串 ‘依秋香巧花紫萱莉玉芳菊碧丽念雅红燕艳莲…

女孩砖厂打工照顾弟妹被网友拍下(图)

8日下午&#xff0c;网友“土家风情郎”在论坛贴出一组图片&#xff0c;反映贵州一名叫张倩倩的小女孩在砖厂打暑期工&#xff0c;还要照顾三个弟妹的情况&#xff0c;该帖发出后&#xff0c;许多网友赞赏女孩懂事。 年纪小小的她&#xff0c;有着同龄人少有的沉着淡定。 生活不…

opencv基础59-霍夫变换原理讲解及示例-cv2.HoughLines()->(直线,圆形检测)

霍夫变换是一种在图像中寻找直线、圆形以及其他简单形状的方法。霍夫变换采用类似于投票的方式来获取当前图像内的形状集合&#xff0c;该变换由 Paul Hough&#xff08;霍夫&#xff09;于 1962 年首次提出。 最初的霍夫变换只能用于检测直线&#xff0c;经过发展后&#xff0…

直播预告|EasyV全新倾斜摄影组件上线!提升大规模、高精度实景建模效率

倾斜摄影&#xff0c;也被称为斜摄影或倾斜摄影测量&#xff0c;是一种高精度、高分辨率的遥感技术&#xff0c;用于获取地表地貌、建筑物、自然环境等目标的三维信息。在城市级数字孪生可视化建设过程中&#xff0c;通常会使用倾斜摄影技术以增强地理信息分析和虚拟建模的能力…

线性回归学习总结

一 、引文 1 回归分析 回归是统计学上用来分析数据的方法&#xff0c;以了解两个或多个变量之前的关系。通常是建立被解释变量Y和解释变量X之间关系的模型。回归分析的最早形式是最小二乘法。 勒让德和高斯都将该方法应用于从天文观测中确定关于太阳的物体的轨道&#xff08;…

Java-低代码平台使用H2内存数据库

一、引言 作者目前在做的平台使用到了H2&#xff0c;这里介绍下使用场景、使用方式&#xff0c;出于以下两个原因会使用H2: 1、平台化的项目一般是用户使用脚本或者sql进行通用的执行&#xff0c;这样可以实现低代码平台&#xff0c;不需要管理类之间的引入、依赖、编译&#x…

制造业企业数字化转型之设备数据采集

导 读 ( 文/ 1894 ) 随着信息技术的快速发展和制造业的转型升级&#xff0c;企业数字化转型已成为保持竞争力和实现可持续发展的关键。在数字化转型过程中&#xff0c;设备数据采集作为重要的一环&#xff0c;发挥着关键的作用。设备数据采集通过收集、分析和利用设备所产生的数…

怎样找回e盘删除的文件夹?分享三种恢复方法

我们都知道&#xff0c;电脑可以划分多个区域来存储数据&#xff0c;例如C盘、D盘、E盘、F盘等&#xff0c;而不论是存储在哪个磁盘&#xff0c;都容易出现文件丢失的问题&#xff0c;那么电脑e盘文件夹删除了怎么恢复呢&#xff1f;下面小编分享一些方法&#xff0c;一起来看下…