Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

a new algorithm #23

Open
wants to merge 1 commit into
base: master
from
Open
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file or symbol
Failed to load files and symbols.

Always

Just for now

a new algorithm

  • Loading branch information...
dalatant committed Nov 8, 2016
commit b0d5d28d2803d852dd85d2a1e53c22bcedba4cbf
@@ -201,7 +201,7 @@ function togglePlayback() {

var rafID = null;
var tracks = null;
var buflen = 1024;
var buflen = 2048;
var buf = new Float32Array( buflen );

var noteStrings = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"];
@@ -219,42 +219,8 @@ function centsOffFromPitch( frequency, note ) {
return Math.floor( 1200 * Math.log( frequency / frequencyFromNoteNumber( note ))/Math.log(2) );
}

// this is a float version of the algorithm below - but it's not currently used.
// this is the previously used pitch detection algorithm.
/*
function autoCorrelateFloat( buf, sampleRate ) {
var MIN_SAMPLES = 4; // corresponds to an 11kHz signal
var MAX_SAMPLES = 1000; // corresponds to a 44Hz signal
var SIZE = 1000;
var best_offset = -1;
var best_correlation = 0;
var rms = 0;
if (buf.length < (SIZE + MAX_SAMPLES - MIN_SAMPLES))
return -1; // Not enough data
for (var i=0;i<SIZE;i++)
rms += buf[i]*buf[i];
rms = Math.sqrt(rms/SIZE);
for (var offset = MIN_SAMPLES; offset <= MAX_SAMPLES; offset++) {
var correlation = 0;
for (var i=0; i<SIZE; i++) {
correlation += Math.abs(buf[i]-buf[i+offset]);
}
correlation = 1 - (correlation/SIZE);
if (correlation > best_correlation) {
best_correlation = correlation;
best_offset = offset;
}
}
if ((rms>0.1)&&(best_correlation > 0.1)) {
console.log("f = " + sampleRate/best_offset + "Hz (rms: " + rms + " confidence: " + best_correlation + ")");
}
// var best_frequency = sampleRate/best_offset;
}
*/

var MIN_SAMPLES = 0; // will be initialized when AudioContext is created.
var GOOD_ENOUGH_CORRELATION = 0.9; // this is the "bar" for how close a correlation needs to be
@@ -312,6 +278,52 @@ function autoCorrelate( buf, sampleRate ) {
return -1;
// var best_frequency = sampleRate/best_offset;
}
*/

function autoCorrelate( buf, sampleRate ) {
// Implements the ACF2+ algorithm
var SIZE = buf.length;
var rms = 0;

for (var i=0;i<SIZE;i++) {
var val = buf[i];
rms += val*val;
}
rms = Math.sqrt(rms/SIZE);
if (rms<0.01) // not enough signal
return -1;

var r1=0, r2=SIZE-1, thres=0.2;
for (var i=0; i<SIZE/2; i++)
if (Math.abs(buf[i])<thres) { r1=i; break; }
for (var i=1; i<SIZE/2; i++)
if (Math.abs(buf[SIZE-i])<thres) { r2=SIZE-i; break; }

buf = buf.slice(r1,r2);
SIZE = buf.length;

var c = new Array(SIZE).fill(0);
for (var i=0; i<SIZE; i++)
for (var j=0; j<SIZE-i; j++)
c[i] = c[i] + buf[j]*buf[j+i];

var d=0; while (c[d]>c[d+1]) d++;
var maxval=-1, maxpos=-1;
for (var i=d; i<SIZE; i++) {
if (c[i] > maxval) {
maxval = c[i];
maxpos = i;
}
}
var T0 = maxpos;

var x1=c[T0-1], x2=c[T0], x3=c[T0+1];
a = (x1 + x3 - 2*x2)/2;
b = (x3 - x1)/2;
if (a) T0 = T0 - b/(2*a);

return sampleRate/T0;
}

function updatePitch( time ) {
var cycles = new Array;
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.