@sebastbake/music-tempo
Version:
Finding out tempo of the music
168 lines (144 loc) • 7.42 kB
HTML
<html>
<head>
<meta charset="utf-8">
<base data-ice="baseUrl">
<title data-ice="title">API Document</title>
<link type="text/css" rel="stylesheet" href="css/style.css">
<link type="text/css" rel="stylesheet" href="css/prettify-tomorrow.css">
<script src="script/prettify/prettify.js"></script>
<script src="script/manual.js"></script>
</head>
<body class="layout-container" data-ice="rootContainer">
<header>
<a href="./">Home</a>
<a href="identifiers.html">Reference</a>
<a href="source.html">Source</a>
<a data-ice="repoURL" href="https://github.com/killercrush/music-tempo" class="repo-url-github">Repository</a>
<div class="search-box">
<span>
<img src="./image/search.png">
<span class="search-input-edge"></span><input class="search-input"><span class="search-input-edge"></span>
</span>
<ul class="search-result"></ul>
</div>
</header>
<nav class="navigation" data-ice="nav"><div>
<ul>
</ul>
</div>
</nav>
<div class="content" data-ice="content"><div data-ice="index" class="github-markdown"><h2 id="description">Description</h2>
<p>Typescript library for finding out tempo (BPM) of a song and beat tracking. It uses an algorithm <a href="http://www.eecs.qmul.ac.uk/~simond/pub/2001/jnmr.pdf">"Beatroot"</a> authored by <a href="http://www.eecs.qmul.ac.uk/~simond/">Simon Dixon</a></p>
<p><strong><a href="https://killercrush.github.io/music-tempo/example/example-advanced.html">Example App</a></strong></p>
<p><strong><a href="https://killercrush.github.io/music-tempo/docs/index.html">Docs</a></strong></p>
<h2 id="instalation">Instalation</h2>
<p>Using npm:</p>
<pre><code class="lang-sh"><code class="source-code prettyprint">npm i music-tempo</code>
</code></pre>
<p>In a browser</p>
<pre><code class="lang-html"><code class="source-code prettyprint"><script src="music-tempo.min.js"></script></code>
</code></pre>
<h2 id="usage">Usage</h2>
<p>Pass to the constructor MusicTempo the buffer that contains data in the following format: non-interleaved IEEE754 32-bit linear PCM with a nominal range between -1 and +1, that is, 32bits floating point buffer, with each samples between -1.0 and 1.0. This format is used in the <a href="https://developer.mozilla.org/en/docs/Web/API/AudioBuffer">AudioBuffer</a> interface of <a href="https://developer.mozilla.org/en/docs/Web/API/Web_Audio_API">Web Audio API</a>. The object returned by the constructor contain properties <code>tempo</code> - tempo value in beats per minute and <code>beats</code> - array with beat times in seconds.</p>
<h3 id="react-js">React.js</h3>
<pre><code class="lang-javascript"><code class="source-code prettyprint">import { useRef, useEffect } from "react";
import { extractTempo } from "music-tempo";
const context = new AudioContext({ sampleRate: 44100 });
const calcTempo = function (buffer) {
let audioData = [];
// Take the average of the two channels
if (buffer.numberOfChannels == 2) {
const channel1Data = buffer.getChannelData(0);
const channel2Data = buffer.getChannelData(1);
const length = channel1Data.length;
for (let i = 0; i < length; i++) {
audioData[i] = (channel1Data[i] + channel2Data[i]) / 2;
}
} else {
audioData = buffer.getChannelData(0);
}
const mt = extractTempo(audioData);
console.log(mt.tempo);
console.log(mt.beats);
};
const GetBPM = () => {
const ref = useRef(null);
useEffect(() => {
ref.current.onchange = function () {
const files = ref.current.files;
if (files.length == 0) return;
const reader = new FileReader();
reader.onload = function (fileEvent) {
context.decodeAudioData(fileEvent.target.result, calcTempo);
};
reader.readAsArrayBuffer(files[0]);
};
}, []);
return <input ref={ref} type="file" accept="audio/*" />;
};</code>
</code></pre>
<h3 id="node-js">Node.js</h3>
<p>In Node.js environment can be used <a href="https://github.com/sebpiq/node-web-audio-api">node-web-audio-api library</a></p>
<pre><code class="lang-javascript"><code class="source-code prettyprint">const AudioContext = require("web-audio-api").AudioContext;
const MusicTempo = require("music-tempo");
const fs = require("fs");
const calcTempo = function (buffer) {
let audioData = [];
// Take the average of the two channels
if (buffer.numberOfChannels == 2) {
const channel1Data = buffer.getChannelData(0);
const channel2Data = buffer.getChannelData(1);
const length = channel1Data.length;
for (let i = 0; i < length; i++) {
audioData[i] = (channel1Data[i] + channel2Data[i]) / 2;
}
} else {
audioData = buffer.getChannelData(0);
}
const mt = extractTempo(audioData);
console.log(mt.tempo);
console.log(mt.beats);
};
const data = fs.readFileSync("songname.mp3");
const context = new AudioContext();
context.decodeAudioData(data, calcTempo);</code>
</code></pre>
<h2 id="optional-parameters">Optional parameters</h2>
<p>You can pass object with parameters as second argument to the constructor:</p>
<pre><code class="lang-javascript"><code class="source-code prettyprint">const result = extractTempo(audioData, {
expiryTime: 30,
maxBeatInterval: 1.5,
});</code>
</code></pre>
<p>Most useful are <code>maxBeatInterval</code>/<code>minBeatInterval</code> and <code>expiryTime</code>. First two used for setting up maximum and minimum BPM. Default value for <code>maxBeatInterval</code> is 1 which means that minimum BPM is 60 (60 / 1 = 60). Default value for <code>minBeatInterval</code> is 0.3 which means that maximum BPM is 200 (60 / 0.3 = 200). Be careful, the more value of maximum BPM, the more probability of 2x-BPM errors (e.g. if max BPM = 210 and real tempo of a song 102 BPM, in the end you can get 204 BPM).
<code>expiryTime</code> can be used if audio file have periods of silence or almost silence and because of that beat tracking is failing.
Other parameters are listed in <a href="https://killercrush.github.io/music-tempo/docs/class/src/MusicTempo.js~MusicTempo.html">documentation</a>.</p>
<h2 id="other">Other</h2>
<h3 id="dependencies">Dependencies</h3>
<p>dependencies can be found on the <code>package.json</code> file and they can be installed using <code>npm install</code> or your favorite package manager.</p>
<h3 id="tests">Tests</h3>
<pre><code class="lang-shell"><code class="source-code prettyprint">npm test</code>
</code></pre>
<h3 id="documentation">Documentation</h3>
<pre><code class="lang-shell"><code class="source-code prettyprint">npm run docs</code>
</code></pre>
<h3 id="build">Build</h3>
<pre><code class="lang-shell"><code class="source-code prettyprint">npm run build</code>
</code></pre>
<h2 id="license">License</h2>
<p><a href="LICENCE">MIT License</a></p>
</div>
</div>
<footer class="footer">
Generated by <a href="https://esdoc.org">ESDoc<span data-ice="esdocVersion">(0.5.2)</span><img src="./image/esdoc-logo-mini-black.png"></a>
</footer>
<script src="script/search_index.js"></script>
<script src="script/search.js"></script>
<script src="script/pretty-print.js"></script>
<script src="script/inherited-summary.js"></script>
<script src="script/test-summary.js"></script>
<script src="script/inner-link.js"></script>
<script src="script/patch-for-local.js"></script>
</body>
</html>