3

たとえば、次の 2 つのオーディオ トラックをミックスするとします。

混合されていない

Audacity では、「Mix and Render」オプションを使用してそれらを混ぜ合わせることができ、次のようになります。

大胆なミックス

ただし、独自のコードを作成して混合しようとすると、次のようになります。

マイミックス

これは基本的に、サンプルをミックスする方法です。

private function mixSamples(sample1:UInt, sample2:UInt):UInt
{
    return (sample1 + sample2) & 0xFF;
}

(構文は Haxe ですが、わからなくても簡単に理解できるはずです。)

これらは 8 ビットのサンプル オーディオ ファイルであり、製品も 8 ビットにしたいので、& 0xFF.

サンプルを追加するだけで、クリッピングが予想されることは理解しています。私の問題は、Audacity を混合してもクリッピングが発生しないことです (少なくとも私のコードが発生する程度ではありません)。2 番目の (長い) トラックの「テール」を見ると、振幅が減少していないようです. 音も柔らかくなりません。

基本的に、私の質問はこれです: Audacity は何をしていて、私はしていないのですか? トラックをミックスして、トラックが重ねて再生されているかのように聞こえるようにしたいのですが、(明らかに) この恐ろしいクリッピングはしたくありません。

編集:

Radiodef が提案するように、追加する前に値に署名し、合計値の署名を解除すると、次のようになります。

私のサイン入りミックス

ご覧のとおり、以前よりもはるかに良くなっていますが、Audacity が生成する結果と比較すると、まだかなり歪んでおり、ノイズが多くなっています。だから私の問題はまだ残っています.Audacityは何か違うことをしているに違いありません.

EDIT2:

最初のトラックを自分のコードと Audacity の両方でミックスし、歪みが発生するポイントを比較しました。これはAudacityの結果です:

大胆さをズーム

そして、これが私の結果です:

ここに画像の説明を入力

4

2 に答える 2

5

起こっていることは、それらを無署名として合計していると思います。典型的な音波は、プラスとマイナスの両方を持っているため、それらが加算されるのです (いくつかの部分は相殺されます)。-96 の 8 ビット サンプルと 96 の別の 8 ビット サンプルがあり、それらを合計すると 0 になります。署名されていないオーディオの場合は、サンプル 32 と 224 の合計 = 256 (オフセットとオーバーフロー) になります。 .

あなたがする必要があるのは、合計する前に署名することです。8 ビット サンプルに署名するには、それらを signed int 型に変換し、それらすべてから 128 を減算します。あなたが持っているのはWAVファイルであり、合計後に再度署名を解除する必要があると思います.

Audacity はおそらく浮動小数点処理を行います。浮動小数点には「無限のダイナミックレンジ」があり、そのようなガベージがあるが、整数と同じように決定的で明白な方法でクリップしないという、本当に疑わしい主張を聞いたことがあります。浮動小数点の値の範囲は整数と同じですが、最大値と最小値ははるかに離れています。(これが最も簡単な言い方です。) 浮動小数点を使用すると、オーディオの振幅を大幅に変更できますが、問題は、全体的な信号対雑音比が整数よりも低いことです。

奇妙な歪みで、私の最善の推測は、あなたがやっているマスクからのものです& 0xFF。オーバーフローする代わりに実際にクリップしたい場合は、自分で行う必要があります。

for (int i = 0; i < samplesLength; i++) {
    if (samples[i] > 127) {
        samples[i] = 127;
    } else if (samples[i] < -128) {
        samples[i] = -128;
    }
}

それ以外の場合、125 のサンプルが 2 つあり、合計すると 250 (11111010) になります。次に、署名を解除 (128 を追加) し、378 (101111010) を取得します。& は、122 である 1111010 を取得します。他の数値を使用すると、実質的に負または 0 に近い結果が得られる場合があります。

8 ビット以外でクリップする場合、ビット深度 n のフル スケールはpositive (2 ^ (n - 1)) - 132767negative 2 ^ (n - 1)になり、16 ビットの場合は -32768 になります。

クリッピングの代わりにできるもう 1 つのことは、クリッピングを検索して正規化することです。何かのようなもの:

double[] normalize(double[] samples, int length, int destBits) {

    double fsNeg = -pow(2, destBits - 1);
    double fsPos = -fsNeg - 1;

    double peak = 0;
    double norm = 1;

    for (int i = 0; i < length; i++) {
        // find highest clip if there is one

        if (samples[i] < fsNeg || samples[i] > fsPos) {
            norm = abs(samples[i]);

            if (norm > peak) {
                norm = peak;
            }
        }
    }

    if (peak != 0) {

        // ratio to reduce to where there is not a clip
        norm = -fsNeg / peak;

        for (int i = 0; i < length; i++) {
            samples[i] *= norm;
        }
    }

    return samples;
}
于 2013-11-21T01:34:22.703 に答える