0

我正在使用javax.sound.sampledJLayer播放MP3文件。我正在尝试分析音频输入流以确定歌曲何时开始以及何时结束(基于 MP3 开头和结尾的音频电平)。一首 4 分钟的歌曲可能只有 3 分 55 秒的实际音乐,而其余的都是无声的,这就是我确定这一点的原因。

我想我可以通过查找流中的第一个和最后一个非零字节来确定此信息。

问题:问题是当我调整缓冲区大小时,第一个非零字节的位置发生了变化。为什么会这样,无论缓冲区大小如何,它都不应该保持不变吗?

例如,在缓冲区大小为 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;
        }

我想我误解了音频输入流和音频的一般工作原理。

4

1 回答 1

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]

您不应该假设读取会填满整个缓冲区,而是使用读取返回的值。

于 2013-09-07T09:18:54.670 回答