is a JavaScript library for recording and comparing rhythms. It can be used for games and for more serious things.
npm install tappy # or whatever
var tappy = require('tappy');
To record rhythms, create a new Rhythm object:
var password = new tappy.Rhythm();
...and call its tap()
method at each beat:
function tapThat () { password.tap(); }
window.addEventListener('click', tapThat, false);
var i = 7;
while (i--) password.tap();
Call done()
when you're done recording.
if (password.length === 7) password.done();
As you might have noticed, Rhythm objects have a length
attribute. They also have a duration
attribute and a playback()
method.
var pwDuration = password.duration; // in ms
// playback() accepts a callback to run at each
// tap, an optional callback for when the Rhythm
// finishes, and an optional multiplier
password.playback(
function (i) { console.log('Tap number ' + i); },
function ( ) { console.log('Finished Rhythm'); },
2
);
// the multiplier in this example makes the Rhythm
// play 2x slower than the original
To compare two rhythms, pass them into tappy.compare()
:
// all Rhythm methods are chainable
var newPassword = new tappy.Rhythm().tap().tap();
newPassword.tap().tap().tap().tap().tap().done();
// returns a confidence value from 0 to 1 (1 === exact match)
tappy.compare(password, newPassword, true);
// the third argument is optional; by default, compare() elastically
// matches rhythms played at different tempos. It's useful for cases
// like the lyrics game, where players may slow down when focusing.
//
// a truthy third argument makes compare() match tempo and rhythm;
// this works well for keystroke dynamics analysis etc.
Tappy works on the client and the server:
// if a Rhythm object is stringified,
// eg. you need to pass it to a server
var stringified = JSON.stringify(password);
// it can be easily reconstructed by passing
// the raw object into the Rhythm constructor
var raw = JSON.parse(stringified);
var recovered = new tappy.Rhythm(raw);
Rhythms can be merged with tappy.average()
to eliminate timing anomalies:
// accepts any number of Rhythms
var steady = tappy.average(password, newPassword, recovered);
// it even works with rhythms that have already been averaged
var intermediate = tappy.average(password, newPassword);
var steady2 = tappy.average(intermediate, recovered);
alert(tappy.compare(steady, steady2));
There are a few more tricks up Tappy's sleeve:
// the Rhythm constructor can accept an array of ms
// time intervals between notes. For example, four
// quarter-notes followed by four half-notes looks like:
var preset = new tappy.Rhythm([1, 1, 1, 1, 2, 2, 2]);
// since there are 8 notes, we input 7 inter-note intervals
That's all there is to it! Have fun.