(ソフトウェア)モデムを作成してください!


14

目的

デザインのMo dulator / DEM odulatorペアできるだけ早く以上のシミュレートとして正確に伝達するデータへの電話サービス(POTS)を

手順

  1. ランダム(/dev/random送信に3〜4秒かかるまたは同様の)データをします。
  2. 変調器でデータを変調して、音声ファイルを生成します
  3. POTSシミュレーターを介してオーディオファイルを渡す。Python / Scipyがない場合は、フォームでファイルをアップロードするか、JSON APIリクエストを実行できます。
  4. オーディオファイルを復調してバイナリデータに戻す
  5. 入力と出力が等値*であることを検証します(1000ビットごとに1つが破損する可能性があります)
  6. スコアは、送信されたビット数をオーディオファイルの長さ(ビット/秒)で割ったものです。

ルール

  • 入力ファイルは3〜4秒、44.1 kHz、モノラルでなければなりません。
  • 30 dBのSNRでシミュレーターを実行します(デフォルト)
  • 復調器は、送信されたデータを10 -3以下のビット誤り率で再構築する必要があります(1000ビットあたり1)ます。
  • デジタル圧縮は許可されません(つまり、データを圧縮します。これは課題の範囲外です)。
  • 4 kHzを超える周波数にデータを押し出そうとはしません。(私のフィルターは完全ではありませんが、比較的少ないタップ数でPOTSに似ています。)
  • モデムプロトコルが受信機を同期/キャリブレーションするために短いプリアンブル(1秒以内)を必要とする場合、ペナルティは課されません。
  • 可能であれば、ビープ音とブープ音の不協和音を聞くことができるように、アクセス可能なオーディオファイルをホストしてください

これは、簡単な「オン/オフキーイング」(オーディオサンプルが含まれています!)による変調/復調を示すノートブックです。

スコアは100(ビット/秒)になります。はるかに悪い5 dB SNRで送信していることに注意してください。


2
これは、通常の「このバイナリデータを圧縮する」チャレンジとは異なりますか?もしそうなら、それがどれほど正確に異なるかを明確にできますか?
ドアノブ

1
ここでは、データを変調(アナログに変換)してから逆にしています。「アナログ圧縮」と呼ぶこともできます
Nick T

申し訳ありませんが、この課題がどのように機能するのか理解できません。リンクしたWikipediaの記事には「変調する」という言葉は現れません。バックグラウンド情報を追加したり、仕様を明確にしたりできますか?
ドアノブ

4
wget wikipedia.org/Special:Random | grep title | texttospeech audio.wav speechtotext POTSaudio.wav | wget wikipedia/wiki/$text
TessellatingHeckler

1
これは素晴らしいチャレンジです。答えを提出する時間を見つけようとします!
GoatInTheMachine

回答:


7

MATLAB、1960 bps

ここに私の更新された試みがあります:

fs = 44100; %44.1kHz audio rate
fc = 2450;  %2.45kHz carrier - nice fraction of fs!
fsym = fc/5; %symbol rate

tmax = 4; %about 4 seconds worth

preamblesyms = 6;

t = 1/fs:1/fs:(tmax+preamblesyms/fsym);

