สร้างโมเด็ม (ซอฟต์แวร์)!


14

วัตถุประสงค์

ออกแบบคู่mo mo dulator / dem odulatorเพื่อส่งข้อมูลอย่างรวดเร็วที่สุดเท่าที่จะทำได้ผ่านบริการโทรศัพท์ธรรมดาแบบเก่า (POTS)(หม้อ)

ขั้นตอน

  1. สร้างแบบสุ่ม (/dev/randomหรือที่คล้ายกัน) ซึ่งจะใช้เวลาในการส่ง 3-4 วินาที
  2. แก้ไขข้อมูลด้วยโมดูเลเตอร์ของคุณเพื่อสร้างไฟล์เสียง
  3. ส่งไฟล์เสียงผ่านเครื่องจำลอง POTSจำลองหม้อหากคุณไม่มี Python / Scipy คุณสามารถอัปโหลดไฟล์ด้วยแบบฟอร์มหรือทำคำขอ JSON API
  4. demodulate ไฟล์เสียงกลับไปเป็นข้อมูลไบนารี
  5. ตรวจสอบว่าอินพุตและเอาต์พุตเท่ากับ -h * (จำกัด 1 จากทุก ๆ 1,000 บิตอาจเสียหายได้)
  6. คะแนนคือจำนวนบิตที่ส่งหารด้วยความยาวของไฟล์เสียง (บิต / วินาที)

กฎระเบียบ

  • ไฟล์อินพุตต้องเป็น 3-4 วินาที, 44.1 kHz, mono
  • รันโปรแกรมจำลองด้วย SNR ที่ 30 เดซิเบล (เป็นค่าเริ่มต้น)
  • demodulator ต้องสร้างข้อมูลที่ส่งใหม่ด้วยอัตราความผิดพลาดบิตไม่เกิน 10 -3 (1 ต่อพันบิต)
  • ไม่อนุญาตให้มีการบีบอัดข้อมูลดิจิทัล (เช่นการบีบอัดข้อมูลซึ่งอยู่นอกขอบเขตของความท้าทาย)
  • ไม่พยายามดันข้อมูลเป็นความถี่สูงกว่า 4 kHz (ตัวกรองของฉันไม่สมบูรณ์แบบ แต่มันก็เหมือนกับ POTS ที่มีจำนวนก๊อกค่อนข้างน้อย)
  • หากโพรโทคอลโมเด็มของคุณต้องการการเริ่มนำแบบสั้น (ไม่เกิน 1 วินาที) เพื่อซิงโครไนซ์ / สอบเทียบตัวรับมันจะไม่ถูกลงโทษ
  • หากเป็นไปได้โปรดโฮสต์ไฟล์เสียงไว้ที่ใดที่สามารถเข้าถึงได้เพื่อให้เราสามารถฟังเสียงขรมของเสียงบี๊บและเสียงโห่

ตัวอย่าง

นี่คือตัวอย่างโน๊ตบุ๊คที่แสดงให้เห็นถึงการปรับ / demodulation ด้วย "key on-off" (ตัวอย่างเสียงรวมอยู่ด้วย!)

มันจะได้คะแนน 100 (บิต / วินาที) โปรดทราบว่ามันกำลังส่งสัญญาณด้วย SNR ที่แย่กว่ามาก 5 dB


2
สิ่งนี้แตกต่างจากการท้าทาย "บีบอัดข้อมูลไบนารีนี้" หรือไม่? ถ้าเป็นเช่นนั้นคุณสามารถอธิบายได้อย่างแม่นยำว่ามันแตกต่างกันอย่างไร
Doorknob

1
ที่นี่คุณกำลังปรับข้อมูล (เปลี่ยนเป็นอะนาล็อกบางอย่าง) จากนั้นย้อนกลับ อาจเรียกได้ว่า "การบีบอัดแบบแอนะล็อก"
Nick T

ขออภัยฉันไม่แน่ใจว่าฉันเข้าใจความท้าทายนี้ได้อย่างไร คำว่า "มอดูเลต" จะไม่ปรากฏในบทความ Wikipedia ที่คุณเชื่อมโยง คุณสามารถรวมข้อมูลพื้นหลังเพิ่มเติมหรือชี้แจงรายละเอียดได้หรือไม่
Doorknob

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 บิต แต่อาจสั้นกว่า) ซึ่งมีเพียงแค่คลื่นโคไซน์ ฉันแยกมันออกมาและทำซ้ำเพื่อสร้าง phased sine และ cosine carrier เพื่อ demodulation อย่างถูกต้อง - เนื่องจากเป็นการเริ่มนำที่สั้นมากฉันไม่ได้นับในอัตราบิตตามคำแนะนำของคุณ

นอกจากนี้ตั้งแต่ครั้งแรกที่ฉันใช้กลุ่ม QAM8 เพื่อให้ได้ 3 บิตต่อสัญญลักษณ์แทน 2 สิ่งนี้ทำให้อัตราการถ่ายโอนเป็นสองเท่าได้อย่างมีประสิทธิภาพ ด้วยผู้ให้บริการ ~ 2.4kHz ตอนนี้ฉันได้รับ 1960bps

ฉันได้ปรับปรุงการตรวจจับสัญลักษณ์เพื่อให้ค่าเฉลี่ยไม่ได้รับผลกระทบจากเวลาที่เพิ่มขึ้นอย่างช้า ๆ ซึ่งเกิดจากการกรองโดยทั่วไปแล้วเพียงช่วงครึ่งหลังของแต่ละช่วงเวลาบิตจะถูกนำมาเฉลี่ยเพื่อขจัดผลกระทบของเวลาที่เพิ่มขึ้น

ยังคงอยู่ใกล้กับแบนด์วิดท์ช่องทฤษฎี 40kbps จากทฤษฎีShannon-Hartley (สมมติว่า 30dB SNR)

สำหรับผู้ที่ชอบเสียงที่น่ากลัวนี่เป็นรายการใหม่:


และในกรณีที่ใครสนใจรายการนี้เป็น 960bps ก่อนหน้า


การให้คะแนนเป็นเพียงอัตราการถ่ายโอนดังนั้นควรรักษารหัสของคุณให้ชัดเจน ฉันได้เพิ่มข้อเสนอแนะเพื่อโฮสต์ไฟล์เสียงของคุณที่ไหนสักแห่งถ้ามันง่ายสำหรับ funsies: D
Nick T

ฉันจะอัปโหลดเสียงไปยังเว็บไซต์ของฉัน มันฟังดูค่อนข้างน่าขนลุก!
Tom Carpenter

อัปโหลดไฟล์เสียง @NickT - ดูลิงก์ที่ด้านล่างของโพสต์
Tom Carpenter

หากคุณมีบัญชี SoundCloud คุณสามารถอัปโหลดเสียงและโพสต์ลิงก์และจะสามารถเล่นได้ในโพสต์ของคุณ ( ตัวอย่าง )
งานอดิเรกของ Calvin

@NickT ขอบคุณ ฉันได้สร้างบัญชี soundcloud และอัปโหลดแล้ว ผมได้ทำยังเป็นรุ่นที่ปรับปรุงคู่กับอัตราการส่งข้อมูล :)
ทอมไม้
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.