为啥缓冲区大小会影响音频数据?

Posted

技术标签:

【中文标题】为啥缓冲区大小会影响音频数据?【英文标题】:Why does buffer size affect audio data?为什么缓冲区大小会影响音频数据? 【发布时间】:2013-09-07 02:05:41 【问题描述】:

我正在使用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;
        

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

【问题讨论】:

【参考方案1】:

您的外部 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] 的零初始化数组。

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

【讨论】:

你可能想看看这个答案***.com/questions/5800649/… 处理样本大小、通道数等。

以上是关于为啥缓冲区大小会影响音频数据?的主要内容,如果未能解决你的问题,请参考以下文章

黑莓减少音频播放器缓冲

Golang:为啥增加缓冲通道的大小会消除我的 goroutine 的输出?

为啥 boost::asio::read 缓冲区数据大小小于读取大小?

为啥我的 iOS 录音回调中的音频缓冲区未满?

为啥 SDL2 为音频样本提供的缓冲区不够大?

每 10 毫秒录制一次音频的音频缓冲区大小和 FFT 大小是多少?