PHP implementation of text-based Morse code generator _php Instance

Source: Internet
Author: User
Recently encountered a requirement to generate Morse code audio files based on input text. After a few searches, I decided to write a generator myself.

Because I wanted to access my Morse code audio files through the web, I decided to use PHP as my main programming language. The above shows a webpage that starts to generate Moss code. In the downloaded zip file, contains the Web page for submitting the text and the PHP source file for generating and presenting the audio file. If you want to test the PHP code, you need to copy the Web page and the associated PHP file to a PHP-enabled server.

For many, the moss code, like some old movies, is a sequence of "dots" and "dashes", or a series of beeps. Obviously, if you want to use computer code to generate Moss code, this understanding is far from enough. This article will describe the elements that generate Moss code, how to generate audio files in wave format, and how to convert Moss code into audio files using PHP.

Moss Code

Moss Code is a text encoding method. It has the advantage of easy coding, and the ear can be easily decoded. In essence, it is the opening and closing of audio (or radio frequency) to form or short or long audio pulses, commonly referred to as dots (dot) and lines (dash), or by radio terminology called "Beep" and "click". In modern digital communications terminology, Moss Code is an amplitude keying (amplitude shift keying, ASK).

In Moss Code, characters (Letters, numbers, punctuation marks, and special symbols) are encoded into a sequence of "beep" and "tick". So in order to convert the text into Morse code, we first have to determine how to represent "tick" and "click". One obvious option is to use 0 for "beep", 1 for "click", or vice versa. Unfortunately, Moss code uses a variable-length encoding scheme. So we also have to use a variable-length sequence, or take a way to package the data into a fixed-bit-width (bit-size) format that is common to computer memory. In addition, it is important to note that Moss code does not differentiate between alphabetic case and some special symbols that cannot be encoded. In our implementation, undefined characters and symbols are ignored.

In this project, memory footprint is not an issue that requires special consideration. So, we propose a simple coding scheme that uses "0" to denote each "tick", "1" for Each "tick", and put them in a string associative array. The PHP code that defines the Moss Code encoding table is like this:

$CWCODE = Array (' A ' = ' + '), ' B ' = ' + ', ' C ' = ' + ', ' D ' = ' + ', ' E ' = ' 0 ', '  F ' = ' 0010 ', ' G ' = > ' A ', ' H ' = ' 0000 ', ' I ' + = ' xx ', ' J ' = ' + ' 0111 ', ' K ' = ' 101 ', ' L ' + ' 0100 ', ' M ' = ' = ', ' N ' = '  Ten ', ' O ' = ' 111 ',  ' P ' = ' 0110 ', ' Q ' = ' 1101 ', ' R ' = ' 010 ', ' S ' ' + ', ' T ' = ' 1 ',  ' U ' and ' = ' 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 ', ', ' = ' and '  110011 ', '/' + ' = ' 10010 ', '-' = ' + ' 10001 ', ' ~ ' = ' 01010 ',  '? ' = ' 001100 ', ' @ ' = ' 00101 ');

It is important to note that if you are particularly concerned about memory usage, the above code can be interpreted as a bitwise (BIT). By adding a start bit to each code, you can form a bit pattern, and each character can be stored in one byte. At the same time, when parsing the final encoding, remove the bit to the left of the start bit (bit) to get a true variable length encoding.

While many people do not realize that the "time interval" is the main factor in defining Moss Code, understanding this is key to generating Moss code. So the first thing we need to do is define the interval between the internal codes of the Moss code (that is, "beep" and "tick"). For the sake of convenience, we define a "beep" for the length of a time unit DT, the interval between "tick" and "tick" is also a time unit DT; defines a "tick" length of 3 dt, the interval between characters (letters) is also 3 DT The interval between defined words (words) is 7 dt. So, to sum up, our time interval table looks like this:

In Moss code, the "playback speed" of encoded sounds is usually expressed in words/minutes (WPM). Since the English words have different lengths and the characters also have different numbers of "tick" and "click", the conversion from WPM to (audio) digital sampling is not as simple as it looks. In a scheme adopted by international organizations, 5 characters are used as the average length of a word, while a number or punctuation mark is treated as 2 characters. In this way, an average of one word is 50 time unit dt. Thus, if you specify WPM, then our total play time is the time unit/minute of the WPM, each "beep" (that is, a time unit dt) length equal to 1.2/wpm seconds. Thus, given a "beep" of the length of time, the length of the other elements can easily be calculated.

You may have noticed that in the pages shown above, we used "Farnsworth spacing" for options below 15WPM. So what is this "Farnsworth spacing"?

When operator learns to decode Moss code with his ear, he realizes that the rhythm of the characters will change as the playback speed changes. When playback speed is less than 10WPM, he can easily identify "beep" and "click", and know which character to send. But when the playback speed exceeds 10WPM, the operator's recognition will be wrong, he will recognize more characters than the actual "beep" and "click". When a person who learns to be accustomed to low-speed moss code, when dealing with high-speed playback code, there will be problems. Because the rhythm has changed, his subconscious identification will go wrong.

To solve this problem, "Farnsworth spacing" was invented. Essentially, the speed at which letters and symbols are played is higher than 15WPM, and the overall playback speed is reduced by inserting more spaces between the characters. In this way, the operator is able to identify each character at a reasonable speed and tempo, and once all the words are nonalphanumeric, the speed can be increased, and the receiver needs to speed up the recognition of the characters. Essentially, the "Farnsworth spacing" technique solves the problem of rhythm change, enabling the receiver to learn quickly.

