Java-调整WAV文件的播放速度

Java-调整WAV文件的播放速度,java,audio,javasound,pcm,audio-processing,Java,Audio,Javasound,Pcm,Audio Processing,我可能很笨,但我似乎找不到解决问题的办法 (注意:我可以找到很多人报告这个问题,似乎这是由于较新的Java(可能是1.5?)造成的。也许不再支持采样率?我找不到任何解决方案) 我正在尝试调整采样率以加快/减慢歌曲。我可以成功地播放.wav文件而不会出现问题,因此我研究了用于调整音量的FloatControl: public void adjustVolume(String audioType, float gain) { FloatControl gainControl = nu

我可能很笨,但我似乎找不到解决问题的办法

注意:我可以找到很多人报告这个问题,似乎这是由于较新的Java(可能是1.5?)造成的。也许不再支持采样率?我找不到任何解决方案)

我正在尝试调整采样率以加快/减慢歌曲。我可以成功地播放.wav文件而不会出现问题,因此我研究了用于调整音量的FloatControl:

public void adjustVolume(String audioType, float gain) {
        FloatControl gainControl = null;

        gainControl = (FloatControl) clipSFX.getControl(FloatControl.Type.MASTER_GAIN);
                if(gain > MAX_VOLUME)
                    gain = MAX_VOLUME;
                if(gain < MIN_VOLUME)
                    gain = MIN_VOLUME;

            //set volume
            gainControl.setValue(gain);
    }

我在网上找到的所有东西似乎都与从麦克风或外线获取输入有关,而且似乎无法转化为使用音频文件,所以我不确定我缺少了什么。任何帮助都将不胜感激!谢谢

这里我们有一种改变速度的方法-通过加倍采样率。基本步骤如下:

  • 打开文件的音频流
  • 获取格式
  • 在更改采样率的情况下创建新格式
  • 打开具有该格式的数据行
  • 读取文件/音频流并在线播放
