2

我有一个关于修改音频文件的快速问题。我可以通过输入流(解码等)访问样本,但我无法找到一种方法来操作该输入流中的样本(可能是多个样本的情况)。
我想要实现的是获取一个文件Ex A.mp3,从中删除几秒钟,最后将其存储到一个新文件中。

通过查看JavaSoundApi 示例,我发现可以通过以下方式创建文件:

    File fileOut = new File(someNewPathName);
    AudioFileFormat.Type fileType = fileFormat.getType();
    if (AudioSystem.isFileTypeSupported(fileType,audioInputStream)) {
        AudioSystem.write(audioInputStream, fileType, fileOut);
    }
4

2 回答 2

3

你只需要让 AudioInputStream​​于它的大小。为此,您可以创建自己的 AudioInputStream 类并使用从声音 API 获得的普通 AudioInputStream 的委托(仅限骨架):

public class CuttingAudioInputStream extends AudioInputStream {

    private AudioInputStream delegate;

    public CuttingAudioInputStream(AudioInputStream delegate) {
        this.delegate = delegate;
    }

    /**
     * Lie about length of delegate
     */
    public long getFrameLength() {
        // simple demo, make the caller think the stream is 44100 samples long
        return Math.min(delegate.getFrameLength(), 44100); 
    }

    // Overrides for all other methods of AudioInputStream, 
    // left as excercise to the reader
}

您只需要实现所有其他方法以遵守您想要的限制。你也可以剪掉中间的部分,只是在 read() 方法中稍微复杂一点。

但是,我觉得有必要指出,如果源/目标是有损格式(例如 MP3 被解码和重新编码),这种方法可能会降低音频质量。如果质量损失不可接受(仅在多次处理同一流时才重要),最好不要解码文件,而是将切割过程直接应用于编码数据。当然,这更复杂(您需要对要处理的每种格式有很好的了解)并且不同格式对您可以剪切的位置有限制。

于 2012-08-02T12:09:18.400 回答
2

您的教程适用于 Java 1.5!还有更多当前版本。

在您引用的页面上,“阅读声音文件”标题下有一些示例代码。请注意带有评论的区域:

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

这是在读取 audioInputStream 的 while 循环内。如果您在帧通过该区域时对其进行跟踪,则可以计算经过的时间。加载的数据可以保存到字节数组中。或者,所需帧内的数据可能是读取 audioInputStream 并实现 TargetDataLine 的类的输出。如果我没记错的话,可以使 TargetDataLine 与 AudioSystem.write(...

我不知道直接编辑压缩数据甚至是 wav。Wav 格式不统一,没有统一的标题。这就是为什么我让 Java 读取流,并使用以这种方式暴露的数据。

于 2012-08-02T19:44:52.890 回答