Piszę przykład przesyłania danych przez dźwięk między 2 komputerami. Niektóre wymagania:
Odległość jest bardzo bliska, tzn. 2 komputery są w zasadzie przylegające do siebie
Bardzo mało hałasu (nie sądzę, żeby mój nauczyciel włączył rockową piosenkę jako źródło hałasu)
Błąd jest dopuszczalny: na przykład, jeśli wyślę „Komunikacja radiowa”, to jeśli drugi komputer odbierze „RadiQ communEcation”, to również jest w porządku.
Jeśli to możliwe: brak nagłówka, flagi, sumy kontrolnej, .... ponieważ chcę tylko bardzo prosty przykład demonstrujący podstawy przesyłania danych przez dźwięk. Nie musisz być fantazyjny.
Próbowałem użyć Audio Shift Keying Shift według tego linku:
Lab 5 APRS (automatyczny system raportowania paczek)
i uzyskałem kilka wyników: Moja strona Github
ale to nie wystarczy. Nie wiem, jak wykonać odzyskiwanie zegara, synchronizację, ... (link ma mechanizm synchronizacji fazy jako mechanizm odzyskiwania czasu, ale najwyraźniej to nie wystarczyło).
Myślę więc, że powinienem znaleźć prostsze podejście. Znaleziono link tutaj:
Dane do audio i wstecz. Modulacja / demodulacja z kodem źródłowym
ale OP nie wdrożył metody sugerowanej w odpowiedzi, więc obawiam się, że może być bardzo złożona. Również nie rozumiem jasno metody dekodowania zaproponowanej w odpowiedzi:
Dekoder jest nieco bardziej skomplikowany, ale oto zarys:
Opcjonalnie filtruj pasmowo-filtrowy próbkowany sygnał około 11 kHz. Poprawi to wydajność w głośnym otoczeniu. Filtry FIR są dość proste i istnieje kilka apletów projektu online, które wygenerują filtr dla Ciebie.
Przekrocz próg sygnału. Każda wartość powyżej 1/2 maksymalnej amplitudy wynosi 1, a każda wartość poniżej wynosi 0. To zakłada, że próbkowałeś cały sygnał. Jeśli odbywa się to w czasie rzeczywistym, albo wybierasz stały próg, albo wykonujesz automatyczną kontrolę wzmocnienia, w której śledzisz maksymalny poziom sygnału przez pewien czas.
Wyszukaj początek kropki lub myślnika. Prawdopodobnie chcesz zobaczyć przynajmniej pewną liczbę jedynek w okresie kropki, aby uznać próbki za kropkę. Następnie kontynuuj skanowanie, aby sprawdzić, czy to kreska. Nie oczekuj idealnego sygnału - zobaczysz kilka zer na środku swoich zer i kilka jedynek na środku swoich zer. Jeśli występuje niewielki hałas, odróżnienie okresów włączenia od okresów wyłączenia powinno być dość łatwe.
Następnie odwróć powyższy proces. Jeśli widzisz myślnik wypchnij 1 bit do bufora, jeśli kropka popchnie zero.
Nie rozumiem, ile cyfr 1 sklasyfikowano jako kropkę ... Więc jest wiele rzeczy, których teraz nie rozumiem. Proszę zasugerować mi prostą metodę przesyłania danych dźwiękiem, aby zrozumieć proces. Dziękuję Ci bardzo :)
AKTUALIZACJA:
Zrobiłem trochę kodu Matlaba, który wydaje się (nieco) działać. Najpierw moduluję sygnał za pomocą kluczowania z przesunięciem amplitudy (częstotliwość próbkowania 48000 Hz, F_on = 5000 Hz, przepływność = 10 bitów / s), a następnie dodaję go z nagłówkiem i sekwencją końcową (oczywiście je również moduluję). Nagłówek i sekwencja końcowa zostały wybrane na zasadzie ad hoc (tak, to był hack):
header = [0 0 1 0 1 1 1 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 1 1 0 1 0 1];
end_seq = [1 1 1 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 1 0 0 1 0 0 0 1];
Następnie przesyłam je dźwiękiem i nagrywam na smartfonie. Następnie wysyłam nagrany dźwięk z powrotem do mojego komputera, użyj innego fragmentu kodu, aby odczytać dźwięk. Następnie koreluję odbierany sygnał (jeszcze nie zdemodulowany) z modulowanym nagłówkiem i sekwencją końcową, aby znaleźć początek i koniec. Następnie biorę tylko odpowiedni sygnał (od początku do końca, jak w części dotyczącej korelacji). Następnie demoduluję i próbkuję, aby znaleźć dane cyfrowe. Oto 3 pliki audio:
„DigitalCommunication_ask”: Link tutaj przesyła tekst „Komunikacja cyfrowa”. Stosunkowo bezszumowy, chociaż na początku i na końcu słychać szum tła. Jednak wynik pokazał tylko „Digital Commincatio”
„HelloWorld_ask”: Link tutaj wysyła tekst „Hello world”. Bez hałasu jak „DigitalCommunication_ask”. Jednak wynik tego był poprawny
„HelloWorld_noise_ask”: Link tutaj wysyła tekst „Hello world”. Jest jednak trochę hałasu, który wydałem (właśnie powiedziałem kilka przypadkowych rzeczy „A, B, C, D, E,…” podczas transmisji). Niestety ten zawiódł
Oto kod nadawcy (sender.m):
clear
fs = 48000;
F_on = 5000;
bit_rate = 10;
% header = [0 0 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ];
% header = [0 0 1 0 1 1 1 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 ];
header = [0 0 1 0 1 1 1 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 1 1 0 1 0 1];
% end_seq = [1 0 0 1 0 1 0 0 1 0 1 1 0 0 0 1 0 0 0 0 1 0 0 1 1 0 0 0 1 0 0 1];
% end_seq = [1 0 0 1 0 1 0 0 1 0 1 1 0 0 0 1 0 0 0 0 1 0 0 1 1 0 0 0 1 0 0 1 0 1 0 0 1 1 0 0 1 1 0 1 1 0 0 1 ];
% end_seq = [0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 1 0 0];
end_seq = [1 1 1 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 1 0 0 1 0 0 0 1];
num_of_samples_per_bit = round(fs / bit_rate);
modulated_header = ask_modulate(header, fs, F_on, bit_rate);
modulated_end_seq = ask_modulate(end_seq, fs, F_on, bit_rate);
% input_str = 'Ah';
input_str = 'Hello world';
ascii_list = double(input_str); % https://www.mathworks.com/matlabcentral/answers/298215-how-to-get-ascii-value-of-characters-stored-in-an-array
bit_stream = [];
for i = 1:numel(ascii_list)
bit = de2bi(ascii_list(i), 8, 'left-msb');
bit_stream = [bit_stream bit];
end
bit_stream = [header bit_stream end_seq];
num_of_bits = numel(bit_stream);
bandlimited_and_modulated_signal = ask_modulate(bit_stream, fs, F_on, bit_rate);
sound(bandlimited_and_modulated_signal, fs);
W przypadku odbiornika (odbiornik.m):
clear
fs = 48000;
F_on = 5000;
bit_rate = 10;
% header = [0 0 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ];
% header = [0 0 1 0 1 1 1 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 ];
header = [0 0 1 0 1 1 1 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 1 1 0 1 0 1];
% end_seq = [1 0 0 1 0 1 0 0 1 0 1 1 0 0 0 1 0 0 0 0 1 0 0 1 1 0 0 0 1 0 0 1];
% end_seq = [1 0 0 1 0 1 0 0 1 0 1 1 0 0 0 1 0 0 0 0 1 0 0 1 1 0 0 0 1 0 0 1 0 1 0 0 1 1 0 0 1 1 0 1 1 0 0 1 ];
% end_seq = [0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 1 0 0];
end_seq = [1 1 1 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 1 0 0 1 0 0 0 1];
modulated_header = ask_modulate(header, fs, F_on, bit_rate);
modulated_end_seq = ask_modulate(end_seq, fs, F_on, bit_rate);
% recObj = audiorecorder(fs,8,1);
% time_to_record = 10; % In seconds
% recordblocking(recObj, time_to_record);
% received_signal = getaudiodata(recObj);
% [received_signal, fs] = audioread('SounddataTruong_Ask.m4a');
% [received_signal, fs] = audioread('HelloWorld_noise_ask.m4a');
% [received_signal, fs] = audioread('HelloWorld_ask.m4a');
[received_signal, fs] = audioread('DigitalCommunication_ask.m4a');
ereceived_signal = received_signal(:)';
num_of_samples_per_bit = round(fs / bit_rate);
modulated_header = ask_modulate(header, fs, F_on, bit_rate);
modulated_end_seq = ask_modulate(end_seq, fs, F_on, bit_rate);
y= xcorr(modulated_header, received_signal); % do cross correlation
[m,ind]=max(y); % location of largest correlation
headstart=length(received_signal)-ind+1;
z = xcorr(modulated_end_seq, received_signal);
[m,ind]=max(z); % location of largest correlation
end_index=length(received_signal)-ind+1;
relevant_signal = received_signal(headstart + num_of_samples_per_bit * numel(header) : end_index - 1);
% relevant_signal = received_signal(headstart + num_of_samples_per_bit * numel(header): end);
demodulated_signal = ask_demodulate(relevant_signal, fs, F_on, bit_rate);
sampled_points_in_demodulated_signal = demodulated_signal(round(num_of_samples_per_bit / 2) : num_of_samples_per_bit :end);
digital_output = (sampled_points_in_demodulated_signal > (max(sampled_points_in_demodulated_signal(:)) / 2));
% digital_output = (sampled_points_in_demodulated_signal > 0.05);
% Convert to characters
total_num_of_bits = numel(digital_output);
total_num_of_characters = total_num_of_bits / 8;
first_idx = 0;
last_idx = 0;
output_str = '';
for i = 1:total_num_of_characters
first_idx = last_idx + 1;
last_idx = first_idx + 7;
binary_repr = digital_output(first_idx:last_idx);
ascii_value = bi2de(binary_repr(:)', 'left-msb');
character = char(ascii_value);
output_str = [output_str character];
end
output_str
ZAPYTAJ kod modulacji (ask_modulate):
function [bandlimited_and_modulated_signal] = ask_modulate(bit_stream, fs, F_on, bit_rate)
% Amplitude shift keying: Modulation
% Dang Manh Truong (dangmanhtruong@gmail.com)
num_of_bits = numel(bit_stream);
num_of_samples_per_bit = round(fs / bit_rate);
alpha = 0;
d_alpha = 2 * pi * F_on / fs;
A = 3;
analog_signal = [];
for i = 1 : num_of_bits
bit = bit_stream(i);
switch bit
case 1
for j = 1 : num_of_samples_per_bit
analog_signal = [analog_signal A * cos(alpha)];
alpha = alpha + d_alpha;
end
case 0
for j = 1 : num_of_samples_per_bit
analog_signal = [analog_signal 0];
alpha = alpha + d_alpha;
end
end
end
filter_order = 15;
LP_filter = fir1(filter_order, (2*6000)/fs, 'low');
bandlimited_analog_signal = conv(analog_signal, LP_filter,'same');
% plot(abs(fft(bandlimited_analog_signal)))
% plot(bandlimited_analog_signal)
bandlimited_and_modulated_signal = bandlimited_analog_signal;
end
ASK demodulation (ask_demodulate.m) (Zasadniczo jest to po prostu wykrywanie obwiedni, dla którego użyłem transformacji Hilberta)
function [demodulated_signal] = ask_demodulate(received_signal, fs, F_on, bit_rate)
% Amplitude shift keying: Demodulation
% Dang Manh Truong (dangmanhtruong@gmail.com)
demodulated_signal = abs(hilbert(received_signal));
end
Powiedz mi, dlaczego to nie działa? Dziękuję Ci bardzo