java - 使用下面的java代码修改文件中特定位置的音频文件的音调

标签 java audio time javasound pitch

我想根据不同时刻的用户输入动态修改音频剪辑的音调,假设用户在 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);

现在,如何使用编辑 1 中的代码更改编辑 2 中设置的持续时间(即 10 毫秒至 50 毫秒)的音高

如果我可以用除 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 不会公开 Clip 中的数据进行编辑。

我从未尝试过通过扰乱采样率来改变音调。也许这是一个好方法。 Java 教程中有一部分介绍了 wav 文件格式的更改: Using Files and Format Converters 。看起来这将是很好的背景信息,甚至可能涵盖您正在尝试的解决方案。

这就是我所做的,将其称为 VarispeedWavPlayer。

(1) 有一个 volatile 实例浮点变量,它是速度因子(1 是相同速度,1.1 是 110%,0.5 是半速等。

(2) 有一个浮子,它将成为运行的“磁带头”

(3) 从普通代码开始,从 AudioInputStream 读取数据并输出到 SourceDataLine(上述 Java 教程链接中的“读取声音文件”中的好示例。

(4)在有评论的区域

// Here, do something useful with the audio data that's 
// now in the audioBytes array...

(a) 将传入字节转换为 PCM 数据。

如何执行此操作的示例,使用 16 位编码、立体声、little-endian(“CD 质量”)。这使用 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) 获取当前的“速度因子”并编写一个迭代 PCM 帧值的循环(请记住,对于立体声,该轨道的“下一个”帧是 +2):

tapehead += speedfactor;

(c) 这通常会出现小数值。使用线性插值计算该中间点的值。例如,如果您降落在磁带头 = 10.25,第 10 帧为 0.5,第 11 帧为 0.6,则您将返回 0.525。

(d) 将插值转换回字节(与步骤 4a 相反)

(e) 累积字节并通过 SourceDataLine 将它们发送出去。

我遗漏了一些管理输入和输出字节缓冲区不会一对一匹配这一事实的细节。但如果你掌握了基本概念,那么我想你就能解决这个问题。

请注意,这只会在每个输入缓冲区查询“speedFactor”变量时更新一次速度。所以你不希望输入缓冲区太大。

关于java - 使用下面的java代码修改文件中特定位置的音频文件的音调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29115389/

相关文章:

ios - 使用 Audio Session 录制时如何减少录音噪音?

c# - 无法播放禁用的音频源(Unity 2d)

c - 试图获取操作时间和接收时间 0 秒

java - 忽略 Spring boot 中特定端点的上下文路径

java - 为实现相同接口(interface)的两个子类定义泛型方法

android - 将JetCreator用于Android应用

java - 避免 double -> 日期转换时的舍入错误

java - StringIndexOutOfBoundsException 字符串索引超出范围错误

java - Matlab Builder JA - 将 Matlab 编译成 Java jar - 免费版本?

mysql - Rails订单每6小时查询一次