Ich habe hier ein Tutorial geschrieben, das zeigt, wie man das mit der JavaScript Web Audio API macht.
https://askmacgyver.com/blog/tutorial/how-to-implement-tempo-detection-in-your-application
Übersicht über die Schritte
- Transform Audio-Datei in ein Array Buffer
- Run Array Buffer Durch Tiefpassfilter
- Schneiden einer 10-sekündigen Clip aus dem Array Buffer
- Nach unten die Daten abtasten
- Normalisieren der Daten
- Count Volume Groupings
- Infer Tempo von Groupings Graf
Dieser Code unten funktioniert das Heben schwerer Lasten.
laden Audio-Datei in Array-Puffer und führen durch Tiefpassfilter
function createBuffers(url) {
// Fetch Audio Track via AJAX with URL
request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';
request.onload = function(ajaxResponseBuffer) {
// Create and Save Original Buffer Audio Context in 'originalBuffer'
var audioCtx = new AudioContext();
var songLength = ajaxResponseBuffer.total;
// Arguments: Channels, Length, Sample Rate
var offlineCtx = new OfflineAudioContext(1, songLength, 44100);
source = offlineCtx.createBufferSource();
var audioData = request.response;
audioCtx.decodeAudioData(audioData, function(buffer) {
window.originalBuffer = buffer.getChannelData(0);
var source = offlineCtx.createBufferSource();
source.buffer = buffer;
// Create a Low Pass Filter to Isolate Low End Beat
var filter = offlineCtx.createBiquadFilter();
filter.type = "lowpass";
filter.frequency.value = 140;
source.connect(filter);
filter.connect(offlineCtx.destination);
// Render this low pass filter data to new Audio Context and Save in 'lowPassBuffer'
offlineCtx.startRendering().then(function(lowPassAudioBuffer) {
var audioCtx = new(window.AudioContext || window.webkitAudioContext)();
var song = audioCtx.createBufferSource();
song.buffer = lowPassAudioBuffer;
song.connect(audioCtx.destination);
// Save lowPassBuffer in Global Array
window.lowPassBuffer = song.buffer.getChannelData(0);
console.log("Low Pass Buffer Rendered!");
});
},
function(e) {});
}
request.send();
}
createBuffers('https://askmacgyver.com/test/Maroon5-Moves-Like-Jagger-128bpm.mp3');
Sie jetzt ein Array-Buffer des tiefpaßgefilterten Lied (und Original)
Es besteht aus eine Anzahl von Einträgen, sampleRate (44100 multipliziert mit der Anzahl der Sekunden des Songs).
window.lowPassBuffer // Low Pass Array Buffer
window.originalBuffer // Original Non Filtered Array Buffer
Trim eine 10 Sekunden-Clip aus der Song-
function getClip(length, startTime, data) {
var clip_length = length * 44100;
var section = startTime * 44100;
var newArr = [];
for (var i = 0; i < clip_length; i++) {
newArr.push(data[section + i]);
}
return newArr;
}
// Overwrite our array buffer to a 10 second clip starting from 00:10s
window.lowPassFilter = getClip(10, 10, lowPassFilter);
Verkleinerungs Ihr Clip
function getSampleClip(data, samples) {
var newArray = [];
var modulus_coefficient = Math.round(data.length/samples);
for (var i = 0; i < data.length; i++) {
if (i % modulus_coefficient == 0) {
newArray.push(data[i]);
}
}
return newArray;
}
// Overwrite our array to down-sampled array.
lowPassBuffer = getSampleClip(lowPassFilter, 300);
Normalisieren Sie Ihre Daten
function normalizeArray(data) {
var newArray = [];
for (var i = 0; i < data.length; i++) {
newArray.push(Math.abs(Math.round((data[i + 1] - data[i]) * 1000)));
}
return newArray;
}
// Overwrite our array to the normalized array
lowPassBuffer = normalizeArray(lowPassBuffer);
Graf die Flat Line Groupings
function countFlatLineGroupings(data) {
var groupings = 0;
var newArray = normalizeArray(data);
function getMax(a) {
var m = -Infinity,
i = 0,
n = a.length;
for (; i != n; ++i) {
if (a[i] > m) {
m = a[i];
}
}
return m;
}
function getMin(a) {
var m = Infinity,
i = 0,
n = a.length;
for (; i != n; ++i) {
if (a[i] < m) {
m = a[i];
}
}
return m;
}
var max = getMax(newArray);
var min = getMin(newArray);
var count = 0;
var threshold = Math.round((max - min) * 0.2);
for (var i = 0; i < newArray.length; i++) {
if (newArray[i] > threshold && newArray[i + 1] < threshold && newArray[i + 2] < threshold && newArray[i + 3] < threshold && newArray[i + 6] < threshold) {
count++;
}
}
return count;
}
// Count the Groupings
countFlatLineGroupings(lowPassBuffer);
Skala 10 Zweite Gruppierung bis 60 Sekunden Count Beats Derive Per Minute
var final_tempo = countFlatLineGroupings(lowPassBuffer);
// final_tempo will be 21
final_tempo = final_tempo * 6;
console.log("Tempo: " + final_tempo);
// final_tempo will be 126
Der Artikel, den Sie das ganze Thema verknüpft deckt vielmehr darn Nun, was speziell hast du schwer mit? – Nit
Ja, ich weiß! Deshalb ist es so frustrierend, ich kann es nicht funktionieren lassen, ich meine, wo bekomme ich die Schwelle oder die Daten für die erste Funktion, benutze ich die Filter, bevor ich die Peaks bekomme oder danach? Ich fühle mich dumm. – undefined
Die Schwelle hängt sehr davon ab, mit welcher Art von Audio Sie arbeiten - in Kürze, es ist eine Nummer, die Sie wählen. Die Daten sind genau die Audiodateien, mit denen Sie arbeiten möchten. – Nit