Я пишу приклад передачі даних через звук між комп'ютерами 2. Деякі вимоги:
Відстань дуже близька, тобто два комп’ютери в основному примикають один до одного
Дуже мало шуму (я не думаю, що мій учитель увімкнув би рок-пісню як джерело шуму)
Помилка є прийнятною. Наприклад, якщо я надсилаю "Радіозв'язок", то якщо інший комп'ютер отримує "RadiQ communEcation", це також добре.
Якщо можливо: Без заголовка, прапора, контрольної суми, .... оскільки я просто хочу дуже базовий приклад, що демонструє основи передачі даних через звук. Не потрібно бути фантазією.
Я спробував скористатися звуковим перемиканням частоти звуку за цим посиланням:
Лабораторія 5 APRS (Система автоматичної звітності про пакети)
і отримав деякі результати: Моя сторінка Github
але цього недостатньо. Я не знаю, як зробити відновлення синхронізації, синхронізацію, ... (посилання має Phase Locked Loop як механізм відновлення синхронізації, але, мабуть, це було недостатньо).
Тому я думаю, що мені слід знайти простіший підхід. Тут знайдено посилання:
Дані на аудіо та назад. Модуляція / демодуляція з вихідним кодом
але ОП не застосував запропонований у відповіді метод, тому я боюся, що це може бути дуже складним. Також я чітко не розумію метод декодування, запропонований у відповіді:
Декодер трохи складніший, але ось такий контур:
Необов'язково смуговий фільтр відібраного сигналу близько 11 кГц. Це поліпшить ефективність роботи в умовах шумного оточення. Фільтри FIR досить прості, і є декілька аплет в Інтернеті, які генерують фільтр для вас.
Поріг сигналу. Кожне значення вище 1/2 максимальної амплітуди - 1, кожне значення нижче - 0. Це передбачає, що ви відібрали весь сигнал. Якщо це в режимі реального часу, ви або вибираєте фіксований поріг, або робите якийсь автоматичний контроль посилення, де ви відстежуєте максимальний рівень сигналу протягом певного часу.
Сканування на початок крапки або тире. Ймовірно, ви хочете побачити принаймні певну кількість значень 1 у точковий період, щоб вважати зразки крапкою. Потім продовжуйте сканувати, щоб побачити, чи це тире. Не чекайте ідеального сигналу - в середині 1-х ви побачите декілька "0" та "1" в середині 0-х. Якщо шуму мало, то диференціювати періоди "увімкнення" від періодів "вимкнення" слід досить просто.
Потім поверніть вищезазначений процес. Якщо ви бачите тире, натисніть 1 біт на свій буфер, якщо крапка натисне нуль.
Я не розумію, скільки 1 до того, як класифікувати його як крапку, ... Отже, є багато речей, які я зараз не розумію. Підкажіть, будь ласка, простий метод передачі даних через звук, щоб я міг зрозуміти процес. Дуже дякую :)
ОНОВЛЕННЯ:
Я зробив якийсь код Matlab, який, здається, (дещо) працює. Я спочатку модулюю сигнал за допомогою клавіші зсуву амплітуди (частота дискретизації 48000 Гц, F_on = 5000 Гц, швидкість передачі бітів = 10 біт / с), потім додаю його із заголовком та кінцевою послідовністю (звичайно, також модулюю їх). Заголовок і кінцева послідовність вибиралися спеціально (так, це був хак):
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];
Потім я передаю їх через звук і записую його своїм смартфоном. Потім я відправляю записане аудіо назад на комп'ютер, використовую інший фрагмент коду для читання аудіо. Потім я співвідносив отриманий сигнал (ще не демодульований) з модульованим заголовком і кінцевою послідовністю, щоб з’ясувати початок і кінець. Після цього я приймаю лише відповідний сигнал (від початку до кінця, як це знайдено в кореляційній частині). Потім я демодулюю і беру зразок, щоб знайти цифрові дані. Ось 3 аудіофайли:
"DigitalCommunication_ask": Посилання тут передає текст "Цифрове спілкування". Відносно безшумний, хоча можна почути фоновий шум на початку та в кінці. Однак результат показав лише "Digital Commincatio"
"HelloWorld_ask": Посилання тут надсилає текст "Hello world". Без шуму, як "DigitalCommunication_ask". Однак результат для цього був правильним
"HelloWorld_noise_ask": Посилання тут передає текст "Hello world". Однак я почув якийсь шум (я просто сказав кілька випадкових матеріалів "A, B, C, D, E, ...." під час передачі). На жаль, цей не вдався
Ось код для відправника (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);
Для приймача (приймача.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
ASK-модуляційний код (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 демодуляція (ask_demodulate.m) (в основному це просто виявлення конвертів, для чого я використав перетворення Гільберта)
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
Скажіть, будь ласка, чому це не працює? Дуже дякую