这里的概念是SourceDataLine、AudioFormat和AudioInputStream。如果你看javax.sound教程,你会发现它们,甚至是类的页面。现在,您可以创建自己的方法(如adjust(factor)),该方法只获取新格式,其他方法保持不变

  public void play() {
    try {
      File fileIn = new File(" ....);
      AudioInputStream audioInputStream=AudioSystem.getAudioInputStream(fileIn);
      AudioFormat formatIn=audioInputStream.getFormat();
      AudioFormat format=new AudioFormat(formatIn.getSampleRate()*2, formatIn.getSampleSizeInBits(), formatIn.getChannels(), true, formatIn.isBigEndian());
          System.out.println(formatIn.toString());
          System.out.println(format.toString());
      byte[] data=new byte[1024];
      DataLine.Info dinfo=new DataLine.Info(SourceDataLine.class, format);
      SourceDataLine line=(SourceDataLine)AudioSystem.getLine(dinfo);
      if(line!=null) {
        line.open(format);
        line.start();
        while(true) {
          int k=audioInputStream.read(data, 0, data.length);
          if(k<0) break;
          line.write(data, 0, k);
        }
        line.stop();
        line.close();
      }
    }
    catch(Exception ex) { ex.printStackTrace(); }
  }
public void play(){
试一试{
File fileIn=新文件(“..”);
AudioInputStream AudioInputStream=AudioSystem.getAudioInputStream(fileIn);
AudioFormat formatIn=audioInputStream.getFormat();
AudioFormat format=新的AudioFormat(formatIn.getSampleRate()*2,formatIn.getSampleSizeInBits(),formatIn.GetChannel(),true,formatIn.isBigEndian());
System.out.println(formatIn.toString());
System.out.println(format.toString());
字节[]数据=新字节[1024];
DataLine.Info dinfo=新的DataLine.Info(SourceDataLine.class,格式);
SourceDataLine=(SourceDataLine)AudioSystem.getLine(dinfo);
如果(行!=null){
行。打开(格式);
line.start();
while(true){
int k=audioInputStream.read(数据,0,数据.长度);

如果(k这里我们有一种改变速度的方法-通过加倍采样率。基本步骤如下:

  • 打开文件的音频流
  • 获取格式
  • 在更改采样率的情况下创建新格式
  • 打开具有该格式的数据行
  • 读取文件/音频流并在线播放
这里的概念是SourceDataLine、AudioFormat和AudioInputStream。如果您查看javax.sound教程,您会发现它们,甚至可以找到类的页面。您现在可以创建自己的方法(如adjust(factor)),该方法只获取新格式,其他方法保持不变

  public void play() {
    try {
      File fileIn = new File(" ....);
      AudioInputStream audioInputStream=AudioSystem.getAudioInputStream(fileIn);
      AudioFormat formatIn=audioInputStream.getFormat();
      AudioFormat format=new AudioFormat(formatIn.getSampleRate()*2, formatIn.getSampleSizeInBits(), formatIn.getChannels(), true, formatIn.isBigEndian());
          System.out.println(formatIn.toString());
          System.out.println(format.toString());
      byte[] data=new byte[1024];
      DataLine.Info dinfo=new DataLine.Info(SourceDataLine.class, format);
      SourceDataLine line=(SourceDataLine)AudioSystem.getLine(dinfo);
      if(line!=null) {
        line.open(format);
        line.start();
        while(true) {
          int k=audioInputStream.read(data, 0, data.length);
          if(k<0) break;
          line.write(data, 0, k);
        }
        line.stop();
        line.close();
      }
    }
    catch(Exception ex) { ex.printStackTrace(); }
  }
public void play(){
试一试{
File fileIn=新文件(“..”);
AudioInputStream AudioInputStream=AudioSystem.getAudioInputStream(fileIn);
AudioFormat formatIn=audioInputStream.getFormat();
AudioFormat format=新的AudioFormat(formatIn.getSampleRate()*2,formatIn.getSampleSizeInBits(),formatIn.GetChannel(),true,formatIn.isBigEndian());
System.out.println(formatIn.toString());
System.out.println(format.toString());
字节[]数据=新字节[1024];
DataLine.Info dinfo=新的DataLine.Info(SourceDataLine.class,格式);
SourceDataLine=(SourceDataLine)AudioSystem.getLine(dinfo);
如果(行!=null){
行。打开(格式);
line.start();
while(true){
int k=audioInputStream.read(数据,0,数据.长度);

如果(k),也可以在音频数据中前进时使用线性插值来改变速度

音频值以数组形式排列,光标通常从一个值移动到另一个值。但您可以设置进度为任意数量,例如1.5帧,并在需要时创建加权值

假设数据如下所示:

  • 0.5
  • 0.8
  • 0.2
  • -0.1
  • -0.5
  • -0.7
  • 您的播放数据(速率为1.5)将为

  • 0.5
  • (0.8+0.2)/2
  • -0.1
  • (-0.5+-0.7)/2
  • 我知道在堆栈溢出之前,有一些帖子更全面地解释了这个算法。请原谅我没有跟踪他们

    我使用此方法允许在以下开源库中实时更改.wav播放速度:。请随意查看代码并利用其中的思想

    以下是从位于两个音频帧之间的点创建立体声音频值对的方法(数据是有符号浮动的,范围从-1到1)。它来自
    AudioCue.java
    中的内部类
    AudioCue播放器
    。可能不是最容易读取的。正在读取的声音数据位于数组
    cue
    中,
    idx
    是当前的“播放头”正在通过此数组的位置。“intIndex”是音频帧,“flatIndex”是帧在数组中的实际位置。我使用帧跟踪播放头的位置并计算插值权重,然后使用flatIndex从数组中获取相应的值

    private float[] readFractionalFrame(float[] audioVals, float idx)
    {
        final int intIndex = (int) idx;
        final int flatIndex = intIndex * 2;
    
        audioVals[0] = cue[flatIndex + 2] * (idx - intIndex) 
                + cue[flatIndex] * ((intIndex + 1) - idx);
    
        audioVals[1] = cue[flatIndex + 3] * (idx - intIndex) 
                + cue[flatIndex + 1] * ((intIndex + 1) - idx);
    
        return audioVals;
    }
    

    如果有问题,我很乐意澄清。

    在处理音频数据时,也可以使用线性插值来改变速度

    音频值以数组形式排列,光标通常从一个值移动到另一个值。但您可以设置进度为任意数量,例如1.5帧,并在需要时创建加权值

    假设数据如下所示:

  • 0.5
  • 0.8
  • 0.2
  • -0.1
  • -0.5
  • -0.7
  • 您的播放数据(速率为1.5)将为

  • 0.5
  • (0.8+0.2)/2
  • -0.1
  • (-0.5+-0.7)/2
  • 我知道有一些帖子更全面地解释了这一点