编写java变声器需要做的前期准备

安装 ffmgeg 下载地址 Releases · BtbN/FFmpeg-Builds · GitHub

win系统下载 ffmpeg-N-103272-g7bba0dd638-win64-gpl.zip

配置环境变量到 bin目录

新建maven程序加入两个引用

<!-- https://mvnrepository.com/artifact/com.github.st-h/TarsosDSP --><dependency><groupId>com.github.st-h</groupId><artifactId>TarsosDSP</artifactId><version>2.4.1</version></dependency><dependency><groupId>ws.schild</groupId><artifactId>jave-core</artifactId><version>2.4.6</version></dependency>

新建两个基础类

AudioOutputToByteArray

import be.tarsos.dsp.AudioEvent;
import be.tarsos.dsp.AudioProcessor;import java.io.ByteArrayOutputStream;public class AudioOutputToByteArray implements AudioProcessor {private boolean isDone = false;private byte[] out = null;private ByteArrayOutputStream bos;public AudioOutputToByteArray() {bos = new ByteArrayOutputStream();}public ByteArrayOutputStream getBos() {return bos;}public byte[] getData() {while (!isDone && out == null) {try {Thread.sleep(10);} catch (InterruptedException ignored) {}}return out;}@Overridepublic boolean process(AudioEvent audioEvent) {bos.write(audioEvent.getByteBuffer(),0,audioEvent.getByteBuffer().length);return true;}@Overridepublic void processingFinished() {out = bos.toByteArray().clone();bos = null;isDone = true;}
}

WaveHeader

import java.io.ByteArrayOutputStream;
import java.io.IOException;public class WaveHeader {public final char fileID[] = {'R', 'I', 'F', 'F'};public int fileLength;public char wavTag[] = {'W', 'A', 'V', 'E'};;public char FmtHdrID[] = {'f', 'm', 't', ' '};public int FmtHdrLeth;public short FormatTag;public short Channels;public int SamplesPerSec;public int AvgBytesPerSec;public short BlockAlign;public short BitsPerSample;public char DataHdrID[] = {'d','a','t','a'};public int DataHdrLeth;public byte[] getHeader() throws IOException {ByteArrayOutputStream bos = new ByteArrayOutputStream();WriteChar(bos, fileID);WriteInt(bos, fileLength);WriteChar(bos, wavTag);WriteChar(bos, FmtHdrID);WriteInt(bos,FmtHdrLeth);WriteShort(bos,FormatTag);WriteShort(bos,Channels);WriteInt(bos,SamplesPerSec);WriteInt(bos,AvgBytesPerSec);WriteShort(bos,BlockAlign);WriteShort(bos,BitsPerSample);WriteChar(bos,DataHdrID);WriteInt(bos,DataHdrLeth);bos.flush();byte[] r = bos.toByteArray();bos.close();return r;}private void WriteShort(ByteArrayOutputStream bos, int s) throws IOException {byte[] mybyte = new byte[2];mybyte[1] =(byte)( (s << 16) >> 24 );mybyte[0] =(byte)( (s << 24) >> 24 );bos.write(mybyte);}private void WriteInt(ByteArrayOutputStream bos, int n) throws IOException {byte[] buf = new byte[4];buf[3] =(byte)( n >> 24 );buf[2] =(byte)( (n << 8) >> 24 );buf[1] =(byte)( (n << 16) >> 24 );buf[0] =(byte)( (n << 24) >> 24 );bos.write(buf);}private void WriteChar(ByteArrayOutputStream bos, char[] id) {for (int i=0; i<id.length; i++) {char c = id[i];bos.write(c);}}
}

现在新建执行类和方法,先在d盘放一个1.mp3的文件。以下代码就是把1.mp3转换成变声后的2.mp3

