MATLAB, 1960 bps
Hier ist mein aktualisierter Versuch:
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
Seit meinem ersten Versuch habe ich ein bisschen rumgespielt. Es gibt jetzt eine kleine Präambel am Anfang (18-Bit-Perioden, die aber kürzer sein könnte), die nur eine Kosinuswelle enthält. Ich extrahiere dies und repliziere es, um korrekt phasengesteuerte Sinus- und Cosinus-Träger für die Demodulation zu erstellen. Da es sich um eine sehr kurze Präambel handelt, habe ich sie nicht gemäß Ihren Anweisungen in der Bitrate gezählt.
Auch seit dem ersten Versuch verwende ich jetzt eine QAM8-Konstellation, um 3 Bits pro Symbol anstelle von 2 zu erzielen. Dies verdoppelt effektiv die Übertragungsrate. Mit einem Träger mit ~ 2,4 kHz erreiche ich jetzt 1960 Bit / s.
Ich habe auch die Symbolerkennung verbessert, damit die Mittelwertbildung nicht durch langsame Anstiegszeiten beeinträchtigt wird, die durch die Filterung verursacht werden. Im Grunde wird nur die zweite Hälfte jeder Bitperiode gemittelt, um den Einfluss von Anstiegszeiten zu beseitigen.
Noch lange nicht annähernd die theoretische Kanalbandbreite von 40kbps von der Shannon-Hartley-Theorie (unter der Annahme des 30-dB-SNR)
Nur für diejenigen, die schreckliche Klänge mögen , ist dies der neue Eintrag:
Und falls jemand interessiert ist, ist dies der vorherige Eintrag mit 960 Bit / s