Estou escrevendo um exemplo de transmissão de dados através de som entre computadores. Alguns requisitos:
A distância é muito próxima, ou seja, os 2 computadores são basicamente adjacentes um ao outro
Muito pouco ruído (acho que meu professor não ligaria uma música de rock como fonte de ruído)
O erro é aceitável: por exemplo, se eu enviar "Radiocomunicação", se o outro computador receber "RadiQ communEcation", tudo bem.
Se possível: sem cabeçalho, sinalizador, soma de verificação, .... já que eu só quero um exemplo muito básico demonstrando o básico da transmissão de dados através do som. Não precisa ser chique.
Eu tentei usar o Audio Frequency Shift Keying de acordo com este link:
Laboratório 5 APRS (Sistema de Relatório Automático de Pacotes)
e obtive alguns resultados: minha página no Github
Mas não é suficiente. Eu não sei como fazer recuperação de relógio, sincronização, ... (o link tem um loop bloqueado de fase como mecanismo de recuperação de tempo, mas aparentemente não foi suficiente).
Então, acho que devo encontrar uma abordagem mais simples. Encontre um link aqui:
Dados para áudio e vice-versa. Modulação / desmodulação com código fonte
mas o OP não implementou o método sugerido na resposta, portanto, receio que possa ser muito complexo. Também não entendo claramente o método de decodificação sugerido na resposta:
O decodificador é um pouco mais complicado, mas aqui está um esboço:
Opcionalmente, passa-banda filtrar o sinal amostrado em torno de 11Khz. Isso melhorará o desempenho em um ambiente barulhento. Os filtros FIR são bem simples e existem alguns applets de design on-line que irão gerar o filtro para você.
Limite o sinal. Todo valor acima de 1/2 da amplitude máxima é 1 e todo valor abaixo é 0. Isso pressupõe que você tenha amostrado todo o sinal. Se for em tempo real, você escolhe um limite fixo ou realiza algum tipo de controle automático de ganho, onde monitora o nível máximo de sinal ao longo de algum tempo.
Procure o início do ponto ou traço. Você provavelmente deseja ver pelo menos um certo número de 1's no período de pontos para considerar as amostras como um ponto. Continue digitalizando para ver se isso é uma piada. Não espere um sinal perfeito - você verá alguns 0 no meio dos seus 1 e alguns 1 no meio dos seus 0. Se houver pouco ruído, diferenciar os períodos "ligado" dos períodos "desligado" deve ser bastante fácil.
Em seguida, inverta o processo acima. Se você vir o traço, empurre um bit para o buffer, se um ponto empurre um zero.
Eu não entendo quantos 1s são antes de classificá-lo como um ponto ... Então, há muitas coisas que eu não entendo agora. Sugira-me um método simples para transmitir dados através do som, para que eu possa entender o processo. Muito obrigado :)
ATUALIZAR:
Eu criei algum código do Matlab que parece estar (um pouco) operacional. Primeiro modulo o sinal usando a amplitude de mudança de amplitude (frequência de amostragem 48000 Hz, F_on = 5000 Hz, taxa de bits = 10 bits / s), depois adiciono-o com um cabeçalho e uma sequência final (é claro que também os modula). O cabeçalho e a sequência final foram escolhidos ad-hoc (sim, foi um 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];
Então eu os transmito através do som e gravei com o meu smartphone. Depois, envio o áudio gravado de volta para o meu computador, use outro código para ler o áudio. Então eu correlaciono o sinal recebido (ainda não desmodulado) com o cabeçalho modulado e a sequência final para descobrir o começo e o fim. Depois disso, pego apenas o sinal relevante (do começo ao fim, como encontrado na parte de correlação). Então eu desmodulo e faço uma amostra para encontrar os dados digitais. Aqui estão 3 arquivos de áudio:
"DigitalCommunication_ask": link aqui envia o texto "Comunicação digital". Relativamente livre de ruído, embora você possa ouvir algum ruído de fundo no início e no final. No entanto, o resultado mostrou apenas "Digital Commincatio"
"HelloWorld_ask": link aqui envia o texto "Hello world". Barulho livre como "DigitalCommunication_ask". No entanto, o resultado para este foi correto
"HelloWorld_noise_ask": link aqui envia o texto "Hello world". No entanto, houve algum ruído que eu fiz (acabei de dizer algumas coisas aleatórias "A, B, C, D, E, ...." durante a transmissão). Infelizmente este falhou
Aqui está o código para o remetente (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);
Para o receptor (receiver.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
Código de modulação 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
Desmodulação ASK (ask_demodulate.m) (Basicamente, é apenas detecção de envelope, para a qual eu usei a transformação 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
Por favor me diga por que não está funcionando? Muito obrigado