当前位置: 首页 > news >正文

Exoplayer(MediaX)实现音频变调和变速播放

在K歌或录音类应用中变调是个常见需求,比如需要播出萝莉音/大叔音等。变速播放在影视播放类应用中普遍存在,在传统播放器Mediaplayer中这两个功能都比较难以实现,特别在低版本SDK中,而Exoplayer作为google官方推出的Mediaplayer替代者就可以轻松实现。在前两篇文章中向大家介绍了Exoplayer拓展FFmpeg实现音频软解码和切换原伴唱功能,我们继续在此基础上实现变调和变速播放。

最新版本Exoplayer扩展FFmpeg音频软解码保姆级教程

最新版本Exoplayer(MediaX)实现K歌原伴唱包括单音轨和双音轨 

一·变调

首先我们回忆一下初中物理学习的声音三大特性:音调-音色-响度

1. 音调

  • 定义:音调是指声音的高低,它是由发声体振动的频率决定的。

  • 原理:振动频率越高,音调越高;振动频率越低,音调越低。例如,女高音的音调通常比男低音高,因为女高音的声带振动频率更高。

  • 单位:频率的单位是赫兹(Hz),表示每秒振动的次数。

2. 响度

  • 定义:响度是指声音的强弱或大小,它是由发声体振动的振幅决定的。

  • 原理:振幅越大,声音越响亮;振幅越小,声音越微弱。同时,响度还与距离发声体的远近有关,距离越远,响度越小。

  • 单位:响度的单位是分贝(dB)。例如,安静的图书馆声音约为30分贝,而摇滚音乐会的声音可能达到100分贝以上。

3. 音色

  • 定义:音色是指不同物体发声时,声音的特色和品质。即使音调和响度相同,不同发声体发出的声音仍然可以通过音色进行区分。

  • 原理:音色由发声体的材料、结构和发声方式决定。例如,小提琴和钢琴演奏同一首曲子,音调和响度可能相似,但音色不同,因为它们的发声结构和材料不同。

  • 应用:音色是人们辨别不同乐器和人声的重要依据。例如,我们可以通过音色区分不同人的说话声,或者区分小提琴、大提琴和吉他等乐器的声音。

变调就是要调节音调,加减音量就是要调节响度。Exoplayer本身并不支持调节音调,而是集成了第三方开源音效库Sonic来实现的,源码地址为:https://github.com/waywardgeek/sonic,Exoplayer在此基础上封装了SonicAudioProcessor供开发调用,源码分析参考Android 分场景集成不同音频倍速算法的实现。而 ijkplayer使用的是soundtouch音效库。下面看具体实现:

