如何进行单声道到立体声转换?

时间:2012-10-03 16:29:16

标签: audio pcm resampling

我正在使用libswresample从任何PCM格式重采样到44.1kHz,16bit int,stereo。

我正在玩一些音频分析结果音频流,我发现如果我有44.1kHz,16bit int mono作为源,我大致有一个公式:

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

但我在期待:

leftSample = sourceSample;
rightSample = sourceSample;

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

我的期望来自几个来源:

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

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

    这是特别的。相关的,因为ReplayGain是通过此实现使用参考声音(粉红噪声,可以下载here)进行校准的,该声音是单声道的。

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

  4. 在我尝试自己实施ReplayGain之后,我发现了混乱,我偶然发现了这一点。

    所以,有些问题:

    1. 为什么libswresample会这样做?
    2. 这是libswresample或bug的预期吗? (我试图从源头上理解(例如here),但我还没有完全理解它。)我添加了一个错误报告here
    3. 什么是“正确”的解决方案?
    4. 其他玩家在做什么?
    5. 如果您向其提供单声道样本,常见的声卡是做什么的?
    6. (我现在也在avp.stackexchange上发布了这个问题;也许这是一个更好的地方询问这一点,不确定。)

1 个答案:

答案 0 :(得分: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转换增益变化,但水平似乎是任意的。