バイナリデータのストリームがあり、それを生の波形サウンドデータに変換してスピーカーに送信したいと考えています。
これは、電話回線を介してバイナリデータを転送するために旧式のモデムが行ったことです(典型的なモデムのような音を生成します)。これは変調と呼ばれます。
次に、逆のプロセスが必要です。生の波形サンプルから、正確なバイナリデータを取得したいと思います。これは復調と呼ばれます。
私はこれを行うための1つの特定の方法を見つけました--- 周波数シフトキーイング 。問題は、ソースコードが見つからないことです。
FSKの任意の言語での実装を教えていただけますか?
または、利用可能なソースコードを使用した代替エンコーディングバイナリ<->サウンドを提供しますか?
最も単純な変調方式は 振幅変調 です(技術的にはデジタル領域では、これは振幅シフトキーイングと呼ばれます)。固定周波数(たとえば10Khz)、つまり「搬送波」を取得し、バイナリデータのビットを使用してオンとオフを切り替えます。データレートが10ビット/秒の場合、そのレートで10KHz信号のオンとオフを切り替えることになります。復調は(オプションの)10KHzフィルタであり、その後にしきい値と比較されます。これは、実装するのにかなり簡単なスキームです。一般に、信号周波数と使用可能な帯域幅が高いほど、その信号のオンとオフをすばやく切り替えることができます。
ここでの非常にクールで楽しいアプリケーションは、モールス信号としてエンコード/デコードし、どれだけ速く進むことができるかを確認することです。
FSK、2つの周波数間をシフトすると、帯域幅がより効率的になり、ノイズの影響を受けにくくなりますが、2つの周波数を区別する必要があるため、復調器がより複雑になります。
位相偏移変調 などの高度な変調方式は、特定の帯域幅と信号対雑音比で最高のビットレートを取得するのに適していますが、実装がより複雑です。アナログ電話モデムは、特定の帯域幅(たとえば、わずか3Khz)とノイズ制限に対処する必要がありました。帯域幅とノイズの制限を考慮して可能な限り高いビットレートを取得する必要がある場合は、それが最適な方法です。
高度な変調方式の実際のコードサンプルについては、DSPベンダーからのアプリケーションノート( [〜#〜] ti [〜#〜] や Analog Devices など)を調査します。 DSPの一般的なアプリケーションでした。
TMS320C50を使用したPI/4シフトD-QPSKベースバンドモデムの実装
V.34 TMS320C50 DSPでの送信機と受信機の実装
もう1つの非常に単純で効率の悪い方法は、DTMFを使用することです。これらは、各記号が2つの周波数の組み合わせである電話のキーパッドによって生成されるトーンです。あなたがグーグルなら、あなたはたくさんのソースコードを見つけるでしょう。アプリケーション/要件によっては、これは簡単な解決策になる場合があります。
先に述べたモールス信号のような、いくつかの簡単なスキーム実装の詳細に飛び込みましょう。 0には「ドット」、1には「ダッシュ」を使用できます。モールスのようなスキームの利点は、スペースごとにサンプリングを再同期できるため、フレーミングの問題も解決できることです。簡単にするために、「搬送波」周波数を選択しましょう。 11KHzで、波の出力が44Khz、16ビット、モノラルであると仮定します。高調波を生成する方形波も使用しますが、あまり気にしません。11KHzがマイクの周波数応答を超えている場合は、すべての周波数を2で割ります。たとえば、任意のレベル10000を選択するため、「オン」の波形は次のようになります。
{10000, 10000, 0, 0, 10000, 10000, 0, 0, 10000, 0, 0, ...} // 4 samples = 11Khz period
「オフ」の波形はすべてゼロです。この部分のコーディングは、読者の演習として残しておきます。
そして、次のようなものがあります。
const int dot_samples = 400; // ~10ms - speed up later
const int space_samples = 400; // ~10ms
const int dash_samples = 800; // ~20ms
void encode( uint8_t* source, int length, int16_t* target ) // assumes enough room in target
{
for(int i=0; i<length; i++)
{
for(int j=0; j<8; j++)
{
if((source[i]>>j) & 1) // If data bit is 1 we'll encode a dot
{
generate_on(&target, dash_samples); // Generate ON wave for n samples and update target ptr
}
else // otherwise a dash
{
generate_on(&target, dot_samples); // Generate ON wave for n samples and update target ptr
}
generate_off(&target, space_samples); // Generate zeros
}
}
}
デコーダーはもう少し複雑ですが、概要は次のとおりです。
変調/復調の目的の1つは、チャネル特性に適応することです。たとえば、チャネルがDCを通過できない場合があります。別の目的は、特定のエラーレートを超えるデータを転送しながら、チャネル内の特定の量とタイプのノイズを克服することです。
FSKの場合、送信側で2つの異なる周波数で正弦波を生成し、受信側で2つの異なる周波数をフィルタリングおよび検出できるルーチンが必要です。正弦波の各セグメントの長さ、周波数の分離、および振幅は、データレートと克服する必要のあるノイズの量によって異なります。
最も単純なケースであるゼロノイズでは、連続する固定時間フレーム内でNまたは2Nの正弦波を生成するだけです。何かのようなもの:
x[i] = amplitude * sin( i * 2 * pi * (data[j] ? 1.0 : 2.0) * freq) / sampleRate )
受信側では、最大周波数の2倍をはるかに超える信号をサンプリングし、ゼロ交差間の距離を測定して、短周期または長周期の波形が多数あるかどうかを確認できます。ゼロ以外のノイズが存在する場合は、デジタル信号処理フィルター(IIR、FIRなど)とさまざまな統計検出器を使用した、より高度な方法を使用できます。