0

背景:我正在使用JLayer播放MP3文件。我正在尝试分析MP3. 通过我的分析,我想确定MP3. 此外,在MP3播放时,我想要一个图表来显示音频电平(如视觉声波)。

问题:为了进行有效的分析,我需要能够分析原始PCM数据。目前,我正在分析通过 byte[] 检索AudioInputStream并发送到SourceDataLine. PCM是 short[] 而不是 byte[],这意味着我没有得到完整的数据。

我使用Root-Mean Square( RMS) 来确定音量。

处理 byte[] 的播放代码:

AudioInputStream in = null;
AudioFile af = null; //Custom class which holds some data about mp3.
SourceDataLine line = null;

// Set current audio file.
af = musicPlaylist.get(0);

line = (SourceDataLine) AudioSystem.getLine(af.getLineInfo());
line.open(af.getAudioFormat());
line.start();

in = getAudioInputStream(af.getAudioFormat(), af.getAudioStream());

int bR = playbackBufferSize;

final byte[] buffer = new byte[bR];
int n = 0;
while (playMedia) {
    if ((n = in.read(buffer, 0, buffer.length)) == -1) {
        break;
    }

    if (line != null) {
        line.write(buffer, 0, n);

        int amp = (int) Math
                .ceil((rmsAudioLevel(decode(buffer)) / 32767) * 100);
        mainScreen.setAmpDisplayLevel(amp, String.valueOf(amp));
        mainScreen.updateGraph(amp);
    }
}

本质上:我如何PCM在播放时现场解码数据MP3,以便我可以显示音量级别并因此检测静音?

4

1 回答 1

1

首先,您将在缓冲区 [] 中获取所有 PCM 数据。但是您可能必须将字节组装成 PCM 数据。您的音频格式将告诉您正在使用多少位编码。最常见的是 16 位,但有时会显示 24 位或 32 位数据。对于 16 位数据,您附加两个连续的字节来构建一个短字节。两个字节的顺序取决于格式是 little-endian 还是 big-endian。我注意到在此屏幕右侧的“相关”列中,有一个链接:如何从 wav 文件中获取 PCM 数据——该链接或其他类似链接应该为您提供所需的代码示例。

第二个问题,我不认为在单独的 buffer[] 数组上做 RMS 是完全正确的。我可能错了。我认为它更像是一个移动平均线,其中一个缓冲区 [] 开头的一些数据应该包括前一个缓冲区 [] 结尾的一些数据。该公式是否要求您“返回”或“平均超过”N 帧?如果是这样,您将希望在 N 数量跨越两帧的情况下保持先前的 buffer[] 方便。您将遍历当前缓冲区 [],一次一个“帧”(或将缓冲区 [] 交给实际上执行此操作的子程序)。

于 2013-09-23T21:59:31.837 回答