java 使用 jtransforms 傅里叶库通过时域转频域实现wav 音频的加速与变慢效果

引入 maven 依赖:
 <dependency><groupId>net.sourceforge.jtransforms</groupId><artifactId>jtransforms</artifactId><version>2.4.0</version></dependency>
FourierTransformTest.java:
import edu.emory.mathcs.jtransforms.fft.DoubleFFT_1D;import javax.sound.sampled.UnsupportedAudioFileException;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;public class FourierTransformTest {public static void main(String[] args) throws UnsupportedAudioFileException, IOException {fastTest();// slowTest();}public static void  fastTest() throws UnsupportedAudioFileException, IOException {double[] audio_src = AudioUtils.wavToDoubleArray( new File("C:\\E\\素材\\音频\\wav\\audio.wav") );// 将 audio_src 进行 时域转频域new DoubleFFT_1D(audio_src.length).realForward(audio_src);// 截取转换成频域以后得 audio_src 的前半部分 作为 audio_target// 这里拷贝频域模式下的 audio_src 的前半部分,因为是频域模式,所以前半部分和后半部分其实都包含 "完整" 的时域信息( 只是失真严重 ),如果是时域模式下直接砍一半,肯定会丢失一半的时域信息( 但是未丢失的时域信息的音质没有任何丢失 )// 所以频域下的double[]砍一半其实是音质砍一半( 即频率信息丢失一半 )// 这里 除以2实现了2x加速效果double[] audio_target = Arrays.copyOfRange(audio_src, 0, audio_src.length / 2);// 将 audio_target 进行频域转时域new DoubleFFT_1D( audio_target.length ).realInverse( audio_target, true );System.out.println("转换完毕");// 将audio_target 时域 double[] 转换成 wav 文件AudioUtils.doubleArrayToWAV( audio_target,new File( "C:\\E\\素材\\音频\\wav\\audio_target.wav" ) );System.out.println("生成完毕");}public static void slowTest() throws UnsupportedAudioFileException, IOException {double[] audio_src = AudioUtils.wavToDoubleArray( new File("C:\\E\\素材\\音频\\wav\\audio.wav") );// 将 audio_src 进行 时域转频域new DoubleFFT_1D(audio_src.length).realForward(audio_src);// 实现了 0.5X 变速效果double[] audio_zero = buildZeroDoubleValueArray( audio_src.length );// 将转换成频域以后的 audio_src 和一个等长度的 全是0的doublep[]合并( 可以把这个 audio_zero看做一个频域格式的 double[],只是各个频率下的振幅全是0)double[] audio_target = combineArray( audio_src,audio_zero );// 将 audio_target 频域转时域new DoubleFFT_1D( audio_target.length ).realInverse( audio_target, true );System.out.println("转换完毕");// 将时域格式下的 audio_target 转成 wav 文件AudioUtils.doubleArrayToWAV( audio_target,new File( "C:\\E\\素材\\音频\\wav\\audio_target.wav" ) );System.out.println("生成完毕");}private static double[] buildZeroDoubleValueArray(int length) {double[] doubleArray = new double[length];for (int i = 0; i < length; i++) {doubleArray[i]=0d;}return doubleArray;}private static double[] combineArray(double[]... arrays) {int arrayCount = arrays.length;int totalLength = 0;for( int i=0;i<arrayCount;i++ ){totalLength += arrays[ i ].length;}double[] array_combine = new double[ totalLength ];int index = 0;for( int arrayNum=0;arrayNum<arrayCount;arrayNum++ ){double[] array = arrays[arrayNum];for (double v:array){array_combine[index] = v;index++;}}return array_combine;}
}

用到的工具类 AudioUtils.java:

import javax.sound.sampled.*;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;public class AudioUtils {public static void main(String[] args) throws UnsupportedAudioFileException, IOException {File file = new File("C:\\E\\素材\\音频\\wav\\一生所爱.wav");double[] doubleArray = wavToDoubleArray(file);System.out.println( doubleArray.length );int partLength = doubleArray.length / 10;doubleArrayToWAV(  Arrays.copyOfRange(doubleArray, 0, partLength),new File( "C:\\E\\素材\\音频\\wav\\一生所爱_part1.wav" ) );doubleArrayToWAV(  Arrays.copyOfRange(doubleArray, partLength, partLength * 2),new File( "C:\\E\\素材\\音频\\wav\\一生所爱_part2.wav" ) );doubleArrayToWAV(  Arrays.copyOfRange(doubleArray, partLength * 2, partLength * 3),new File( "C:\\E\\素材\\音频\\wav\\一生所爱_part3.wav" ) );doubleArrayToWAV(  Arrays.copyOfRange(doubleArray, partLength * 3, partLength * 4),new File( "C:\\E\\素材\\音频\\wav\\一生所爱_part4.wav" ) );doubleArrayToWAV(  Arrays.copyOfRange(doubleArray, partLength * 4, partLength * 5),new File( "C:\\E\\素材\\音频\\wav\\一生所爱_part5.wav" ) );doubleArrayToWAV(  Arrays.copyOfRange(doubleArray, partLength * 5, partLength * 6),new File( "C:\\E\\素材\\音频\\wav\\一生所爱_part6.wav" ) );}public static double[] wavToDoubleArray(File mp3File) throws UnsupportedAudioFileException, IOException {AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(mp3File);AudioFormat audioFormat = audioInputStream.getFormat();int numChannels = audioFormat.getChannels();int sampleSizeInBytes = audioFormat.getSampleSizeInBits() / 8;int frameSize = numChannels * sampleSizeInBytes;int bufferSize = (int) (audioInputStream.getFrameLength() * frameSize);byte[] audioBytes = new byte[bufferSize];audioInputStream.read(audioBytes);double[] audioData = new double[audioBytes.length / 2];for (int i = 0, j = 0; i < audioBytes.length; i += 2, j++) {int sample = (audioBytes[i + 1] << 8) | (audioBytes[i] & 0xFF);audioData[j] = sample / 32768.0;}return audioData;}public static void doubleArrayToWAV(double[] audioData, File outputFile) throws IOException, UnsupportedAudioFileException {AudioFormat audioFormat = new AudioFormat(44100, 16, 2, true, false);byte[] audioBytes = new byte[audioData.length * 2];for (int i = 0, j = 0; i < audioData.length; i++, j += 2) {short sample = (short) (audioData[i] * 32767);audioBytes[j] = (byte) (sample & 0xFF);audioBytes[j + 1] = (byte) ((sample >> 8) & 0xFF);}AudioInputStream audioInputStream = new AudioInputStream(new ByteArrayInputStream(audioBytes), audioFormat, audioData.length);AudioSystem.write(audioInputStream, AudioFileFormat.Type.WAVE, outputFile);}
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一、Vue3基础[常用的循环]

一、循环 1. filter 解释&#xff1a;filter 方法会创建一个新的数组&#xff0c;其中包含满足指定条件的所有元素。这个方法非常适合循环遍历数组并根据特定条件过滤元素的情况。例如&#xff0c;可以使用 filter 方法来找出数组中所有大于特定值的元素&#xff0c;或者找出…

华为bgp之多级RR及团体属性、正则表达式多种应用案例

1、实现总部和分部的oa、财务网段互通 2、分部之间oa也能互通 3、分部之间不能互通财务 主要用到bgp自定义团体属性、一级二级RR配置、bgp正则表达式匹配规则 R1 router id 1.1.1.1 //配全局地址池&#xff0c;又可以给ospf用也可以给bgp用 interface GigabitEthernet0/0/0 …

延迟加载:提升性能的隐形利器

引言 想象一下&#xff0c;你正在玩一款大型电子游戏。如果游戏在启动的时候就加载了所有的关卡、角色和道具&#xff0c;那玩家可能需要等待很长时间才能开始游戏&#xff0c;而且大部分内容可能在游戏的初期都不会被用到。显然&#xff0c;这样的做法既低效又耗时。 而延迟加…

位移贴图还原电影3D角色

在线工具推荐&#xff1a; 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 位移贴图&#xff08;Displacement Map&#xff09;在电影制作中是一…

OpenCV图像处理——C++实现亚像素尺寸标定板边缘轮廓提取

前言 标定模板&#xff08;Calibration Target&#xff09;在机器视觉、图像测量、摄影测量以及三维重建等应用中起着重要的作用。它被用于校正相机的畸变&#xff0c;确定物理尺寸和像素之间的换算关系&#xff0c;并建立相机成像的几何模型。通过使用相机拍摄带有固定间距图…

进程和计划任务-------后续(二)

一、进程管理 1.进程启动---------- 前台启动与后台启动 进程需要手动启动 前台启动&#xff08;运行&#xff09;&#xff1a;通过终端启动&#xff0c;且启动后一直占据终端&#xff08;影响当先终端的操作&#xff09; 后台启动&#xff1a;可通过终端启动&#xff0c;但启…

Unity添加所有场景到BuildSettings

Unity添加所有场景到BuildSettings using UnityEngine; using UnityEditor; using System.Collections.Generic; using System.IO; public class Tools : Editor {[MenuItem("Tools/添加所有场景到BuildSettings")]static void CheckSceneSetting(){List<string&…

java基于ssm的线上选课系统的设计与实现论文

摘 要 在如今社会上&#xff0c;关于信息上面的处理&#xff0c;没有任何一个企业或者个人会忽视&#xff0c;如何让信息急速传递&#xff0c;并且归档储存查询&#xff0c;采用之前的纸张记录模式已经不符合当前使用要求了。所以&#xff0c;对学生选课信息管理的提升&#x…

【AI视野·今日Robot 机器人论文速览 第六十八期】Tue, 2 Jan 2024

AI视野今日CS.Robotics 机器人学论文速览 Tue, 2 Jan 2024 Totally 12 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Robotics Papers Edge Computing based Human-Robot Cognitive Fusion: A Medical Case Study in the Autism Spectrum Disorder Therapy Author…

【华为OD真题 Python】查找一个有向网络的头节点和尾节点

文章目录 题目描述输入输出示例1输入输出示例2输入输出备注实现代码题目描述 给定一个有向图,图中可能包含有环,图使用二维矩阵表示,每一行的第一列表示起始节点,第二列表示终止节点,如[0, 1]表示从0到1的路径。每个节点用正整数表示。求这个数据的首节点与尾节点,题目给…

java基于ssm框架的博客系统的开发论文

目 录 目 录 I 摘 要 III ABSTRACT IV 1 绪论 1 1.1 课题背景 1 1.2 研究现状 1 1.3 研究内容 2 2 系统开发环境 3 2.1 vue技术 3 2.2 JAVA技术 3 2.3 MYSQL数据库 3 2.4 B/S结构 4 2.5 SSM框架技术 4 3 系统分析 5 3.1 可行性分析 5 3.1.1 技术可行性 5 3.1.2 操作可行性 5 3…

Mendix 创客访谈录|太迅的闪电侠如何发动闪电战

本期创客 房杰 上海太迅自动识别技术有限公司 移动开发经理 大家好&#xff0c;我叫房杰&#xff0c;软件工程专业毕业&#xff0c;目前任职于上海太迅自动识别技术有限公司&#xff0c;任职的部门是软件事业部&#xff0c;担任移动开发经理。 上海太迅是一家专注于自动识…

安装Keras用于影像分割

conda create -n tfkeras2024 python3.9.18 activate tfkeras2024 pip install tensorflow-gpu2.9.0 pip install keras pip install scipy pip install ipykernel ipython python -m ipykernel install --name tfkeras2024 删除环境conda remove -n tfkeras2024 --all

谈一谈报考高校异地研究院的利弊

这篇文章是抖音和b站上上传的同名视频的原文稿件&#xff0c;感兴趣的csdn用户可以关注我的抖音和b站账号&#xff08;GeekPower极客力量&#xff09;。同时这篇文章也为视频观众提供方便&#xff0c;可以更加冷静地分析和思考。文章同时在知乎发表。 前年国家出台文件&#x…

Jenkins修改全局maven配置后不生效解决办法、以及任务读取不同的settings.xml文件配置

一、修改Global Tool Configuration的maven配置不生效 说明&#xff1a;搭建好jenkins后&#xff0c;修改了全局的settings.xml&#xff0c;导致读取settings一直是之前配置的。 解决办法一 Jenkins在创建工作任务时&#xff0c;会读取当前配置文件内容&#xff0c;固定在这…

目标检测:深度学习引领视觉智能的未来

目标检测&#xff1a;深度学习引领视觉智能的未来 目标检测是计算机视觉领域中的一项重要任务&#xff0c;旨在从图像或视频中确定和定位特定物体的存在。这一领域的发展在很大程度上得益于深度学习技术的崛起&#xff0c;为机器在理解和处理视觉信息上带来了质的飞跃。本文将…

Scrum的工件

我们采用了Scrum进行开发方面的管理&#xff0c;那么所有的计划和工作都应该是透明的&#xff0c;这给了我们检查这些东西的机会&#xff0c;以便能够即时做出调整来适应即将发生的变化。 那么Scrum为我们设计了一些工件帮助我们检查我们的工作和计划&#xff0c;每个工件都有…

【学习笔记】[AGC060D] Same Descent Set

本来是想做点多项式调节一下&#xff0c;结果发现这玩意太肝了&#xff0c;似乎并没有起到调节作用。 设 f ( S ) f(S) f(S)表示符号为 < < <的下标集合恰好为 S S S的方案数&#xff0c;因为两个序列完全等同&#xff0c;因此答案等于 ∑ S ⊆ { 1 , 2 , . . . , n …

如何在SpringBoot中优雅地重试调用第三方API?

1.引言 在实际的应用中,我们经常需要调用第三方API来获取数据或执行某些操作。然而,由于网络不稳定、第三方服务异常等原因,API调用可能会失败。为了提高系统的稳定性和可靠性,我们通常会考虑实现重试机制。 2.重试机制的必要性 第三方API调用可能面临各种不可预测的问题…

【面试高频算法解析】算法练习5 深度优先搜索

前言 本专栏旨在通过分类学习算法&#xff0c;使您能够牢固掌握不同算法的理论要点。通过策略性地练习精选的经典题目&#xff0c;帮助您深度理解每种算法&#xff0c;避免出现刷了很多算法题&#xff0c;还是一知半解的状态 专栏导航 二分查找回溯&#xff08;Backtracking&…