File transfer over sound card II: Phase Shift Keying

来源:互联网 发布:英语听力软件哪个好 编辑:程序博客网 时间:2024/05/20 23:35

墙外的文章,转载贴过来慢慢看,慢慢翻译。

I've played around further with the file transfer over sound card idea, and developed a more advanced method that uses a technique called Phase Shift Keying. Similar techniques are used in wireless network connections. 

I've played around further with the file transfer over sound card idea, and developed a more advanced method that uses a technique called Phase Shift Keying. Similar techniques are used in wireless network connections.

I've played around fur­ther with the file trans­fer over sound card idea, and de­vel­oped a more ad­vanced method that uses a tech­nique called Phase Shift Key­ing .Sim­i­lar tech­niques are used in wire­less net­work con­nec­tions. 

In­stead of cod­ing data in the am­pli­tude or fre­quency of the car­rier sig­nal, phase shift key­ing (as the name in­di­cates) en­codes it in the phase. It is sig­nif­i­cantly faster, par­tially be­cause it doesn't waste as much time with si­lences, but also be­cause it's more re­liant. 




I must admit it's a good thing I wasn't drink­ing cof­fee when tin­ker­ing with this tech­nique, be­cause it's very likely I would have blown cof­fee through my nose and onto the key­board when I first saw trans­fer rates over around 200 baud, with no ran­dom gar­bling. I'm sure it's pos­si­ble to go higher with bet­ter equip­ment than my cheaper-than-dirt head­sets that came with my we­b­cams. 

How it works 

The math­e­mat­ics of the method is as fol­low­ing, if the sig­nal is ex­pressed as 

S(t) = A0 sin(ωt + φ) 

Then the Fourier trans­form of S would give you 

Fω(S) = A0 e 

Nor­mally, one would sim­ply dis­card the phase fac­tor by tak­ing the norm of the fre­quency co­ef­fi­cient, but for this we're going to make use of it. You can't just yank the phase out of the ex­pres­sion as it is though (phase is al­ways rel­a­tive to some­thing). But! You can com­pare this phase with the phase of the last sam­ple you got (this is called dif­fer­en­tial phase-shift key­ing, by the way). 

So, I pro­pose the fol­low­ing scheme:ΔφMean­ing0Still the same sam­ple as last timeπ / 2Next bit is 1πNext bit is 03 &pi / 2New byteThis has sev­eral nice fea­tures. You can jump into the sig­nal al­most any­where and at most one byte will be gar­bled. Fur­ther­more, every­thing has an uni­form length, so bit rate doesn't de­pend on how many ones and zeros is in the byte. 

Mod­i­fy­ing the fourier code from the last blog post on sonic file trans­fers, the fol­low­ing func­tion will allow you to make use of the phase: 

