自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

PHP實現(xiàn)基于文本的莫斯電碼生成器

開發(fā) 后端
文本莫斯代碼生成器目前看起來還不錯。當然,我們還可以對它做很多的修改和完善,比如使用其他字符集、直接從文件中讀取文本、生成壓縮音頻等等。因為我們這個項目的目的是使其能夠在網(wǎng)絡上方便的使用,所以我們這個簡單的方案,已經達到我們的目的了。

介紹

我最近遇到一個基于輸入文本生成摩斯代碼音頻文件的需求。幾番搜索無果之后,我決定自己編寫一個生成器。

下載源代碼 – 2.63 KB

PHP內核探索之PHP中的哈希表

因為我希望通過web的方式訪問我的摩斯代碼音頻文件,所以我決定采用PHP作為我主要的編程語言。上面的截圖顯示了一個開始生成莫斯代碼的網(wǎng)頁。在下載的zip文件中,包含了用于提交文本的網(wǎng)頁以及用于生成和展現(xiàn)音頻文件的PHP源文件。如果你想測試PHP代碼,你需要將網(wǎng)頁和相關的PHP文件復制到啟用了PHP的服務器上。

對于許多人來說,莫斯代碼就像一些老電影中表現(xiàn)的那樣,就是一些“點”和“橫線”的序列,或者一連串的嗶嗶聲。顯然,如果你想用計算機代碼來生成莫斯代碼,這樣的了解是遠遠不夠的。這篇文章將會介紹生成莫斯代碼的要素,如何生成WAVE 格式的音頻文件,以及如何用PHP將莫斯代碼轉化成音頻文件。

莫斯代碼

莫斯代碼是一種文本編碼方式。它的優(yōu)點是編碼方便,而且用人耳就能夠方便的解碼。本質上,是通過音頻(或者無線電頻)的開和關,從而形成或短或長的音頻脈沖,一般稱作點(dot)和線(dash),或者用無線電術語稱作“嘀”和“嗒”。用現(xiàn)代數(shù)字通信術語,莫斯代碼是一種振幅鍵控(amplitude shift keying ,ASK)。

在莫斯代碼中,字符(字母,數(shù)字,標點符號和特殊符號)被編碼成一個“嘀”和“嗒”的序列。所以為了把文本轉化成莫斯代碼,我們首先要確定如何來表示“嘀”和“嗒”。一個很顯然的選擇就是,用0表示“嘀”,用1表示“嗒”,或者反過來。不幸的是,莫斯代碼采用的是可變長編碼方案。所以我們也必須要使用一種可變長序列,或者采取一種方式,把數(shù)據(jù)打包成一種計算機內存通用的固定位寬(fixed bit-size)的格式。另外,需要特別注意的是,莫斯代碼并不區(qū)分字母大小寫,而且對一些特殊符號無法編碼。在我們這個實現(xiàn)中,未定義的字符和符號將會被忽略。

在這個項目中,內存占用并不是一個需要特別考慮的問題。所以,我們提出一個簡單的編碼方案,即用“0”來表示每個“嘀”,用“1”來表示每個“嗒”,并且把他們放在一個字符串關聯(lián)數(shù)組中。定義莫斯代碼編碼表的PHP代碼就像下面這樣:

 

  1. $CWCODE = array ('A'=>'01','B'=>'1000','C'=>'1010','D'=>'100','E'=>'0'
  2.      'F'=>'0010','G'=>'110','H'=>'0000','I'=>'00','J'=>'0111'
  3.      'K'=>'101','L'=>'0100','M'=>'11','N'=>'10''O'=>'111'
  4.      'P'=>'0110','Q'=>'1101','R'=>'010','S'=>'000','T'=>'1'
  5.      'U'=>'001','V'=>'0001','W'=>'011','X'=>'1001','Y'=>'1011'
  6.      'Z'=>'1100''0'=>'11111','1'=>'01111','2'=>'00111'
  7.      '3'=>'00011','4'=>'00001','5'=>'00000','6'=>'10000'
  8.      '7'=>'11000','8'=>'11100','9'=>'11110','.'=>'010101'
  9.      ','=>'110011','/'=>'10010','-'=>'10001','~'=>'01010'
  10.      '?'=>'001100','@'=>'00101'); 

