java - 使用 Java 声音 API 修剪 WAV 文件的开头和结尾

标签 java audio trim

我已经做好了基础。然而,输出文件只是一遍又一遍地重复 WAV headerbytes。生成的文件大小合适,但它是垃圾文件。

我正在尝试使用一个扩展 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 个小时里,我一直在试图解决这个问题,但我的头脑有点焦躁。因此,如果有什么不明白的地方,请随时要求澄清。我宁愿不解析文件,但如果必须的话,我必须这样做。

最佳答案

嘿嘿嘿!只需要删除 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"));
}
}

关于java - 使用 Java 声音 API 修剪 WAV 文件的开头和结尾,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9744767/

相关文章:

java - 同步方法x调用另一个y,y也必须同步吗?

java - getClass() getResource 返回 null

java - 为什么这个方法是错误的呢?

Linux 音频子系统

c - C 中的 trim 函数是否需要 memmove?

logstash - 修剪字段值,或删除部分值

iOS:使用 Swift 修剪音频文件?

java - 在 Android 中启用当前禁用的 Spinner

audio - 检测 MOV 文件中丢失的音频

java - 如何使用 Java 从 url 流式传输音乐 - Android