bpm-detective
Advanced tools
Comparing version 2.0.1 to 2.0.2
@@ -1,1 +0,1 @@ | ||
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.DetectBPM=f()}})(function(){var define,module,exports;return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s}({1:[function(require,module,exports){"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.default=detect;var OfflineContext=window.OfflineAudioContext||window.webkitOfflineAudioContext;function detect(buffer){var source=getLowPassSource(buffer);source.start(0);return[findPeaks,identifyIntervals,groupByTempo(buffer.sampleRate),getTopCandidate].reduce(function(state,fn){return fn(state)},source.buffer.getChannelData(0))}function getTopCandidate(candidates){return candidates.sort(function(a,b){return b.count-a.count}).splice(0,5)[0].tempo}function getLowPassSource(buffer){var length=buffer.length;var numberOfChannels=buffer.numberOfChannels;var sampleRate=buffer.sampleRate;var context=new OfflineContext(numberOfChannels,length,sampleRate);var source=context.createBufferSource();source.buffer=buffer;var filter=context.createBiquadFilter();filter.type="lowpass";source.connect(filter);filter.connect(context.destination);return source}function findPeaks(data){var peaks=[];var threshold=.9;var minThresold=.3;var minPeaks=15;while(peaks.length<minPeaks&&threshold>=minThresold){peaks=findPeaksAtThreshold(data,threshold);threshold-=.05}if(peaks.length<minPeaks){throw new Error("Could not find enough samples for a reliable detection.")}return peaks}function findPeaksAtThreshold(data,threshold){var peaks=[];for(var i=0,l=data.length;i<l;i+=1){if(data[i]>threshold){peaks.push(i);i+=1e4}}return peaks}function identifyIntervals(peaks){var intervals=[];peaks.forEach(function(peak,index){var _loop=function _loop(i){var interval=peaks[index+i]-peak;var foundInterval=intervals.some(function(intervalCount){if(intervalCount.interval===interval){return intervalCount.count+=1}});if(!foundInterval){intervals.push({interval:interval,count:1})}};for(var i=0;i<10;i+=1){_loop(i)}});return intervals}function groupByTempo(sampleRate){return function(intervalCounts){var tempoCounts=[];intervalCounts.forEach(function(intervalCount){if(intervalCount.interval!==0){(function(){var theoreticalTempo=60/(intervalCount.interval/sampleRate);while(theoreticalTempo<90){theoreticalTempo*=2}while(theoreticalTempo>180){theoreticalTempo/=2}theoreticalTempo=Math.round(theoreticalTempo);var foundTempo=tempoCounts.some(function(tempoCount){if(tempoCount.tempo===theoreticalTempo){return tempoCount.count+=intervalCount.count}});if(!foundTempo){tempoCounts.push({tempo:theoreticalTempo,count:intervalCount.count})}})()}});return tempoCounts}}},{}],2:[function(require,module,exports){module.exports=require("./detect").default},{"./detect":1}]},{},[2])(2)}); | ||
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.DetectBPM=f()}})(function(){var define,module,exports;return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s}({1:[function(require,module,exports){"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.default=detect;var OfflineContext=window.OfflineAudioContext||window.webkitOfflineAudioContext;function detect(buffer){var source=getLowPassSource(buffer);source.start(0);return[findPeaks,identifyIntervals,groupByTempo(buffer.sampleRate),getTopCandidate].reduce(function(state,fn){return fn(state)},source.buffer.getChannelData(0))}function getTopCandidate(candidates){return candidates.sort(function(a,b){return b.count-a.count}).splice(0,5)[0].tempo}function getLowPassSource(buffer){var length=buffer.length,numberOfChannels=buffer.numberOfChannels,sampleRate=buffer.sampleRate;var context=new OfflineContext(numberOfChannels,length,sampleRate);var source=context.createBufferSource();source.buffer=buffer;var filter=context.createBiquadFilter();filter.type="lowpass";source.connect(filter);filter.connect(context.destination);return source}function findPeaks(data){var peaks=[];var threshold=.9;var minThresold=.3;var minPeaks=15;while(peaks.length<minPeaks&&threshold>=minThresold){peaks=findPeaksAtThreshold(data,threshold);threshold-=.05}if(peaks.length<minPeaks){throw new Error("Could not find enough samples for a reliable detection.")}return peaks}function findPeaksAtThreshold(data,threshold){var peaks=[];for(var i=0,l=data.length;i<l;i+=1){if(data[i]>threshold){peaks.push(i);i+=1e4}}return peaks}function identifyIntervals(peaks){var intervals=[];peaks.forEach(function(peak,index){var _loop=function _loop(i){var interval=peaks[index+i]-peak;var foundInterval=intervals.some(function(intervalCount){if(intervalCount.interval===interval){return intervalCount.count+=1}});if(!foundInterval){intervals.push({interval:interval,count:1})}};for(var i=0;i<10;i+=1){_loop(i)}});return intervals}function groupByTempo(sampleRate){return function(intervalCounts){var tempoCounts=[];intervalCounts.forEach(function(intervalCount){if(intervalCount.interval!==0){var theoreticalTempo=60/(intervalCount.interval/sampleRate);while(theoreticalTempo<90){theoreticalTempo*=2}while(theoreticalTempo>180){theoreticalTempo/=2}theoreticalTempo=Math.round(theoreticalTempo);var foundTempo=tempoCounts.some(function(tempoCount){if(tempoCount.tempo===theoreticalTempo){return tempoCount.count+=intervalCount.count}});if(!foundTempo){tempoCounts.push({tempo:theoreticalTempo,count:intervalCount.count})}}});return tempoCounts}}},{}],2:[function(require,module,exports){module.exports=require("./detect").default},{"./detect":1}]},{},[2])(2)}); |
@@ -52,5 +52,5 @@ 'use strict'; | ||
function getLowPassSource(buffer) { | ||
var length = buffer.length; | ||
var numberOfChannels = buffer.numberOfChannels; | ||
var sampleRate = buffer.sampleRate; | ||
var length = buffer.length, | ||
numberOfChannels = buffer.numberOfChannels, | ||
sampleRate = buffer.sampleRate; | ||
@@ -207,44 +207,42 @@ var context = new OfflineContext(numberOfChannels, length, sampleRate); | ||
if (intervalCount.interval !== 0) { | ||
(function () { | ||
/** | ||
* Convert an interval to tempo | ||
*/ | ||
/** | ||
* Convert an interval to tempo | ||
*/ | ||
var theoreticalTempo = 60 / (intervalCount.interval / sampleRate); | ||
var theoreticalTempo = 60 / (intervalCount.interval / sampleRate); | ||
/** | ||
* Adjust the tempo to fit within the 90-180 BPM range | ||
/** | ||
* Adjust the tempo to fit within the 90-180 BPM range | ||
*/ | ||
while (theoreticalTempo < 90) { | ||
theoreticalTempo *= 2; | ||
}while (theoreticalTempo > 180) { | ||
theoreticalTempo /= 2; | ||
} /** | ||
* Round to legible integer | ||
*/ | ||
while (theoreticalTempo < 90) { | ||
theoreticalTempo *= 2; | ||
}while (theoreticalTempo > 180) { | ||
theoreticalTempo /= 2; | ||
} /** | ||
* Round to legible integer | ||
*/ | ||
theoreticalTempo = Math.round(theoreticalTempo); | ||
theoreticalTempo = Math.round(theoreticalTempo); | ||
/** | ||
* See if another interval resolved to the same tempo | ||
*/ | ||
/** | ||
* See if another interval resolved to the same tempo | ||
*/ | ||
var foundTempo = tempoCounts.some(function (tempoCount) { | ||
if (tempoCount.tempo === theoreticalTempo) { | ||
return tempoCount.count += intervalCount.count; | ||
} | ||
}); | ||
var foundTempo = tempoCounts.some(function (tempoCount) { | ||
if (tempoCount.tempo === theoreticalTempo) { | ||
return tempoCount.count += intervalCount.count; | ||
} | ||
/** | ||
* Add a unique tempo to the collection | ||
*/ | ||
if (!foundTempo) { | ||
tempoCounts.push({ | ||
tempo: theoreticalTempo, | ||
count: intervalCount.count | ||
}); | ||
/** | ||
* Add a unique tempo to the collection | ||
*/ | ||
if (!foundTempo) { | ||
tempoCounts.push({ | ||
tempo: theoreticalTempo, | ||
count: intervalCount.count | ||
}); | ||
} | ||
})(); | ||
} | ||
} | ||
@@ -251,0 +249,0 @@ }); |
{ | ||
"name": "bpm-detective", | ||
"version": "2.0.1", | ||
"version": "2.0.2", | ||
"description": "Detects the BPM of a song or audio sample", | ||
@@ -5,0 +5,0 @@ "main": "lib/index.js", |
@@ -5,3 +5,3 @@ # bpm-detective | ||
This module uses the [Web Audio API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API) to try and detect the BPM of a given sound. You can find more on the implementation and how it works by reading the blog post [Beat Detection Using JavaScript and the Web Audio API](http://tech.beatport.com/2014/web-audio/beat-detection-using-web-audio/) which happens to be where I got most of the code. | ||
This module uses the [Web Audio API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API) to try and detect the BPM of a given sound. You can find more on the implementation and how it works by reading the blog post [Beat Detection Using JavaScript and the Web Audio API](http://web.archive.org/web/20160401073744/http://tech.beatport.com/2014/web-audio/beat-detection-using-web-audio/) which happens to be where I got most of the code. | ||
@@ -21,2 +21,3 @@ ## Install | ||
const AudioContext = window.AudioContext || window.webkitAudioContext; | ||
let context = new AudioContext(); | ||
@@ -28,4 +29,8 @@ | ||
.then(response => response.arrayBuffer()) | ||
// Decode audio into an AudioBuffer | ||
.then(data => context.decodeAudioData(data)) | ||
.then(buffer => { | ||
// Decode audio into an AudioBuffer | ||
return new Promise((resolve, reject) => { | ||
context.decodeAudioData(buffer, resolve, reject); | ||
}); | ||
}) | ||
// Run detection | ||
@@ -32,0 +37,0 @@ .then(buffer => { |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
50
2
17299
7
399
1