从原始文件中获取最多 x 个字节的 AudioInputStream(剪切音频文件)

Posted

技术标签:

【中文标题】从原始文件中获取最多 x 个字节的 AudioInputStream(剪切音频文件)【英文标题】:obtaining an AudioInputStream upto some x bytes from the original (Cutting an Audio File) 【发布时间】:2011-09-25 14:06:14 【问题描述】:

如何读取AudioInputStream 到特定数量的字节/微秒位置? 例如:

AudioInputStream ais = Audiosystem.getAudioInputStream( new File("file.wav") );
// let the file.wav be of y bytes

现在我想获得一个AudioInputStream,它的数据高达x 字节,其中x < y 字节。

我该怎么做?

我一直在努力思考,但没有任何方法可以做到这一点?

【问题讨论】:

您可能应该考虑“帧”,而不是“字节”。 @Andrew Thompson Let it be in frames ,我获得x帧后如何进行 【参考方案1】:

下面的代码向您展示了如何复制音频流的一部分,从一个文件读取并写入另一个文件。

import java.io.*;
import javax.sound.sampled.*;

class AudioFileProcessor 

  public static void main(String[] args) 
    copyAudio("/tmp/uke.wav", "/tmp/uke-shortened.wav", 2, 1);
  

  public static void copyAudio(String sourceFileName, String destinationFileName, int startSecond, int secondsToCopy) 
    AudioInputStream inputStream = null;
    AudioInputStream shortenedStream = null;
    try 
      File file = new File(sourceFileName);
      AudioFileFormat fileFormat = AudioSystem.getAudioFileFormat(file);
      AudioFormat format = fileFormat.getFormat();
      inputStream = AudioSystem.getAudioInputStream(file);
      int bytesPerSecond = format.getFrameSize() * (int)format.getFrameRate();
      inputStream.skip(startSecond * bytesPerSecond);
      long framesOfAudioToCopy = secondsToCopy * (int)format.getFrameRate();
      shortenedStream = new AudioInputStream(inputStream, format, framesOfAudioToCopy);
      File destinationFile = new File(destinationFileName);
      AudioSystem.write(shortenedStream, fileFormat.getType(), destinationFile);
     catch (Exception e) 
      println(e);
     finally 
      if (inputStream != null) try  inputStream.close();  catch (Exception e)  println(e); 
      if (shortenedStream != null) try  shortenedStream.close();  catch (Exception e)  println(e); 
    
  

  public static void println(Object o) 
    System.out.println(o);
  

  public static void print(Object o) 
    System.out.print(o);
  


【讨论】:

为什么字节数组的大小被取为bPS/500?你能解释一下你在写inputStream.skip(bytesPerSecond)然后读到字节数组时在做什么吗?请详细说明并将其包含在您的答案中 JavaDocs 解释了这些方法的作用:download.oracle.com/javase/6/docs/api/javax/sound/sampled/…, int, int) “从音频流中读取指定的最大字节数,并将它们放入给定的字节数组中。” download.oracle.com/javase/6/docs/api/javax/sound/sampled/… "跳过并丢弃此音频输入流中指定数量的字节。" byte[] bytes = new byte[bytesPerSecond / 500] 给了我 2 毫秒的字节,如下面的评论中所示。 @Martin Dow 谢谢你回到这个问题。但这并没有解决我的问题。我想剪切音频文件但不跳过它的某些部分。这就是问题所在:获取数据少于原始数据的ais。在上面的程序中,我们没有得到任何数据少于流的流。我知道一个特定的位置它可能以字节、帧位置、毫秒为单位。 我想获得一个数据流到那个位置。 即剪切音频文件 您的问题并不清楚。我已经更新了我的答案。你应该能够从那里弄清楚。 @Martin Dow 它不会剪切文件。让我验证一下,上面程序中的secondsToCopycurrentPosInSec【参考方案2】:

现在您有了流,您可以使用read() 一次读取一个字节,最多可读取您想要的最大ob 字节数,或者使用read(byte[] b) 读取固定数量的字节。

【讨论】:

以上是关于从原始文件中获取最多 x 个字节的 AudioInputStream(剪切音频文件)的主要内容,如果未能解决你的问题,请参考以下文章

如何从 32 字节原始私钥中获取 java.security.PrivateKey ? (Secp256k1 算法)

原始音频文件中的样本字节是啥意思?

php 文件读取方式

文本和字节序列

使用 Core Audio 从 PCM 原始数据中获取电平值

字符串列表字典