Tôi đang viết một ví dụ về việc truyền dữ liệu qua âm thanh betwwen 2 máy tính. Một số yêu cầu:
Khoảng cách rất gần, tức là 2 máy tính về cơ bản liền kề nhau
Rất ít tiếng ồn (Tôi không nghĩ rằng giáo viên của tôi sẽ bật một bài hát rock như một nguồn tiếng ồn)
Lỗi có thể chấp nhận: Ví dụ: nếu tôi gửi "Liên lạc vô tuyến" thì nếu máy tính khác nhận được "RadiQ CommunEcation" thì cũng không sao.
Nếu có thể: Không có tiêu đề, cờ, tổng kiểm tra, .... vì tôi chỉ muốn một ví dụ rất cơ bản thể hiện những điều cơ bản của việc truyền dữ liệu qua âm thanh. Không cần phải cầu kỳ.
Tôi đã thử sử dụng Phím Shift Tần số Âm thanh theo liên kết này:
Lab 5 APRS (Hệ thống báo cáo gói tự động)
và đã nhận được một số kết quả: Trang Github của tôi
Nhưng nó không phải là đủ. Tôi không biết cách phục hồi đồng bộ hóa, đồng bộ hóa, ... (liên kết có Giai đoạn khóa vòng như cơ chế phục hồi thời gian, nhưng rõ ràng là không đủ).
Vì vậy, tôi nghĩ rằng tôi nên tìm một cách tiếp cận đơn giản hơn. Tìm thấy một liên kết ở đây:
Dữ liệu vào âm thanh và trở lại. Điều chế / giải điều chế với mã nguồn
nhưng OP đã không thực hiện phương pháp được đề xuất trong câu trả lời, vì vậy tôi e rằng nó có thể rất phức tạp. Ngoài ra tôi không hiểu rõ phương pháp giải mã được đề xuất trong câu trả lời:
Bộ giải mã phức tạp hơn một chút nhưng đây là một phác thảo:
Tùy chọn lọc băng thông, tín hiệu được lấy mẫu khoảng 11Khz. Điều này sẽ cải thiện hiệu suất trong một môi trường ồn ào. Bộ lọc FIR khá đơn giản và có một vài applet thiết kế trực tuyến sẽ tạo bộ lọc cho bạn.
Ngưỡng tín hiệu. Mỗi giá trị trên 1/2 biên độ tối đa là 1 mỗi giá trị dưới đây là 0. Điều này giả sử bạn đã lấy mẫu toàn bộ tín hiệu. Nếu đây là thời gian thực, bạn có thể chọn một ngưỡng cố định hoặc thực hiện một số loại điều khiển khuếch đại tự động trong đó bạn theo dõi mức tín hiệu tối đa trong một thời gian.
Quét để bắt đầu dấu chấm hoặc dấu gạch ngang. Bạn có thể muốn xem ít nhất một số 1 nhất định trong dấu chấm của mình để xem các mẫu là một dấu chấm. Sau đó tiếp tục quét để xem nếu đây là một dấu gạch ngang. Đừng mong đợi một tín hiệu hoàn hảo - bạn sẽ thấy một vài 0 ở giữa số 1 của bạn và một số 1 ở giữa số 0 của bạn. Nếu có ít tiếng ồn thì việc phân biệt các khoảng thời gian "bật" với các khoảng thời gian "tắt" sẽ khá dễ dàng.
Sau đó đảo ngược quá trình trên. Nếu bạn thấy dấu gạch ngang đẩy 1 bit vào bộ đệm của bạn, nếu một dấu chấm đẩy số không.
Tôi không hiểu có bao nhiêu 1 trước khi phân loại nó thành một dấu chấm, ... Vì vậy, có nhiều điều mà tôi không hiểu ngay bây giờ. Vui lòng gợi ý cho tôi một phương pháp đơn giản để truyền dữ liệu qua âm thanh để tôi có thể hiểu quy trình. Cảm ơn rât nhiều :)
CẬP NHẬT:
Tôi đã thực hiện một số mã Matlab có vẻ như (phần nào) hoạt động. Trước tiên tôi điều chỉnh tín hiệu bằng cách sử dụng khóa dịch chuyển Biên độ (tần số lấy mẫu 48000 Hz, F_on = 5000 Hz, tốc độ bit = 10 bit / s), sau đó thêm nó bằng một tiêu đề và chuỗi kết thúc (tất nhiên cũng điều chỉnh chúng). Tiêu đề và chuỗi kết thúc đã được chọn trên cơ sở đặc biệt (vâng, đó là một vụ 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];
Sau đó, tôi truyền chúng qua âm thanh và ghi lại bằng điện thoại thông minh của mình. Sau đó, tôi gửi âm thanh được ghi lại vào máy tính của mình, sử dụng một đoạn mã khác để đọc âm thanh. Sau đó, tôi tương quan tín hiệu thu được (chưa được giải điều chế) với tiêu đề và chuỗi kết thúc được điều chế để tìm ra điểm bắt đầu và kết thúc. Sau đó tôi chỉ lấy tín hiệu liên quan (từ đầu đến cuối, như được tìm thấy trong phần tương quan). Sau đó tôi giải điều chế và lấy mẫu để tìm dữ liệu số. Dưới đây là 3 tệp âm thanh:
"DigitalC truyền thông_ask": Liên kết ở đây nó sẽ gửi văn bản "Giao tiếp kỹ thuật số". Tương đối không có tiếng ồn mặc dù bạn có thể nghe thấy một số tiếng ồn nền ở đầu và cuối. Tuy nhiên, kết quả chỉ cho thấy "Digital Commincatio"
"HelloWorld_ask": Liên kết tại đây, nó sẽ gửi văn bản "Hello world". Không có tiếng ồn như "DigitalC truyền thông_ask". Tuy nhiên, kết quả cho điều này là chính xác
"HelloWorld_noir_ask": Liên kết tại đây, nó sẽ gửi văn bản "Hello world". Tuy nhiên, có một số tiếng ồn mà tôi đã tạo ra (tôi chỉ nói một số nội dung ngẫu nhiên "A, B, C, D, E, ...." trong quá trình truyền tải). Thật không may, điều này đã thất bại
Đây là mã cho người gửi (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);
Đối với người nhận (người nhận.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
Mã điều chế ASK (ask_modulation):
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
Giải điều chế ASK (ask_demodulation.m) (Về cơ bản nó chỉ là phát hiện đường bao, mà tôi đã sử dụng biến đổi Hilbert)
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
Xin vui lòng cho tôi biết tại sao nó không hoạt động? Cảm ơn rât nhiều