-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #65 from dlepaux/feature/web-test-runner
Feature/web test runner
- Loading branch information
Showing
13 changed files
with
2,471 additions
and
1,949 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
export default `"use strict";(()=>{var x="realtime-bpm-processor";async function p(n,o=.2,e=.95,s=.05){let t=e;do if(t-=s,await n(t))break;while(t>o)}function y(n=.2,o=.95,e=.05){let s={},t=o;do t-=e,s[t.toString()]=[];while(t>n);return s}function A(n=.2,o=.95,e=.05){let s={},t=o;do t-=e,s[t.toString()]=0;while(t>n);return s}function h(){let o=0,e=new Float32Array(0);function s(){o=0,e=new Float32Array(0)}function t(){return o===4096}function a(){s()}return function(r){t()&&a();let l=new Float32Array(e.length+r.length);return l.set(e,0),l.set(r,e.length),e=l,o+=r.length,{isBufferFull:t(),buffer:e,bufferSize:4096}}}function v(n,o,e=0,s=1e4){let t=[],{length:a}=n;for(let r=e;r<a;r+=1)n[r]>o&&(t.push(r),r+=s);return{peaks:t,threshold:o}}async function b(n,o){let e=15,s=!1,t=.2;if(await p(async a=>s?!0:(n[a].length>e&&(s=!0,t=a),!1)),s&&t){let a=w(n[t]),r=C(o,a);return{bpm:V(r),threshold:t}}return{bpm:[],threshold:t}}function V(n,o=5){return n.sort((e,s)=>s.count-e.count).splice(0,o)}function w(n){let o=[];for(let e=0;e<n.length;e++)for(let s=0;s<10;s++){let t=n[e],a=e+s,r=n[a]-t;if(!o.some(i=>i.interval===r?(i.count+=1,i.count):!1)){let i={interval:r,count:1};o.push(i)}}return o}function C(n,o){let e=[];for(let s of o){if(s.interval===0)continue;s.interval=Math.abs(s.interval);let t=60/(s.interval/n);for(;t<90;)t*=2;for(;t>180;)t/=2;if(t=Math.round(t),!e.some(r=>r.tempo===t?(r.count+=s.count,r.count):!1)){let r={tempo:t,count:s.count,confidence:0};e.push(r)}}return e}var d={minValidThreshold:()=>.2,validPeaks:()=>y(),nextIndexPeaks:()=>A(),skipIndexes:()=>1,effectiveBufferTime:()=>0},m=class{constructor(){this.options={continuousAnalysis:!1,stabilizationTime:2e4,muteTimeInIndexes:1e4,debug:!1};this.minValidThreshold=d.minValidThreshold();this.validPeaks=d.validPeaks();this.nextIndexPeaks=d.nextIndexPeaks();this.skipIndexes=d.skipIndexes();this.effectiveBufferTime=d.effectiveBufferTime();this.computedStabilizationTimeInSeconds=0;this.updateComputedValues()}setAsyncConfiguration(o){Object.assign(this.options,o),this.updateComputedValues()}updateComputedValues(){this.computedStabilizationTimeInSeconds=this.options.stabilizationTime/1e3}reset(){this.minValidThreshold=d.minValidThreshold(),this.validPeaks=d.validPeaks(),this.nextIndexPeaks=d.nextIndexPeaks(),this.skipIndexes=d.skipIndexes(),this.effectiveBufferTime=d.effectiveBufferTime()}async clearValidPeaks(o){this.minValidThreshold=Number.parseFloat(o.toFixed(2)),await p(async e=>(e<o&&typeof this.validPeaks[e]<"u"&&(delete this.validPeaks[e],delete this.nextIndexPeaks[e]),!1))}async analyzeChunck(o,e,s,t){this.options.debug&&t({message:"ANALYZE_CHUNK",data:o}),this.effectiveBufferTime+=s;let a=s*this.skipIndexes,r=a-s;await this.findPeaks(o,s,r,a,t),this.skipIndexes++;let l=await b(this.validPeaks,e),{threshold:i}=l;t({message:"BPM",result:l}),this.minValidThreshold<i&&(t({message:"BPM_STABLE",result:l}),await this.clearValidPeaks(i)),this.options.continuousAnalysis&&this.effectiveBufferTime/e>this.computedStabilizationTimeInSeconds&&(this.reset(),t({message:"ANALYZER_RESETED"}))}async findPeaks(o,e,s,t,a){await p(async r=>{if(this.nextIndexPeaks[r]>=t)return!1;let l=this.nextIndexPeaks[r]%e,{peaks:i,threshold:c}=v(o,r,l);if(i.length===0)return!1;for(let I of i){let f=s+I;this.nextIndexPeaks[c]=f+this.options.muteTimeInIndexes,this.validPeaks[c].push(f),this.options.debug&&a({message:"VALID_PEAK",data:{threshold:c,index:f}})}return!1},this.minValidThreshold)}};var T=class extends AudioWorkletProcessor{constructor(){super();this.realTimeBpmAnalyzer=new m;this.stopped=!1;this.aggregate=h(),this.port.addEventListener("message",this.onMessage.bind(this)),this.port.start()}onMessage(e){e.data.message==="ASYNC_CONFIGURATION"&&(console.log("[processor.onMessage] ASYNC_CONFIGURATION"),this.realTimeBpmAnalyzer.setAsyncConfiguration(e.data.parameters)),e.data.message==="RESET"&&(console.log("[processor.onMessage] RESET"),this.aggregate=h(),this.stopped=!1,this.realTimeBpmAnalyzer.reset()),e.data.message==="STOP"&&(console.log("[processor.onMessage] STOP"),this.aggregate=h(),this.stopped=!0,this.realTimeBpmAnalyzer.reset())}process(e,s,t){let a=e[0][0];if(this.stopped||!a)return!0;let{isBufferFull:r,buffer:l,bufferSize:i}=this.aggregate(a);return r&&this.realTimeBpmAnalyzer.analyzeChunck(l,sampleRate,i,c=>{this.port.postMessage(c)}).catch(c=>{console.error(c)}),!0}};registerProcessor(x,T);var Q={};})(); | ||
export default `"use strict";(()=>{var c=(a,o,e)=>new Promise((s,t)=>{var n=i=>{try{l(e.next(i))}catch(d){t(d)}},r=i=>{try{l(e.throw(i))}catch(d){t(d)}},l=i=>i.done?s(i.value):Promise.resolve(i.value).then(n,r);l((e=e.apply(a,o)).next())});var y="realtime-bpm-processor";function h(t){return c(this,arguments,function*(a,o=.2,e=.95,s=.05){let n=e;do if(n-=s,yield a(n))break;while(n>o)})}function A(a=.2,o=.95,e=.05){let s={},t=o;do t-=e,s[t.toString()]=[];while(t>a);return s}function v(a=.2,o=.95,e=.05){let s={},t=o;do t-=e,s[t.toString()]=0;while(t>a);return s}function m(){let o=0,e=new Float32Array(0);function s(){o=0,e=new Float32Array(0)}function t(){return o===4096}function n(){s()}return function(r){t()&&n();let l=new Float32Array(e.length+r.length);return l.set(e,0),l.set(r,e.length),e=l,o+=r.length,{isBufferFull:t(),buffer:e,bufferSize:4096}}}function b(a,o,e=0,s=1e4){let t=[],{length:n}=a;for(let r=e;r<n;r+=1)a[r]>o&&(t.push(r),r+=s);return{peaks:t,threshold:o}}function I(a,o){return c(this,null,function*(){let e=15,s=!1,t=.2;if(yield h(n=>c(this,null,function*(){return s?!0:(a[n].length>e&&(s=!0,t=n),!1)})),s&&t){let n=C(a[t]),r=S(o,n);return{bpm:w(r),threshold:t}}return{bpm:[],threshold:t}})}function w(a,o=5){return a.sort((e,s)=>s.count-e.count).splice(0,o)}function C(a){let o=[];for(let e=0;e<a.length;e++)for(let s=0;s<10;s++){let t=a[e],n=e+s,r=a[n]-t;if(!o.some(i=>i.interval===r?(i.count+=1,i.count):!1)){let i={interval:r,count:1};o.push(i)}}return o}function S(a,o){let e=[];for(let s of o){if(s.interval===0)continue;s.interval=Math.abs(s.interval);let t=60/(s.interval/a);for(;t<90;)t*=2;for(;t>180;)t/=2;if(t=Math.round(t),!e.some(r=>r.tempo===t?(r.count+=s.count,r.count):!1)){let r={tempo:t,count:s.count,confidence:0};e.push(r)}}return e}var u={minValidThreshold:()=>.2,validPeaks:()=>A(),nextIndexPeaks:()=>v(),skipIndexes:()=>1,effectiveBufferTime:()=>0},f=class{constructor(){this.options={continuousAnalysis:!1,stabilizationTime:2e4,muteTimeInIndexes:1e4,debug:!1};this.minValidThreshold=u.minValidThreshold();this.validPeaks=u.validPeaks();this.nextIndexPeaks=u.nextIndexPeaks();this.skipIndexes=u.skipIndexes();this.effectiveBufferTime=u.effectiveBufferTime();this.computedStabilizationTimeInSeconds=0;this.updateComputedValues()}setAsyncConfiguration(o){Object.assign(this.options,o),this.updateComputedValues()}updateComputedValues(){this.computedStabilizationTimeInSeconds=this.options.stabilizationTime/1e3}reset(){this.minValidThreshold=u.minValidThreshold(),this.validPeaks=u.validPeaks(),this.nextIndexPeaks=u.nextIndexPeaks(),this.skipIndexes=u.skipIndexes(),this.effectiveBufferTime=u.effectiveBufferTime()}clearValidPeaks(o){return c(this,null,function*(){this.minValidThreshold=Number.parseFloat(o.toFixed(2)),yield h(e=>c(this,null,function*(){return e<o&&typeof this.validPeaks[e]!="undefined"&&(delete this.validPeaks[e],delete this.nextIndexPeaks[e]),!1}))})}analyzeChunck(o,e,s,t){return c(this,null,function*(){this.options.debug&&t({message:"ANALYZE_CHUNK",data:o}),this.effectiveBufferTime+=s;let n=s*this.skipIndexes,r=n-s;yield this.findPeaks(o,s,r,n,t),this.skipIndexes++;let l=yield I(this.validPeaks,e),{threshold:i}=l;t({message:"BPM",result:l}),this.minValidThreshold<i&&(t({message:"BPM_STABLE",result:l}),yield this.clearValidPeaks(i)),this.options.continuousAnalysis&&this.effectiveBufferTime/e>this.computedStabilizationTimeInSeconds&&(this.reset(),t({message:"ANALYZER_RESETED"}))})}findPeaks(o,e,s,t,n){return c(this,null,function*(){yield h(r=>c(this,null,function*(){if(this.nextIndexPeaks[r]>=t)return!1;let l=this.nextIndexPeaks[r]%e,{peaks:i,threshold:d}=b(o,r,l);if(i.length===0)return!1;for(let F of i){let g=s+F;this.nextIndexPeaks[d]=g+this.options.muteTimeInIndexes,this.validPeaks[d].push(g),this.options.debug&&n({message:"VALID_PEAK",data:{threshold:d,index:g}})}return!1}),this.minValidThreshold)})}};var x=class extends AudioWorkletProcessor{constructor(){super();this.realTimeBpmAnalyzer=new f;this.stopped=!1;this.aggregate=m(),this.port.addEventListener("message",this.onMessage.bind(this)),this.port.start()}onMessage(e){e.data.message==="ASYNC_CONFIGURATION"&&(console.log("[processor.onMessage] ASYNC_CONFIGURATION"),this.realTimeBpmAnalyzer.setAsyncConfiguration(e.data.parameters)),e.data.message==="RESET"&&(console.log("[processor.onMessage] RESET"),this.aggregate=m(),this.stopped=!1,this.realTimeBpmAnalyzer.reset()),e.data.message==="STOP"&&(console.log("[processor.onMessage] STOP"),this.aggregate=m(),this.stopped=!0,this.realTimeBpmAnalyzer.reset())}process(e,s,t){let n=e[0][0];if(this.stopped||!n)return!0;let{isBufferFull:r,buffer:l,bufferSize:i}=this.aggregate(n);return r&&this.realTimeBpmAnalyzer.analyzeChunck(l,sampleRate,i,d=>{this.port.postMessage(d)}).catch(d=>{console.error(d)}),!0}};registerProcessor(y,x);var K={};})(); | ||
//# sourceMappingURL=realtime-bpm-processor.js.map | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,17 @@ | ||
import {analyzeFullBuffer} from '../src/analyzer'; | ||
|
||
async function runTests() { | ||
const audioContext = new AudioContext(); | ||
const response = await fetch('http://localhost:9876/base/tests/datasets/manifest.json'); | ||
const audioContext = new OfflineAudioContext(2, 44100 * 40, 44100); | ||
const response = await fetch('/tests/datasets/manifest.json'); | ||
const json: Record<string, number> = await response.json(); // eslint-disable-line @typescript-eslint/no-unsafe-assignment | ||
for (const fileName of Object.keys(json)) { | ||
const bpm = json[fileName]; | ||
const response = await fetch(`http://localhost:9876/base/tests/datasets/${fileName}`); | ||
const response = await fetch(`/tests/datasets/${fileName}`); | ||
const buffer = await response.arrayBuffer(); | ||
const audioBuffer = await audioContext.decodeAudioData(buffer); | ||
const tempo = await analyzeFullBuffer(audioBuffer); | ||
console.assert(tempo[0].tempo === bpm, 'The computed tempo is not matching'); | ||
} | ||
|
||
await audioContext.close(); | ||
} | ||
|
||
runTests(); // eslint-disable-line @typescript-eslint/no-floating-promises |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.