1.自定义DefaultRenderersFactory,得到AudioSink

    @SuppressLint("UnsafeOptInUsageError")public class PluginRenderFactory extends DefaultRenderersFactory {/*** @param context A {@link Context}.*/public PluginRenderFactory(Context context) {super(context);}@Nullable@Overrideprotected AudioSink buildAudioSink(Context context, boolean enableFloatOutput, boolean enableAudioTrackPlaybackParams) {audioSink = new DefaultAudioSink.Builder().setAudioProcessors(new AudioProcessor[]{new SonicAudioProcessor()}).setEnableAudioTrackPlaybackParams(true).build();return audioSink;// return super.buildAudioSink(context, enableFloatOutput, enableAudioTrackPlaybackParams);}@Overrideprotected void buildAudioRenderers(Context context, int extensionRendererMode, MediaCodecSelector mediaCodecSelector, boolean enableDecoderFallback, AudioSink audioSink, Handler eventHandler, AudioRendererEventListener eventListener, ArrayList<Renderer> out) {//  audioSink.setPlaybackParameters(new PlaybackParameters(1.0f,0.1f));Log.i(TAG, "=audio pitch=" + audioSink.getPlaybackParameters().pitch);ffmpegAudioRenderer = new FfmpegAudioRenderer(eventHandler, eventListener, audioSink);out.add(ffmpegAudioRenderer);super.buildAudioRenderers(context, extensionRendererMode, mediaCodecSelector, enableDecoderFallback, audioSink, eventHandler, eventListener, out);}}

 2.初始化Exoplayer并设置上述自定义的Renderer

 renderersFactory = new PluginRenderFactory(context).setEnableAudioTrackPlaybackParams(true)// .setEnableDecoderFallback(true).setExtensionRendererMode(DefaultRenderersFactory.EXTENSION_RENDERER_MODE_ON);mExoPlayer = new ExoPlayer.Builder(context, renderersFactory).setTrackSelector(trackSelector)// .setHandleAudioBecomingNoisy(true).build();

3. 通过audioSink.setPlaybackParameters(new PlaybackParameters(1.0f, pitch));实现变调不变速,pitch取值【0.1~1.0】越大,音调越高,第一个参数是speed,可设置音频播放速度

    public void setPitch(int tone) {if (!mExoPlayer.isPlaying() || lastTone == tone)return;try {lastTone = tone;// Log.i(TAG,"=setPitch="+tone);//   ffmpegAudioRenderer.setPitchMode(tone + 10);float pitch = 1.0f;if (tone >= -5 && tone <= 5) {pitch = 1.0f + 0.1f * tone;}Log.i(TAG, "=setPitch=" + tone + "=pitch=" + pitch);audioSink.pause();audioSink.setPlaybackParameters(new PlaybackParameters(1.0f, pitch));audioSink.play();} catch (Exception e) {Log.i(TAG, "=setPitch error=" + e.toString());}}

二 设置音量

方式一通过AudioSink设置:

audioSink.setVolume(defaultVol);

方式二·通过Exoplayer实例直接设置

mExoPlayer.setVolume(defaultVol);

三 变速播放

   public void setSpeed(float speed) {PlaybackParameters parameters = new PlaybackParameters(speed);mExoPlayer.setPlaybackParameters(parameters);}

http://www.lryc.cn/news/544129.html

相关文章:

  • 服务器间迁移conda环境
  • docker高级
  • Redis Stream基本使用及应用场景
  • DAY40|动态规划Part08|LeetCode: 121. 买卖股票的最佳时机 、 122.买卖股票的最佳时机II 、 123.买卖股票的最佳时机III
  • 【安装及调试旧版Chrome + 多版本环境测试全攻略】
  • 【Linux】进程间通信——命名管道
  • Qt在Linux嵌入式开发过程中复杂界面滑动时卡顿掉帧问题分析及解决方案
  • AI学习第六天-python的基础使用-趣味图形
  • [VMware]卸载VMware虚拟机和Linux系统ubuntu(自记录版)
  • J-LangChain,用Java实现LangChain编排!轻松加载PDF、切分文档、向量化存储,再到智能问答
  • Cuppa CMS v1.0 任意文件读取(CVE-2022-25401)
  • 可以免费无限次下载PPT的网站
  • STM32中使用PWM对舵机控制
  • 使用插件 `vue2-water-marker`添加全局水印
  • MySQL表约束的种类与应用
  • 【大模型+知识图谱】大模型与知识图谱融合:技术演进、实践应用与未来挑战
  • MS SQL 2008 技术内幕:T-SQL 语言基础
  • MySQL-MATCH ... AGAINST工具
  • 微服务合并
  • Shell脚本基础:用Bash自动化任务
  • 基于W2605C语音识别合成芯片的智能语音交互闹钟方案-AI对话享受智能生活
  • 【Java项目】基于Spring Boot的网上商城购物系统
  • 开放标准(RFC 7519):JSON Web Token (JWT)
  • JBoltAI_SpringBoot如何基于Deepseek官网API区分 R1大模型深度思考和具体回答的内容?
  • YOLOv11-ultralytics-8.3.67部分代码阅读笔记-model.py
  • MySQL 事务笔记
  • react使用拖拽,缩放组件,采用react-rnd解决
  • 【C++基础】什么是C++?
  • 3 算法1-3 火星人
  • 【原创工具】同文件夹PDF文件合并 By怜渠客