Source: Parser/cleaner.js

/**
 * @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;