New blog post: Morse Code Generator done in AIR, HTML, and JavaScript. Loading audio with AIR and JavaScript

Back in October Ray Camden posted a quick tutorial on how to play sound effects in AIR using JavaScript. One of the commentors mentioned that he teaches a class on morse code and thought it would be cool to have an app that can play morse code on command. I thought it was a good challenge, so I accepted it. Most of it is plain vanilla JavaScript, with the exception of the Sound object. Let's take a look at what's involved. You can download a zip file with the entire project, or you can download the AIR app by itself.

The first thing I needed to to was to get the Morse alphabet, and serialize it. Morse code is simple, consisting of a series of long and short sounds, represented visually by a dot ( . ), and a dash ( - ). I created an object and used the letters and numbers of the alphabet as keys. The values of those keys were the dots and dashes that made up each character.


var morse = {
	a: '.-',	b: '-...',	c: '-.-.',	d: '-..',
	e: '.',		f: '..-.',	g: '--.',	h: '....',
	i: '..',	j: '.---',	k: '-.-',	l: '.-..',
	m: '--',	n: '-.',	o: '---',	p: '.--.',
	q: '--.-',	r: '.-.',	s: '...',	t: '-',
	u: '..-',	v: '...-',	w: '.--',	x: '-..-',
	y: '-.--',	z: '--..',	0: '-----',	1: '.----',
	2: '..---',	3: '...--',	4: '....-',	5: '.....',
	6: '-....',	7: '--...',	8: '---..',	9: '----.'
}

Then I created a simple input field allowing users to type in the text they wanted converted. Next I found 2 sound clips over at SoundJay.com that I felt best represented a dot and a dash. Using AIR we load them into memory as a Sound object, like so. To keep things organized I created another object to store the sound clips. I used a dot and dash as the keys in this object, you'll see why in a minute.


//preload the sounds
var snd = {};
var shortClip = air.File.applicationDirectory.resolvePath("assets/short.mp3");
var longClip = air.File.applicationDirectory.resolvePath("assets/long.mp3");
snd['.'] = new air.Sound(new air.URLRequest(shortClip.url));
snd['-'] = new air.Sound(new air.URLRequest(longClip.url));

The next part is pretty straightforward. I grab the contents of the input field, allowing only letters and numbers. I then loop over the length of the string, matching the character with a key in the morse code object. Because I'm only working with two sound files, each character needs to be broken down to it's dots/dashes, so I store each individual dot/dash of the matching string into an array index for efficient looping later on.


$('input[type=button]').bind('click', function(e) {
	// get the text from the input box
	var txt = $('#morse').val().replace(/\W/gi,'');
	var fullStr = [];
	var html = '';
	$output.html('');
	if (txt == '') {
		alert('text is required');
	} else {
		for ( var letter = 0; letter < txt.length; letter++ ) {
			var c = txt.substring(letter, letter+1);
			var chr = morse[c];
			html +=  '' + c + ' = ' + chr +  '' ;
			for ( sym = 0; sym < chr.length; sym++ ) {
				fullStr.push(chr[sym]);
			}
		}
		$output.html(html);
		playAudio(fullStr);
	}
});

When I'm done matching all the characters from the input field I loop over the resulting array matching each dot and dash with the corresponding audio file. The final piece of the app was to add a slight pause during each loop of the array. Because the SquirrelFish JavaScript engine in AIR is so fast, all the sounds would play at the same time. The pause occurs while the sound is playing and prevents overlap.


function playAudio(str) {
	var chr = str.shift();
	try {
		snd[chr].play();
		if (chr != '') {
				setTimeout(function(){
					playAudio(str)
				}, (chr == '.') ? 265 : 515
			);
		}
	} catch(e) { }
}

The final piece was to add a handy little output window so that users could see the resulting morse code tied to each individual letter. This app was a lot of fun to build and I hope you learn something from it.