double fourier1p(double x_in[], double n, int length, double* phase_r, double* phase_i) { 
double x_complex[2] = { 0, 0 }; 
int i; 

for(i = 0; i < length; i++) { 
x_complex[0] += x_in[i] * cos(M_PI * 2 * i * n / (double) length); 
x_complex[1] += x_in[i] * sin(M_PI * 2 * i * n / (double) length); 


double norm = sqrt(x_complex[0]*x_complex[0] + x_complex[1]*x_complex[1]); 
*phase_i = x_complex[1] / norm; 
*phase_r = x_complex[0] / norm; 
return norm / length; 
}
 


So how do we fig­ure out the phase dif­fer­ence? Let φ be the phase of the cur­rent sam­ple, and ψ be the phase of the pre­vi­ous sam­ple. 

ee-iψ = ei(φ - ψ) = cos(φ - ψ) + i sin(φ - ψ) 

The real term will dom­i­nate if φ - ψ ~ nπ , and the imag­i­nary term will dom­i­nate if φ - ψ ~ (n+1)π/2 and their sign will fur­ther tell you if n is odd or even. 

The de­mod­u­la­tion al­go­rithm is fairly short: 


double carrier_phase[2]; 
double carrier_strength = fourier1p(dbuffer, (float) length * carrier / (float)rate, length, &carrier_phase[0], &carrier_phase[1]); 

if(carrier_strength < threshold) continue; 

double delta_re = carrier_phase[0] * old_carrier_phase[0] + carrier_phase[1]*old_carrier_phase[1]; 
double delta_im = -carrier_phase[1]*old_carrier_phase[0] + carrier_phase[0] * old_carrier_phase[1]; 

if(delta_re * delta_re > delta_im * delta_im) { /* Phase difference is a multiple of pi */ 
if(delta_re > 0); /* No change */ 
else { 
bit_data = bit_data * 2; 

} else { 
if(delta_im > 0) { 
bit_data = bit_data * 2 + 1; 
} else { 
if(isprint(bit_data)) printf("%c", bit_data); 
else printf("<%.2x>", bit_data); 
bit_data = 0; 


old_carrier_phase[0] = carrier_phase[0]; 
old_carrier_phase[1] = carrier_phase[1]; 




For sev­eral rea­sons, it's a good idea to use a pretty high car­rier fre­quency for this method. At some point, your speaker or mi­cro­phone will not be able to process the in­for­ma­tion, so you'll want to stay under that, but a high fre­quency will re­sult in less per­tur­ba­tion of the sig­nal since fairly few ob­jects have eigen­fre­quen­cies in the 5 kHz range or higher, and even os­cil­la­tion at har­monic fre­quen­cies drops off pretty sig­nif­i­cantly at such fre­quen­cies. 

Sources 

The com­plete source code for the pro­gram: 

gen­er­ate_psk.
an­a­lyze_psk.c 

You may have grabbed these the last time, but they are slightly al­tered now, so get them again: 

fourier.
fourier.c 

You also need the play­back and record pro­grams I posted in the pre­vi­ous post.They haven't changed though. 

play­back.
record.c 


Using 

Same old warn­ing: Never try these pro­grams with your head­phones on. THEY MAKE LOUD NOISES! It is pos­si­ble to con­fig­ure these pro­grams to make noises way louder than you ever imag­ined your head­phones could make. You can dam­age your hear­ing when play­ing with audio pro­gram­ming. Tin­ni­tus isn't fun. 

To trans­fer a file (let's trans­fer /etc/fstab again), put the mi­cro­phone next to the speaker, pre-type the fol­low­ing on the trans­mit­ting com­puter (with­out run­ning it): 

>./generate_psk -r 48000 -c 8000 -b 100 /etc/fstab | ./playback -r 48000 

Type the fol­low­ing on the re­ceiv­ing com­puter: 

>./record -r 48000 > mydata 

Press enter on the trans­mit­ting com­puter. Be quiet (this should be fairly quick. Maybe 30 sec­onds?) When the high pitched noise stops, press Ctrl+C on the re­ceiv­ing com­puter's ter­mi­nal. 

Run­ning 
./analyze_psk -r 48000 -c 8000 -b 100 mydata 
on the re­ceiv­ing com­puter should re­treive the mes­sage. 

The pa­ra­me­ters are 
-r : Sam­ple rate -- car­rier fre­quency and sig­nal qual­ity 
-c : Car­rier fre­quency -- lim­its baud rate and sig­nal qual­ity 
-b : Baud rate -- de­ter­mines how fast the trans­fer is 

What works and doesn't with the sam­pling rates and fre­quen­cies is a bit tricky.It all boils down to Nyquist-Shan­non . That the­o­rem is all in­no­cent look­ing, until you make it mad. Then it turns green and grows three times it's size and goes on a fu­ri­ous ram­page through your hopes and dreams. 

Any­ways, have fun ex­per­i­ment­ing with this tech­nique. 

2011 up­date: Moved the sources to a github repo.  

This has several nice features. You can jump into the signal almost anywhere and at most one byte will be garbled. Furthermore, everything has an uniform length, so bit rate doesn't depend on how many ones and zeros is in the byte. 

Modifying the fourier code from the last blog post on sonic file transfers, the following function will allow you to make use of the phase:

原创粉丝点击