【问题标题】:Trim beginning and end from a WAV file with the Java sound API使用 Java 声音 API 修剪 WAV 文件的开头和结尾
【发布时间】:2012-03-16 21:30:36
【问题描述】:

我已经做好了基础。但是,输出文件只是一遍又一遍地重复 WAV 标头字节。生成的文件大小合适,但文件中包含垃圾文件。

我正在尝试使用一个扩展 AudioInputStream 的类,以便我可以将它与其他代码无缝使用,从而将它与另一个 AudioInputStream 混合(效果很好)。

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;

public class TrimmerAIS extends AudioInputStream{

private final AudioInputStream stream;
private final long startByte,endByte;
private long t_bytesRead=0;
public TrimmerAIS(AudioFormat audioFormat,AudioInputStream audioInputStream,long startMilli,long endMilli){
    super(new ByteArrayInputStream(new byte[0]),audioFormat,AudioSystem.NOT_SPECIFIED);
    stream=audioInputStream;
    //startByte=(long)((startMilli/1000f)*stream.getFormat().getSampleRate()*stream.getFormat().getSampleSizeInBits()*stream.getFormat().getChannels())/8;
    //endByte=(long)((endMilli/1000f)*stream.getFormat().getSampleRate()*stream.getFormat().getSampleSizeInBits()*stream.getFormat().getChannels())/8;
    startByte=(long)((startMilli/1000)*stream.getFormat().getFrameRate()*stream.getFormat().getFrameSize());
    endByte=(long)((endMilli/1000)*stream.getFormat().getFrameRate()*stream.getFormat().getFrameSize());
}
private byte[] tempBuffer;

@Override
public int available() throws IOException{
    return (int)(endByte-startByte-t_bytesRead);
}
public int read(byte[] abData,int nOffset,int nLength) throws IOException{
    // set up the temporary byte buffer
    if(tempBuffer==null||tempBuffer.length<nLength){
        tempBuffer=new byte[nLength];
    }
    int bytesRead=0;
    if(t_bytesRead<startByte){
        do{//skip to starting byte
            bytesRead=(int)skip(startByte-t_bytesRead);
            t_bytesRead+=bytesRead;
        }while(t_bytesRead<startByte);
    }
    if(t_bytesRead>=endByte){
        return -1;
    }

    bytesRead=stream.read(tempBuffer,0,nLength);
    if(bytesRead==-1){//premature EOF
        return -1;
    }else if(bytesRead==0){
        return 0;
    }
    t_bytesRead+=bytesRead;
    if(t_bytesRead>=endByte){//correct bytes read to exclude any bytes over the limit
        bytesRead=(int)(bytesRead-(t_bytesRead-endByte));
    }
    return bytesRead;
}
public static void main(String[] args) throws UnsupportedAudioFileException, IOException{
    AudioInputStream music=null;
    music = AudioSystem.getAudioInputStream(new File("music/0.wav"));
    music=new TrimmerAIS(music.getFormat(),music,0,15000);
    AudioSystem.write(music,AudioFileFormat.Type.WAVE,new File("out.wav"));
}
}

我根本找不到任何问题。 我确实在这里找到了链接到https://forums.oracle.com/forums/thread.jspa?threadID=2136229&tstart=0 的类似帖子。这是我的工作,除了您以毫秒为单位给它开始和结束位置,并且它可以传递到/包装在另一个 AIS 或输出中,而无需将所需的段读入数组然后写入它。在过去的 3 个小时里一直试图弄清楚这一点,但我的头脑有些发火。因此,如果某些事情没有意义,请随时要求澄清。我宁愿不解析文件,但如果必须,我必须这样做。

【问题讨论】:

    标签: java audio trim


    【解决方案1】:

    嘿,哎呀!只需要删除 tempBuffer 并将其替换为 abData。是漫长的一天。 以下是更正后的代码。考虑删除它,因为这是一个简单的错误,但我制作这个类的唯一原因是因为它不存在。

    import java.io.ByteArrayInputStream;
    import java.io.File;
    import java.io.IOException;
    
    import javax.sound.sampled.AudioFileFormat;
    import javax.sound.sampled.AudioFormat;
    import javax.sound.sampled.AudioInputStream;
    import javax.sound.sampled.AudioSystem;
    import javax.sound.sampled.UnsupportedAudioFileException;
    
    public class TrimmerAIS extends AudioInputStream{
    
    private final AudioInputStream stream;
    private final long startByte,endByte;
    private long t_bytesRead=0;
    
    public TrimmerAIS(AudioFormat audioFormat,AudioInputStream audioInputStream,long startMilli,long endMilli){
        super(new ByteArrayInputStream(new byte[0]),audioFormat,AudioSystem.NOT_SPECIFIED);
        stream=audioInputStream;
        //calculate where to start and where to end
        startByte=(long)((startMilli/1000)*stream.getFormat().getFrameRate()*stream.getFormat().getFrameSize());
        endByte=(long)((endMilli/1000)*stream.getFormat().getFrameRate()*stream.getFormat().getFrameSize());
    }
    
    @Override
    public int available() throws IOException{
        return (int)(endByte-startByte-t_bytesRead);
    }
    public int read(byte[] abData,int nOffset,int nLength) throws IOException{
        int bytesRead=0;
        if(t_bytesRead<startByte){
            do{
                bytesRead=(int)skip(startByte-t_bytesRead);
                t_bytesRead+=bytesRead;
            }while(t_bytesRead<startByte);
        }
        if(t_bytesRead>=endByte)//end reached. signal EOF
            return -1;
    
        bytesRead=stream.read(abData,0,nLength);
        if(bytesRead==-1)
            return -1;
        else if(bytesRead==0)
            return 0;
    
        t_bytesRead+=bytesRead;
        if(t_bytesRead>=endByte)// "trim" the extra by altering the number of bytes read
            bytesRead=(int)(bytesRead-(t_bytesRead-endByte));
    
        return bytesRead;
    }
    public static void main(String[] args) throws UnsupportedAudioFileException, IOException{
        AudioInputStream music=null;
        music = AudioSystem.getAudioInputStream(new File("music/0.wav"));
        music=new TrimmerAIS(music.getFormat(),music,0,15000);
        AudioSystem.write(music,AudioFileFormat.Type.WAVE,new File("out.wav"));
    }
    }
    

    【讨论】:

      【解决方案2】:

      我不完全确定,但似乎您还需要为您的 read() 函数添加覆盖。 我之所以说我不完全确定,是因为某些 IDE 可能会自动运行,就好像该功能被覆盖一样。应用我的更正,看看它是否有效。

      【讨论】:

      • @Override 只是我的 IDE 自动添加到其他函数的注释。为了最终版本的一致性,我确实添加了注释。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-03-28
      • 2017-05-14
      • 2013-04-13
      • 2011-03-01
      • 2021-05-12
      • 1970-01-01
      • 2015-06-25
      相关资源
      最近更新 更多