Python中的二进制相位移键控
我现在正在写一些代码,通过激光传输消息、文件和其他数据,使用的是音频转换的方法。我的代码目前使用了Python中的binascii模块里的hexlify函数,把数据转换成二进制,然后发出一个音调代表1,发出另一个音调代表0。理论上这个方法是可行的,虽然不是编码和解码的最快方式,但在测试中发现了一些错误。
生成的音调不太准确,比如说发出150Hz的音调,接收端可能会变成145-155Hz。这不是个大问题,因为我可以在接收端调整一下音调的范围。
真正的问题是,如果我发出一个音调,接收端的电脑可能会多次读取这个音调,或者根本就不读取,这取决于它采样音频的速度。我试过让音调播放的速度和采样速度一致,但这很不稳定。
总的来说,我用短消息成功传输过几次,但由于上述问题,这种方法非常不可靠和不准确。
我进一步研究了一下,似乎可以用BPSK(双相位移键控)来解决这个问题,虽然我还不太清楚怎么实现。如果有任何建议或代码示例,我会非常感激!
我的项目代码可以在这里找到,但我主要在处理的文件是用于二进制编码和解码的,分别在这里和这里。我不是Python专家,如果我说错了什么,或者我的代码不太好,或者我忽略了一些基础的东西,请多多包涵。
谢谢!:-)
2 个回答
关于第一个问题,关于频率的部分:
看你的解码器,我看到你的采样率是44100,数据块大小是2048。如果我理解得没错,这意味着你的FFT大小也是2048。这就意味着你的FFT频率分辨率大约是21赫兹。你有没有尝试过给你的FFT加零填充?加零填充不会改变频率,但可以让你得到更清晰的结果。我注意到你在用二次插值来提高频率的估算。我没有用过这种方法,所以不太清楚它能带来什么样的改善。也许在零填充和二次插值之间找到一个平衡,会让你的频率更准确。
另外,根据进行传输和接收的硬件,频率误差可能是因为驱动A/D转换器的时钟不同步——一个或两个时钟的频率可能并不完全是44100赫兹。这种情况可能会影响你在FFT输出中看到的频率。
看看GNU Radio吧!
http://gnuradio.org/redmine/projects/gnuradio/wiki
GNU Radio是一个项目,旨在通过软件尽可能实现无线信号的发送和接收。因为无线电本身就使用相位调制,GNU Radio的团队已经为你解决了这个问题,而且GNU Radio本身就是一个Python项目!虽然一些复杂的数字信号处理(DSP)部分是用C++写的,以提高速度,但它们已经被封装好,可以在Python中使用。
这里有一个页面讨论了一个使用差分二进制相位调制(DBPSK)和差分正交相位调制(DQPSK)来传输二进制数据的项目(示例中是一个JPEG图片)。你可以下载Python的源代码。
http://www.wu.ece.ufl.edu/projects/softwareRadio/
我看到你的项目是MIT许可证的,而GNU Radio是GPL3许可证,这可能会对你造成问题。你需要弄清楚是否可以使用GNU Radio,而不需要将你的项目变成衍生作品,这样就不会强迫你更改许可证。理论上,你可以制作一个独立的“发送守护进程”和一个独立的“接收守护进程”,它们的源代码都是GPL3,然后让你的MIT代码通过套接字或其他方式与它们连接。
顺便提一下,我在搜索中发现了一个非常清晰的BPSK工作原理的解释:
http://cnx.org/content/m10280/latest/
祝你好运!