需要注意的是,如果你特別在意內存占用的話,上面的代碼可以解釋為位(bit)。給每個代碼增加一個開始位,就可以形成一個位的模式,每個字符就可以用一個字節(jié)來儲存。同時,當解析最終編碼的時候,要刪除開始位左邊的位(bit),從而獲得真正的變長編碼。

盡管許多人沒有意識到,事實上“時間間隔”是定義莫斯代碼的主要因素,所以理解這一點是生成莫斯代碼的關鍵。所以,我們要做的第一件事,就是定義莫斯代碼的內部碼(即“嘀”和“嗒”)的時間間隔。為了方便起見,我們定義一個“嘀”的聲音長度為一個時間單位dt,“嘀”和“嗒”之間的間隔也是一個時間單位dt;定義一個“嗒”的長度為3個dt,字符(letters)之間的間隔也是3個dt;定義單詞(words)之間的間隔是7個dt。所以,總結起來,我們的時間間隔表就像下面這樣:

項目

時間長度

dt

“嘀”/“嗒”之間的間隔

dt

“嗒”

3*dt

字符之間的間隔

3*dt

單詞之間的間隔

7*dt

在莫斯代碼中,編碼聲音的“播放速度”通常用 單詞數(shù)/分鐘(WPM) 來表示。由于英文單詞有不同的長度,而且字符也有不同數(shù)量的“嘀”和“嗒”,所以,從WPM轉化成(音頻)數(shù)字采樣并不是看上去那樣簡單。在一份被國際組織采用的方案中,采用5個字符作為單詞的平均長度,同時,一個數(shù)字或標點符號被當做2個字符。這樣,平均一個單詞就是50個時間單位dt。這樣,如果你指定了WPM,那么我們總的播放時間就是 50 * WPM的時間單位/分鐘,每個“嘀”(即一個時間單位dt)的長度等于1.2/WPM秒。這樣,給出一個“嘀”的時間長度,其他元素的時間長度很容易就能夠計算出來。

你可能已經注意到,在上面顯示的網(wǎng)頁中,對于低于15WPM的選項,我們使用了“Farnsworth spacing”。那么這個“Farnsworth spacing”又是個什么鬼?

當報務員學習用耳朵來解碼莫斯代碼的時候,他就會意識到,當播放速度變化的時候,字符出現(xiàn)的節(jié)奏也會跟著變化。當播放速度低于10WPM的時候,他能夠從容的識別“嘀”和“嗒”,并且知道發(fā)送的哪個字符。但是當播放速度超過10WPM的時候,報務員的識別就會出錯,他識別出來的字符會多于實際的“嘀”和“嗒”。當一個學習的時候習慣低速莫斯代碼的人,在處理高速播放代碼的時候,就會出現(xiàn)問題。因為節(jié)奏變了,他潛意識的識別就會出錯。

為了解決這個問題,“Farnsworth spacing”就被發(fā)明出來了。本質上來講,字母和符號的播放速度依然采取高于15WPM的速度,同時,通過在字符之間插入更多的空格,來使整體的播放速度降低。這樣,報務員就能夠以一個合理的速度和節(jié)奏來識別每個字符,一旦所有的字符都學習完畢,就可以增加速度,而接收員只需要加快識別字符的速度就可以了。本質上來說,“Farnsworth spacing”這個技巧解決了節(jié)奏變化這個問題,使接收員能夠快速學習。

所以,在整個系統(tǒng)中,對于更低的播放速度,都統(tǒng)一成15WPM。相對應的,一個“嘀”的長度是0.08秒,但是字符之間和單詞之間的間隔就不再是3個dit或者7個dit,而是進行的調整以適應整體速度。

生成聲音

在PHP代碼中,一個字符(即前面數(shù)組的索引)代表一組由“嘀”、“嗒”和空白間隔組成的莫斯聲音。我們用數(shù)字采樣來組成音頻序列,并且將其寫入到文件中,同時加上適當?shù)念^信息來將其定義成WAVE格式。

生成聲音的代碼其實相當簡單,你可以在項目中PHP文件中找到它們。我發(fā)現(xiàn)定義一個“數(shù)字振蕩器”相當方便。每調用一次osc(),它就會返回一個從正玄波產生的定時采樣。運用聲音采樣和聲頻規(guī)范,生成WAVE格式的音頻已經足夠了。在產生的正玄波中的-1到+1之間是被移動和調整過的,這樣聲音的字節(jié)數(shù)據(jù)可以用0到255來表示,同時128表示零振幅。

