2016-04-14 25 views
3

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

+0

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? –

+0

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. –

Antwort

1

Das Problem ist mit dem Algorithmus von einem 1999 Papier. Sie scheinen FFT für Amplitudenspitzen zu verwenden, was ein Schätzer für grobe Spektralfrequenzen ist, kein musikalischer Tonhöhen-Detektor/Schätzer. Polyphonische Akkordschätzung ist eine noch schwierigere/komplexere Aufgabe. Hier finden Sie Forschungsberichte über die neuesten Algorithmen zur polyphonen Musikextraktion: http://www.music-ir.org/mirex/wiki/2015:MIREX2015_Results

+0

Ich bin nicht sicher, ob ich genug Wissen habe, um dies als korrekt zu markieren. Ich habe mich entschieden, den Algorithmus in dem Papier von 1999 zu implementieren, weil es so aussieht, als ob ich etwas implementieren könnte, und es behauptet, es sei ein Algorithmus zur Akkorderkennung. In diesen beiden Papieren wurde auch auf sie verwiesen: http://www.fim.uni-passau.de/fileadmin/files/lehrstuhl/sauer/geyer/BA_MA_Arbeiten/BA-HausnerChristoph-201409.pdf und https: //ccrma.stanford .edu/~ kglee/pubs/klee-ismir06.pdf Innerhalb des 1999 Papiers gibt es Ausgabe seines Algorithmus, der Akkorde entdeckt. Vielleicht hat er etwas aus der Zeitung gelassen? – user3220901