Therefore, in the entire system, for the lower playback speed, are unified into 15WPM. Correspondingly, the length of a "beep" is 0.08 seconds, but the interval between characters and words is no longer 3 dit or 7 dit, but is adjusted to fit the overall speed.

Generate sound

In PHP code, a character (the index of the preceding array) represents a set of moss sounds made up of "tick", "tick", and blank spacing. We use digital sampling to compose the audio sequence and write it to a file, with the appropriate header information defined as the wave format.

The code that generates the sound is actually quite simple, and you can find them in the PHP file in your project. I find it quite convenient to define a "digital oscillator". Each time the OSC () is called, it returns a timed sample generated from a positive wave. Using sound sampling and audio specifications, it is sufficient to generate the wave format. In the generated positive and dark waves between 1 to + 1 is moved and adjusted, so that the sound of the byte data can be expressed in 0 to 255来, while 128 represents the 0 amplitude.

At the same time, we need to consider another issue in generating sound. In general, we generate Moss code through the switch of the positive and the dark waves. But if you do this directly, you will find that the signals you generate take up a very large amount of bandwidth. As a result, the radio is usually modified to reduce the bandwidth consumption.

In our project, we will also make such corrections, just in the form of numbers. Now that we know the length of a minimum sound sample "beep", it can be proved that the minimum bandwidth of the sound amplitude occurs at length equal to "beep" of the half period of the positive and the wave. In fact, we can also achieve the same effect by filtering the audio signal using the low pass filter. However, since we already know all the signal characters, we can simply filter each character signal.

The PHP code that generates "beep", "tick", and blank signals is like this:

while ($dt < $DitTime) {$x = OSC (), if ($dt < (0.5* $DitTime)) {//Generate the rising part of a dit and dah Half the Dit-time $x = $x *sin ((m_pi/2.0) * $dt/(0.5* $DitTime)); $ditstr. = Chr (Floor (120* $x +128)); $dahstr. = Chr (Floor (120* $x +128)); } else if ($dt > (0.5* $DitTime)) {//For a dah, the second part of the Dit-time is constant amplitude $dahstr. = Chr (f Loor (120* $x +128)); For a dit, the second half decays with a sine shape $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)),}//A space has an amplitude of 0 shifted to $spcstr. = Chr (128); $dt + = $sampleDT;  }//at the "the DIT sound had been generated//for another dit-time unit" The dah sound has a constant AMPLITUDE$DT = 0;while ($dt < $DitTime) {$x = OSC (); $dahstr. = Chr (Floor (120* $x +128)); $dt + = $sampleDT;} Finally during the 3rd dit-time, the Dah sound must is completed//and Decay during the final half 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)); $dahstr. = Chr (Floor (120* $x +128)); } else {$dahstr. = Chr (Floor (120* $x +128));} $dt + = $sampleDT; }

Wave format Files

Wave is a general-purpose audio format. In its simplest form, wave files represent the audio amplitude of a given sample rate by including an integer sequence in the head. For more information about wave files, please see here Audio file Format specifications website. For the production of Moss Code, we do not need to use all the parameters of the wave format options, just need a 8-bit mono on it, so easy. It is important to note that multibyte data requires low-priority (Little-endian) byte order. Wave files use a riff format that consists of records called "Blocks (chunks)".

The wave file starts with an ASCII identifier riff, followed by a 4-byte "block", followed by a header message containing the ASCII character wave, and finally the data and sound data that defines the format.

In our program, the first "block" contains a format specifier, which consists of the ASCII character FMT and a 4 times-byte "block". In this case, since I am using the normal pulse-coded modulation (plain vanilla PCM) format, each "block" is 16 bytes. We will then need these data: number of channels, sound samples/sec, Average Bytes/sec, block alignment indicator, bit (bit)/sound sampling. In addition, since we do not need high-quality stereo, we only use mono, we use 11050 samples per second (standard CD quality audio sample rate is 44200 samples/second) of the sample rate to generate sound, and with 8 bit (bit) to save.

Finally, the real audio data is stored in the next "block". It contains the ASCII character data, a 4-byte "block", and finally a real-world audio data consisting of a sequence of bytes (because we are using 8-bit (bit)/sampling).

In the program, a sound composed of 8-bit audio amplitude sequences is stored in the variable $SOUNDSTR. Once the audio data has been generated, you can calculate all the "block" sizes, and then you can merge them together to write to the disk file. The following code shows how to generate header information and audio "blocks". Note that the $RIFFSTR represents the riff header, $fmtstr represents the "block" format, $SOUNDSTR represents the audio data "block".

$riffstr = ' RIFF ' $NSizeStr. ' WAVE '; $x = samplerate; $SampRateStr = '; for ($i =0; $i <4; $i + +) {$SampRateStr. = chr ($x% 256); $x = Floor ($x/256); } $fmtstr = ' Fmt '. 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; $i <4; $i + +) {$NSampStr. = chr ($x%); $x = Floor ($x/256);} $SOUNDSTR = ' data '. $NSampStr. $soundstr;

Summary and Comment

Our text Moss code generator looks pretty good at the moment. Of course, we can also make a lot of modifications and improvements, such as the use of other character sets, directly from the file to read text, generate compressed audio and so on. Because the purpose of our project is to make it easy to use on the Web, so our simple solution has reached our goal.

Of course, as always, I hope you will make suggestions for these simple and crude code.

  • Related Article

    Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.