- Author:
- Chris Smoak
- Twitter:
- @
- GitHub:
- Facebook:
- Google+:
- +
- Reddit:
- /r/
- Pouet:
- Website:
- Compo:
- classic
- Demo link:
- https://js1k.com/2010-first/demo/806
- Shortlink:
- https://js1k.com/806
- Blog post:
- please update here!
- Bytes:
- 994
- Chars:
- 987
- Submission
S=String.fromCharCode
A=32,O=127
f=function(l,v){for(k=l*(v?2:3);k--;)m+='ÿó$ÀZZ`'+(v?'$':'ZZ')+'ZZZZþÐ'+Array(34).join('Z');for(;k++<l*2646;u++)d+=S(Math.sin(k*.085)*!!v*A+O)}
with(document.body.children[0])with(getContext('2d'))r=function(E){if(E){d=m='',v=[],u=i=j=0
s=prompt('Message to encode:','SOS 1K dead ahead!')
for(f(9);g=x=2,c=s[Y='charCodeAt'](i);i++,f(g))for(e=c-A?'~^NFB@`px|'[Y](c-48)||'\x0a04$ .(,:"268'[Y](95&c-65):f(2),v[i]=u;e>3;e>>=1,g*=s.substr(i-x--,3)!='SOS')f(e&2|1,1),f(1)
for(w=['RIFF','WAVEfmt ZZZZZD¬ZZD¬ZZZZdata'];h=[u+36,u][j];j++)for(i=4;i--;h>>=8)w[j]+=S(h&255)
with(a=new Audio)play(src='data:'+(canPlayType(t='audio/wav')?t:t='')+';base64,'+btoa((t?w.join('')+d:m).replace(/Z/g,'\x00')))}width=W=500;font='20pt X';beginPath(p=a.currentTime*44100|0);for(moveTo(i=0,A);i++<W;)lineTo(i,(d[Y](p+i*50-W*25>>6<<6)-O|0)+A);stroke(lineTo(W,A));for(i in v)fillText(S(s[Y](i)),(v[i]-p)/50+W/2|0,85);p<u&&setTimeout('r()',9)||r(1)}
r(1)
- Description
- Creates and plays a WAV or MP3 (depending on browser) of your message encoded in Morse code.
Features:
. Cross-browser support through creation of both WAV and MP3
. Supports A-Z,a-z,0-9
. Handles SOS prosign correctly, with no character-length silences
. Packed by hand, actually looks like JS!
UPDATE #2: changed to use prompt, found other size optimizations
UPDATE #1: changed use of hashtag to input tag so it works embedded in a frame (doh!), added some more hand-optimizations
- Base64 encoded
Uz1TdHJpbmcuZnJvbUNoYXJDb2RlDQpBPTMyLE89MTI3DQpmPWZ1bmN0aW9uKGwsdil7Zm9yKGs9bCoodj8yOjMpO2stLTspbSs9J8O/w7Mkw4BaWmAnKyh2PycDJCc6J1paJykrJ1paWlrDvsOQJytBcnJheSgzNCkuam9pbignWicpO2Zvcig7aysrPGwqMjY0Njt1KyspZCs9UyhNYXRoLnNpbihrKi4wODUpKiEhdipBK08pfQ0Kd2l0aChkb2N1bWVudC5ib2R5LmNoaWxkcmVuWzBdKXdpdGgoZ2V0Q29udGV4dCgnMmQnKSlyPWZ1bmN0aW9uKEUpe2lmKEUpe2Q9bT0nJyx2PVtdLHU9aT1qPTANCnM9cHJvbXB0KCdNZXNzYWdlIHRvIGVuY29kZTonLCdTT1MgMUsgZGVhZCBhaGVhZCEnKQ0KZm9yKGYoOSk7Zz14PTIsYz1zW1k9J2NoYXJDb2RlQXQnXShpKTtpKyssZihnKSlmb3IoZT1jLUE/J35eTkZCQGBweHwnW1ldKGMtNDgpfHwnXHgwYTA0GAQkHCAILhooDgweLDoUEAYSIhYyNjgnW1ldKDk1JmMtNjUpOmYoMiksdltpXT11O2U+MztlPj49MSxnKj1zLnN1YnN0cihpLXgtLSwzKSE9J1NPUycpZihlJjJ8MSwxKSxmKDEpDQpmb3Iodz1bJ1JJRkYnLCdXQVZFZm10IBBaWloBWgFaRMKsWlpEwqxaWgFaCFpkYXRhJ107aD1bdSszNix1XVtqXTtqKyspZm9yKGk9NDtpLS07aD4+PTgpd1tqXSs9UyhoJjI1NSkNCndpdGgoYT1uZXcgQXVkaW8pcGxheShzcmM9J2RhdGE6JysoY2FuUGxheVR5cGUodD0nYXVkaW8vd2F2Jyk/dDp0PScnKSsnO2Jhc2U2NCwnK2J0b2EoKHQ/dy5qb2luKCcnKStkOm0pLnJlcGxhY2UoL1ovZywnXHgwMCcpKSl9d2lkdGg9Vz01MDA7Zm9udD0nMjBwdCBYJztiZWdpblBhdGgocD1hLmN1cnJlbnRUaW1lKjQ0MTAwfDApO2Zvcihtb3ZlVG8oaT0wLEEpO2krKzxXOylsaW5lVG8oaSwoZFtZXShwK2kqNTAtVyoyNT4+Njw8NiktT3wwKStBKTtzdHJva2UobGluZVRvKFcsQSkpO2ZvcihpIGluIHYpZmlsbFRleHQoUyhzW1ldKGkpKSwodltpXS1wKS81MCtXLzJ8MCw4NSk7cDx1JiZzZXRUaW1lb3V0KCdyKCknLDkpfHxyKDEpfQ0KcigxKQ==
- Original source
/**
* Plays message as Morse code WAV/MP3 (cross-browser), displays the waveform
* Chris Smoak, chris.smoak@gmail.com, @chrissmoak
* August 13, 2010
*
* Enter your message at the prompt, wait a few seconds, and then listen and
* watch your message play back as morse code. The message will be converted
* to Morse code, encoded as a WAV or MP3 depending on browser, and the
* waveform will scroll across the screen.
*
* Features:
* . Cross-browser support through creation of both WAV and MP3
* . Supports A-Z,a-z,0-9
* . Handles SOS prosign correctly, with no character-length silences
* . Packed by hand, actually looks like JS!
*
* Algorithm:
* - get the input string from the user
* - loop through each character; for each recognized character:
* - if it's a space, emit word-length silence
* - otherwise, look up in the number and/or letter dictionary:
* - emit dits and dahs based on the dictionary entry
* - emit character-length silence unless we're in the middle of an 'SOS'
* where emit is:
* - create and append MP3 frames for the sound or silence
* - create and append WAV samples for the sound or silence
* - map character to WAV sample index for later use in display
* - fill in the missing WAV header fields
* - create the audio element
* - use canPlayType to determine which data to use
* - create the data uri and replace 'Z' with '\x00'
* - start playing the audio
* - until the audio has stopped:
* - clear the canvas
* - start with the audio current playhead
* - draw the waveform amplitude across the width of the canvas
* - for each character in the input:
* - draw the character under the waveform
*
* Morse code dictionary:
* each mapped character takes 1 byte. least significant bit is 0 to ease
* calculation of 1 or 3 for dit/dah length. each bit after LSb is 1 for dah,
* 0 for dit. the bit after all tone bits is 1, indicating end of character.
* to read, repeatedly read the byte & 2 | 1 for the length of the tone,
* shift right and continue until byte <= 2.
* Ideas from: http://www.ioccc.org/1998/dorssel.hint2
*
* WAV
* an 8-bit 44.1khz mono WAV is created. tones are sampled from a 600hz sine
* wave.
* Ideas from: http://acko.net/blog/javascript-audio-synthesis-with-html-5
*
* MP3
* a 16kbps mono MP3 sampled at 24khz is created. the structure of each frame
* is as follows:
* - header = '\xff\xf3\x24\xc0'
* - sync bits: 1111 1111 111
* - version: 10 (MPEG2)
* - layer: 01 (layer III)
* - CRC?: 1 (no crc)
* - bit rate: 0010 (16kbps)
* - sampling rate: 01 (24khz)
* - use padding: 0 (no)
* - private bit: 0
* - channel mode: 11 (mono)
* - mode extension: 00 (none)
* - copyright: 0 (false)
* - original 0 (false)
* - emphasis: 00 (none)
* - side info =
* '\x00\x00\x60'
* + (volume ? '\x03\x24' : '\x00\x00')
* + '\x00\x00\x00\x00'
* - main_data_begin: 0000 0000
* - private: 0
* - part2_3_length: 0000 0000 1100
* - big_values: 0000 0000 0
* - global_gain: volume ? 1100 1001 : 0000 0000
* - scalefac_compress: 0000 0000 0
* - window_switching_flag: 0
* - table_select[0..2]: 0000 0, 0000 0, 0000 0
* - region0_count: 0000
* - region1_count: 000
* - scalefac_scale: 0
* - count1table_select: 0
* - main data = '\xfe\xd0'
* - scale factors: no bits used
* - big_values: no bits used
* - +1/0/-1 region: 1111 1110 1101
* - padding to end of frame = '\x00' x 33
*/