Permalink
Browse files

First, hacky commit

  • Loading branch information...
latentflip committed Jun 29, 2013
0 parents commit 68278f7cd34ff881c6d04a454226d02924e97f5b
Showing with 633 additions and 0 deletions.
  1. +1 −0 .gitignore
  2. +44 −0 README.md
  3. +12 −0 build.js
  4. +303 −0 example/demo.bundle.js
  5. +20 −0 example/demo.js
  6. +1 −0 example/index.html
  7. +188 −0 hark.bundle.js
  8. +45 −0 hark.js
  9. +19 −0 package.json
@@ -0,0 +1 @@
node_modules
@@ -0,0 +1,44 @@
# Hark
### Warning: This is a work in progress
Hark is a tiny browser/commonJS module that listens to an audio stream, and emits events indicating whether the user is speaking or not.
## Usage:
`npm install hark`
If you aren't using browserify, you'll want hark.bundle.js.
```javascript
var hark = require('../hark.js')
var getUserMedia = require('getusermedia')
getUserMedia(function(err, stream) {
if (err) throw err
var speechEvents = hark(stream);
speechEvents.on('speaking', function() {
console.log('speaking');
});
speechEvents.on('stopped_speaking', function() {
console.log('stopped_speaking');
});
});
```
## Demo:
Clone and open example/index.html
## Requirements:
Chrome with webrtc audio input flag enabled
## License
MIT
@@ -0,0 +1,12 @@
var browserify = require('browserify'),
fs = require('fs');
var bundle = browserify();
bundle.add('./hark');
bundle.bundle({standalone: 'hark'})
.pipe(fs.createWriteStream('hark.bundle.js'));
var demo = browserify(['./example/demo.js'])
.bundle()
.pipe(fs.createWriteStream('./example/demo.bundle.js'));
@@ -0,0 +1,303 @@
;(function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require=="function"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error("Cannot find module '"+n+"'")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require=="function"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({1:[function(require,module,exports){
var hark = require('../hark.js')
var log = require('bows')('Demo');
var getUserMedia = require('getusermedia')
getUserMedia(function(err, stream) {
if (err) throw err
var speechEvents = hark(stream);
speechEvents.on('speaking', function() {
document.write('Speaking<br>');
log('speaking');
});
speechEvents.on('stopped_speaking', function() {
document.write('Not Speaking<br>');
log('stopped_speaking');
});
});
},{"../hark.js":2,"bows":3,"getusermedia":4}],4:[function(require,module,exports){
// getUserMedia helper by @HenrikJoreteg
var func = (navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia);
module.exports = function (contstraints, cb) {
var options;
var haveOpts = arguments.length === 2;
var defaultOpts = {video: true, audio: true};
// make contstraints optional
if (!haveOpts) {
cb = contstraints;
contstraints = defaultOpts;
}
// treat lack of browser support like an error
if (!func) return cb(new Error('notSupported'));
func.call(navigator, contstraints, function (stream) {
cb(null, stream);
}, function (err) {
cb(err);
});
};
},{}],2:[function(require,module,exports){
var WildEmitter = require('wildemitter');
module.exports = function(stream) {
var speakingThreshold = -45;
var smoothing = 0.5;
var pollPeriod = 100;
var audioContext = new webkitAudioContext();
var sourceNode = audioContext.createMediaStreamSource(stream);
var analyser = audioContext.createAnalyser();
var fftBins = new Float32Array(analyser.fftSize);
analyser.fftSize = 512;
analyser.smoothingTimeConstant = smoothing;
sourceNode.connect(analyser);
var emitter = new WildEmitter();
var speaking = false;
// Poll the analyser node to determine if speaking
// and emit events if changed
setInterval(function() {
var currentVolume = -Infinity;
analyser.getFloatFrequencyData(fftBins)
for(var i=0, ii=fftBins.length; i < ii; i++) {
if (fftBins[i] > currentVolume && fftBins[i] < 0) {
currentVolume = fftBins[i];
}
};
if (currentVolume > speakingThreshold) {
if (!speaking) {
speaking = true;
emitter.emit('speaking');
}
} else {
if (speaking) {
speaking = false;
emitter.emit('stopped_speaking');
}
}
}, pollPeriod);
return emitter;
}
},{"wildemitter":5}],5:[function(require,module,exports){
/*
WildEmitter.js is a slim little event emitter by @henrikjoreteg largely based
on @visionmedia's Emitter from UI Kit.
Why? I wanted it standalone.
I also wanted support for wildcard emitters like this:
emitter.on('*', function (eventName, other, event, payloads) {
});
emitter.on('somenamespace*', function (eventName, payloads) {
});
Please note that callbacks triggered by wildcard registered events also get
the event name as the first argument.
*/
module.exports = WildEmitter;
function WildEmitter() {
this.callbacks = {};
}
// Listen on the given `event` with `fn`. Store a group name if present.
WildEmitter.prototype.on = function (event, groupName, fn) {
var hasGroup = (arguments.length === 3),
group = hasGroup ? arguments[1] : undefined,
func = hasGroup ? arguments[2] : arguments[1];
func._groupName = group;
(this.callbacks[event] = this.callbacks[event] || []).push(func);
return this;
};
// Adds an `event` listener that will be invoked a single
// time then automatically removed.
WildEmitter.prototype.once = function (event, groupName, fn) {
var self = this,
hasGroup = (arguments.length === 3),
group = hasGroup ? arguments[1] : undefined,
func = hasGroup ? arguments[2] : arguments[1];
function on() {
self.off(event, on);
func.apply(this, arguments);
}
this.on(event, group, on);
return this;
};
// Unbinds an entire group
WildEmitter.prototype.releaseGroup = function (groupName) {
var item, i, len, handlers;
for (item in this.callbacks) {
handlers = this.callbacks[item];
for (i = 0, len = handlers.length; i < len; i++) {
if (handlers[i]._groupName === groupName) {
//console.log('removing');
// remove it and shorten the array we're looping through
handlers.splice(i, 1);
i--;
len--;
}
}
}
return this;
};
// Remove the given callback for `event` or all
// registered callbacks.
WildEmitter.prototype.off = function (event, fn) {
var callbacks = this.callbacks[event],
i;
if (!callbacks) return this;
// remove all handlers
if (arguments.length === 1) {
delete this.callbacks[event];
return this;
}
// remove specific handler
i = callbacks.indexOf(fn);
callbacks.splice(i, 1);
return this;
};
// Emit `event` with the given args.
// also calls any `*` handlers
WildEmitter.prototype.emit = function (event) {
var args = [].slice.call(arguments, 1),
callbacks = this.callbacks[event],
specialCallbacks = this.getWildcardCallbacks(event),
i,
len,
item;
if (callbacks) {
for (i = 0, len = callbacks.length; i < len; ++i) {
if (callbacks[i]) {
callbacks[i].apply(this, args);
} else {
break;
}
}
}
if (specialCallbacks) {
for (i = 0, len = specialCallbacks.length; i < len; ++i) {
if (specialCallbacks[i]) {
specialCallbacks[i].apply(this, [event].concat(args));
} else {
break;
}
}
}
return this;
};
// Helper for for finding special wildcard event handlers that match the event
WildEmitter.prototype.getWildcardCallbacks = function (eventName) {
var item,
split,
result = [];
for (item in this.callbacks) {
split = item.split('*');
if (item === '*' || (split.length === 2 && eventName.slice(0, split[1].length) === split[1])) {
result = result.concat(this.callbacks[item]);
}
}
return result;
};
},{}],3:[function(require,module,exports){
(function(window) {
var logger = require('andlog'),
goldenRatio = 0.618033988749895,
hue = 0,
padLength = 15,
yieldColor,
bows;
yieldColor = function() {
hue += goldenRatio;
hue = hue % 1;
return hue * 360;
};
bows = function(str) {
var msg;
msg = "%c" + (str.slice(0, padLength));
msg += Array(padLength + 3 - msg.length).join(' ') + '|';
return logger.log.bind(logger, msg, "color: hsl(" + (yieldColor()) + ",99%,40%); font-weight: bold");
};
bows.config = function(config) {
if (config.padLength) {
return padLength = config.padLength;
}
};
if (typeof module !== 'undefined') {
module.exports = bows;
} else {
window.bows = bows;
}
}).call(this);
},{"andlog":6}],6:[function(require,module,exports){
// follow @HenrikJoreteg and @andyet if you like this ;)
(function () {
var inNode = typeof window === 'undefined',
ls = !inNode && window.localStorage,
out = {};
if (inNode) {
module.exports = console;
return;
}
if (ls && ls.debug && window.console) {
out = window.console;
} else {
var methods = "assert,count,debug,dir,dirxml,error,exception,group,groupCollapsed,groupEnd,info,log,markTimeline,profile,profileEnd,time,timeEnd,trace,warn".split(","),
l = methods.length,
fn = function () {};
while (l--) {
out[methods[l]] = fn;
}
}
if (typeof exports !== 'undefined') {
module.exports = out;
} else {
window.console = out;
}
})();
},{}]},{},[1])
;
@@ -0,0 +1,20 @@
var hark = require('../hark.js')
var log = require('bows')('Demo');
var getUserMedia = require('getusermedia')
getUserMedia(function(err, stream) {
if (err) throw err
var speechEvents = hark(stream);
speechEvents.on('speaking', function() {
document.write('Speaking<br>');
log('speaking');
});
speechEvents.on('stopped_speaking', function() {
document.write('Not Speaking<br>');
log('stopped_speaking');
});
});
@@ -0,0 +1 @@
<script src='demo.bundle.js'></script>
Oops, something went wrong.

0 comments on commit 68278f7

Please sign in to comment.