1

我发现了一些问题,我实际上read使用AudioInputStream. 下面的程序只是打印我得到的字节数组,但实际上我什至不知道字节是否实际上是样本,所以字节数组是音频

File fileIn;
AudioInputStream audio_in;
byte[] audioBytes;
int numBytesRead;
int numFramesRead;
int numBytes;
int totalFramesRead;
int bytesPerFrame;

try {
        audio_in = AudioSystem.getAudioInputStream(fileIn);
        bytesPerFrame = audio_in.getFormat().getFrameSize();


        if (bytesPerFrame == AudioSystem.NOT_SPECIFIED) {
            bytesPerFrame = 1;
        } 

        numBytes = 1024 * bytesPerFrame; 
        audioBytes = new byte[numBytes];
        try {
            numBytesRead = 0;
            numFramesRead = 0;   
        } catch (Exception ex) { 
            System.out.println("Something went completely wrong");
        }
    } catch (Exception e) {
        System.out.println("Something went completely wrong");
    }

在其他一些部分,我用这个读取了一些字节:

try {
        if ((numBytesRead = audio_in.read(audioBytes)) != -1) {                 
              numFramesRead = numBytesRead / bytesPerFrame;                 
              totalFramesRead += numFramesRead;            
        }
    } catch (Exception e) {
        System.out.println("Had problems reading new content");
    }

所以首先,这段代码不是我的。这是我第一次阅读音频文件,所以我从互联网上得到了一些帮助。(找到链接: Java - 读取、操作和编写 WAV 文件 stackoverflow,谁会知道。

问题是,audioBytes 中的字节代表什么?由于源是 44kHz 立体声,因此必须有 2 个波隐藏在某个地方,对吗?那么如何从这些字节中过滤出重要信息呢?

// 编辑

所以我添加的是这个功能:

public short[] Get_Sample() {
    if(samplesRead == 1024) {
        Read_Buffer();
        samplesRead = 4;
    } else {
        samplesRead = samplesRead + 4;
    }
    short sample[] = new short[2];
    sample[0] = (short)(audioBytes[samplesRead-4] + 256*audioBytes[samplesRead-3]);
    sample[1] = (short)(audioBytes[samplesRead-2] + 256*audioBytes[samplesRead-1]); 
    return sample;
}

其中 Read_Buffer() 读取接下来的 1024(或更少)字节并将它们加载到 audioBytes 中。sample[0] 用于左侧,sample[1] 用于右侧。但我仍然不确定,因为我从中得到的波浪看起来很“嘈杂”。(编辑:使用的 WAV 实际上使用了 little-endian 字节顺序,所以我不得不更改计算。)

4

1 回答 1

2

AudioInputStream read() 方法返回原始音频数据。在使用返回 AudioFormat 的 getFormat() 读取音频格式之前,您不知道数据的“构造”是什么。从 AudioFormat 中,您可以获得 getChannels() 和 getSampleSizeInBits() 等等......这是因为 AudioInputStream 是为已知格式制作的。

如果您计算样本值,则数据的符号和字节序有不同的可能性(在 16 位样本的情况下)。要制作更通用的代码,请使用从 AudioInputStream 返回的 AudioFormat 对象来获取有关数据缓冲区的更多信息:

  • 编码():PCM_SIGNED,PCM_UNSIGNED ...
  • bigEndian() : 真或假

正如您已经发现的那样,不正确的样本构建可能会导致一些干扰声音。如果您使用各种文件,将来可能会出现问题。如果您不支持某些格式,只需检查 AudioFormat 的内容并抛出异常(例如 javax.sound.sampled.UnsupportedAudioFileException)。这将节省您的时间。

于 2013-06-28T19:22:53.783 回答