byte[] pcmBytes = speechPitchShiftMp3("d://1.mp3", 0.73, 0.73); 后面的0.73就是变声参数。最后会给出各种变声参数

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;import javax.sound.sampled.UnsupportedAudioFileException;import be.tarsos.dsp.AudioDispatcher;
import be.tarsos.dsp.WaveformSimilarityBasedOverlapAdd;
import be.tarsos.dsp.effects.DelayEffect;
import be.tarsos.dsp.io.jvm.AudioDispatcherFactory;
import be.tarsos.dsp.resample.RateTransposer;public class ceshi {public static void main(String[] args) throws Exception {//这里返回的是pcm格式的音频byte[] pcmBytes = speechPitchShiftMp3("d://1.mp3", 0.73, 0.73);//如果需要转成wav则需要给pcmBytes增加一个头部信息//TarsosDSP中也有输出Wav格式音频的处理器,这里没有使用。byte[] wavHeader = pcm2wav(pcmBytes);OutputStream wavOutPut = new FileOutputStream("d://2.mp3");wavOutPut.write(wavHeader);wavOutPut.write(pcmBytes);wavOutPut.flush();wavOutPut.close();// 对于各种声音类型,以及所需添加的处理器,还有处理器参数代码,将在本文最后给出。//如果需要转mp3格式的,也可以给我留言,我会加上。}/*** 变声* @param speedFactor 变速率 (0,2) 大于1为加快语速,小于1为放慢语速* @param rateFactor 音调变化率 (0,2) 大于1为降低音调(深沉),小于1为提升音调(尖锐)* @return 变声后的MP3数据输入流*/public static byte[] speechPitchShiftMp3(String fileUrl, double rateFactor, double speedFactor) throws IOException, UnsupportedAudioFileException {WaveformSimilarityBasedOverlapAdd w = new WaveformSimilarityBasedOverlapAdd(WaveformSimilarityBasedOverlapAdd.Parameters.speechDefaults(rateFactor, 16000));int inputBufferSize = w.getInputBufferSize();int overlap = w.getOverlap();AudioDispatcher dispatcher = AudioDispatcherFactory.fromPipe(fileUrl,16000,inputBufferSize,overlap);w.setDispatcher(dispatcher);dispatcher.addAudioProcessor(w);/** 采样率转换器。 使用插值更改采样率, 与时间拉伸器一起可用于音高转换。 **/dispatcher.addAudioProcessor(new RateTransposer(speedFactor));AudioOutputToByteArray out = new AudioOutputToByteArray();/** 声音速率转换器 -- 失败 **//*SoundTouchRateTransposer soundTouchRateTransposer = new SoundTouchRateTransposer(2);soundTouchRateTransposer.setDispatcher(dispatcher);dispatcher.addAudioProcessor(soundTouchRateTransposer);*//** 正弦波发生器 -- 无反应 **//*SineGenerator sineGenerator = new SineGenerator(0.5, 0.5);dispatcher.addAudioProcessor(sineGenerator);*//** 音调转换器 -- 无效果 **/
//          dispatcher.addAudioProcessor(new PitchShifter(0.1,16000,448,overlap));/** 制粒机使用颗粒合成回放样本。方法可用于控制播放速率,音高,颗粒大小, -- 无效果 **/
//          dispatcher.addAudioProcessor(new OptimizedGranulator(16000, 448));/** 噪音产生器 -- 有效果 **/
//          dispatcher.addAudioProcessor(new NoiseGenerator(0.2   ));/** 增益处理器  增益为1,则无任何反应。 增益大于1表示音量增加a -- 有反应 **/
//          dispatcher.addAudioProcessor(new GainProcessor(10));/**镶边效果 -- 有反应 **/
//          dispatcher.addAudioProcessor(new FlangerEffect(64, 0.3, 16000, 16000));// 回声效果
//          dispatcher.addAudioProcessor(new FlangerEffect(1 << 4, 0.8, 8000, 2000));// 感冒
//          dispatcher.addAudioProcessor(new ZeroCrossingRateProcessor());//感冒/** 淡出 --声音慢慢变小 **/
//          dispatcher.addAudioProcessor(new FadeOut(5));/** 淡入-- 声音慢慢变大 **/
//          dispatcher.addAudioProcessor(new FadeIn(5));/** 在信号上添加回声效果。echoLength以秒为单位  elay回声的衰减,介于0到1之间的值。1表示无衰减,0表示立即衰减 **/dispatcher.addAudioProcessor(new DelayEffect(0.2, 0.24, 12000) );/** 调幅噪声 -- 将声音转换为噪声**/
//          dispatcher.addAudioProcessor(new AmplitudeModulatedNoise());/** 振幅LFO -- 声音波动 **/
//          dispatcher.addAudioProcessor(new AmplitudeLFO());dispatcher.addAudioProcessor(out);dispatcher.run();//          return new ByteArrayInputStream(out.getData());return out.getData();}public static byte[] pcm2wav(byte[] bytes) throws IOException {//填入参数,比特率等等。这里用的是16位单声道 8000 hzWaveHeader header = new WaveHeader();//长度字段 = 内容的大小(PCMSize) + 头部字段的大小(不包括前面4字节的标识符RIFF以及fileLength本身的4字节)header.fileLength = bytes.length + (44 - 8);header.FmtHdrLeth = 16;header.BitsPerSample = 16;header.Channels = 1;header.FormatTag = 0x0001;header.SamplesPerSec = 16000;header.BlockAlign = (short)(header.Channels * header.BitsPerSample / 8);header.AvgBytesPerSec = header.BlockAlign * header.SamplesPerSec;header.DataHdrLeth = bytes.length;byte[] h = header.getHeader();assert h.length == 44; //WAV标准,头部应该是44字节return h;}}

各种参数类

LUOLI(0.6, 0.6, "萝莉", 1, dispatcher -> {})

byte[] pcmBytes = speechPitchShiftMp3("d://1.mp3", 0.73, 0.73);改为

byte[] pcmBytes = speechPitchShiftMp3("d://1.mp3", 0.6, 0.6);就可以了

import be.tarsos.dsp.AudioDispatcher;
import be.tarsos.dsp.WaveformSimilarityBasedOverlapAdd;
import be.tarsos.dsp.ZeroCrossingRateProcessor;
import be.tarsos.dsp.effects.DelayEffect;
import be.tarsos.dsp.io.jvm.AudioDispatcherFactory;
import be.tarsos.dsp.resample.RateTransposer;import java.io.File;
import java.io.IOException;
import java.util.Optional;
import java.util.function.Consumer;public enum SoundEnum {LUOLI(0.6, 0.6, "萝莉", 1, dispatcher -> {}),DASHU(1.2, 1.2, "大叔", 2, dispatcher -> {}),FEIZAI(1.5, 1.5, "肥仔", 3, dispatcher -> {}),GAOGUAI(1.5, 0.8, "搞怪", 4, dispatcher -> {}),XIONGHAIZI(0.73, 0.73, "熊孩子", 5, dispatcher -> {}),MANTUNTUN(0.35,1, "慢吞吞",6 , dispatcher -> {}),WANGHONGNV(1.2,0.7, "网红女",7 , dispatcher -> {}),/*** dispatcher.addAudioProcessor(new DelayEffect(0.2, 0.24, 12000) );*/KUNSHOU(1.55,1.55, "困兽", 8, dispatcher -> dispatcher.addAudioProcessor(new DelayEffect(0.2, 0.24, 12000))),/*** dispatcher.addAudioProcessor(new DelayEffect(0.2, 0.24, 12000) );*/ZHONGJIXIE(1.50,1.50, "重机械", 9, dispatcher -> dispatcher.addAudioProcessor(new DelayEffect(0.2, 0.24, 12000))),/***          dispatcher.addAudioProcessor(new FlangerEffect(1 << 4, 0.8, 8000, 2000));*         dispatcher.addAudioProcessor(new ZeroCrossingRateProcessor());*/GANMAO(1.05,1.05, "感冒", 10, dispatcher -> {dispatcher.addAudioProcessor(new DelayEffect(0.2, 0.24, 12000));dispatcher.addAudioProcessor(new ZeroCrossingRateProcessor());}),/***          dispatcher.addAudioProcessor(new DelayEffect(0.8, 0.5, 12000) );*         dispatcher.addAudioProcessor(new DelayEffect(0.5, 0.3, 8000) );*/KONGLING(1, 1, "空灵", 11, dispatcher -> {dispatcher.addAudioProcessor(new DelayEffect(0.8, 0.5, 12000) );dispatcher.addAudioProcessor(new DelayEffect(0.5, 0.3, 8000) );});/*** @param speedFactor 变速率 (0,2) 大于1为加快语速,小于1为放慢语速* @param rateFactor 音调变化率 (0,2) 大于1为降低音调(深沉),小于1为提升音调(尖锐)*/SoundEnum(double rateFactor, double speedFactor, String name, int type, Consumer<AudioDispatcher> consumer){this.rateFactor = rateFactor;this.speedFactor = speedFactor;this.name = name;this.type = type;this.consumer = consumer;}private double rateFactor;private double speedFactor;private String name;private int type;private Consumer consumer;public byte[] run(String fileUrl){WaveformSimilarityBasedOverlapAdd w = new WaveformSimilarityBasedOverlapAdd(WaveformSimilarityBasedOverlapAdd.Parameters.speechDefaults(rateFactor, 16000));int inputBufferSize = w.getInputBufferSize();int overlap = w.getOverlap();AudioDispatcher dispatcher = AudioDispatcherFactory.fromPipe(fileUrl,16000,inputBufferSize,overlap);w.setDispatcher(dispatcher);dispatcher.addAudioProcessor(w);/** 采样率转换器。 使用插值更改采样率, 与时间拉伸器一起可用于音高转换。 **/dispatcher.addAudioProcessor(new RateTransposer(speedFactor));AudioOutputToByteArray out = new AudioOutputToByteArray();consumer.accept(dispatcher);dispatcher.addAudioProcessor(out);dispatcher.run();return out.getData();}public static byte[] pcm2wav(byte[] bytes) {try {//填入参数,比特率等等。这里用的是16位单声道 8000 hzWaveHeader header = new WaveHeader();//长度字段 = 内容的大小(PCMSize) + 头部字段的大小(不包括前面4字节的标识符RIFF以及fileLength本身的4字节)header.fileLength = bytes.length + (44 - 8);header.FmtHdrLeth = 16;header.BitsPerSample = 16;header.Channels = 1;header.FormatTag = 0x0001;header.SamplesPerSec = 16000;header.BlockAlign = (short)(header.Channels * header.BitsPerSample / 8);header.AvgBytesPerSec = header.BlockAlign * header.SamplesPerSec;header.DataHdrLeth = bytes.length;byte[] h = header.getHeader();assert h.length == 44; //WAV标准,头部应该是44字节return h;} catch (IOException e) {//log.error("pcm2wav-error", e);}return null;}public static Optional<SoundEnum> getInstance(int type){for (int i = 0; i < SoundEnum.values().length; i++) {if(SoundEnum.values()[i].type == type)return Optional.of(SoundEnum.values()[i]);}return Optional.empty();}
}

java实现变声器--变声萝莉相关推荐

  1. MORPHVOX PRO 变声器 软件 Crack

    MORPHVOX PRO 变声器 变音的全新层次 在网上聊天和游戏中使你变音 它具有超高语音学习技术,背景取消和高音质特点,将变音带向全新层次. 上好的变音质量 聆听MorphVOX Pro上好的变音 ...

  2. eja变送器故障代码al01_EJA变送器故障诊断检修

    展开全部 我是从事自动化仪表的我来告诉你 差压变送器故障诊断 变送器在测量过程中,常常会62616964757a686964616fe59b9ee7ad9431333238663564出现一些故障,故 ...

  3. 罗斯蒙特3051变送器的优势在哪里?

    罗斯蒙特3051变送器变送器在市场装机量非常的高,这说明产品质量是非常的过硬,罗斯蒙特3051变送器有它自身的优势,别的品牌的变送器是不可同类而比的,今天我们就来说说罗斯蒙特3051变送器的优势在哪里 ...

  4. eja智能压力变送器工作原理_告诉你横河EJA变送器原理和故障分析!

    熟悉过程控制行业的人都知道压力变送器的应用广泛.在一条5000t/d的水泥生产线,窑头.窑尾,各级预热器的顶部和底部,各次风管和冷却机各室等,这些地方都必须设置过程变量变送器,目的是为了通过这些变送器 ...

  5. NDK JNI 变声器实现

    Android NDK 导入 C库的开发流程学习:通过使用fmod的C库,实现变声器功能. 导入库文件 1)复制fmod的C库到cpp目录下 2)复制fmod的so库到jniLibs目录下 3)复制f ...

  6. 语音变声器微信小程序源码下载支持多种音效

    如标题所示这就是一款变声器小程序源码 程序支持多种音效生成, 另外支持本地音频文件上传变声 也支持直接录音变声 当然啦,也是支持在线试听的这样可以方便查看每一种效果 好了,不多说了下面来看看小编的测试 ...

  7. 小程序源码:语音变声器微信小程序-多玩法安装简单

    如标题所示这就是一款变声器小程序源码 程序支持多种音效生成,如少女,鬼畜,恐怖,萝莉等等! 另外支持本地音频文件上传变声 也支持直接录音变声 最后支持观看激励视频保存音频文件 当然啦,也是支持在线试听 ...

  8. 语音变声器微信小程序源码_支持多种音效

    简介: 如标题所示这就是一款变声器小程序源码 程序支持多种音效生成,如少女,鬼畜,恐怖,萝莉等等! 另外支持本地音频文件上传变声 也支持直接录音变声 最后支持观看激励视频保存音频文件 当然啦,也是支持 ...

  9. 时代拓灵变声器SDK集成调试过程

    时代拓灵变声器SDK集成调试过程 时代拓灵变声器SDK效果概述 时代拓灵变声器SDK通过"变调不变速"的方法,改变说话人基频的大小,同时保持语速和语义不变,即保持短时频谱包络(共振 ...

  10. 2022最新语音变声器小程序源码+支持激励视频

    正文: 2022最新语音变声器小程序源码+支持激励视频,如标题所示这就是一款变声器小程序源码. 程序支持多种音效生成,如少女音/鬼畜/恐怖/萝莉音效等等,另外支持本地音频文件上传变声,也支持直接录音变 ...

最新文章

  1. 让智能手机和居家电脑互联互通(WM6 GPRS)
  2. 恭贺各位鸡年好运,新年快乐,万事如意!!!
  3. 开源ImageFilter库v0.3:新增22种图片效果
  4. 每天一点Swift(五)控制器的生命周期和SizeClass
  5. Tp5.0 PHPMailer邮件发送
  6. POJ 1088 滑雪 记忆化搜索
  7. android平板电脑维修电路图,《图解windows10平板电脑电路原理和维修》大家可以读读看看...
  8. 通过IDM插件让本就不限速的阿里云盘直接起飞
  9. 宏观经济模型代码来源 :MMB库
  10. java毕业设计——基于java+Java3D的网络三维技术设计与实现(毕业论文+程序源码)——三维技术
  11. uni-app小程序实现图片上传和压缩
  12. pycharm虚拟环境 更换interpreter
  13. 活法 - 第五章 宇宙潮涌 因果之法
  14. 怎样利用python做一个软件,python可以自己做软件吗
  15. 李宏毅老师机器学习第二部分:回归问题
  16. 基于JAVA的KTV点歌系统,管理系统。
  17. QGC源码分析——航向规划中航点编辑流程(QGroundControl)
  18. 420个生活小窍门,很有用的哦!
  19. Linux之网络设置
  20. 剑灵力士卡刀ahk_技术宅分享 剑灵召唤一键卡刀代码使用教程

热门文章

  1. 常用开发板接口执行器
  2. Unity 之 ShaderGraph 模拟“吃鸡”海面效果入门级教程
  3. JavaScript实现简单星星闪烁特效
  4. php判断移动端和pc端访问_PHP函数判断移动端和PC端
  5. vuex中subscribe的使用
  6. 全球运输工业的升级会带来什么
  7. 以自动化为“遮羞布”,亚马逊掩盖了惊人的工伤记录
  8. (真实经验)我干了5年的JAVA面试官,发现很多求职者都忽略这七大方面的问题!
  9. postgresql 事务隔离级别与锁
  10. 艾永亮:亏损7年到年销100亿,百果园如何在小水果里做出大生意?