1

サウンド カードのみを使用してファイルを転送する必要があります。

これまでの私のアルゴリズムは、振幅シフト キーイング (ASK) に基づいています。

送信機:
プログラムは、変調されたデータを WAV ファイルに書き込みます。
ビットが 1 のときは単に「ノイズ」(波を作る) と書き、それ以外の場合は「無音」(振幅 0) と書きます。
無音とノイズのサンプル数は事前に定義されており、どちらの場合も同じです。

レシーバー:
プログラムは録音を開始し、あらかじめ定義されたノイズしきい値を超えるサンプルを待ちます。
ノイズを検出すると、「終了信号」が検出されるまで、録音されたサンプルを WAV ファイルに復調します。

プロトコル:

  1. 最初のバイトは 255 で、データの一部ではありません (新しいファイルで受信者に通知します)。
  2. 次に、データ (ファイルの内容) を書き込みます。
  3. セッションの終了を示す事前定義された 4 バイトを書き込みます。
  4. 各ビットは 3 回転送されるため、エラーが発生した場合、残りの 2 つ (ECC) によって正しいビットを推測できます。

NAudio C# ライブラリを使用して、WAV ファイル (録音、再生、書き込み、読み取り) を処理しています。

理解を深めるために、以下にコードの一部を追加しましたが、問題を解決できると思います。アルゴリズムの欠陥とそれを改善するにはどうすればよいかを知りたいだけです。

送信機:

//creates file with 44.1kHz sample-rate and 1 channel.
mWaveFileWriter = new WaveFileWriter(tempFile, new WaveFormat(44100, 1));

....

// save to WAV file modulated data the contains bytesData
public void Modulate(byte[] bytesData)
{
    foreach (var dataByte in bytesData)
    {
         // return 8 bit representation of the byte
         bool[] binaryByte = ToBinary(dataByte);

         foreach (bool bit in binaryByte)
         {
             if (bit)
                SaveNoise();
             else
                SaveSilence();
         }
         mWaveFileWriter.Dispose();
    }
}

private void SaveSilence()
{
    for (int n = 0; n < mSamplesPerBit; n++)
    {
        mWaveFileWriter.WriteSample(0);
    }
}

private void SaveNoise()
{
    // writes SamplesPerBit samples
    for (int n = 0; n < mSamplesPerBit; n++)
    {
        float sample = (float)(mNoiseAmplitude * Math.Sin((2 * Math.PI * n * mFrequency) / mWaveFileWriter.WaveFormat.SampleRate));
        mWaveFileWriter.WriteSample(sample);
    }
 }

このファイルを取得した後、一度再生されます。

System.Media.SoundPlayer player = new System.Media.SoundPlayer(tempFile);
player.Play();

レシーバー:

WaveInEvent mWaveIn = new WaveInEvent();
mWaveIn.WaveFormat = new WaveFormat(44100, 1);
mWaveIn.DataAvailable += mWaveIn_DataAvailable;

....

void mWaveIn_DataAvailable(object sender, WaveInEventArgs e)
{
    // since it's 16bit sampling, I normalize each 2 bytes to samples of range (-1.0f) - 1.0f.
    float[] samples = ToSamples(e.Buffer);

    ...   // saves data, process it etc...
}

すべてを書いたわけではありませんが、基本的に受信機は8 * SamplesPerBitノイズ サンプルを探します。(サンプルをノイズしきい値と比較して、サンプルにノイズがあるかどうかを判断します)。その後、終了信号が検出されるまで、他のすべてのデータを保存します。最後に、コンテンツをファイルに保存します。

問題は、これが適切に機能するためには、SamplesPerBit を少なくとも 100 にする必要があることです。1 秒あたり 44100 サンプルあるため、1 秒あたり約 441 ビットを書き込みます。
私のデータは 3 倍になったので、全体としては 20 バイト/秒未満です。

少なくとも 1KB/秒でデータを送信できる必要があります。

ビットレートを上げる方法についての提案は非常に役立ちます。

Naudio の The FastFourierTransform クラスを使用して、FSK (振幅は同じまま、周波数が変化する) でそれを行うことを考えましたが、その方法の方が高速になるとは思いません (エラーが発生しにくい可能性があります)。

4

1 に答える 1

0

あなたのアプローチの問題

  • 無音またはノイズが長すぎると、ストリームの同期が失われる可能性があります
  • たとえば、100MBのゼロを転送すると、最終的にデコードされたビット数が異なる場合があります
  • これは、時折の同期信号で修復できます
  • 適切に検出するのが容易ではないノイズを使用している (したがって転送速度が遅い)
  • オーディオ HW では途中にコンデンサがあるため、DC 信号が破壊されます。
  • DC信号を使用するコードは問題外ですが、他にもたくさんあるので...

ASK に縛られていない場合は、他にも多くのコーディングの可能性があります。

  1. FM

    • たとえば、0 は 22050Hz、1 は 44100Hz になります。
    • 各ビットは、いくつかの期間 (少なくとも 2 つ) にコーディングできます。
    • また、同期信号が時々必要になります (たとえば、11025Hz 10 周期で 1 分間に 1 回)。
  2. PCM

    • たとえば、44100Hz の 4 つのパルスは 1 です。
    • 44100hzの2パルスが0
    • およびすべてのビット間の無音の 2 期間
    • これには追加の同期信号は必要ありません

開始信号を追加することもできます

  • データの前のいくつかの明確な周波数と正確な一時停止
  • また、データの前に何らかのヘッダーを追加することもできます
  • 受信者は期待するデータ量を知っている
  • または、実験したい場合はどのコーディングを使用するか

[ノート]

  • パルス数または周波数を試すことができます
  • 高速で動作するはずのセットアップを提供します
  • ただし、エラー率をテストし、ハードウェアのセットアップに合わせて構成する必要があります...
  • 頻度を安全に特定するには、少なくとも 2 つの期間が必要です。
  • 騒がしい環境ではさらに...
于 2014-07-06T08:49:00.523 に答える