Skip to content
Browse files

improve midi debouncing, will refactor into tpad core shortly

  • Loading branch information...
1 parent 617cf14 commit 4d820e905d7519a17dfb056065ca469076b2fa2b @tmpvar committed Oct 19, 2012
Showing with 102 additions and 19 deletions.
  1. +44 −14 command/midi/index.js
  2. +49 −3 lib/button.js
  3. +9 −2 package.json
View
58 command/midi/index.js
@@ -6,45 +6,75 @@ try {
return;
}
var MAX = 18000;
+var offColor = '#002200';
+
var output = new midi.output();
output.getPortCount();
output.getPortName(0);
output.openPort(0);
var state = {0:false, 1:false, 2: false, 3: false };
-module.exports = function(tpad) {
+var calculateVelocity = function(value, activationThreshold, lower) {
+ lower = lower || 0;
+ var velocity = Math.floor(lower + ((value- activationThreshold )/(18000- activationThreshold))*127-lower);
+ if (velocity > 127) { velocity = 127; }
+ return velocity;
+};
+module.exports = function(tpad, scale, activationThreshold) {
+ activationThreshold = activationThreshold || 3000;
+ scale = scale || 1;
var handlePress = function(pad) {
- if (!state[pad.index]) {
- var velocity = Math.floor(63.5 + ((pad.value-tpad.activationThreshold)/(18000-tpad.activationThreshold))*63.5);
-
- if (velocity > 127) { velocity = 127; }
+ if (!state[pad.index] ||
+ (!state[pad.index].on && Date.now() - state[pad.index].time > 1000/64)
+ )
+ {
output.sendMessage([
144,
- 60+pad.index,
- velocity
+ 60+pad.index*scale,
+ calculateVelocity(pad.value, activationThreshold)
]);
- state[pad.index] = true
+ state[pad.index] = { on : true, time : Date.now() };
pad.color('#00FF00');
- pad.once('depress', handleDepress);
}
};
var handleDepress = function(pad) {
- if (state[pad.index]) {
+ if (state[pad.index].on) {
- output.sendMessage([128, 60+pad.index, 127]);
+ output.sendMessage([128, 60+pad.index*scale, 127]);
- state[pad.index] = false;
- pad.color('#000000');
+ state[pad.index].on = false;
+ pad.color(offColor);
pad.once('press', handlePress);
}
};
tpad.each(function(pad, i) {
- pad.once('press', handlePress);
+ pad.color(offColor);
+ pad.change(activationThreshold, 1, function(val) {
+ if (val < 0) {
+ handleDepress(pad);
+ } else {
+ handlePress(pad);
+ }
+ });
+
+ pad.on('raw', function() {
+ console.log(pad.value);
+ if (pad.value === 0) {
+ handleDepress(pad);
+ } else if (state[pad.index].on && pad.value > activationThreshold) {
+ // aftertouch
+ output.sendMessage([
+ 160,
+ 60+pad.index*scale,
+ calculateVelocity(pad.value, activationThreshold)
+ ]);
+ }
+ });
});
};
View
52 lib/button.js
@@ -13,9 +13,49 @@ var Button = module.exports = function Button(index, serialport) {
};
Button.prototype = new EventEmitter();
-Button.prototype.activationThreshold = 4000;
+
+// Activation threshold is based on the amount of change
+// over a millisecond. 8000 is pretty high, and requires
+// a confident press of the buttons
+Button.prototype.activationThreshold = 8000;
+
+// Allow the button to be hit 64 times a second
+Button.prototype.activationWindow = 1000/64;
+
+// the current raw value of this button
Button.prototype.value = 0;
+// the number of historical entries to keep around
+// this is used for tracking change over time and
+// helps debounce
+Button.prototype.historyLength = 100;
+
+Button.prototype.change = function(amount, time, fn) {
+ var
+ that = this,
+ history = this.history
+ last = 0;
+
+ this.on('pressure', function() {
+ var now = Date.now(), value = that.value;
+ for (var i=0; i<history.length; i++) {
+
+ if (history[i].time + time <= now) {
+ var diff = value - history[i].value;
+
+ if (diff > amount) {
+ fn(diff, last);
+ } else if (diff < -amount) {
+ fn(diff, last);
+ }
+ last = diff;
+
+ return;
+ }
+ }
+ });
+};
+
Button.prototype.init = function() {
var that = this;
@@ -31,8 +71,14 @@ Button.prototype.init = function() {
that.pressed = false;
}
- that.history.unshift(value);
- that.history.length = 5;
+ that.history.unshift({
+ value : value,
+ time : Date.now()
+ });
+
+ if (this.history.length > this.historyLength) {
+ that.history.length = this.historyLength;
+ }
that.value = value;
that.emit('pressure', this);
View
11 package.json
@@ -6,15 +6,19 @@
"contributors": [
{
"name": "Mikeal Rogers",
- "email": "mikeal.rogers@gmail.com>"
+ "email": "mikeal.rogers@gmail.com"
+ },
+ {
+ "name": "Max Ogden",
+ "email": "max@maxogden.com"
}
],
"repository": {
"type": "git",
"url": "git://github.com/tmpvar/tpad.git"
},
"dependencies": {
- "serialport": "~0.7.4",
+ "serialport": "*",
"ansi": "~0.1.2",
"glob": "~3.1.10",
"async": "~0.1.22",
@@ -30,6 +34,9 @@
"bin": {
"tpad": "./bin/tpad"
},
+ "optionalDependencies": {
+ "midi" : "https://github.com/tmpvar/node-midi/tarball/master"
+ },
"devDependencies": {},
"engines": {
"node": "*"

0 comments on commit 4d820e9

Please sign in to comment.
Something went wrong with that request. Please try again.