2013-09-21 40 views
0

背景:我正在使用JLayer播放MP3文件。我试图分析MP3中不同的幅度/音频电平。通过我的分析,我想确定MP3开始和结束时的静音持续时间。另外,当正在播放MP3时,我想要一个图形来显示音频电平(如视觉声波)。使用JLayer将MP3解码为PCM来检测幅度

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

我正在使用Root-Mean SquareRMS)来确定音量级别。

回放代码,其中所述字节[]进行处理:

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

为了更快提供更好的帮助,请发布[SSCCE](http://sscce.org/)。 –

回答

1

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

第二个问题,我不认为在单独的缓冲区[]数组上做RMS是完全正确的。我可能是错的。我认为它更像是一个移动平均值,其中一个缓冲区[]开头的一些数据应该包含前一个缓冲区[]的末尾的一些数据。公式是否要求您“返回”或“平均超过”N帧?如果是这样的话,那么在N量跨越两帧的情况下,您会希望保留前一个缓冲区[]。你将迭代当前缓冲区[],一次一个“帧”(或者将缓冲区[]传递给子程序,实际上是这样做的)。