Buat modem (perangkat lunak)!

14

Objektif

Desain mo dulator / dem pasangan odulator data akurat mengirimkan secepat mungkin lebih simulasi layanan telepon biasa lama (POTS) .

Langkah

  1. Hasilkan beberapa acak (/dev/random atau sejenisnya) yang akan membutuhkan 3-4 detik untuk dikirim
  2. Memodulasi data dengan modulator Anda untuk menghasilkan file audio
  3. Lulus file audio melalui simulator POTS . Jika Anda tidak memiliki Python / Scipy, Anda dapat mengunggah file dengan formulir, atau melakukan permintaan API JSON.
  4. Demodulasi file audio kembali ke data biner
  5. Validasi bahwa input dan output sama dengan ish * (batas 1 dari setiap 1000 bit dapat rusak)
  6. Skor adalah jumlah bit yang dikirim dibagi dengan panjang file audio (bit / detik)

Aturan

  • File input harus 3-4 detik, 44,1 kHz, mono.
  • Jalankan simulator dengan SNR 30 dB (default)
  • Demodulator harus merekonstruksi data yang dikirimkan dengan tingkat kesalahan bit tidak lebih dari 10 -3 (1 per seribu bit).
  • Tidak ada kompresi digital yang diizinkan (yaitu zipping data. Ini di luar ruang lingkup tantangan.)
  • Tidak berusaha memasukkan data ke frekuensi di atas 4 kHz. (Filter saya tidak sempurna, tetapi cukup seperti POT dengan sedikit keran.)
  • Jika protokol modem Anda memerlukan pembukaan singkat (tidak lebih dari 1 detik) untuk menyinkronkan / mengkalibrasi penerima, protokol itu tidak dikenakan sanksi.
  • Jika memungkinkan, silakan host file audio di tempat yang dapat diakses sehingga kami dapat mendengarkan hiruk-pikuk bunyi bip dan boops.

Contoh

Berikut adalah contoh buku catatan yang menunjukkan modulasi / demodulasi dengan "on-off keying" sederhana (termasuk sampel audio!).

Itu akan skor 100 (bit / detik). Perhatikan bahwa transmisi dengan SNR 5 dB jauh lebih buruk.

Nick T
sumber
2
Apakah ini berbeda dari tantangan "kompres data biner ini" yang biasa? Jika demikian, dapatkah Anda menjelaskan seberapa tepatnya perbedaannya?
Gagang Pintu
1
Di sini Anda memodulasi data (mengubahnya menjadi sesuatu yang analog) kemudian sebaliknya. Orang mungkin bisa menyebutnya "kompresi analog"
Nick T
Maaf, saya tidak yakin saya mengerti bagaimana tantangan ini bekerja. Kata "memodulasi" bahkan tidak muncul di artikel Wikipedia yang Anda tautkan. Bisakah Anda memasukkan lebih banyak informasi latar belakang, atau memperjelas spesifikasi?
Gagang Pintu
4
wget wikipedia.org/Special:Random | grep title | texttospeech audio.wav speechtotext POTSaudio.wav | wget wikipedia/wiki/$text
TessellatingHeckler
1
Ini adalah tantangan yang luar biasa, saya akan mencoba mencari waktu untuk mengirimkan jawaban!
GoatInTheMachine

Jawaban:

7

MATLAB, 1960 bps

Ini adalah upaya saya yang diperbarui:

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

Sejak upaya pertama saya, saya telah bermain-main sedikit. Sekarang ada pembukaan kecil di awal (periode 18 bit, tetapi bisa lebih pendek) yang hanya berisi gelombang kosinus. Saya mengekstrak ini dan mereplikasinya untuk membuat pembawa sinus dan kosinus fase yang benar untuk demodulasi - karena ini adalah pembukaan yang sangat singkat, saya belum menghitungnya dalam bit rate sesuai instruksi Anda.

Juga sejak upaya pertama saya sekarang menggunakan konstelasi QAM8 untuk mencapai 3 bit per simbol daripada 2. Ini secara efektif menggandakan kecepatan transfer. Jadi dengan operator ~ 2.4kHz saya sekarang mencapai 1960bps.

Saya juga telah meningkatkan deteksi simbol sehingga rata-rata tidak terpengaruh oleh waktu naik lambat yang disebabkan oleh penyaringan - pada dasarnya hanya paruh kedua dari setiap periode bit dirata-rata untuk menghilangkan dampak waktu naik.

Masih jauh dari bandwidth saluran teoritis 40kbps dari teori Shannon-Hartley (dengan asumsi 30dB SNR)

Hanya untuk mereka yang menyukai suara mengerikan , ini adalah entri baru:


Dan jika ada yang tertarik, ini adalah entri 960bps sebelumnya

Tom Carpenter
sumber
Penilaian hanyalah tingkat transfer, jadi jaga kode Anda tetap jelas. Saya menambahkan saran untuk meng-host file audio Anda di suatu tempat jika mudah untuk funsies: D
Nick T
Saya akan mengunggah audio ke situs saya. Kedengarannya agak menakutkan!
Tom Carpenter
@NickT file audio yang diunggah - lihat tautan di bagian bawah posting.
Tom Carpenter
Jika Anda memiliki akun SoundCloud, Anda dapat mengunggah audio dan memposting tautan dan itu akan dapat diputar di pos Anda. ( Contoh )
Hobbies Calvin pada
@NickT terima kasih. Saya telah membuat akun soundcloud dan mengunggahnya. Saya juga membuat versi yang diperbarui dengan menggandakan data rate :)
Tom Carpenter