Crea un modem (software)!


14

Obbiettivo

Progettare un mo dulator / DEM coppia odulator di dati con precisione trasmettere il più rapidamente possibile nel corso simulato Plain Old Telephone Service (POTS) .

passi

  1. Genera alcuni dati casuali ( /dev/randomo simili) che impiegheranno 3-4 secondi per trasmettere
  2. Modula i dati con il tuo modulatore per produrre un file audio
  3. Passa il file audio attraverso il simulatore POTS . Se non hai Python / Scipy puoi caricare un file con il modulo o fare una richiesta API JSON.
  4. Demodula il file audio in dati binari
  5. Convalida che input e output siano uguali * (il limite 1 su ogni 1000 bit può essere danneggiato)
  6. Il punteggio è il numero di bit trasmessi diviso per la lunghezza del file audio (bit / secondo)

Regole

  • Il file di input deve essere 3-4 secondi, 44,1 kHz, mono.
  • Esegui il simulatore con un SNR di 30 dB (impostazione predefinita)
  • Il demodulatore deve ricostruire i dati trasmessi con un tasso di errore di bit non superiore a 10 -3 (1 per mille bit).
  • Non è consentita la compressione digitale (ovvero comprimere i dati. È al di fuori dell'ambito della sfida.)
  • Nessun tentativo di trasferire i dati a frequenze superiori a 4 kHz. (I miei filtri non sono perfetti, ma sono ragionevolmente simili a POTS con un numero relativamente piccolo di tocchi.)
  • Se il protocollo del modem richiede un breve preambolo (non più di 1 secondo) per sincronizzare / calibrare il ricevitore, non viene penalizzato.
  • Se possibile, si prega di ospitare il file audio da qualche parte accessibile in modo da poter ascoltare una cacofonia di segnali acustici e boops.

Esempio

Ecco un quaderno di esempio che dimostra la modulazione / demodulazione con un semplice "on-off keying" (campioni audio inclusi!).

Avrebbe segnato 100 (bit / secondo). Si noti che sta trasmettendo con un SNR 5 dB molto peggiore.


2
È diverso da una normale sfida "comprimere questi dati binari"? In tal caso, potresti chiarire con quale precisione differisce?
Maniglia della porta

1
Qui stai modulando i dati (trasformandoli in qualcosa di analogico) e poi il contrario. Si potrebbe forse chiamarlo "compressione analogica"
Nick T

Spiacenti, non sono sicuro di aver capito come funziona questa sfida. La parola "modulare" non appare nemmeno nell'articolo di Wikipedia che hai collegato. Potresti includere ulteriori informazioni di base o chiarire le specifiche?
Maniglia della porta

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

1
Questa è una sfida fantastica, cercherò di trovare il tempo per inviare una risposta!
GoatInTheMachine,

Risposte:


7

MATLAB, 1960 bps

Ecco il mio tentativo aggiornato:

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

Dal mio primo tentativo, ho giocato un po '. Ora c'è un piccolo preambolo all'inizio (periodi di 18 bit, ma potrebbe essere più breve) che contiene solo un'onda di coseno. L'ho estratto e l'ho replicato per creare corrieri di seno e coseno per fasi in fase corretta per la demodulazione - dato che è un preambolo molto breve, non l'ho conteggiato nel bit rate secondo le tue istruzioni.

Anche dal primo tentativo ora sto usando una costellazione QAM8 per ottenere 3 bit per simbolo invece di 2. Questo raddoppia effettivamente la velocità di trasferimento. Quindi con un vettore ~ ​​2.4kHz sto raggiungendo i 1960 bps.

Ho anche migliorato il rilevamento dei simboli in modo che la media non venga influenzata dai tempi di salita lenti causati dal filtro - in pratica viene calcolata la media solo della seconda metà di ogni periodo di bit per rimuovere l'impatto dei tempi di salita.

Ancora da nessuna parte vicino alla larghezza di banda del canale teorico 40kbps dal teoria di Shannon-Hartley (assumendo il SNR 30dB)

Solo per quelli a cui piacciono i suoni orribili , questa è la nuova voce:


E nel caso qualcuno fosse interessato, questa è la precedente voce a 960bps


Il punteggio è solo la velocità di trasferimento, quindi mantieni il tuo codice chiaro. Ho aggiunto un suggerimento per ospitare il tuo file audio da qualche parte se è facile per i divertimenti: D
Nick T

Carico l'audio sul mio sito. Sembra piuttosto inquietante!
Tom Carpenter,

File audio @NickT caricato - vedi il link in fondo al post.
Tom Carpenter,

Se hai un account SoundCloud puoi caricare il tuo audio e pubblicare un link e sarà riproducibile nel tuo post. ( Esempio )
Calvin's Hobbies,

@NickT grazie. Ho creato un account soundcloud e l'ho caricato. Ho anche realizzato una versione aggiornata con una velocità dati doppia :)
Tom Carpenter,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.