【问题标题】:Does "16bit integer PCM data" mean it's signed or unsigned?“16 位整数 PCM 数据”是指有符号还是无符号?
【发布时间】:2015-04-22 08:28:05
【问题描述】:

我正在使用 FMOD 开发一个应用程序,当用户单击“下一个/上一个”按钮时,该应用程序将立即从包含语音但没有音乐的 MP3 文件的开头开始播放下一个/上一个句子的录音。我通过调用Sound::lock得到了一个mp3文件的PCM数据,但是Sound::getFormat只告诉我是“16bit integer PCM data”,没有说是否它是签名的未签名的。我怎么会知道?

网上有些文章说几乎所有的16位整数PCM数据都是有符号的。如果我的 PCM 数据是有符号,什么范围的值表示静音,接近 0 的值(例如 -10 ~ 10)或接近 -32768 的值(例如 -32768 ~ -32750)?如果它们是接近 0 的值,这是否意味着相反的数字(如 -32767 和 32767)在含义上没有区别?

我需要检测足够长的静音,例如超过 500 毫秒,以确定语音中每个句子的开始位置。

谁能给我任何关于如何检测句子之间的沉默的建议?

【问题讨论】:

    标签: audio signal-processing pcm fmod


    【解决方案1】:

    按照惯例,16 位音频通常是有符号的。

    想一想 PCM 音频是什么:每个衡量标准都是扬声器在该时刻物理上应该沿其轴放置多远。因此,完全静音绝对是任何重复值——代表说话者不动。

    0 是范围的中心,通常是麦克风应该没有输入的位置。 -32768 是扬声器尽可能靠近其轴的一端,32767 是在另一端。

    检测静音的最安全方法是在相关范围内运行频谱分析,并寻找在任何可听频率范围内没有活动的时段。

    如果您正在寻找语音之间的停顿,那么最简单的方法可能是转到this 之类的地方,插入可接受的语音频率范围(在电话中被认为是 300Hz 到 3500Hz 左右),您的采样率以及您认为可以承受的许多乘法。复制提供的系数。例如。我假设您将使用 44100Hz 输入在语音范围内进行 37 次抽头,然后转换为 C 数组,我得到:

    double coefficients[] = {
        -0.000560, -0.001290, -0.002332, -0.003606, -0.004911, -0.005921,  -0.006201, 
        -0.005256, -0.002610, 0.002106, 0.009059, 0.018139, 0.028924, 0.040691,  0.052479, 
        0.063203, 0.071794, 0.077351, 0.079274, 0.077351, 0.071794, 0.063203,  0.052479, 
        0.040691, 0.028924, 0.018139, 0.009059, 0.002106, -0.002610, -0.005256, -0.006201, 
        -0.005921, -0.004911, -0.003606, -0.002332, -0.001290, -0.000560};
    

    如果是double 输入,那么对于每个输入样本c,我会计算一个采样值:

    double *inputWave = ... input, an infinite array for the purposes of the example ...
    double sampledValue = 0.0;
    for(size_t coeff = 0; coeff < numberOfTaps; coeff++) {
        sampledValue += coefficients[coeff] * inputWave[c + coeff];
    }
    
    // (where numberOfTaps = sizeof(coefficients) / sizeof(coefficients[0]),
    // i.e. the number of coefficients: 37 with the array given above)
    

    然后我得到的是带通滤波器。只有在 300-3500Hz 频率范围内代表声音的那部分信号应该保留在输出值中。在现实生活中,没有这样的过滤器是完美的。增加系数的数量以提高过滤器的质量。

    剪掉信号中不相关的部分后,我可以寻找长时间的sampledValue = [close to] 0.0

    【讨论】:

    • 非常感谢,汤米。我想我只需要直接将 PCM 数据与一个数字进行比较即可找到句子之间的停顿。请原谅我的无知,但“水龙头”是什么意思?为什么要有 37 个水龙头?数组 inputWave[] 是否像我提到的 16 位整数一样引用 PCM 数据?您的示例代码是否旨在确定示例 inputWave[c] 是否表示静音?很抱歉有这么多问题和我糟糕的英语。
    • Taps 是信号处理术语,用于表示组合以执行一个输出样本的输入样本的数量。它更多地来自硬件传统方面。它不需要是 37,这只是该页面上的默认值。您可能应该根据主观表现进行选择 - 通常,更多 = 更好。至于 CPU 性能,请考虑将处理器的 SIMD 单元用于整个事情(这可能意味着使用定点短路而不是双倍,但无论如何)。输出是滤波后的波。你可以直接听。寻找接近 0 的长时间以找到静音。
    【解决方案2】:

    令人惊讶的是,如果我创建 8 位格式的 directsound 声音缓冲区,directsound 预计我的机器上的样本是 8 位已签名 (-127 - 127),而当我创建 16 位缓冲区时,directsound 预计它们是 16 位未签名 (0 - 65535)。所以至少在我的机器上,标准似乎与汤米的答案相反。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-12-26
      • 2011-11-10
      • 1970-01-01
      • 1970-01-01
      • 2010-09-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多