📈 GitHub Activity
🔭 I’m currently working on:
Library using WebAudioAPI to analyse BPM from files, audionodes. It's also able to compute BPM from streams as well as realtime using a microphone. This tool might be useful for music producers and DJs or anybody that wants to get BPM from any music source.
Home Page: https://www.realtime-bpm-analyzer.com
License: Apache License 2.0
📈 GitHub Activity
🔭 I’m currently working on:
Hi !
I am trying to get a real time bpm for the uploaded file in my React application.
However, the Error below is what I get.
EDIT : I get the reason of the error, but the file is valid, I can slice it into different chunks and play them, so I can say that the file is not spoiled. I don't understand how I can convert the existing arrayBuffer to make createScriptProcessor like it
Main.js:73 Uncaught (in promise) DOMException: Failed to execute 'createScriptProcessor' on 'BaseAudioContext': buffer size (13307982) must be 0 or a power of two between 256 and 16384.
at Socket.<anonymous> (http://localhost:3000/static/js/bundle.js:1048:50)
at Socket.Emitter.emit (http://localhost:3000/static/js/bundle.js:13328:20)
at Socket.emitEvent (http://localhost:3000/static/js/bundle.js:93155:16)
at Socket.onevent (http://localhost:3000/static/js/bundle.js:93140:12)
at Socket.onpacket (http://localhost:3000/static/js/bundle.js:93096:14)
at Manager.Emitter.emit (http://localhost:3000/static/js/bundle.js:13328:20)
at Manager.ondecoded (http://localhost:3000/static/js/bundle.js:92610:10)
at Decoder.Emitter.emit (http://localhost:3000/static/js/bundle.js:13328:20)
at Decoder.add (http://localhost:3000/static/js/bundle.js:93733:15)
at Manager.ondata (http://localhost:3000/static/js/bundle.js:92600:18)
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-scripts": "5.0.0",
"realtime-bpm-analyzer": "^2.1.6",
const audio = document.createElement("audio");
audio.src = window.URL.createObjectURL(uploadedFile);
audio.volume = 0.5;
audio.play();
audio.addEventListener("timeupdate", (e) => setCurrentAudioTime(e.path?.[0]?.currentTime || e.explicitOriginalTarget.currentTime));
audio.addEventListener("ended", () => setIsMusicEnded(true));
updateAudioPlayer(audio);
//
const audioContext = new AudioContext();
const source = audioContext.createMediaElementSource(audio);
const scriptProcessorNode = audioContext.createScriptProcessor(uploadedFile.size, 1, 1);
scriptProcessorNode.connect(audioContext.destination);
source.connect(scriptProcessorNode);
source.connect(audioContext.destination);
const onAudioProcess = new RealTimeBPMAnalyzer({
scriptNode: {
bufferSize: uploadedFile.size,
},
pushTime: 2000,
pushCallback: (err, bpm) => {
if (err) return console.log(err);
console.log("bpm", bpm);
},
});
scriptProcessorNode.onaudioprocess = (e) => {
onAudioProcess.analyze(e);
};
In the upper code, uploadedFile is a blob. I also tried converting it to arrayBuffer to its size property (I know the number would be the same, but I still tried), but I have same error.
I'm trying to get this working with my React app and I am running into the following issue.
I copied ./node_modules/realtime-bpm-analyzer/dist/realtime-bpm-processor.js
into my public directory and followed the steps in the Continuous Analysis strategy.
Upon activation, I'm seeing the following error repeating in the console:
realtime-bpm-processor.js:330 ReferenceError: clearTimeout is not defined
at RealTimeBpmAnalyzer.<anonymous> (realtime-bpm-processor.js:260:11)
at Generator.next (<anonymous>)
at fulfilled (realtime-bpm-processor.js:7:26)
After learning about Audio Worklets, I think this might be a bug. If my understanding is correct, the processor runs in a separate execution context and does not have access to the DOM, therefore setTimeout/clearTimeout will not be available to the processor. Instead, the main thread has to be responsible for managing timers and triggering the stabilization by communicating with the worklet.
I try to use the nice package for a realtime BPM analysis with line / mic input using navigator.getUserMedia
BPM detection works fine, but I don't understand why the value is not updated when input BPM changes.
Maybe I made a mistake in my code (or comprehension), but I think the analyzer does not update BPM continiously.
Starting from functionnal example edit app.js :
'use strict';
const RealTimeBPMAnalyzer = require('realtime-bpm-analyzer');
const App = {
init() {
var AudioContext = window.AudioContext || window.webkitAudioContext;
navigator.getUserMedia = ( navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia);
var context = new AudioContext();
// Enable mic / line input watching
navigator.getUserMedia({audio: true}, onStream.bind(this), function() {});
function onStream(stream) {
// Set the source with the HTML Audio Node
var input = context.createMediaStreamSource(stream);
// Set the scriptProcessorNode to get PCM data in real time
var scriptProcessorNode = context.createScriptProcessor(4096, 1, 1);
// Connect everythings together (do not connect input to context.destination to avoid sound looping)
scriptProcessorNode.connect(context.destination);
input.connect(scriptProcessorNode);
var onAudioProcess = new RealTimeBPMAnalyzer({
scriptNode: {
bufferSize: 4096,
numberOfInputChannels: 1,
numberOfOutputChannels: 1
},
pushTime: 2000,
pushCallback: function(err, bpm) {
if(bpm && bpm.length)
console.log('bpm', bpm[0].tempo); // <= When stabilized, always displays the same BPM
}
});
// Attach realTime function to audioprocess event.inputBuffer (AudioBuffer)
scriptProcessorNode.onaudioprocess = function (e) {
onAudioProcess.analyze(e);
};
}
}
}
module.exports = App;
Any idea ?
I'm trying to connect it to a live radio stream but it just keeps throwing that error. is there a way to do this with a live feed?
getBPM = () => {
console.log("bpm");
let { source } = this.state;
let audioContext = this.props.audioContext;
const scriptProcessorNode = audioContext.createScriptProcessor(4096, 1, 1);
scriptProcessorNode.connect(audioContext.destination);
source.connect(scriptProcessorNode);
const onAudioProcess = new RealTimeBPMAnalyzer({
debug: true,
scriptNode: {
bufferSize: 4096,
numberOfInputChannels: 1,
numberOfOutputChannels: 1,
},
pushTime: 1000,
pushCallback: (err, bpm) => {
console.log("65", err);
console.log("bpm", bpm);
},
});
scriptProcessorNode.onaudioprocess = (e) => {
onAudioProcess.analyze(e);
};
};
I have seen other web audio projects using the following technique to register audio worklets without the need to expose a separate file.
import {processor} from '../src/processor';
const blob = new Blob([processor], {type: 'application/javascript'});
const objectURL = URL.createObjectURL(blob);
await audioContext.audioWorklet.addModule(objectURL);
const audioWorkletNode = new AudioWorkletNode(audioContext, processorName);
Have you tried this? If it works it would make deployment and upgrade much simpler and avoid issues with caching, CORS, and HTTPS.
An example of this technique can be seen here:
I was trying to find the bpm of a local audio file, but I cannot figure out from where I can get the actual value as shown here. Here is a demo
I also tried to calculate the bpm of audio in real time but still could not figure it out, as shown here
import { createRealTimeBpmProcessor, getBiquadFilters } from 'realtime-bpm-analyzer';
let audioCtx;
let mediaElementSource;
const { type, node } = detectVideo();
if (!node) {
return;
}
if (!audioCtx) {
audioCtx = new AudioContext();
}
const realtimeAnalyzerNode = await createRealTimeBpmProcessor(audioCtx);
if (!mediaElementSource) {
mediaElementSource = audioCtx.createMediaElementSource(node); // node is a YouTube video tag
}
const { lowpass, highpass } = getBiquadFilters(audioCtx);
mediaElementSource.connect(lowpass).connect(highpass).connect(realtimeAnalyzerNode);
mediaElementSource.connect(audioCtx.destination);
realtimeAnalyzerNode.port.postMessage({
message: 'ASYNC_CONFIGURATION',
parameters: {
continuousAnalysis: true,
stabilizationTime: 5_000,
},
});
realtimeAnalyzerNode.port.onmessage = (event) => {
if (event.data.message === 'BPM') {
console.log('BPM', event.data.result);
}
if (event.data.message === 'BPM_STABLE') {
console.log('BPM_STABLE', event.data.result);
}
};
After upgrading to v4, the data returned during continuous analysis is inconsistent with the documentation.
This does not work:
realtimeAnalyzerNode.port.onmessage = (event) => {
if (event.data.message === 'BPM_STABLE') {
console.log('BPM_STABLE', event.data.result);
}
};
Dumping the data to the console I see this:
So I figured that to get the stable BPM it should be:
realtimeAnalyzerNode.port.onmessage = (event) => {
if (event.data.message === 'BPM_STABLE') {
console.log('BPM_STABLE', event.data.data.bpm[0].tempo);
}
};
Also I noticed that you no longer provide a high pass filter. I assume this is no longer required for analysis? I assume not, as the analyzer still works fine for me.
☝️ Greenkeeper’s updated Terms of Service will come into effect on April 6th, 2018.
Branch | Build failing 🚨 |
---|---|
Dependency | mocha |
Current Version | 5.0.4 |
Type | devDependency |
This version is covered by your current version range and after updating it in your project the build failed.
mocha is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.
Welcome @outsideris to the team!
--bail
failing to bail within hooks (@outsideris)describe.skip()
) (@outsideris)CHANGELOG.md
(@tagoro9, @honzajavorek)The new version differs by 18 commits.
c11e1e2
Release v5.0.5
b5a556e
add changes for v5.0.5 [ci skip]
424ef84
increase default timeout for browser unit tests
19104e3
fix debug msg in Runnable#slow; closes #2952
f4275b6
extract checking AMD bundle as own test
19b764d
Addressed feedback
2c19503
Fixed linting
ab84f02
chore(docs): rewording pending tests
6383916
fix to bail option works properly with hooks (#3278)
0060884
keep hierarchy for skipped suites w/o a callback
39df783
docs: Fix typo in an emoji
27af2cf
fix(changelog): update links to some PRs
d76f490
chore(ci): Remove PHANTOMJS_CDNURL, nit
86af6bb
fix my carelessness in e19e879
e19e879
ensure lib/mocha.js is not ignored by ESLint
There are 18 commits in total.
See the full diff
There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.
Your Greenkeeper Bot 🌴
Thanks for the great library. I am wondering if it is possible to add time offsets to each BPM candidate? A use case would be in rhythm games, the chart designer often wants to align notes with beats, so having both start offset of the first bar and BPM will make the alignment much easier and more accurate.
Just a nit pick, but the src code on the readme page for "Player strategy" is missing some imports and definitions. For example, I had to update the import like this
import { createRealTimeBpmProcessor, getBiquadFilter } from 'realtime-bpm-analyzer';
And define an audio context like so
const audioContext = new AudioContext();
Also the track
appears to be missing, how do you get this from the DOM / html page defined? These things might be really obvious to some people but not to others :)
Branch | Build failing 🚨 |
---|---|
Dependency | coveralls |
Current Version | 3.0.0 |
Type | devDependency |
This version is covered by your current version range and after updating it in your project the build failed.
coveralls is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.
Maintenance:
The new version differs by 9 commits.
e7ae2bf
version bump; logger test fix
9b892bf
Verbose use log level debug
9cfb496
Add buildkite support (#177)
aa8c257
Done callback waits for unlink in testRepoTokenDetection to prevent race condition (#179)
18c71c2
Fix a mistype in tests: fs.exists -> fs.existsSync (#184)
bd667c6
Add Semaphore support (#180)
10d8b3e
Update examples to include Jest (#183)
720ee7c
Add license (#175)
83ff2cb
Add mention about AppVeyor to the README (#164)
See the full diff
There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.
Your Greenkeeper Bot 🌴
🚨 You need to enable Continuous Integration on all branches of this repository. 🚨
To enable Greenkeeper, you need to make sure that a commit status is reported on all branches. This is required by Greenkeeper because it uses your CI build statuses to figure out when to notify you about breaking changes.
Since we didn’t receive a CI status on the greenkeeper/initial
branch, it’s possible that you don’t have CI set up yet. We recommend using Travis CI, but Greenkeeper will work with every other CI service as well.
If you have already set up a CI for this repository, you might need to check how it’s configured. Make sure it is set to run on all new branches. If you don’t want it to run on absolutely every branch, you can whitelist branches starting with greenkeeper/
.
Once you have installed and configured CI on this repository correctly, you’ll need to re-trigger Greenkeeper’s initial pull request. To do this, please delete the greenkeeper/initial
branch in this repository, and then remove and re-add this repository to the Greenkeeper App’s white list on Github. You'll find this list on your repo or organization’s settings page, under Installed GitHub Apps.
Branch | Build failing 🚨 |
---|---|
Dependency | nyc |
Current Version | 11.7.0 |
Type | devDependency |
This version is covered by your current version range and after updating it in your project the build failed.
nyc is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.
There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.
Your Greenkeeper Bot 🌴
6.0.0
to 6.0.1
.This version is covered by your current version range and after updating it in your project the build failed.
eslint is a direct dependency of this project, and it is very likely causing it to break. If other packages depend on yours, this update is probably also breaking those in turn.
b5bde06
Fix: --rulesdir option didn't work (fixes #11888) (#11890) (Toru Nagashima)13f0418
Fix: improve error message on --print-config (fixes #11874) (#11885) (Toru Nagashima)056c2aa
Fix: improve diagnostics for shareable-config-missing errors (#11880) (Teddy Katz)566b7aa
Docs: Update no-confusing-arrow with the new default option (#11886) (Yuping Zuo)d07f3fa
Fix: CLIEngine#getRules() contains plugin rules (fixes #11871) (#11872) (Toru Nagashima)21f4a80
Docs: Fix inconsistent linking in migration guide (#11881) (Teddy Katz)f3a0774
Docs: Fix typo in 6.0.0 migration guide (#11870) (Kevin Partington)The new version differs by 9 commits.
54ee60b
6.0.1
3975d50
Build: changelog update for 6.0.1
b5bde06
Fix: --rulesdir option didn't work (fixes #11888) (#11890)
13f0418
Fix: improve error message on --print-config (fixes #11874) (#11885)
056c2aa
Fix: improve diagnostics for shareable-config-missing errors (#11880)
566b7aa
Docs: Update no-confusing-arrow with the new default option (#11886)
d07f3fa
Fix: CLIEngine#getRules() contains plugin rules (fixes #11871) (#11872)
21f4a80
Docs: Fix inconsistent linking in migration guide (#11881)
f3a0774
Docs: Fix typo in 6.0.0 migration guide (#11870)
See the full diff
There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.
Your Greenkeeper Bot 🌴
It would be fantastic if an "Ableton Link" interface was implemented
Hey,
awesome job on this!
I had a look through the code and noticed it uses createScriptProcessor
to process the audio data.
This seems to be deprecated now and AudioWorklets
are the replacement.
Do you have any plans to switch over to those?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.