2

我正在使用 libswresample 将任何 PCM 格式重新采样为 44.1kHz、16bit int、立体声。

我正在对生成的音频流进行一些音频音量分析,我发现如果我有 44.1kHz、16 位 int 单声道作为源,我有大致的公式:

leftSample = sourceSample / sqrt(2);
rightSample = sourceSample / sqrt(2);

但我期待:

leftSample = sourceSample;
rightSample = sourceSample;

(如果源是立体声,我只是有leftSample = leftSourceSample; rightSample = rightSourceSample;。)

我的期望来自几个方面:

  1. 我自己的直接解决方案可能就是这样。
  2. 我四处搜索了一下,其他人似乎也在做同样的事情,例如这里
  3. 在一个非常常见的 ReplayGain 实现中(实际上我知道的唯一一个,基本上到处都在使用,我认为最初来自 mp3gain;一个副本可以在这里看到),它也这样做:

    switch ( num_channels) {
    case  1: right_samples = left_samples;
    case  2: break;
    default: return GAIN_ANALYSIS_ERROR;
    }
    

    这是特别的。相关,因为 ReplayGain 是由这个实现使用单声道的参考声音(粉红噪声,可以在这里下载)校准的。

    在 ReplayGain 规范中,它也是这样计算的(参见此处)。

在我尝试自己实现 ReplayGain 之后,我的困惑就出现了,我偶然发现了这一点。

所以,一些问题:

  1. 为什么 libswresample 会这样做?
  2. 这是 libswresample 中的预期还是错误?(我试图从源头(例如这里)理解,但我还没有完全理解它。)我在这里添加了一个错误报告。
  3. 什么是“正确”的解决方案?
  4. 其他玩家在做什么?
  5. 如果您向其提供单声道样本,常见的声卡会做什么?

(我现在也在avp.stackexchange上发布了这个问题;也许这是一个更好的地方来询问这个问题,不确定。)

4

1 回答 1

3

该实现是将单声道信号“平移”到立体声场的一种正确实现。如果您平移,而不是一直向左或一直向右,您希望信号强度与在中间平移一样,因此向左平移将是:

//left panning
leftSample = sourceSample;
rightSample = 0;
//right panning
leftSample = 0;
rightSample = sourceSample;
//center panning (same power as hard left/right conversion/)
leftSample = sourceSample * sqrt(2)/2;
rightSample = sourceSample * sqrt(2)/2;

但是,如果您是从单声道转换为立体声,那么您的直觉是正确的。没有理由降低电平,因为您不会将居中信号与平移信号进行比较。最好的方法是让信号保持最大强度:

//mono to stereo conversion
leftSample = sourceSample;
rightSample = sourceSample;

他们也可能会留下一些 s/r 转换后的增益变化,但水平似乎是任意的。

于 2012-10-04T02:09:20.167 回答