Skip to content

Instantly share code, notes, and snippets.

@hertzg
Last active February 13, 2018 21:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hertzg/c75aa10072d10f00b38e to your computer and use it in GitHub Desktop.
Save hertzg/c75aa10072d10f00b38e to your computer and use it in GitHub Desktop.
compare_acoustid.js
const fs = require('fs')
let fp1Map = parseFPStr(fs.readFileSync('fpcalc.mp3.fp').toString('utf8'))
, fp2Map = parseFPStr(fs.readFileSync('fpcalc-16.mp3.fp').toString('utf8'))
;
function parseFPStr(fpStr) {
let lines = fpStr.split('\n')
, map = Object.create(null)
;
lines.forEach(function(line){
let parts = line.split('=');
map[parts.shift()] = parts.join('=');
});
map['FINGERPRINT'] = map['FINGERPRINT'].split(',').map(parseFloat);
return map;
}
const ACOUSTID_MAX_ALIGN_OFFSET = 120
, ACOUSTID_MAX_BIT_ERROR = 2
;
const POPCOUNT_TABLE_8BIT = [
0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
];
function popcount_lookup8(x) {
return POPCOUNT_TABLE_8BIT[ x & 0xff ] +
POPCOUNT_TABLE_8BIT[ (x >> 8) & 0xff ] +
POPCOUNT_TABLE_8BIT[ (x >> 16) & 0xff ] +
POPCOUNT_TABLE_8BIT[ x >> 24 ];
}
function calculate_distance(fp1Arr, fp2Arr) {
//must be one dimensional array
//TODO: check
//both Must have data
//TODO: check return 0
let totalLength = fp1Arr.length + fp2Arr.length + 1
, counts = Array.apply(null, new Array(totalLength)).map(Number.prototype.valueOf, 0)
;
console.log('FP1.length=%d FP2.length=%d', fp1Arr.length, fp2Arr.length);
for(let i=0; i<fp1Arr.length; i++) {
let jMin = Math.max(0, i-ACOUSTID_MAX_ALIGN_OFFSET)
, jMax = Math.min(fp2Arr.length, i+ACOUSTID_MAX_ALIGN_OFFSET);
;
for(let j=jMin; j<jMax; j++) {
let bitErr = popcount_lookup8(fp1Arr[i] ^ fp2Arr[j]);
//console.log('%s xor %s = %s', fp1Arr[i].toString(2), fp2Arr[j].toString(2), bitErr.toString(2));
//console.log("comparing %d and %d with error %d", i, j, bitErr);
if(bitErr <= ACOUSTID_MAX_BIT_ERROR) {
let offset = i - j + fp2Arr.length;
counts[offset] += 1;
}
}
}
//console.log(counts.join(','))
let maxCount = Math.max.apply(Math, counts)
, minLength = Math.min(fp1Arr.length, fp2Arr.length)
return 1 - (maxCount / (1* minLength ));
}
console.log('Calculating distance from from "%s" to "%s"', fp1Map.FILE, fp2Map.FILE);
console.log('Distance=%s', calculate_distance(fp1Map.FINGERPRINT, fp2Map.FINGERPRINT));
@dantedrd
Copy link

dantedrd commented Feb 13, 2018

hello hertzg
how much would you charge for implementing the same code with the aggrate framework in mongo db

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment