PHP实现基于文本的莫尔斯码生成器
最近,需要基于输入文本生成莫尔斯码音频文件。经过几次不成功的搜索,我决定自己写一个生成器。
因为我想通过网络访问我的莫尔斯电码音频文件,所以我决定使用PHP作为我的主要编程语言。上面的截图显示了一个开始生成Moss代码的网页。下载的zip文件包含用于提交文本的网页和用于生成和呈现音频文件的PHP源文件。如果你想测试PHP代码,你需要把网页和相关的PHP文件复制到一个支持PHP的服务器上。
对很多人来说,Moss代码,就像一些老电影里演的那样,是一系列的“点”和“横线”,或者是一系列的哔哔声。显然,如果要用计算机代码生成Moss代码,这种理解是远远不够的。本文将介绍生成Moss代码的要素,如何生成WAVE格式的音频文件,以及如何使用PHP将Moss代码转换为音频文件。
Moss代码
Moss代码是一种文本编码方法。它的优点是易于编码,人耳容易解码。本质上,音频(或射频)被打开和关闭,以形成短或长的音频脉冲,这些脉冲通常被称为点和破折号,或无线电术语中的“嘀嗒”和“咔嗒”。在现代数字通信术语中,莫斯码是一种振幅移位键控(ASK)。
在Moss代码中,字符(字母、数字、标点符号和特殊符号)被编码成一系列的“嘀嗒”和“嘀嗒”。因此,为了将文本转换为Moss代码,我们必须首先确定如何表达“di”和“click”。一个显而易见的选择是使用0表示“勾选”,1表示“点击”,反之亦然。遗憾的是,Moss码采用了变长编码方案。因此,我们还必须使用可变长度序列,或者采用一种方式将数据打包成计算机内存中常见的固定位大小格式。此外,需要注意的是Moss代码不区分大小写,不能对一些特殊符号进行编码。在我们的实现中,未定义的字符和符号将被忽略。
在这个项目中,内存占用不是一个需要特别考虑的问题。因此,我们提出了一种简单的编码方案,即使用“0”表示每个“刻度”,使用“1”表示每个“刻度”,并将它们放在一个字符串关联数组中。定义Moss代码编码表的PHP代码如下所示:
$CWCODE=数组(' A'='01 ',' B'='1000 ',' C'='1010 ',' D'='100 ',' E'='0 ',' F'='0010 ',' G'='110 ',' H'='0000 ',' I'='00 ',' J'='0111 ',' K'='101 ',' L'='0100 ',' M'='11 ',' N'='10 ',' O'='111 '='010101', ','='110011','/'='10010','-'='10001','~'='01010', '?'='001100','@'='00101');需要注意的是,如果你特别关心内存的使用,上面的代码可以解释为bit。通过向每个代码添加一个起始位,可以形成一个位模式,并且每个字符可以存储在一个字节中。同时,在解析最终代码时,需要删除起始位左边的位,从而得到真正的变长代码。
虽然很多人没有意识到实际上“时间间隔”是定义Moss代码的主要因素,但是理解这一点是生成Moss代码的关键。所以我们首先要做的就是定义Moss代码内部代码的时间间隔(即“嘀嗒”“嘀嗒”)。为了方便起见,我们把“嘀嗒”的音长定义为时间单位dt,“嘀嗒”和“嘀嗒”之间的间隔也是时间单位dt。“点击”的长度定义为3个DTs,字母之间的间隔也是3个DTs。定义的单词之间的间隔是7 dt。所以,综上所述,我们的时间间隔计划表如下:
在Moss代码中,编码声音的“播放速度”通常用每分钟字数(WPM)来表示。因为英文单词长度不同,字符有不同的“di”和“click”数字,所以从WPM转换成(音频)数字样本并不像看起来那么简单。在国际组织采用的方案中,一个单词的平均长度是5个字符,一个数字或标点符号被视为2个字符。这样,平均一个字就是50个时间单位dt。这样,如果指定WPM,那么我们的总播放时间为50 * WPM时间单位/分钟,每个“滴答”的长度(即一个时间单位dt)等于1.2/WPM秒。这样,给定一个“滴答”时间长度,其他元素的时间长度可以很容易地计算出来。
您可能已经注意到,在上面显示的网页中,对于低于15WPM的选项,我们使用“法恩斯沃斯间距”。那么这到底是什么“法恩斯沃斯间距”?
当操作者学会用耳朵解码Moss码时,他会意识到,当播放速度变化时,人物的节奏也会发生变化。当播放速度低于10WPM时,他可以轻松识别“di”和“click”,知道要发送哪个字符。但是,当播放速度超过10WPM时,操作者的识别就会出现错误,他识别的字符会比实际的“嘀”和“咔”多。当一个学习的时候习惯低速Moss代码的人,在处理高速播放代码的时候会出现问题。因为节奏变了,他的潜意识识别就会出错。
为了解决这个问题,发明了“法恩斯沃斯间距”。本质上,字母和符号的播放速度仍然高于15WPM。同时,通过在字符之间插入更多的空格,降低了整体的播放速度。这样,操作者可以以合理的速度和节奏识别每个字符。一旦所有的字符都学会了,就可以提高速度,而接收者只需要加快字符识别的速度。本质上,“法恩斯沃斯间距”的技术解决了节奏变化的问题,使接受者能够快速学习。
所以在整个系统中,对于较低的播放速度,是15WPM。相应地,一个“勾”的长度是0.08秒,但字符和单词之间的间隔不再是3 DITs或7 DITs,而是根据整体速度进行调整。
产生声音。
在PHP代码中,一个字符(即前一个数组的索引)代表一组Moss音,由“tick”、“click”和空白间隔组成。我们使用数字样本组成一个音频序列,并将其写入一个文件,并添加适当的头信息将其定义为WAVE格式。
生成声音的代码实际上非常简单,您可以在项目的PHP文件中找到它们。我发现定义“数控振荡器”非常方便。每次调用osc()时,它都会返回一个从正宣博生成的定时样本。使用声音采样和音频规范,生成WAVE格式的音频就足够了。生成的正宣波中-1到1的范围被移位和调整,使得声音的字节数据可以用0到255表示,而128表示零振幅。
同时,我们还得考虑另一个产生声音的问题。一般来说,我们通过切换正玄波来生成Moss代码。但是如果你直接这样做,你会发现你产生的信号会占用非常大的带宽。因此,无线电设备通常会对其进行修改,以减少带宽占用。
在我们的项目中,我们也会进行这样的修正,只是以数字的形式。既然我们已经知道了一个最小声音样本“di”的时间长度,那么就可以证明,具有最小带宽的声音幅度出现在长度等于“di”的正宣波的半周期内。事实上,我们可以通过使用低通滤波器来过滤音频信号来达到同样的效果。然而,由于我们已经知道所有的信号字符,我们可以简单地过滤每个字符信号。
生成“滴答”、“点击”和空白信号的PHP代码如下所示:
while($ dt $ DitTime){ $ x=Osc();if ($dt (0.5*$DitTime)) { //生成dit和dah的上升部分,最多为dit-time的一半$ x=$ x * sin((M _ PI/2.0)* $ dt/(0.5 * $ DitTime));$ditstr。=chr(楼层(120 * $ x 128));达斯特。=chr(楼层(120 * $ x 128));} else if ($dt (0.5*$DitTime)) { //对于dah,dit-time的第二部分是恒定振幅$dahstr。=chr(楼层(120 * $ x 128));//对于dit,后半部分以正弦形状衰减$ x=$ x * sin((M _ PI/2.0)*($ DitTime-$ dt)/(0.5 * $ DitTime));$ditstr。=chr(楼层(120 * $ x 128));} else { $ditstr。=chr(楼层(120 * $ x 128));达斯特。=chr(楼层(120 * $ x 128));} //一个空间的振幅0移动到128 $spcstr。=chr(128);$ dt=$ sampleDT}//此时,抖动声音已经生成//对于另一个抖动时间单位,dah声音具有恒定的振幅$ dt=0;while($ dt $ DitTime){ $ x=Osc();达斯特。=chr(楼层(120 * $ x 128));$ dt=$ sampleDT}//最后在第三个dit-time期间,dah声音必须完成//,并在最后半个dit-time期间衰减$ dt=0;while($ dt $ DitTime){ $ x=Osc();if($ dt(0.5 * $ DitTime)){ $ x=$ x * sin((M _ PI/2.0)*($ DitTime-$ dt)/(0.5 * $ DitTime));达斯特。=chr(楼层(120 * $ x 128));} else { $dahstr。=chr(楼层(120 * $ x 128));} $ dt=$ sampleDT}WAVE格式的文件。
WAVE是一种通用的音频格式。在最简单的形式中,WAVE文件通过在报头中包含一个整数序列来表示指定采样率下的音频幅度。有关WAVE文件的更多信息,请参见音频文件格式规范网站。为了生成Moss代码,我们不需要使用WAVE格式的所有参数选项,只需要一个8位的单声道,如此简单。需要注意的是,多字节数据需要采用小端字节顺序。WAVE文件使用一种由称为“块”的记录组成的RIFF格式。
WAVE文件以一个ASCII标识符RIFF开始,后面是一个4字节的“块”,然后是一个包含ASCII字符WAVE的头消息,最后是定义格式和声音数据的数据。
在我们的程序中,第一个“块”包含一个格式描述符,它由ASCII字符fmt和一个4倍字节的“块”组成。这里,因为我使用普通的PCM格式,每个“块”是16字节。然后,我们还需要这些数据:通道数、声音样本/秒、平均字节/秒、块对齐指示器和比特/声音样本。此外,因为我们不需要高质量的立体声,所以我们只使用单声道。我们使用11,050个样本/秒的采样率(CD质量音频的标准采样率为44,200个样本/秒)来产生声音,并将其保存在8位中。
最后,真正的音频数据存储在下一个“块”中。它包含ASCII字符数据,一个4字节的“块”,最后是由字节序列组成的真实音频数据(因为我们使用8位/样本)。
在程序中,由8位音频振幅序列组成的声音保存在变量$soundstr中。一旦生成了音频数据,就可以计算出所有的“块”大小,然后将它们组合并写入磁盘文件。下面的代码展示了如何生成标题信息和音频“块”。请注意,$RIFFstr表示riff头,$fmtstr表示“块”格式,$soundstr表示音频数据的“块”。
$riffstr='RIFF '。$ NSizeStr。WAVE ';$ x=SAMPLERATE$ SampRateStr=for($ I=0;$ i4$i ) { $SampRateStr。=chr($ x % 256);$x=下限($ x/256);}$fmtstr='fmt '。chr(16)。chr(0)。chr(0)。chr(0)。chr(1)。chr(0)。chr(1)。chr(0)。$SampRateStr。$SampRateStr.chr(1)。chr(0)。chr(8)。chr(0);$ x=$ n;$ NSampStr=for($ I=0;$ i4$i ) { $NSampStr。=chr($ x % 256);$x=下限($ x/256);}$soundstr=“数据”。$NSampStr。$ soundstr总结评论。
我们的文本Moss代码生成器目前看起来不错。当然,我们也可以对其进行很多修改和改进,比如使用其他字符集,直接从文件中读取文本,生成压缩音频等等。因为我们的项目的目的是使它在互联网上易于使用,所以我们的简单方案已经达到了我们的目标。
当然,一如既往,希望大家能对这些简单粗暴的代码给出一些建议。
版权声明:PHP实现基于文本的莫尔斯码生成器是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。