squash a bug in some sound playing code
New here? Learn about Bountify and follow @bountify to get notified of new bounties! x

The following in-progress Meteor app is a simple memory game. In the game, a pattern of beeps is played once, and the player repeats the pattern by tapping it out using the space bar. There's a bug that I can't seem to get rid of where around 1 out of every 5 taps fails to produce a sound, even though the tap is registered. The bug can be replicated by running the app, then tapping the space bar on, off, on, off, ..., in 1 second intervals. Please modify the app, contained here (https://dl.dropbox.com/u/71262/Collective.zip), so that the space bar always produces the tone.

Please provide a zip file with an updated version of the app.

There are additional opportunities for work on this app if you are interested.

awarded to Skyler

Crowdsource coding tasks.

1 Solution

Winning solution

The solution to this issue is, on the surface, very simple.

var audio = beeper.play(1000, 4, [Beep.utils.amplify(10000)]);

You generate a 4 second wave file with this line. If you hold down the space bar for any more than 4 seconds, the sound cuts off. If your browser/OS has a key repeat interval defined for the keydown event, then the sound will start back up after a small pause because of this line of code:

Mousetrap.bind('space', function() {audio.play(); console.log('down');}, 'keydown');

Here, audio.play() would be triggered at every key repeat of the keydown event, so if the audio stops playing, audio.play() would start it back up again at the next key repeat.

So why is this an issue if you only hold down the space bar for a second at a time? You defined the keyup event to call audio.pause(), which retains the audio play position. When the keydown event is triggered and a call to audio.play() is made, the audio is resumed at the retained play position. With your instructions to hold down the space bar for 5 intervals of 1 second in length, the 5th press will likely fail because the retained audio position is very close to the end of the audio clip. So, when audio.play() is called at this 5th space bar press, only a small fraction of the audio clip is played until the end is reached and the playback stops.

A long explanation for a 1 line fix. Add this line of code after you instantiate var audio:

audio.loop = true;

This will ensure that the audio clip automatically starts back up again when the position marker hits the end. This solution works, but practically all browsers have non-optimal support for the loop attribute. When testing this solution in multiple browsers, they all had a very short but noticeable pause between the end of the clip and the restarting of it. One way to circumvent this if you assume that all key presses will last for less than 4 seconds is to reset the position marker to zero every time the keyup event occurs:

...
audio.pause();
audio.currentTime = 0;
...

This solution is most likely suitable enough. However, I have also created a solution that lessens or completely gets rid of the loop gap by utilizing Hivenfour's SeamlessLoop. I will include my solution implementation with this method as well.

Solution ZIP Folder

Hope that helps!

Thanks, this was a great solution. The problem is gone, your explanation was clear, I learned something, and you even fixed a browser compatibility issue that I didn't even know about! Cheers.
suchow over 8 years ago