同時,在生成聲音方面我們還要考慮另外一個問題。一般來講,我們是通過正玄波的開關來生成莫斯代碼。但是你直接這樣來做的話,就會發(fā)現(xiàn)你生成的信號會占用非常大的帶寬。所以,通常無線電設備會對其加以修正,以減少帶寬占用。

在我們的項目中,也會做這樣的修正,只不過是用數(shù)字的方式。既然我們已經知道了一個最小聲音樣本“嘀”的時間長度,那么,可以證明,最小帶寬的聲幅發(fā)生在長度等于“嘀”的正玄波半周期。事實上,我們使用低通濾波器(low pass filter)來過濾音頻信號也能達到同樣的效果。不過,既然我們已經知道所有的信號字符,我們直接簡單的過濾一下每一個字符信號就可以了。

生成“嘀”、“嗒”和空白信號的PHP代碼就像下面這樣:

  1. while ($dt < $DitTime) { 
  2.   $x = Osc(); 
  3.   if ($dt < (0.5*$DitTime)) { 
  4.     // Generate the rising part of a dit and dah up to half the dit-time 
  5.     $x = $x*sin((M_PI/2.0)*$dt/(0.5*$DitTime)); 
  6.     $ditstr .= chr(floor(120*$x+128)); 
  7.     $dahstr .= chr(floor(120*$x+128)); 
  8.     } 
  9.   else if ($dt > (0.5*$DitTime)) { 
  10.     // For a dah, the second part of the dit-time is constant amplitude 
  11.     $dahstr .= chr(floor(120*$x+128)); 
  12.     // For a dit, the second half decays with a sine shape 
  13.     $x = $x*sin((M_PI/2.0)*($DitTime-$dt)/(0.5*$DitTime)); 
  14.     $ditstr .= chr(floor(120*$x+128)); 
  15.     } 
  16.   else { 
  17.     $ditstr .= chr(floor(120*$x+128)); 
  18.     $dahstr .= chr(floor(120*$x+128)); 
  19.     } 
  20.   // a space has an amplitude of 0 shifted to 128 
  21.   $spcstr .= chr(128); 
  22.   $dt += $sampleDT; 
  23.   } 
  24. // At this point the dit sound has been generated 
  25. // For another dit-time unit the dah sound has a constant amplitude 
  26. $dt = 0
  27. while ($dt < $DitTime) { 
  28.   $x = Osc(); 
  29.   $dahstr .= chr(floor(120*$x+128)); 
  30.   $dt += $sampleDT; 
  31.   } 
  32. // Finally during the 3rd dit-time, the dah sound must be completed 
  33. // and decay during the final half dit-time 
  34. $dt = 0
  35. while ($dt < $DitTime) { 
  36.   $x = Osc(); 
  37.   if ($dt > (0.5*$DitTime)) { 
  38.     $x = $x*sin((M_PI/2.0)*($DitTime-$dt)/(0.5*$DitTime)); 
  39.     $dahstr .= chr(floor(120*$x+128)); 
  40.     } 
  41.   else { 
  42.     $dahstr .= chr(floor(120*$x+128)); 
  43.     } 
  44.   $dt += $sampleDT; 
  45.   } 

WAVE格式的文件

WAVE是一種通用的音頻格式。從最簡單的形式來看,WAVE文件通過在頭部包含一個整數(shù)序列來表示指定采樣率的音頻振幅。關于WAVE文件的詳細信息請查看這里Audio File Format Specifications website。對于產生莫斯代碼,我們并不需要用到WAVE格式的所有參數(shù)選項,僅僅需要一個8位的單聲道就可以了,所以,so easy。需要注意的是,多字節(jié)數(shù)據(jù)需要采用低位優(yōu)先(little-endian)的字節(jié)順序。WAVE文件使用一種由叫做“塊(chunks)”的記錄組成的RIFF格式。

WAVE文件由一個ASCII標識符RIFF開始,緊跟著一個4字節(jié)的“塊”,然后是一個包含ASCII字符WAVE的頭信息,最后是定義格式的數(shù)據(jù)和聲音數(shù)據(jù)。

