Home Transmit data through sound between 2 computers in close distance - in need of a very simple method
Reply: 1

# Transmit data through sound between 2 computers in close distance - in need of a very simple method

Dang Manh Truong
1#
Dang Manh Truong Published in 2017-12-05 11:14:26Z
 I have a project that requires transmitting sound data between two computers. One computer emits sound while the other one listens and reads the data. I've done some research and decided on using Audio Frequency Shift Keying for modulation/demodulation, since I've found a course here which goes into details about the method: Lab 6 Audio frequency shift keying Lab 5 Audio frequency shift keying Lab 5 APRS (Automatic package reporting system These were useful links, thanks to them I've been able to successfully modulate and demodulate the signal, and also timing recovery using Phase-Locked Loop (PLL), here is my results: Transmit data through sound using AFSK1200 Some screenshots: However this is not enough, I need to perform the experiment in a real life condition (transmit data as sound between 2 computers). But the thing is the description about this part on the links above were very difficult to understand, for example here is some code on the 3rd link that is supposed to read the data from the demodulated signal: def findPackets(bits): # function take a bitarray and looks for AX.25 packets in it. # It implements a 2-state machine of searching for flag or collecting packets flg = bitarray.bitarray([0,1,1,1,1,1,1,0]) packets = [] n = 0 pktcounter = 0 packet = [] state = 'search' # Loop over bits while (n < len(bits)-7) : # default state is searching for packets if state is 'search': # look for 1111110, because can't be sure if the first zero is decoded # well if the packet is not padded. if bits[n:n+7] == flg[1:]: # flag detected, so switch state to collecting bits in a packet # start by copying the flag to the packet # start counter to count the number of bits in the packet state = 'pkt' packet=flg.copy() pktcounter = 8 # Advance to the end of the flag n = n + 7 else: # flag was not found, advance by 1 n = n + 1 # state is to collect packet data. elif state is 'pkt': # Check if we reached a flag by comparing with 0111111 # 6 times ones is not allowed in a packet, hence it must be a flag (if there's no error) if bits[n:n+7] == flg[:7]: # Flag detected, check if packet is longer than some minimum if pktcounter > 200: # End of packet reached! append packet to list and switch to searching state # We don't advance pointer since this our packet might have been # flase detection and this flag could be the beginning of a real packet state = 'search' packet.extend(flg) packets.append(packet.copy()) else: # packet is too short! false alarm. Keep searching # We don't advance pointer since this this flag could be the beginning of a real packet state = 'search' # No flag, so collect the bit and add to the packet else: # check if packet is too long... if so, must be false alarm if pktcounter < 2680: # Not a false alarm, collect the bit and advance pointer packet.append(bits[n]) pktcounter = pktcounter + 1 n = n + 1 else: #runaway packet, switch state to searching, and advance pointer state = 'search' n = n + 1 return packets  I tried but it did not work! And I really do not know why. Perharps it has to do with the Morse code ? (they encoded data as Morse code before sending it, but I did not). They used the AX.25 protocol but I did not use it but only the essential part (bit stuffing, then convert to Non Return to Zero Inverted). Another method was described here: Lab 5 APRS but it also did not work! So I think it was because I did not really understand how to read the data from the demodulated signal. I checked around on the web and found this link: ChirpCast: Data transmission via Audio They did implement Frequency Shift Keying but they used a separate CLOCK signal as synchronization mechanism: Our implementation consists of two simultaneously transmitted bit streams, a DATA signal on the left speaker channel and a CLOCK signal on the right signal channel. The decision to send a separate clock signal simplifies the sender and receiver synchronization, since the clock signal informs the receiver when it should sample the data without requiring a receiver-maintained reference clock. Which is not suitable for my use case since I need to transmit just sound and have the receiving computer read it on its own. I also found a link on Stack Exchange: Data to audio and back. Modulation / demodulation with source code The answer suggested using Amplitude Shift Keying, however the OP did not implement that method, so I'm afraid it may be quite complex. And also the answer did not give details about whether one should send the data in a packet (header, flag,...). I really don't know if sending in a packet is a must or not. Also I did not really understand how to decode the message: The decoder is a bit more complicated but here's an outline: Optionally band-pass filter the sampled signal around 11Khz. This will improve performance in a noisy enviornment. FIR filters are pretty simple and there are a few online design applets that will generate the filter for you. Threshold the signal. Every value above 1/2 maximum amplitude is 1 every value below is 0. This assumes you have sampled the entire signal. If this is in real time you either pick a fixed threshold or do some sort of automatic gain control where you track the maximum signal level over some time. Scan for start of dot or dash. You probably want to see at least a certain number of 1's in your dot period to consider the samples a dot. Then keep scanning to see if this is a dash. Don't expect a perfect signal - you'll see a few 0's in the middle of your 1's and a few 1's in the middle of your 0's. If there's little noise then differentiating the "on" periods from the "off" periods should be fairly easy. Then reverse the above process. If you see dash push a 1 bit to your buffer, if a dot push a zero. I do not understand how many 1's before classifying it as a dot,... So there are many things that I do not understand right now. I'm not asking everyone to solve my homework, I just want someone to point me in the right direction. Here is the requirements: The distance is very close , i.e the 2 computers are basically adjacent to each other Very little noise (I do not think my teacher would turn on a rock song as a noise source) Error is acceptable: For example if I send "Radio communication" then if the other computer receives "RadiQ communEcation" it's alright as well. If possible: No header, flag, checksum,.... since I just want a very basic example demonstrating the basics of transmitting data through sound. No need to be fancy. I'm not asking for everyone to solve my homeworks, just to help me find the right direction. Please help me, thank you very much :) UPDATE: I have made some Matlab code which appear to be (somewhat) operational. I first modulate the signal using Amplitude shift keying (sampling frequency 48000 Hz, F_on = 5000 Hz, bit rate = 10 bits/s), then add it with a header and an end sequence (of course modulate them as well). The header and the end sequence was chosen on an ad-hoc basis (yeah it was a 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];  Then I transmit them through sound, and recorded it with my smartphone . Then I send the recorded audio back to my computer, use another piece of code to read the audio. Here are 3 audio files: "DigitalCommunication_ask": Link here it sends the text "Digital communication". Relatively noise-free although you can hear some background noise at the beginning and the end. However the result showed only "Digital Commincatio" "HelloWorld_ask": Link here it sends the text "Hello world". Noise free like "DigitalCommunication_ask". However the result for this one was correct "HelloWorld_noise_ask": Link here it sends the text "Hello world". However there is some noise that I've made (I just said some random stuff "A,B,C,D,E,...." during the transmission). Unfortunately this one failed Here is the code for the sender (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);  For the receiver (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  ASK modulation code (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) (Basically it is just envelope detection, for which I used the Hilbert transform) 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  Please tell me why is it not working? Thank you very much
Omkaar.K
2#
Omkaar.K Reply to 2017-12-16 10:55:04Z
 When communicating for information, we need 5 components. Message source(in this case, it's the "Hello world".) Transmitter which encodes your message into signals(in this case, first translate to ASCII, then ASFK) Channel which signals can pass(this case, it's sound) A receiver which decodes signal and gets the message. Message target(this case, the other computer) So, you can do all this when there is no noise. It means you already have a basic communication system and you have problem when the Channel has noise, your signal is distorted, you send 1001, and you get 011100, you need error correction, that's fancy stuff, so I suggest just send the message length and message digest before the message, so you receiver can know whether message is correct or not. This simple approach may require you Transmitter send the signal many times. If you need real stuff, then read Error_detection_and_correction and build your own protocol.
 You need to login account before you can post.
Processed in 0.336945 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO