First off Ich versuche, diesen Akkord-Erkennungsalgorithmus zu implementieren: http://www.music.mcgill.ca/~jason/mumt621/papers5/fujishima_1999.pdfChord-Erkennungsalgorithmus mit dem Web Audio API
ich implementiert ursprünglich den Algorithmus mein Mikrofon zu verwenden, aber es hat nicht funktioniert. Als Test habe ich drei Oszillatoren erstellt, um einen c-Akkord zu erzeugen, aber der Algorithmus funktioniert immer noch nicht. Ich denke, ich sollte nur eine höhere Zahl für C, E und G sehen, aber ich sehe Zahlen für alle Noten. Gibt es ein Problem mit meiner Implementierung des Algorithmus? oder ist es mein N, Fref oder FS-Wert?
Hier ist ein Code-Snippet mit den wichtigen Teilen:
// Set audio Context
window.AudioContext = window.AudioContext || window.webkitAudioContext;
var mediaStreamSource = null;
var analyser = null;
var N = 4096;//8192;//2048; // Samples of Sound
var bufferLen = null;
var buffer = null;
var PCP = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // Pitch Class Profiles
var fref = 261.63; // Reference frequency middle C (C4)
// fref = 65.4; // Reference frequency C2
// fref = 440.0; // Reference frequency A4
var audioContext = new AudioContext();
var fs = audioContext.sampleRate; // Retrieve sampling rate. Usually 48KHz
var useMicrophone = false;
navigator.mediaDevices.getUserMedia(constraints)
.then(function(stream) {
// Create an analyzer node to process the audio
analyser = audioContext.createAnalyser();
analyser.fftSize = N;
bufferLen = N/2;
//bufferLen = analyser.frequencyBinCount;
console.log('bufferLen = ' + bufferLen);
buffer = new Float32Array(bufferLen);
if (useMicrophone) {
// Create an AudioNode from the stream.
mediaStreamSource = audioContext.createMediaStreamSource(stream);
// Connect it to the destination.
mediaStreamSource.connect(analyser);
}
else {
// As a test, feed a C chord directly into the analyzer
// C4, E4, G4
var freqs = [261.63, 329.63, 392.00];
for(var i=0; i < freqs.length; i++) {
var o = audioContext.createOscillator();
var g = audioContext.createGain(); //Create Gain Node
o.frequency.value = freqs[i];
o.connect(g);
g.gain.value = 0.25;
g.connect(audioContext.destination);
g.connect(analyser);
o.start(0);
//setTimeout(function(s) {s.stop(0)}, 1000, o);
}
}
// Call algorithm every 50 ms
setInterval(function() {
pcpAlg();
}, 50);
})
.catch(function(err) {
console.log(err.name + ": " + err.message);
});
function pcpAlg() {
analyser.getFloatTimeDomainData(buffer);
//analyser.getFloatFrequencyData(buffer);
// Reset PCP
PCP = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
// M(0)=-1 so we don't have to start at 0
for (var l = 1; l < bufferLen; l++) { // l = 0,1,...,[(N/2) - 1]
// Calculate M(l)
var ML = Math.round(12 * Math.log2((fs * (l/N))/fref)) % 12; //
//console.log(ML);
if (ML >= 0 && ML <= 11) {
PCP[ML] += Math.pow(Math.abs(buffer[l]), 2);
}
}
// Display Data on UI and also try to determine if the sound is a C or F chord
displayAndCategorize();
}
Hier ist meine vollen codepen wenn Sie es selbst laufen zu versuchen. Warnung Ich habe useMicrophone auf false gesetzt, damit es einen c-Akkordton erzeugt: https://codepen.io/mapmaps/pen/ONQPpw
Klingt wie ein cooles Projekt, aber sind Sie sicher, dass die Eingabe korrekt ist? Haben Sie mit falschen hartcodierten Eingabewerten versucht, um zu sehen, ob die Ausgabe in diesem Fall korrekt ist? –
Wollen Sie nicht die Float-Frequenzdaten anstelle der Zeitdomänendaten im Puffer abrufen? Ich nehme auch an, dass Sie den entsprechenden Behälter aus dem fft-Ergebnis extrahieren möchten, um ihn in PCP zu akkumulieren. Sie greifen gerade den ersten Zeitwert. –