Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use requestAnimationFrame() instead of setTimeout/setInterval() #24

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,12 @@ speech.on('speaking', function() {
* `stopped_speaking` emitted when the audio doesn't seem to be speaking
* `volume_change` emitted on every poll event by the event emitter with the current volume (in decibels) and the current threshold for speech
* The hark object also has the following methods to update the config of hark. Both of these options can be passed in on instantiation, but you may wish to alter them either for debug or fine tuning as your app runs.
* `setInterval(interval_in_ms)` change
* `setThreshold(threshold_in_db)` change the minimum volume at which the audio will emit a `speaking` event
* hark can be stopped by calling this method
* `stop()` will stop the polling and events will not be emitted.

## Options

* `interval` (optional, default 100ms) how frequently the analyser polls the audio stream to check if speaking has started or stopped. This will also be the frequency of the `volume_change` events.
* `threshold` (optional, default -50db) the volume at which `speaking`/`stopped\_speaking` events will be fired
* `play` (optional, default true for audio tags, false for webrtc streams) whether the audio stream should also be piped to the speakers, or just swallowed by the analyser. Typically for audio tags you would want to hear them, but for microphone based webrtc streams you may not to avoid feedback.

Expand Down
71 changes: 28 additions & 43 deletions example/demo.bundle.js
Original file line number Diff line number Diff line change
Expand Up @@ -232,11 +232,10 @@ module.exports = function(stream, options) {
//Config
var options = options || {},
smoothing = (options.smoothing || 0.1),
interval = (options.interval || 50),
threshold = options.threshold,
play = options.play,
history = options.history || 10,
running = true;
timer;

//Setup Audio Context
if (!audioContext) {
Expand Down Expand Up @@ -270,12 +269,8 @@ module.exports = function(stream, options) {
threshold = t;
};

harker.setInterval = function(i) {
interval = i;
};

harker.stop = function() {
running = false;
cancelAnimationFrame(timer);
harker.emit('volume_change', -100, threshold);
if (harker.speaking) {
harker.speaking = false;
Expand All @@ -289,47 +284,37 @@ module.exports = function(stream, options) {
harker.speakingHistory.push(0);
}

// Poll the analyser node to determine if speaking
// and emit events if changed
var looper = function() {
setTimeout(function() {

//check if stop has been called
if(!running) {
return;
}

var currentVolume = getMaxVolume(analyser, fftBins);
function checkVolume() {
var currentVolume = getMaxVolume(analyser, fftBins);

harker.emit('volume_change', currentVolume, threshold);
harker.emit('volume_change', currentVolume, threshold);

var history = 0;
if (currentVolume > threshold && !harker.speaking) {
// trigger quickly, short history
for (var i = harker.speakingHistory.length - 3; i < harker.speakingHistory.length; i++) {
history += harker.speakingHistory[i];
}
if (history >= 2) {
harker.speaking = true;
harker.emit('speaking');
}
} else if (currentVolume < threshold && harker.speaking) {
for (var i = 0; i < harker.speakingHistory.length; i++) {
history += harker.speakingHistory[i];
}
if (history == 0) {
harker.speaking = false;
harker.emit('stopped_speaking');
}
var history = 0;
if (currentVolume > threshold && !harker.speaking) {
// trigger quickly, short history
for (var i = harker.speakingHistory.length - 3; i < harker.speakingHistory.length; i++) {
history += harker.speakingHistory[i];
}
if (history >= 2) {
harker.speaking = true;
harker.emit('speaking');
}
} else if (currentVolume < threshold && harker.speaking) {
for (var i = 0; i < harker.speakingHistory.length; i++) {
history += harker.speakingHistory[i];
}
harker.speakingHistory.shift();
harker.speakingHistory.push(0 + (currentVolume > threshold));
if (history == 0) {
harker.speaking = false;
harker.emit('stopped_speaking');
}
}
harker.speakingHistory.shift();
harker.speakingHistory.push(0 + (currentVolume > threshold));

looper();
}, interval);
};
looper();
timer = requestAnimationFrame(checkVolume);
}

checkVolume();

return harker;
}
Expand Down
71 changes: 28 additions & 43 deletions hark.bundle.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,10 @@ module.exports = function(stream, options) {
//Config
var options = options || {},
smoothing = (options.smoothing || 0.1),
interval = (options.interval || 50),
threshold = options.threshold,
play = options.play,
history = options.history || 10,
running = true;
timer;

//Setup Audio Context
if (!audioContext) {
Expand Down Expand Up @@ -67,12 +66,8 @@ module.exports = function(stream, options) {
threshold = t;
};

harker.setInterval = function(i) {
interval = i;
};

harker.stop = function() {
running = false;
cancelAnimationFrame(timer);
harker.emit('volume_change', -100, threshold);
if (harker.speaking) {
harker.speaking = false;
Expand All @@ -86,47 +81,37 @@ module.exports = function(stream, options) {
harker.speakingHistory.push(0);
}

// Poll the analyser node to determine if speaking
// and emit events if changed
var looper = function() {
setTimeout(function() {

//check if stop has been called
if(!running) {
return;
}

var currentVolume = getMaxVolume(analyser, fftBins);
function checkVolume() {
var currentVolume = getMaxVolume(analyser, fftBins);

harker.emit('volume_change', currentVolume, threshold);
harker.emit('volume_change', currentVolume, threshold);

var history = 0;
if (currentVolume > threshold && !harker.speaking) {
// trigger quickly, short history
for (var i = harker.speakingHistory.length - 3; i < harker.speakingHistory.length; i++) {
history += harker.speakingHistory[i];
}
if (history >= 2) {
harker.speaking = true;
harker.emit('speaking');
}
} else if (currentVolume < threshold && harker.speaking) {
for (var i = 0; i < harker.speakingHistory.length; i++) {
history += harker.speakingHistory[i];
}
if (history == 0) {
harker.speaking = false;
harker.emit('stopped_speaking');
}
var history = 0;
if (currentVolume > threshold && !harker.speaking) {
// trigger quickly, short history
for (var i = harker.speakingHistory.length - 3; i < harker.speakingHistory.length; i++) {
history += harker.speakingHistory[i];
}
if (history >= 2) {
harker.speaking = true;
harker.emit('speaking');
}
harker.speakingHistory.shift();
harker.speakingHistory.push(0 + (currentVolume > threshold));
} else if (currentVolume < threshold && harker.speaking) {
for (var i = 0; i < harker.speakingHistory.length; i++) {
history += harker.speakingHistory[i];
}
if (history == 0) {
harker.speaking = false;
harker.emit('stopped_speaking');
}
}
harker.speakingHistory.shift();
harker.speakingHistory.push(0 + (currentVolume > threshold));

looper();
}, interval);
};
looper();
timer = requestAnimationFrame(checkVolume);
}

checkVolume();

return harker;
}
Expand Down
71 changes: 28 additions & 43 deletions hark.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,10 @@ module.exports = function(stream, options) {
//Config
var options = options || {},
smoothing = (options.smoothing || 0.1),
interval = (options.interval || 50),
threshold = options.threshold,
play = options.play,
history = options.history || 10,
running = true;
timer;

//Setup Audio Context
if (!audioContext) {
Expand Down Expand Up @@ -65,12 +64,8 @@ module.exports = function(stream, options) {
threshold = t;
};

harker.setInterval = function(i) {
interval = i;
};

harker.stop = function() {
running = false;
cancelAnimationFrame(timer);
harker.emit('volume_change', -100, threshold);
if (harker.speaking) {
harker.speaking = false;
Expand All @@ -84,47 +79,37 @@ module.exports = function(stream, options) {
harker.speakingHistory.push(0);
}

// Poll the analyser node to determine if speaking
// and emit events if changed
var looper = function() {
setTimeout(function() {
function checkVolume() {
var currentVolume = getMaxVolume(analyser, fftBins);

//check if stop has been called
if(!running) {
return;
}
harker.emit('volume_change', currentVolume, threshold);

var currentVolume = getMaxVolume(analyser, fftBins);

harker.emit('volume_change', currentVolume, threshold);

var history = 0;
if (currentVolume > threshold && !harker.speaking) {
// trigger quickly, short history
for (var i = harker.speakingHistory.length - 3; i < harker.speakingHistory.length; i++) {
history += harker.speakingHistory[i];
}
if (history >= 2) {
harker.speaking = true;
harker.emit('speaking');
}
} else if (currentVolume < threshold && harker.speaking) {
for (var i = 0; i < harker.speakingHistory.length; i++) {
history += harker.speakingHistory[i];
}
if (history == 0) {
harker.speaking = false;
harker.emit('stopped_speaking');
}
var history = 0;
if (currentVolume > threshold && !harker.speaking) {
// trigger quickly, short history
for (var i = harker.speakingHistory.length - 3; i < harker.speakingHistory.length; i++) {
history += harker.speakingHistory[i];
}
if (history >= 2) {
harker.speaking = true;
harker.emit('speaking');
}
} else if (currentVolume < threshold && harker.speaking) {
for (var i = 0; i < harker.speakingHistory.length; i++) {
history += harker.speakingHistory[i];
}
harker.speakingHistory.shift();
harker.speakingHistory.push(0 + (currentVolume > threshold));
if (history == 0) {
harker.speaking = false;
harker.emit('stopped_speaking');
}
}
harker.speakingHistory.shift();
harker.speakingHistory.push(0 + (currentVolume > threshold));

looper();
}, interval);
};
looper();
timer = requestAnimationFrame(checkVolume);
}

checkVolume();

return harker;
}