介绍最近遇到需要根据输入的文本生成摩尔斯电码音频文件。经过一番无果而终的搜索后,我决定自己编写一个生成器。下载源代码-2.63KB因为我想通过网络访问我的摩尔斯电码音频文件,所以我决定使用PHP作为我的主要编程语言。上面的屏幕截图显示了一个开始生成摩尔斯电码的网页。下载的zip文件中包含用于提交文本的网页和用于生成和显示音频文件的PHP源文件。如果要测试PHP代码,需要将网页和相关的PHP文件复制到启用了PHP的服务器上。对很多人来说,摩尔斯电码就像是一些老电影的表现形式,一串“点”和“条”,或者一连串的哔哔声。显然,如果你想用计算机代码生成摩尔斯电码,这些知识是不够的。本文将介绍摩尔斯电码生成的要素,如何生成WAVE格式的音频文件,以及如何使用PHP将摩尔斯电码转换成音频文件。摩尔斯电码摩尔斯电码是一种文字编码方法。它的优点是容易编码,用人耳很容易解码。本质上,音频(或射频)被打开和关闭以形成短或长的音频脉冲,通常称为点和破折号,或在无线电术语中为“di”和“dash”。绝望”。在现代数字通信术语中,摩尔斯电码是振幅键控(ASK)的一种形式。在摩尔斯电码中,字符(字母、数字、标点符号和特殊符号)被编码为一系列“滴答”和“ticks”。因此,为了将文本转换为摩尔斯电码,我们首先需要确定如何表示“tick”和“tick”。一个明显的选择是使用0表示ticks,使用1表示ticks,反之亦然。不幸的是,Morse代码使用的是变长编码方案,所以我们也得使用变长序列,或者采取一种方式将数据打包成计算机内存通用的固定位大小的格式。另外,需要注意的是摩尔斯电码不区分大小写字母,不能对一些特殊符号进行编码,在我们的实现中,忽略了未定义的字符和符号。内存占用不是本项目的特殊考虑因素。因此,我们提出一种简单的编码方案,即用“0”代表每一个“tick”,用“1”代表每一个“tick”,将它们放在一个字符串的关联数组中。定义摩尔斯电码编码表的PHP代码如下所示:$CWCODE=array('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','P'=>'0110','Q'=>'1101','R'=>'010','S'=>'000','T'=>'1','U'=>'001','V'=>'0001','W'=>'011','X'=>'1001','Y'=>'1011','Z'=>'1100','0'=>'11111','1'=>'01111','2'=>'00111','3'=>'00011','4'=>'00001','5'=>'00000','6'=>'10000','7'=>'11000','8'=>'11100','9'=>'11110','.'=>'010101',','=>'110011','/'=>'10010','-'=>'10001','~'=>'01010','?'=>'001100','@'=>'00101');需要注意的是,如果你特别在意内存的使用,上面的代码可以理解为位。每个码加一个起始位可以组成一个位模式,每个字符可以存储在一个字节中。同时,在解析最终代码时,要删除起始位左边的位(bit),这样才能得到真正的变长代码。虽然很多人没有意识到,其实“时间间隔”是定义摩尔斯电码的主要因素,所以理解这一点是生成摩尔斯电码的关键。所以,我们要做的第一件事就是定义摩尔斯电码内码的时间间隔(即“滴答”和“滴答”)。为了方便起见,我们把一个“滴答”的声音长度定义为一个时间单位dt,“滴答”与“滴答”之间的间隔也是一个时间单位dt;定义一个“tick”的长度为3dt,字符(字母之间的间隔)也是3dt;定义词(words)之间的间隔为7dt。因此,总而言之,我们的时间间隔表如下所示:项目持续时间ticksdtticks/clicks之间的间隔dtticks3*dt字符之间的间隔3*dt单词之间的间隔Interval7*dt在摩尔斯电码中,“播放率”编码声音的数量通常以每分钟字数(WPM)表示。从WPM转换为(音频)数字样本并不像看起来那么简单,因为英语单词的长度不同,字符具有不同数量的“tits”和“tats”。在国际组织采用的方案中,5个字符作为一个词的平均长度,数字或标点符号被视为2个字符。这样,平均一个词就是50个时间单位dt。这样,如果指定WPM,那么我们的总播放时间就是50*WPM时间单位/分钟,每个“tick”(即一个时间单位dt)的长度就等于1.2/WPM秒。这样,给定一个“tick”的时间长度,就可以很容易地计算出其他元素的时间长度。您可能已经注意到,在上面显示的网页中,我们对低于15WPM的选项使用了“Farnsworthspacing”。那么这个“法恩斯沃斯间距”到底是什么?当无线电操作员学会用耳朵解码摩尔斯电码时,他意识到当播放速度改变时,字符出现的节奏也会改变。当播放速度低于10WPM时,他可以轻松识别“滴答”和“滴答”,知道发送的是哪个字符。但是当播放速度超过10WPM时,操作者的识别就会出现错误,他识别出的字符会比实际的“嘀”、“嘀”多。当一个在学习时习惯于低速摩尔斯电码的人正在处理高速播放电码时,就会出现问题。因为节奏变了,他下意识的认知就会出错。为了解决这个问题,发明了“法恩斯沃斯间距”。本质上,字母和符号的播放速度仍然高于15WPM,同时通过在字符之间插入更多的空格来降低整体播放速度。这样,操作者就可以以合理的速度和节奏识别每个字符。一旦所有的字符都学会了,就可以提高速度,接收者只需要提高识别字符的速度即可。从本质上讲,“法恩斯沃斯间距”技术解决了节奏变化的问题,让接球者可以快速学习。所以在整个系统中,对于较低的播放速度,统一为15WPM。相应地,一个“滴”的长度为0.08秒,但字与词的间隔不再是3滴或7滴,而是根据整体速度进行了调整。生成声音在PHP代码中,一个字符(即前面数组的索引)表示一组由“tick”、“tat”和空白间隔组成的Moss声音。我们使用数字样本组成音频序列,并将其写入文件,并添加适当的头信息以将其定义为WAVE格式。生成声音的代码其实很简单,您可以在项目的PHP文件中找到它。我发现定义“数字振荡器”非常方便。每次调用osc()时,它都会返回一个从正弦波生成的定时样本。使用声音样本和音频规范,生成WAVE格式的音频就足够了。生成的正弦波中-1和+1之间的范围被移动和调整,使得声音的字节数据可以用0到255表示,而128表示零幅度。同时,我们还得考虑另一个产生声音的问题。一般来说,我们通过正弦波的开关来产生摩尔斯电码。但是如果你直接去做,你会发现你产生的信号会占用非常大的带宽。因此,通常无线电设备会对其进行修改以减少带宽占用。在我们的项目中,也进行了此类更正,但是是数字上的。既然我们已经知道了一个最小声音样本“di”的时间长度,那么,可以证明最小带宽的声音幅度出现在长度等于“di”的正弦波的半个周期内。事实上,我们可以通过低通滤波器对音频信号进行滤波来达到同样的效果。但是,由于我们已经知道所有的信号字符,我们可以简单地直接过滤每个字符信号。生成“di”、“da”和空白信号的PHP代码如下:while($dt<$DitTime){$x=Osc();if($dt<(0.5*$DitTime)){//生成编辑时间的一半$x=$x*sin((M_PI/2.0)*$dt/(0.5*$DitTime));$ditstr.=chr(floor(120*$x+128));$dahstr.=chr(floor(120*$x+128));}elseif($dt>(0.5*$DitTime)){//Foradah,thesecondpartofthedit-timeisconstantamplitude$dahstr.=chr(floor(120*$x+128));//Foradit,第二个半衰变具有正弦形状$x=$x*sin((M_PI/2.0)*($DitTime-$dt)/(0.5*$DitTime));$ditstr.=chr(floor(120*$x+128)));}else{$ditstr.=chr(floor(120*$x+128));$dahstr.=chr(floor(120*$x+128));}//aspacehasanamplitudeof0shiftedto128$spcstr.=chr(128);$dt+=$sampleDT;}//此时已生成编辑声音//对于另一个dit-timeunitthedahsoundhasaconstantamplitude$dt=0;while($dt<$DitTime){$x=Osc();$dahstr.=chr(floor(120*$x+128));$dt+=$sampleDT;}//最后在第3个时间,thedah声音必须完成//并在最后的halfdit时间衰减$dt=0;while($dt<$DitTime){$x=Osc();if($dt>(0.5*$DitTime)){$x=$x*sin((M_PI/2.0)*($DitTime-$dt)/(0.5*$DitTime));$dahstr.=chr(floor(120*$x+128));}else{$dahstr.=chr(floor(120*$x+128));}$dt+=$sampleDT;}WAVE格式文件WAVE是一个A通用音频格式在其最简单的形式中,WAVE文件由标题中的一系列整数组成,表示指定采样率下的音频幅度。有关WAVE文件的更多信息,请参阅此处的音频文件格式规范网站。为了生成摩尔斯电码,我们不需要使用WAVE格式的所有参数选项,我们只需要一个8位单声道,so,soeasy。需要注意的是,多字节数据需要按照little-endian字节顺序。WAVE文件使用由称为“块”的记录组成的RIFF格式。WAVE文件以ASCII标识符RIFF开头,后跟一个4字节“块”,然后是包含ASCII字符WAVE的标头,最后是定义格式的数据和声音数据。在我们的程序中,第一个“块”包含一个由ASCII字符fmt和一个4字节的“块”组成的格式说明符。在这里,由于我使用的是普通PCM格式,每个“块”都是16个字节。然后,我们还需要这些数据:通道数、声音样本/秒、平均字节数/秒、块对齐指示符、比特/声音样本。另外,由于我们不需要高质量的立体声,我们只使用单声道,我们使用每秒11050个样本的采样率(标准CD质量音频采样率为每秒44200个样本)来生成声音,并使用8位(bit)来保存。最后,实际的音频数据存储在下一个“块”中。它包含ASCII字符数据、一个4字节的“块”,最后是字节序列的实际音频数据(因为我们使用8位/样本)。在程序中,由一系列8位音频振幅组成的声音存储在变量$soundstr中。一旦生成了音频数据,就可以计算出所有“块”的大小,然后将它们合并到一个磁盘文件中。下面的代码显示了如何生成标题信息和音频“块”。需要注意的是,$riffstr代表RIFF头,$fmtstr代表“chunk”格式,$soundstr代表音频数据“chunk”。$riffstr='RIFF'.$NSizeStr.'WAVE';$x=SAMPLERATE;$SampRateStr='';for($i=0;$i<4;$i++){$SampRateStr.=chr($x%256);$x=floor($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='';对于($i=0;$i<4;$i++){$NSampStr.=chr($x%256);$x=floor($x/256);}$soundstr='data'.$NSampStr.$声带;总结和评论我们的文本摩尔斯电码生成器到目前为止看起来不错。当然,我们也可以对其进行很多修改和改进,比如使用其他字符集,直接从文件中读取文本,生成压缩音频等等。因为我们项目的目的是为了方便在互联网上使用,所以我们简单的解决方案就达到了我们的目的。当然,一如既往的希望大家对这些简单粗暴的代码提出建议。尽管多年来一直教我,但我缺乏摩尔斯电码的背景知识,所以任何错误或遗漏都是我的错。翻译链接:http://www.codeceo.com/article/php-morse-code-generation.html英文原文:MorseCodeGenerationfromText
