1

ピアノのサンプルをミックスするソフトウェアを実装しようとしています。一方のサウンド、もう一方のサウンド、および両方のミックスを含むwavファイルを作成したいと思います。

サンプルを1秒で切り捨てるので、次のようになります。[サウンド1の1秒][サウンド2の1秒][サウンド1の1秒+サウンド2]

問題は、トランジションごとに奇妙なサウンドアーティファクトがあることです。誰かがそれがどこから来たのか知っていますか?

前もって感謝します。

これが私が使用しているコードです:

#include "stdafx.h"
#include <cstdlib>
#include <sndfile.h>


int _tmain(int argc, _TCHAR* argv[])
{
    SF_INFO sInfo1;
    SF_INFO sInfo2;
    SF_INFO sInfo3;

    SNDFILE *sFile1 = NULL;
    SNDFILE *sFile2 = NULL;
    SNDFILE *sFile3 = NULL;

    double *buff1;
    double *buff2;
    double *buff3;

    sf_count_t count1 = 0;
    sf_count_t count2 = 0;
    sf_count_t count3 = 0;

    buff1 = (double*)malloc(88200*sizeof(double));
    buff2 = (double*)malloc(88200*sizeof(double));
    buff3 = (double*)malloc(88200*sizeof(double));

    sInfo1.format = 0;
    sInfo2.format = 0;
    sFile1 = sf_open("C:/samples/mezzo forte/mcg_mf_022.wav", SFM_READ, &sInfo1);
    sFile2 = sf_open("C:/samples/mezzo forte/mcg_mf_046.wav", SFM_READ, &sInfo2);

    sInfo3 = sInfo2;
    sFile3 = sf_open("C:/samples/test1.wav", SFM_WRITE, &sInfo3);

    count1 = sf_read_double(sFile1, buff1, 88200);
    count2 = sf_read_double(sFile2, buff2, 88200);

    for(int i=0; i<88200; i++)
    {
        buff3[i] = buff1[i] + buff2[i] - ( buff1[i] * buff2[i] );
    }

    count1 = sf_write_double(sFile3, buff1, 88200);
    count2 = sf_write_double(sFile3, buff2, 88200);
    count3 = sf_write_double(sFile3, buff3, 88200);

    sf_close(sFile1);
    sf_close(sFile2);
    sf_close(sFile3);

    free(buff1);
    free(buff2);
    free(buff3);

    //getchar();
    return 0;
}
4

2 に答える 2

1

これはlibsndfileの問題ではありません。これは一般的なオーディオ合成の質問です。

サンプルを任意の値(たとえば、1秒)に切り捨てるときはいつでも、結果のファイルをAudacityにロードし、遷移境界でスペクトログラムと波形をチェックアウトすることを期待できます(または、結果のファイルを確認することができます)。 )アーティファクト。これは、サンプル波形が急激に変化するためです。帯域制限を取り巻く問題について説明する試みはスキップし、サンプルを切り捨てるのではなく、サンプルをすばやくフェードアウトするように促します。これにより、トランジションの直前にオーディオ波形が[急速に]ゼロに近づきます-スムーズに。

次のサンプルの最初の数サンプルをゼロに近い値で重み付けし、それを[急速に、またはあなたが攻撃を逃します]本格的に。まず、各トランジションの前に高速フェードアウトを実行することから始めます。必要な場合にのみ、フェードインについて心配します。実装は同じです(ランプアップまたはランプダウンするサンプルスケーリング値)が、最も問題を引き起こす可能性が高いのは、1秒でのサンプルの任意の切り捨て(終了)です。

何が機能するかを確認するには、いくつかの異なるパラメーターを試してみる必要があります。たとえば、簡単にするために、指数関数的または放物線状の減衰関数ではなく、線形ランプダウンから始めたい場合があります。いずれの場合も、サンプル値のスケールダウンを開始するには、遷移点からのサンプル数(またはミリ秒数)を決定する必要があります。

編集:

トランジションアーティファクトについてのみ質問したので、最初はミキシングは問題ないと思いました。私の答えはそれに対処します。buff3しかし、あなたが述べた目的を考えると、なぜあなたがあなたがそうであるように正確に混合しているのか私にはわかりません。buff32つのサウンドを単純に組み合わせて、他の2つの対応するサンプルを足し合わせて、クリップしないようにする(つまり、範囲[-1.0、+ 1.0]を超える)ことを正しく理解している場合。libsndfileは自動的にクリッピングを「保護」しますが、設定できるのは、たとえば、1.0から1.0を超えるサンプル値のみです。両方のオーディオ波形が等しく混合されることを保証するものではありません。

2つの入力サウンドのいずれかのレベルが十分に高い場合、単純なアディティブミックスがクリップします。これは、別のタイプの「アーティファクト」になります(ただし、サウンド全体を台無しにする可能性があるため、この特定のケースでは、おそらく注意が必要です。できるだけ多く)。ただし、一般的なミキシングの場合、ループは次のようになります。

for(int i=0; i<88200; i++)
{
    /* multiply sum of signals by factor slightly
       less than reciprocal of their count to guard
       also against floating-point error. */

    buff3[i] = (buff1[i] + buff2[i]) * 0.499;
}
于 2012-11-18T05:58:44.637 に答える
0

あなたが何をしようとしているのか、私にはまったくわかりません。あなたの説明によると、「一方のサウンド、もう一方のサウンド、および両方のミックスを含むwavファイルを作成したい」とのことです。ある音と別の音を組み合わせたいのなら、なぜこの2つの音を組み合わせて混ぜるのですか?それは、ミルクとクリームの混合物を取り、半分と半分を加えるようなものです。

たぶん、出力を3秒の長さにしようとしていて、最初の1秒には最初のサウンドが含まれ、2番目の秒には2番目のサウンドが含まれ、3番目の秒には2つのミックスが含まれていますが、コードはそのようなものではありません。私はその可能性を無視するつもりです。

少し基本的なことをしましょう。

最初のファイルの最初の1秒をコピーするには、ループは次のようになります。

buff3[i] = buff1[i] ;

2番目のファイルの最初の1秒をコピーするには、ループは次のようになります。

buff3[i] = buff2[i] ;

2つを混合するには、単にそれらを追加します。混合は結合と同じです。2つの信号の「重ね合わせ」を行っていると言うことがあります。

buff3[i] = buff1[i] + buff2[i] ;

通常、信号が「範囲外」になるのを防ぐために、2で除算する必要があります。

buff3[i] = ( buff1[i] + buff2[i] ) / 2  ;

信号のサンプル値を互いに乗算した場所がないことに注意してください。あなたが行っていたようなサンプルごとの乗算は、AM合成のような非常に珍しい状況のために予約されています。

于 2012-11-18T05:50:10.887 に答える