背景:我正在使用JLayer来播放MP3
文件。我试图分析MP3
中不同的幅度/音频电平。通过我的分析,我想确定MP3
开始和结束时的沉默持续时间。另外,当正在播放MP3
时,我想要一个图形来显示音频电平(如视觉声波)。
问题:为了进行有效分析,我需要能够分析原始PCM
数据。目前,我正在分析通过AudioInputStream
检索到的字节[]并发送到SourceDataLine
。 PCM
是短[]而不是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
数据,以便我可以显示音量级别,从而检测到静音?
答案 0 :(得分:1)
首先,你得到缓冲区[]中的所有PCM数据。但您可能必须将字节组合成PCM数据。您的音频格式将告诉您正在使用多少位编码。最常见的是16位,但有时会显示24位或32位数据。对于16位数据,您附加两个连续的字节来构建short。两个字节的顺序取决于格式是little-endian还是big-endian。我注意到这个屏幕的右边,在“相关”列中,是一个链接:如何从wav文件中获取PCM数据 - 该链接或其他类似应该为您提供所需代码的示例。 / p>
第二个问题,我不认为在单独的buffer []数组上进行RMS是完全正确的。我可能错了。我认为它更像是移动平均线,其中一个缓冲区[]开头的一些数据应该包含前一个缓冲区末尾的一些数据[]。公式是否要求您“返回”或“平均”超过N个帧?如果是这样,您将希望保留先前的缓冲区[],以适应N量跨越两帧的情况。并且您将遍历当前缓冲区[],一次一个“帧”(或将缓冲区[]交给一个实际执行此操作的子程序。