2016-04-14 2 views
3

Во-первых, я пытаюсь реализовать этот аккорд алгоритм обнаружения: http://www.music.mcgill.ca/~jason/mumt621/papers5/fujishima_1999.pdfChord Detection Algorithm с Web Audio API

Я первоначально реализован алгоритм, чтобы использовать свой микрофон, но это не сработало. В качестве теста я создал три осциллятора, чтобы сделать c-аккорд, но алгоритм все еще не работает. Я думаю, что я должен видеть только большее число для C, E и G, но я вижу цифры для всех заметок. Есть ли проблема с моей реализацией алгоритма? или это мое значение N, fref или fs?

Вот фрагмент кода с важными частями:

// 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(); 
} 

Вот мой полный codepen если вы хотите попробовать запустить его самостоятельно. Предупреждение У меня есть useMicrophone установлен на false, поэтому он будет создавать звук с аккордом: https://codepen.io/mapmaps/pen/ONQPpw

+0

Звучит как классный проект, но вы уверены, что вход правильный? Пробовали ли вы с поддельными жестко закодированными входными значениями, чтобы убедиться, что результат в этом случае правильный? –

+0

Не хотите ли вы получать данные с поплавковой частотой вместо данных временной области в буфере? Я также предполагаю, что вы хотите извлечь соответствующий бит из fft-результата для накопления в PCP. Вы только сейчас получаете первое значение. –

ответ

1

Проблема заключается в использовании алгоритма из документа 1999 года. Кажется, вы используете БПФ для пиков амплитуды, которая является грубой спектральной оценкой частоты, а не детектором/оценкой музыкального тона. Полифоническая оценка аккордов является еще более сложной/сложной задачей. Посмотрите здесь на научные статьи по новейшим алгоритмам для извлечения полифонической музыки: http://www.music-ir.org/mirex/wiki/2015:MIREX2015_Results

+0

Я не уверен, что у меня достаточно знаний, чтобы отметить это как правильное. Я решил реализовать алгоритм в документе 1999 года, потому что он кажется тем, что я мог бы реализовать, и он утверждает, что он является алгоритмом обнаружения аккордов. Он также упоминался в этих двух статьях: http://www.fim.uni-passau.de/fileadmin/files/lehrstuhl/sauer/geyer/BA_MA_Arbeiten/BA-HausnerChristoph-201409.pdf и https: //ccrma.stanford .edu/~ kglee/pubs/klee-ismir06.pdf В статье за ​​1999 год представлен результат его алгоритма обнаружения аккордов. Может, он что-то оставил из бумаги? – user3220901