Java 使用JLayer将MP3解码到PCM中以检测振幅

Java 使用JLayer将MP3解码到PCM中以检测振幅,java,mp3,javasound,pcm,javax.sound.sampled,Java,Mp3,Javasound,Pcm,Javax.sound.sampled,背景:我正在播放一个MP3文件。我试图分析MP3中不同的振幅/音频电平。通过我的分析,我想确定MP3开始和结束时的静默时间。此外,在播放MP3时,我想用一个图表来显示音频级别(如可视声波) 问题:为了进行有效分析,我需要能够分析原始PCM数据。目前,我正在分析通过AudioInputStream检索并发送到SourceDataLine的字节[]PCM是短[]而不是字节[],这意味着我没有获得完整数据 我使用均方根(RMS)来确定音量水平 处理字节[]的播放代码: AudioInputStream

背景:我正在播放一个
MP3
文件。我试图分析
MP3
中不同的振幅/音频电平。通过我的分析,我想确定
MP3
开始和结束时的静默时间。此外,在播放MP3时,我想用一个图表来显示音频级别(如可视声波)

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

我使用
均方根
RMS
)来确定音量水平

处理字节[]的播放代码:

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);
    }
}

本质上:如何在播放
MP3
时当场解码
PCM
数据,以便显示音量水平,从而检测静音?

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


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

要更快获得更好的帮助,请发布一个。