使用下面java中的代码修改文件中特定位置的音频文件的音高
To modify the pitch of an audio file at specific positions in the files using the codes in java below
我想根据用户在不同时刻的输入动态修改音频片段的音高,比如说如果用户在 10 秒后输入更改音频的音高,我该如何实现?
我发现这个 link 描述了如何修改音高,但我想在音频剪辑的不同时刻重复这个过程,并且只持续很短的时间。有人可以指导我吗?
一些编辑
编辑 1
我找到了这段代码,正如我之前提到的那样
//source file
final File file1 = new File(“Sample.mp3”);
//destination file
final File file2 = new File(“Sample_cat.wav”);
//audio stream of file1
final AudioInputStream in1 = getAudioInputStream(file1);
//get audio format for targetted sound
final AudioFormat inFormat = getOutFormat(in1.getFormat());
//change the frequency of Audio format
private AudioFormat getOutFormat(AudioFormat inFormat) {
int ch = inFormat.getChannels();
float rate = inFormat.getSampleRate();
return new AudioFormat(PCM_SIGNED, 72000, 16, ch, ch * 2, rate,
inFormat.isBigEndian());
}
//get the target file audio stream using file format
final AudioInputStream in2 = getAudioInputStream(inFormat, in1);
//write the audio file in targeted pitch file
AudioSystem.write(in2, AudioFileFormat.Type.WAVE, file2);
编辑 2
我找到了另一个代码,它设置了音频文件从你想要开始和停止音频的位置。
File audioFile = new File(audioFilePath);
AudioInputStream audioStream = AudioSystem.getAudioInputStream(audioFile);
AudioFormat format = audioStream.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, format);
Clip audioClip = (Clip) AudioSystem.getLine(info);
audioClip.open(audioStream);
audioClip.setLoopPoints(10_000, 500_000);
audioClip.loop(1);
现在,如何使用 Edit 1[=43] 中的代码更改 Edit 2 中设置的持续时间的音高,即 10 ms 到 50 ms =]
如果我可以用 Java 以外的任何其他方式做同样的事情,有人能建议我吗?那么欢迎提出建议...
请帮忙。我是新来的。
**编辑 3 **
可以参考这个 link 的确切问题:
这些是我指的值(以毫秒为单位):
public static void convertMsgToAudio(String msg){
int len = msg.length();
duration = new double[len];
msg = msg.toUpperCase();
System.out.println("Msg 2 : " + msg);
int i;
//char ch;
for(i=0;i<msg.length();i++){
if(msg.charAt(i) == 'A'){
duration[i] = 50000;
}
else if (msg.charAt(i) == 'B'){
duration[i] = 100000;
}
else if (msg.charAt(i) == 'C'){
duration[i] = 150000;
}
else if (msg.charAt(i) == 'D'){
duration[i] = 200000;
}
else if (msg.charAt(i) == 'E'){
duration[i] = 250000;
}
else if (msg.charAt(i) == 'F'){
duration[i] = 300000;
}
else if (msg.charAt(i) == 'G'){
duration[i] = 350000;
}
else if (msg.charAt(i) == 'H'){
duration[i] = 400000;
}
else if (msg.charAt(i) == 'I'){
duration[i] = 450000;
}
else if (msg.charAt(i) == 'J'){
duration[i] = 500000;
}
else if (msg.charAt(i) == 'K'){
duration[i] = 550000;
}
else if (msg.charAt(i) == 'L'){
duration[i] = 600000;
}
else if (msg.charAt(i) == 'M'){
duration[i] = 650000;
}
else if (msg.charAt(i) == 'N'){
duration[i] = 700000;
}
else if (msg.charAt(i) == 'O'){
duration[i] = 750000;
}
else if (msg.charAt(i) == 'P'){
duration[i] = 800000;
}
else if (msg.charAt(i) == 'Q'){
duration[i] = 850000;
}
else if (msg.charAt(i) == 'R'){
duration[i] = 900000;
}
else if (msg.charAt(i) == 'S'){
duration[i] = 950000;
}
else if (msg.charAt(i) == 'T'){
duration[i] = 1000000;
}
else if (msg.charAt(i) == 'U'){
duration[i] = 1100000;
}
else if (msg.charAt(i) == 'V'){
duration[i] = 1200000;
}
else if (msg.charAt(i) == 'W'){
duration[i] = 1300000;
}
else if (msg.charAt(i) == 'X'){
duration[i] = 1400000;
}
else if (msg.charAt(i) == 'Y'){
duration[i] = 1500000;
}
else if (msg.charAt(i) == 'Z'){
duration[i] = 1600000;
}
}
}
据我所知,Java 不会公开剪辑中的数据进行编辑。
我从来没有尝试通过扰乱采样率来改变音高。也许这是一个好方法。 Java 教程中有一节介绍了 wav 文件格式的更改:Using Files and Format Converters。这似乎是很好的背景信息,甚至可能涵盖您正在尝试的解决方案。
这是我所做的,称之为 VarispeedWavPlayer。
(1) 有一个 volatile 实例浮点变量,它是一个速度因子(1 是相同的速度,1.1 是 110%,0.5 是一半的速度,等等
(2) 有一个浮点数 运行 'tapehead'
(3) 从普通代码开始,用于从 AudioInputStream 读取并输出到 SourceDataLine(上面 Java 教程 link 中的 "Reading Sound Files" 中的好例子 link.
(4)在评论区
// Here, do something useful with the audio data that's
// now in the audioBytes array...
(a) 将传入字节转换为 PCM 数据。
使用 16 位编码、立体声、little-endian ("CD quality") 执行此操作的示例。这使用 1024 字节的读取缓冲区大小,它转换为 256 帧(记住,有两个轨道,左和右)的短数据,范围从 -32767 到 32767(或者可能是 32768,我不记得那个细节在那一刻)。
while((bytesRead = audioInputStream.read(rawByteBuffer, 0, 1024)) != -1)
{
for (int i = 0, n = bytesRead / 2); i < n; i ++)
{
pcmBuffer[i] = ( rawByteBuffer[i * 2] & 0xff )
| ( rawByteBuffer[(i * 2) + 1)] << 8 ) ;
}
}
以上内容已编辑清楚,可以使用一些性能优化。
(b) 获取当前 "speedfactor" 并编写循环遍历 PCM 帧值(请记住,对于立体声,该轨道的 "next" 帧为 +2):
tapehead += speedfactor;
(c) 这通常会以分数值着陆。使用线性插值计算该中间点的值。例如,如果您在 tapehead = 10.25 着陆,第 10 帧为 0.5,第 11 帧为 0.6,则您将 return 0.525。
(d) 将内插值转换回字节(与步骤 4a 相反)
(e) 累积字节并通过 SourceDataLine 将它们发送出去。
关于管理输入和输出字节缓冲区不会一对一匹配这一事实,我省略了一些细节。但是如果你掌握了基本概念,那么我想你就能解决这个问题。
注意,这只会在查询 "speedFactor" 变量时更新速度,每个输入缓冲区一次。所以你不希望输入缓冲区太大。
我想根据用户在不同时刻的输入动态修改音频片段的音高,比如说如果用户在 10 秒后输入更改音频的音高,我该如何实现?
我发现这个 link 描述了如何修改音高,但我想在音频剪辑的不同时刻重复这个过程,并且只持续很短的时间。有人可以指导我吗?
一些编辑
编辑 1
我找到了这段代码,正如我之前提到的那样
//source file
final File file1 = new File(“Sample.mp3”);
//destination file
final File file2 = new File(“Sample_cat.wav”);
//audio stream of file1
final AudioInputStream in1 = getAudioInputStream(file1);
//get audio format for targetted sound
final AudioFormat inFormat = getOutFormat(in1.getFormat());
//change the frequency of Audio format
private AudioFormat getOutFormat(AudioFormat inFormat) {
int ch = inFormat.getChannels();
float rate = inFormat.getSampleRate();
return new AudioFormat(PCM_SIGNED, 72000, 16, ch, ch * 2, rate,
inFormat.isBigEndian());
}
//get the target file audio stream using file format
final AudioInputStream in2 = getAudioInputStream(inFormat, in1);
//write the audio file in targeted pitch file
AudioSystem.write(in2, AudioFileFormat.Type.WAVE, file2);
编辑 2 我找到了另一个代码,它设置了音频文件从你想要开始和停止音频的位置。
File audioFile = new File(audioFilePath);
AudioInputStream audioStream = AudioSystem.getAudioInputStream(audioFile);
AudioFormat format = audioStream.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, format);
Clip audioClip = (Clip) AudioSystem.getLine(info);
audioClip.open(audioStream);
audioClip.setLoopPoints(10_000, 500_000);
audioClip.loop(1);
现在,如何使用 Edit 1[=43] 中的代码更改 Edit 2 中设置的持续时间的音高,即 10 ms 到 50 ms =]
如果我可以用 Java 以外的任何其他方式做同样的事情,有人能建议我吗?那么欢迎提出建议... 请帮忙。我是新来的。
**编辑 3 **
可以参考这个 link 的确切问题:
这些是我指的值(以毫秒为单位):
public static void convertMsgToAudio(String msg){
int len = msg.length();
duration = new double[len];
msg = msg.toUpperCase();
System.out.println("Msg 2 : " + msg);
int i;
//char ch;
for(i=0;i<msg.length();i++){
if(msg.charAt(i) == 'A'){
duration[i] = 50000;
}
else if (msg.charAt(i) == 'B'){
duration[i] = 100000;
}
else if (msg.charAt(i) == 'C'){
duration[i] = 150000;
}
else if (msg.charAt(i) == 'D'){
duration[i] = 200000;
}
else if (msg.charAt(i) == 'E'){
duration[i] = 250000;
}
else if (msg.charAt(i) == 'F'){
duration[i] = 300000;
}
else if (msg.charAt(i) == 'G'){
duration[i] = 350000;
}
else if (msg.charAt(i) == 'H'){
duration[i] = 400000;
}
else if (msg.charAt(i) == 'I'){
duration[i] = 450000;
}
else if (msg.charAt(i) == 'J'){
duration[i] = 500000;
}
else if (msg.charAt(i) == 'K'){
duration[i] = 550000;
}
else if (msg.charAt(i) == 'L'){
duration[i] = 600000;
}
else if (msg.charAt(i) == 'M'){
duration[i] = 650000;
}
else if (msg.charAt(i) == 'N'){
duration[i] = 700000;
}
else if (msg.charAt(i) == 'O'){
duration[i] = 750000;
}
else if (msg.charAt(i) == 'P'){
duration[i] = 800000;
}
else if (msg.charAt(i) == 'Q'){
duration[i] = 850000;
}
else if (msg.charAt(i) == 'R'){
duration[i] = 900000;
}
else if (msg.charAt(i) == 'S'){
duration[i] = 950000;
}
else if (msg.charAt(i) == 'T'){
duration[i] = 1000000;
}
else if (msg.charAt(i) == 'U'){
duration[i] = 1100000;
}
else if (msg.charAt(i) == 'V'){
duration[i] = 1200000;
}
else if (msg.charAt(i) == 'W'){
duration[i] = 1300000;
}
else if (msg.charAt(i) == 'X'){
duration[i] = 1400000;
}
else if (msg.charAt(i) == 'Y'){
duration[i] = 1500000;
}
else if (msg.charAt(i) == 'Z'){
duration[i] = 1600000;
}
}
}
Java 不会公开剪辑中的数据进行编辑。
我从来没有尝试通过扰乱采样率来改变音高。也许这是一个好方法。 Java 教程中有一节介绍了 wav 文件格式的更改:Using Files and Format Converters。这似乎是很好的背景信息,甚至可能涵盖您正在尝试的解决方案。
这是我所做的,称之为 VarispeedWavPlayer。
(1) 有一个 volatile 实例浮点变量,它是一个速度因子(1 是相同的速度,1.1 是 110%,0.5 是一半的速度,等等
(2) 有一个浮点数 运行 'tapehead'
(3) 从普通代码开始,用于从 AudioInputStream 读取并输出到 SourceDataLine(上面 Java 教程 link 中的 "Reading Sound Files" 中的好例子 link.
(4)在评论区
// Here, do something useful with the audio data that's
// now in the audioBytes array...
(a) 将传入字节转换为 PCM 数据。
使用 16 位编码、立体声、little-endian ("CD quality") 执行此操作的示例。这使用 1024 字节的读取缓冲区大小,它转换为 256 帧(记住,有两个轨道,左和右)的短数据,范围从 -32767 到 32767(或者可能是 32768,我不记得那个细节在那一刻)。
while((bytesRead = audioInputStream.read(rawByteBuffer, 0, 1024)) != -1)
{
for (int i = 0, n = bytesRead / 2); i < n; i ++)
{
pcmBuffer[i] = ( rawByteBuffer[i * 2] & 0xff )
| ( rawByteBuffer[(i * 2) + 1)] << 8 ) ;
}
}
以上内容已编辑清楚,可以使用一些性能优化。
(b) 获取当前 "speedfactor" 并编写循环遍历 PCM 帧值(请记住,对于立体声,该轨道的 "next" 帧为 +2):
tapehead += speedfactor;
(c) 这通常会以分数值着陆。使用线性插值计算该中间点的值。例如,如果您在 tapehead = 10.25 着陆,第 10 帧为 0.5,第 11 帧为 0.6,则您将 return 0.525。
(d) 将内插值转换回字节(与步骤 4a 相反)
(e) 累积字节并通过 SourceDataLine 将它们发送出去。
关于管理输入和输出字节缓冲区不会一对一匹配这一事实,我省略了一些细节。但是如果你掌握了基本概念,那么我想你就能解决这个问题。
注意,这只会在查询 "speedFactor" 变量时更新速度,每个输入缓冲区一次。所以你不希望输入缓冲区太大。