symbols = preamblesyms+fsym*tmax;
symbollength = length(t)/symbols;
bits = symbols*3;
bitstream = [zeros(1,preamblesyms*3),rand(1,bits-preamblesyms*3)>0.5]; %Add a little preamble of 18 bits
data = bin2dec(char(reshape(bitstream,3,symbols)'+'0'))';

greycode = [0 1 3 2 6 7 5 4];

%Encode the symbols using QAM8 - we use effectively grey code so that
%adjacent symbols in the constellation have only one bit difference
%(minimises error rate)
encoded = zeros(2,symbols);
encoded(1,data==1) = 1/sqrt(2);
encoded(1,data==3) = 1;
encoded(1,data==2) = 1/sqrt(2);
encoded(1,data==7) = -1/sqrt(2);
encoded(1,data==5) = -1;
encoded(1,data==4) = -1/sqrt(2);
encoded(2,data==0) = 1;
encoded(2,data==1) = 1/sqrt(2);
encoded(2,data==2) = -1/sqrt(2);
encoded(2,data==6) = -1;
encoded(2,data==7) = -1/sqrt(2);
encoded(2,data==4) = 1/sqrt(2);

%Modulate onto carrier
carrier = [sin(2*pi*fc*t);cos(2*pi*fc*t)];
signal = reshape(repmat(encoded(1,:)',1,symbollength)',1,[]);
signal(2,:) = reshape(repmat(encoded(2,:)',1,symbollength)',1,[]);
modulated = sum(signal.*carrier)';

%Write out an audio file
audiowrite('audio.wav',modulated,fs);

%Wait for the user to run through the POTS simulator
input('');

%Read in the filtered data
filtered=audioread('audio.pots-filtered.wav')';

%Recover the two carrier signals
preamblecos = filtered(symbollength+1:symbollength*2);
preamblesin = filtered(symbollength+1+round(symbollength*3/4):symbollength*2+round(symbollength*3/4));

%Replicated the recovered carriers for all symbols
carrierfiltered = [repmat(preamblesin,1,symbols);repmat(preamblecos,1,symbols)];

%Generate a demodulation filter (pass up to 0.66*fc, stop at 1.33*fc
%(really we just need to kill everything around 2*fc where the alias ends up)
d=fdesign.lowpass('Fp,Fst,Ap,Ast',0.05,0.1,0.5,60);
Hd = design(d,'equiripple');

%Demodulate the incoming stream
demodulated = carrierfiltered .* [filtered;filtered];
demodulated(1,:)=filtfilt(Hd.Numerator,1,demodulated(1,:));
demodulated(2,:)=filtfilt(Hd.Numerator,1,demodulated(2,:));

%Split signal up into bit periods
recovereddemodulated=[];
recovereddemodulated(1,:,:) = reshape(demodulated(1,:),symbollength,symbols);
recovereddemodulated(2,:,:) = reshape(demodulated(2,:),symbollength,symbols);

%Extract the average level for each bit period. Only look at the second
%half to account for slow rise times in the signal due to filtering
recoveredsignal=mean(recovereddemodulated(1,round(symbollength/2):symbollength,:));
recoveredsignal(2,:)=mean(recovereddemodulated(2,round(symbollength/2):symbollength,:));

%Convert the recovered signal into a complex number.
recoveredsignal=recoveredsignal(2,:) + 1j*recoveredsignal(1,:);

%Determine the magnitude and angle of the symbol. The phase is normalised
%to pi/4 as that is the angle between the symbols. Rounding this to the
%nearest integer will tell us which of the 8 phases it is closest to
recoveredphase = round(angle(recoveredsignal)/(pi/4));
recoveredphase = mod(recoveredphase+8,8)+1; %Remap to an index in the grey code vector.

%Determine the symbol in the QAM8 constellation
recoveredencoded=greycode(recoveredphase);
recoveredencoded(1:preamblesyms)=0; %Assume the preamble is correct for comparison

%Turn it back in to a bit stream
bitstreamRecovered = reshape(dec2bin(recoveredencoded)'-'0',1,[]);

%And check if they are all correct...
if(all(bitstream==bitstreamRecovered))
    disp(['Woop, ' num2str(fsym*4) 'bps']);
else
    error('Its corrupt Jim.');
end

私の最初の試み以来、私は少し遊んでいます。余弦波のみを含む小さなプリアンブルが最初にあります(18ビット周期ですが、短くすることもできます)。これを抽出して複製し、復調用の正しい位相の正弦波と余弦波の搬送波を作成しました。これは非常に短いプリアンブルであるため、指示どおりにビットレートでカウントしていません。

また、最初の試行以来、QAM8コンスタレーションを使用して、シンボルごとに2ではなく3ビットを達成しています。これにより、転送速度が事実上2倍になります。そのため、約2.4kHzのキャリアで1960bpsを達成しています。

シンボル検出を改善し、平均化がフィルタリングによる遅い立ち上がり時間の影響を受けないようにしました。基本的に、各ビット周期の後半のみが平均化され、立ち上がり時間の影響が除去されます。

まだシャノン-ハートレー理論からの40kbps理論チャネル帯域幅の近くにはどこにもありません(30dB SNRを想定)

恐ろしい音が好き人のために、これは新しいエントリです:


そして、誰かが興味を持っている場合、これは前の960bpsエントリです


スコアリングは単なる転送速度であるため、コードを明確にしてください。それはfunsiesのために簡単だ場合、私はホストあなたのオーディオファイルのどこかに提案を追加しました:D
ニック・T

音声を自分のサイトにアップロードします。かなり不気味ですね!
トムカーペンター

@NickT音声ファイルがアップロードされました-投稿の下部にあるリンクをご覧ください。
トムカーペンター

SoundCloudアカウントをお持ちの場合は、音声をアップロードしてリンクを投稿すると、投稿で再生可能になります。(
カルビンの趣味

@NickTありがとう。soundcloudアカウントを作成してアップロードしました。また、データレートを2倍にした更新バージョンも作成しました:)
トムカーペンター
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.