在我們的程序中,第一個“塊”包含了一個格式說明符,它由ASCII字符fmt和一個4倍字節(jié)的“塊”。在這里,由于我使用的是普通脈沖編碼調制(plain vanilla PCM)格式,所以每個“塊”都是16字節(jié)。然后,我們還需要這些數(shù)據(jù):聲道數(shù)、聲音采樣/秒、平均字節(jié)/秒、一個區(qū)塊(block)對齊指示器、位(bit)/聲音采樣。另外,由于我們不需要高質量立體聲,我們只采用單聲道,我們使用 11050采樣/秒(標準的CD質量音頻的采樣率是 44200采樣/秒)的采樣率來生成聲音,并且用8位(bit)保存。

最后,真實的音頻數(shù)據(jù)儲存在接下來的“塊”中。其中包含ASCII字符data,一個4字節(jié)的“塊”,最后是由字節(jié)序列(因為我們采用的是8位(bit)/采樣)組成的真實音頻數(shù)據(jù)。

在程序中,由8位音頻振幅序列組成的聲音保存在變量$soundstr中。一旦音頻數(shù)據(jù)生成完畢,就可以計算出所有的“塊”大小,然后就可以把它們合并在一起寫入磁盤文件中。下面的代碼展示了如何生成頭信息和音頻“塊”。需要注意的是,$riffstr表示RIFF頭,$fmtstr表示“塊”格式,$soundstr表示音頻數(shù)據(jù)“塊”。

  1. $riffstr = 'RIFF'.$NSizeStr.'WAVE'
  2. $x = SAMPLERATE; 
  3. $SampRateStr = ''
  4. for ($i=0; $i<4; $i++) { 
  5.   $SampRateStr .= chr($x % 256); 
  6.   $x = floor($x/256); 
  7.   } 
  8. $fmtstr = 'fmt '.chr(16).chr(0).chr(0).chr(0).chr(1).chr(0).chr(1).chr(0
  9.           .$SampRateStr.$SampRateStr.chr(1).chr(0).chr(8).chr(0); 
  10. $x = $n; 
  11. $NSampStr = ''
  12. for ($i=0; $i<4; $i++) { 
  13.   $NSampStr .= chr($x % 256); 
  14.   $x = floor($x/256); 
  15.   } 
  16. $soundstr = 'data'.$NSampStr.$soundstr; 

總結和評論

我們的文本莫斯代碼生成器目前看起來還不錯。當然,我們還可以對它做很多的修改和完善,比如使用其他字符集、直接從文件中讀取文本、生成壓縮音頻等等。因為我們這個項目的目的是使其能夠在網(wǎng)絡上方便的使用,所以我們這個簡單的方案,已經達到我們的目的了。

當然,一如既往的,希望大家對這些簡單粗暴的代碼提出建議。這些年來雖然一直有人在教我,但我還是缺乏莫斯代碼相關背景知識,所以,如果出現(xiàn)任何的錯誤或遺漏都算是我的錯。

責任編輯:張燕妮 來源: 碼農網(wǎng)
相關推薦

2016-01-08 10:55:31

PHP莫斯電碼生成器

2024-01-26 08:28:41

工單號生成器場景

2024-02-23 15:53:13

OpenAISora人工智能

2017-03-20 17:49:21

Java Web模板代碼

2022-11-21 17:44:03

機器學習文本生成器自然語言

2017-09-06 09:26:03

Python生成器協(xié)程

2010-09-07 16:31:17

SQL語句insert

2021-04-22 21:15:38

Generator函數(shù)生成器

2011-12-23 13:42:05

JavaScript

2015-08-25 11:07:58

2017-07-01 16:02:39

分布式ID生成器

2025-01-23 08:36:27

CSS開發(fā)工具

2023-05-04 16:24:10

人工智能圖像生成器

2023-02-07 16:11:41

2022-07-25 10:27:36

背景生成器工具前端

2024-11-01 15:51:06

2023-05-17 16:02:00

CSS工具代碼生成器

2023-07-02 14:14:37

ChatGPTMidjourney

2021-12-04 22:07:44

Python

2015-08-25 15:54:17

程序員代碼生成器
點贊
收藏

51CTO技術棧公眾號