UNPKG

musicvis-lib

Version:

Music analysis and visualization library

142 lines (135 loc) 4.39 kB
import NoteArray from './NoteArray.js' import { arrayShallowEquals } from '../utils/ArrayUtils.js' /** * Class for storing recorded notes alongside meta information. */ class Recording extends NoteArray { /** * Creates a new Recording * * @param {string} name name if the song * @param {Date} date date of the recording * @param {Note[]} notes array of Note objects * @param {number} [speed=1] relative speed compared to ground truth, * e.g. 0.5 for half as fast * @param {number} [selectedTrack=0] track number of the ground truth to which * this recording belongs * @param {number[]|null} [timeSelection=null] time selection of the ground * truth to which this recording belongs, or null if full duration * @param {string} [comment=''] a free-text comment for the user to annotate * the recording */ constructor (name, date, notes, speed = 1, selectedTrack = 0, timeSelection = null, comment = '') { super(notes) this.name = name this.date = date // Save formatted date for faster access this.dateString = date.toISOString() .slice(0, 19) .replace('T', ' ') this.speed = +speed this.selectedTrack = +selectedTrack this.timeSelection = timeSelection this.comment = comment this.sortByTime() } /** * Returns a copy of the Note object * * @returns {Recording} new recording */ clone () { return new Recording( this.name, this.date, this.getNotes().map(d => d.clone()), this.speed, this.selectedTrack, this.timeSelection === null ? null : [...this.timeSelection], this.comment ) } /** * Returns true if this Recording and otherRecording have equal attributes. * * @param {Recording} otherRecording another Recording * @returns {boolean} true if equal */ equals (otherRecording) { if (!(otherRecording instanceof Recording)) { return false } if (this.name !== otherRecording.name) { return false } if (this.date.getTime() !== otherRecording.date.getTime()) { return false } if (this.speed !== otherRecording.speed) { return false } if (this.selectedTrack !== otherRecording.selectedTrack) { return false } if (this.timeSelection !== otherRecording.timeSelection) { if (this.timeSelection === null || otherRecording.timeSelection === null) { return false } if (!arrayShallowEquals(this.timeSelection, otherRecording.timeSelection)) { return false } } // Below is the same as NoteArray const notes1 = this.getNotes() const notes2 = otherRecording.getNotes() if (notes1.length !== notes2.length) { return false } for (const [index, element] of notes1.entries()) { if (!element.equals(notes2[index])) { return false } } if (this.comment !== otherRecording.comment) { return false } return true } /** * Turns the recoring into a simple object with the same properties * * @returns {object} simple object representation of the recording */ toSimpleObject () { return { name: this.name, date: this.date, notes: this.getNotes(), speed: this.speed, selectedTrack: this.selectedTrack, timeSelection: this.timeSelection, comment: this.comment } } /** * Creates a Note object from an object via destructuring * * @param {object} object object with at least {name, date, notes, speed} * @returns {Recording} new note * @throws {Error} when name, date, or notes are missing */ static from (object) { let { name, date, notes } = object // Check for undefined const values = [name, date, notes] const names = ['name', 'date', 'notes'] for (const [index, value] of values.entries()) { if (value === undefined || value === null) { throw new Error(`Cannot create Recording with undefined ${names[index]}`) } } // Parse date if it is a string if (typeof (date) === 'string') { date = new Date(Date.parse(date)) } const { speed, selectedTrack, timeSelection, comment } = object return new Recording( name, date, notes, speed, selectedTrack, timeSelection, comment ) } } export default Recording