我正在使用javax.sound.sampled
和JLayer
来播放MP3
文件。我正在尝试分析音频输入流以确定歌曲何时开始以及何时结束(基于MP3开头和结尾的音频电平)。一首4分钟的歌曲可能只有3分55秒的实际音乐,而其余的则是静音,这就是我决定这一点的原因。
我以为我可以通过查找流中的第一个和最后一个非零字节来确定此信息。
问题:问题是当我调整缓冲区大小时,第一个非零字节的位置会发生变化。为什么这样,不管缓冲区大小如何都不应该保持不变?
E.g。缓冲区大小为16时,startFrame与第17个字节相关。缓冲区大小为64时,startFrame与第65个字节相关。
以下是代码:
byte[] buffer;
int pos = 0;
short silenceThreshold = 1;
startFrame = 0;
endFrame = -1;
boolean startFrameSet = false;
buffer = new byte[16];
byte prevVal = 0;
for (int n = 0; n != -1; n = audioInputStream.read(buffer, 0,
buffer.length)) {
for (int i = 0; i < buffer.length; i++) {
if (buffer[i] >= silenceThreshold || buffer[i] <= -silenceThreshold) {
// Is not silent
if (!startFrameSet) {
startFrame = (pos * buffer.length) + i;
startFrameSet = true;
}
} else {
// Silence
// If the previous value is > 0 or < 0, set endFrame
if (prevVal >= silenceThreshold || prevVal <= silenceThreshold) {
endFrame = (pos * buffer.length) + i;
}
}
prevVal = buffer[i];
}
pos++;
}
//If last byte is not within silence threshold (song doesn't end in silence).
if (prevVal >= silenceThreshold || prevVal <= silenceThreshold) {
// last frame is not silent
endFrame = -1;
}
我想我误解了音频输入流和音频的工作方式。
答案 0 :(得分:2)
第一次通过循环时,您的外部for
循环无法从音频输入流中读取
for (int n = 0; n != -1; n = audioInputStream.read(buffer, 0,
buffer.length)) {
相当于:
int n = 0;
while (n != -1) {
// Inner loop
n = audioInputStream.read(buffer, 0, buffer.length);
}
所以在第一个循环中,缓冲区只是来自new byte[16]
的零初始化数组。
您不应该假设读取填充整个缓冲区,使用读取返回的值。