/**
* @typedef {Object} PitchPackage
* @property {number} midival The midi value of the note
* @property {number} timepos The start time of the note
*/
/**
* Checks if the pitch at the currentIndex is too close to the next note
* @param {PitchPackage[]} pitches Collection of pitches
* @param {number} currentIndex Current index into pitches
* @param {number} nextMidi The midi value of the next note
* @param {number} nextTimePos The start time of the next note
*/
const differenceChecker = (pitches, currentIndex, nextMidi, nextTimePos) => {
const EPSILON = 0.00001;
try {
if (pitches[currentIndex].midival !== nextMidi) {
return Math.abs(pitches[currentIndex].timepos - nextTimePos) < EPSILON;
}
} catch(e) {}
return false;
}
/**
* @typedef {object} PerformancePackage
* @property {PitchPackage[]} pitches Collection of notes heard
*/
/**
* @typedef {object} CleanedPitchesPackage
* @property {number} midival The midi value of the note
* @property {number} duration The duration of the note
*/
/**
* Cleans the provided performance removing pitches that are too close together and notes the duration of each note
* @param {PerformancePackage} input The percieved performance to be analyzed.
* @returns {CleanedPitchesPackage[]} The cleaned input data
*/
const clean = (input) => {
input = input["pitches"];
let actualPitches = [];
for (let i = 0; i < input.length - 1; i++) {
let nestedPitches = input[i]["pitches"];
if (nestedPitches) {
for (let j = 0; j < nestedPitches.length - 1; j++) {
if (!differenceChecker(nestedPitches, j, nestedPitches[j+1]["midival"], nestedPitches[j+1]["timepos"])) {
actualPitches.push(nestedPitches[j]);
}
}
} else {
if (!differenceChecker(input, i, input[i+1]["midival"], input[i+1]["timepos"])) {
actualPitches.push(input[i]);
}
}
}
let outputData = [];
let currentIndex = -1;
for (let i = 0; i < actualPitches.length; i++) {
let duration = 1;
if (i < actualPitches.length - 1) {
duration = Math.abs(actualPitches[i+1].timepos - actualPitches[i].timepos);
}
let midi = actualPitches[i].midival;
if (midi < 0) {
midi = 0;
}
if (duration * 2 > 0.24) {
outputData.push({midival: midi, duration});
currentIndex++;
} else {
if (currentIndex === -1) {
outputData.push({midival: midi, duration});
currentIndex++;
} else {
outputData[currentIndex].duration += duration;
}
}
}
return outputData;
}
module.exports = clean;