UNPKG

music21j-port

Version:

A toolkit for computer-aided musicology, Javascript version

973 lines (785 loc) 27.2 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Music21j Source: music21/base.js</title> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/sunlight.default.css"> <link type="text/css" rel="stylesheet" href="styles/site.spruce.css"> </head> <body> <div class="container-fluid"> <div class="navbar navbar-fixed-top navbar-inverse"> <div class="navbar-inner"> <a class="brand" href="index.html">Music21j</a> <ul class="nav"> <li class="dropdown"> <a href="namespaces.list.html" class="dropdown-toggle" data-toggle="dropdown">Namespaces<b class="caret"></b></a> <ul class="dropdown-menu "> <li> <a href="music21.html">music21</a> </li> <li> <a href="music21.articulations.html">music21.articulations</a> </li> <li> <a href="music21.audioSearch.html">music21.audioSearch</a> </li> <li> <a href="music21.base.html">music21.base</a> </li> <li> <a href="music21.beam.html">music21.beam</a> </li> <li> <a href="music21.chord.html">music21.chord</a> </li> <li> <a href="music21.clef.html">music21.clef</a> </li> <li> <a href="music21.common.html">music21.common</a> </li> <li> <a href="music21.duration.html">music21.duration</a> </li> <li> <a href="music21.dynamics.html">music21.dynamics</a> </li> <li> <a href="music21.expressions.html">music21.expressions</a> </li> <li> <a href="music21.fromPython.html">music21.fromPython</a> </li> <li> <a href="music21.instrument.html">music21.instrument</a> </li> <li> <a href="music21.interval.html">music21.interval</a> </li> <li> <a href="music21.key.html">music21.key</a> </li> <li> <a href="music21.keyboard.html">music21.keyboard</a> </li> <li> <a href="music21.meter.html">music21.meter</a> </li> <li> <a href="music21.miditools.html">music21.miditools</a> </li> <li> <a href="music21.note.html">music21.note</a> </li> <li> <a href="music21.pitch.html">music21.pitch</a> </li> <li> <a href="music21.prebase.html">music21.prebase</a> </li> <li> <a href="music21.renderOptions.html">music21.renderOptions</a> </li> <li> <a href="music21.roman.html">music21.roman</a> </li> <li> <a href="music21.scale.html">music21.scale</a> </li> <li> <a href="music21.sites.html">music21.sites</a> </li> <li> <a href="music21.stream.html">music21.stream</a> </li> <li> <a href="music21.tempo.html">music21.tempo</a> </li> <li> <a href="music21.tie.html">music21.tie</a> </li> <li> <a href="music21.tinyNotation.html">music21.tinyNotation</a> </li> <li> <a href="music21.vfShow.html">music21.vfShow</a> </li> <li> <a href="music21.webmidi.html">music21.webmidi</a> </li> </ul> </li> <li class="dropdown"> <a href="classes.list.html" class="dropdown-toggle" data-toggle="dropdown">Classes<b class="caret"></b></a> <ul class="dropdown-menu "> <li> <a href="music21.articulations.Accent.html">music21.articulations.Accent</a> </li> <li> <a href="music21.articulations.Articulation.html">music21.articulations.Articulation</a> </li> <li> <a href="music21.articulations.DynamicArticulation.html">music21.articulations.DynamicArticulation</a> </li> <li> <a href="music21.articulations.LengthArticulation.html">music21.articulations.LengthArticulation</a> </li> <li> <a href="music21.articulations.Marcato.html">music21.articulations.Marcato</a> </li> <li> <a href="music21.articulations.PitchArticulation.html">music21.articulations.PitchArticulation</a> </li> <li> <a href="music21.articulations.Spiccato.html">music21.articulations.Spiccato</a> </li> <li> <a href="music21.articulations.Staccatissimo.html">music21.articulations.Staccatissimo</a> </li> <li> <a href="music21.articulations.Staccato.html">music21.articulations.Staccato</a> </li> <li> <a href="music21.articulations.StrongAccent.html">music21.articulations.StrongAccent</a> </li> <li> <a href="music21.articulations.Tenuto.html">music21.articulations.Tenuto</a> </li> <li> <a href="music21.articulations.TimbreArticulation.html">music21.articulations.TimbreArticulation</a> </li> <li> <a href="music21.base.Music21Object.html">music21.base.Music21Object</a> </li> <li> <a href="music21.beam.Beam.html">music21.beam.Beam</a> </li> <li> <a href="music21.beam.Beams.html">music21.beam.Beams</a> </li> <li> <a href="music21.chord.Chord.html">music21.chord.Chord</a> </li> <li> <a href="music21.clef.AltoClef.html">music21.clef.AltoClef</a> </li> <li> <a href="music21.clef.BassClef.html">music21.clef.BassClef</a> </li> <li> <a href="music21.clef.Clef.html">music21.clef.Clef</a> </li> <li> <a href="music21.clef.MezzoSopranoClef.html">music21.clef.MezzoSopranoClef</a> </li> <li> <a href="music21.clef.PercussionClef.html">music21.clef.PercussionClef</a> </li> <li> <a href="music21.clef.SopranoClef.html">music21.clef.SopranoClef</a> </li> <li> <a href="music21.clef.TenorClef.html">music21.clef.TenorClef</a> </li> <li> <a href="music21.clef.Treble8vaClef.html">music21.clef.Treble8vaClef</a> </li> <li> <a href="music21.clef.Treble8vbClef.html">music21.clef.Treble8vbClef</a> </li> <li> <a href="music21.clef.TrebleClef.html">music21.clef.TrebleClef</a> </li> <li> <a href="music21.duration.Duration.html">music21.duration.Duration</a> </li> <li> <a href="music21.duration.Tuplet.html">music21.duration.Tuplet</a> </li> <li> <a href="music21.dynamics.Dynamic.html">music21.dynamics.Dynamic</a> </li> <li> <a href="music21.expressions.Expression.html">music21.expressions.Expression</a> </li> <li> <a href="music21.expressions.Fermata.html">music21.expressions.Fermata</a> </li> <li> <a href="music21.fromPython.Converter.html">music21.fromPython.Converter</a> </li> <li> <a href="music21.instrument.Instrument.html">music21.instrument.Instrument</a> </li> <li> <a href="music21.interval.ChromaticInterval.html">music21.interval.ChromaticInterval</a> </li> <li> <a href="music21.interval.DiatonicInterval.html">music21.interval.DiatonicInterval</a> </li> <li> <a href="music21.interval.GenericInterval.html">music21.interval.GenericInterval</a> </li> <li> <a href="music21.interval.Interval.html">music21.interval.Interval</a> </li> <li> <a href="music21.key.Key.html">music21.key.Key</a> </li> <li> <a href="music21.key.KeySignature.html">music21.key.KeySignature</a> </li> <li> <a href="music21.keyboard.BlackKey.html">music21.keyboard.BlackKey</a> </li> <li> <a href="music21.keyboard.Key.html">music21.keyboard.Key</a> </li> <li> <a href="music21.keyboard.Keyboard.html">music21.keyboard.Keyboard</a> </li> <li> <a href="music21.keyboard.WhiteKey.html">music21.keyboard.WhiteKey</a> </li> <li> <a href="music21.meter.TimeSignature.html">music21.meter.TimeSignature</a> </li> <li> <a href="music21.miditools.Event.html">music21.miditools.Event</a> </li> <li> <a href="music21.miditools.MidiPlayer.html">music21.miditools.MidiPlayer</a> </li> <li> <a href="music21.note.GeneralNote.html">music21.note.GeneralNote</a> </li> <li> <a href="music21.note.Lyric.html">music21.note.Lyric</a> </li> <li> <a href="music21.note.Note.html">music21.note.Note</a> </li> <li> <a href="music21.note.NotRest.html">music21.note.NotRest</a> </li> <li> <a href="music21.note.Rest.html">music21.note.Rest</a> </li> <li> <a href="music21.pitch.Accidental.html">music21.pitch.Accidental</a> </li> <li> <a href="music21.pitch.Pitch.html">music21.pitch.Pitch</a> </li> <li> <a href="music21.prebase.ProtoM21Object.html">music21.prebase.ProtoM21Object</a> </li> <li> <a href="music21.renderOptions.RenderOptions.html">music21.renderOptions.RenderOptions</a> </li> <li> <a href="music21.roman.RomanNumeral.html">music21.roman.RomanNumeral</a> </li> <li> <a href="music21.stream.Measure.html">music21.stream.Measure</a> </li> <li> <a href="music21.stream.Part.html">music21.stream.Part</a> </li> <li> <a href="music21.stream.Score.html">music21.stream.Score</a> </li> <li> <a href="music21.stream.Stream.html">music21.stream.Stream</a> </li> <li> <a href="music21.stream.Voice.html">music21.stream.Voice</a> </li> <li> <a href="music21.tempo.Metronome.html">music21.tempo.Metronome</a> </li> <li> <a href="music21.tie.Tie.html">music21.tie.Tie</a> </li> <li> <a href="music21.vfShow.Renderer.html">music21.vfShow.Renderer</a> </li> <li> <a href="music21.vfShow.RenderStack.html">music21.vfShow.RenderStack</a> </li> <li> <a href="Notation.html">Notation</a> </li> <li> <a href="Page.html">Page</a> </li> <li> <a href="Recorder.html">Recorder</a> </li> </ul> </li> <li class="dropdown"> <a href="global.html" class="dropdown-toggle" data-toggle="dropdown">Global<b class="caret"></b></a> <ul class="dropdown-menu "> <li> <a href="global.html#getM21attribute">getM21attribute</a> </li> <li> <a href="global.html#layout">layout</a> </li> <li> <a href="global.html#midiNumDiffFromFrequency">midiNumDiffFromFrequency</a> </li> <li> <a href="global.html#recorderWorkerJs">recorderWorkerJs</a> </li> <li> <a href="global.html#unpickler">unpickler</a> </li> <li> <a href="global.html#warnBanner">warnBanner</a> </li> </ul> </li> </ul> </div> </div> <div class="row-fluid"> <div class="span12"> <div id="main"> <h1 class="page-title">Source: music21/base.js</h1> <section> <article> <pre class="sunlight-highlight-javascript linenums">/** * music21j -- Javascript reimplementation of Core music21p features. * music21/base -- objects in base in music21p routines * * does not load the other modules, music21/moduleLoader.js does that. * * Copyright (c) 2013-16, Michael Scott Cuthbert and cuthbertLab * Based on music21 (=music21p), Copyright (c) 2006–16, Michael Scott Cuthbert and cuthbertLab * */ import { common } from './common.js'; import { duration } from './duration.js'; import { prebase } from './prebase.js'; import { sites } from './sites.js'; /** * module for Music21Objects, see {@link music21.base} * * @requires music21/common * @requires music21/duration * @requires music21/prebase * @requires music21/sites * @exports music21/base */ /** * Module for Music21Objects. Does not load other modules, see {@link music21.moduleLoader} * for this functionality. * * @namespace music21.base * @memberof music21 */ export const base = {}; /** * Base class for any object that can be placed in a {@link music21.stream.Stream}. * * @class Music21Object * @memberof music21.base * @extends music21.prebase.ProtoM21Object * @property {Object} activeSite - hardlink to a {@link music21.stream.Stream} containing the element. * @property {number} classSortOrder - Default sort order for this class (default 20; override in other classes). Lower numbered objects will sort before other objects in the staff if priority and offset are the same. * @property {music21.duration.Duration} duration - the duration (object) for the element. (can be set with a quarterLength also) * @property {Array} groups - An Array of strings representing group (equivalent to css classes) to assign to the object. (default []) * @property {boolean} isMusic21Object - true * @property {boolean} isStream - false * @property {number} offset - offset from the beginning of the stream (in quarterLength) * @property {number} priority - The priority (lower = earlier or more left) for elements at the same offset. (default 0) */ export class Music21Object extends prebase.ProtoM21Object { constructor(keywords) { super(); this.classSortOrder = 20; // default; this.activeSite = undefined; this.offset = 0; // for now this._naiveOffset = 0; // this._activeSite = undefined; this._activeSiteStoredOffset = undefined; // this._derivation = undefined; // this._style = undefined; // this._editorial = undefined; this._duration = new duration.Duration(); this._priority = 0; // default; // this.id = sites.getId(this); this.groups = []; // groups this.sites = new sites.Sites(); this.isMusic21Object = true; this.isStream = false; this.groups = []; // custom object in m21p // this.sites, this.activeSites, this.offset -- not yet... // beat, measureNumber, etc. // lots to do... this._cloneCallbacks.activeSite = function Music21Object_cloneCallbacks_activeSite( keyName, newObj, self ) { newObj[keyName] = undefined; }; this._cloneCallbacks.sites = function Music21Object_cloneCallbacks_sites( keyName, newObj, self ) { newObj[keyName] = new sites.Sites(); }; } get priority() { return this._priority; } set priority(p) { this._priority = p; } get duration() { return this._duration; } set duration(newDuration) { if (typeof newDuration === 'object') { this._duration = newDuration; // common errors below... } else if (typeof newDuration === 'number') { this._duration.quarterLength = newDuration; } else if (typeof newDuration === 'string') { this._duration.type = newDuration; } } get quarterLength() { return this.duration.quarterLength; } set quarterLength(ql) { this.duration.quarterLength = ql; } /** * Return the offset of this element in a given site -- use .offset if you are sure that * site === activeSite. * * Does not change activeSite or .offset * * @memberof music21.base.Music21Object * @param {music21.stream.Stream} site * @returns Number|undefined */ getOffsetBySite(site, stringReturns = false) { if (site === undefined) { return this._naiveOffset; } return site.elementOffset(this, stringReturns); } /** * setOffsetBySite - sets the offset for a given Stream * * @memberof music21.base.Music21Object * @param {music21.stream.Stream} site Stream object * @param {number} value offset */ setOffsetBySite(site, value) { if (site !== undefined) { site.setElementOffset(this, value); } else { this._naiveOffset = value; } } // ---------- Contexts ------------- getContextByClass(className, options) { const payloadExtractor = function payloadExtractor( useSite, flatten, positionStart, getElementMethod, classList ) { // this should all be done as a tree... // do not use .flat or .semiFlat so as not // to create new sites. // VERY HACKY... let lastElement; for (let i = 0; i &lt; useSite.length; i++) { const indexOffset = useSite._elementOffsets[i]; const thisElement = useSite._elements[i]; const matchClass = thisElement.isClassOrSubclass(classList); if (flatten === false &amp;&amp; !matchClass) { continue; } else if (!thisElement.isStream &amp;&amp; !matchClass) { continue; } // is a stream or an element of the appropriate class... // first check normal elements if ( getElementMethod.includes('Before') &amp;&amp; indexOffset >= positionStart ) { if ( getElementMethod.includes('At') &amp;&amp; lastElement === undefined ) { lastElement = thisElement; } else if (matchClass) { return lastElement; } } else { lastElement = thisElement; } if ( getElementMethod.includes('After') &amp;&amp; indexOffset > positionStart &amp;&amp; matchClass ) { return thisElement; } // now cleck stream... already filtered out flatten == false; if (thisElement.isStream) { const potentialElement = payloadExtractor( thisElement, flatten, positionStart + indexOffset, getElementMethod, classList ); if (potentialElement !== undefined) { return potentialElement; } } } return undefined; }; const params = { getElementMethod: 'getElementAtOrBefore', sortByCreationTime: false, }; common.merge(params, options); const getElementMethod = params.getElementMethod; const sortByCreationTime = params.sortByCreationTime; if (className !== undefined &amp;&amp; !(className instanceof Array)) { className = [className]; } if ( getElementMethod.includes('At') &amp;&amp; this.isClassOrSubclass(className) ) { return this; } for (const [site, positionStart, searchType] of this.contextSites({ returnSortTuples: true, sortByCreationTime, })) { if ( getElementMethod.includes('At') &amp;&amp; site.isClassOrSubclass(className) ) { return site; } if ( searchType === 'elementsOnly' || searchType === 'elementsFirst' ) { const contextEl = payloadExtractor( site, false, positionStart, getElementMethod, className ); if (contextEl !== undefined) { contextEl.activeSite = site; return contextEl; } } else if (searchType !== 'elementsOnly') { if ( getElementMethod.includes('After') &amp;&amp; (className === undefined || site.isClassOrSubclass(className)) ) { if ( !getElementMethod.includes('NotSelf') &amp;&amp; this !== site ) { return site; } } const contextEl = payloadExtractor( site, 'semiFlat', positionStart, getElementMethod, className ); if (contextEl !== undefined) { contextEl.activeSite = site; return contextEl; } if ( getElementMethod.includes('Before') &amp;&amp; (className === undefined || site.isClassOrSubclass(className)) ) { if ( !getElementMethod.includes('NotSelf') || this !== site ) { return site; } } } } return undefined; } * contextSites(options) { const params = { callerFirst: undefined, memo: [], offsetAppend: 0.0, sortByCreationTime: false, priorityTarget: undefined, returnSortTuples: false, followDerivation: true, }; common.merge(params, options); const memo = params.memo; if (params.callerFirst === undefined) { params.callerFirst = this; if (this.isStream &amp;&amp; !(this in memo)) { const recursionType = this.recursionType; yield [this, 0.0, recursionType]; } memo.push(this); } if (params.priorityTarget === undefined &amp;&amp; !params.sortByCreationType) { params.priorityTarget = this.activeSite; } // const topLevel = this; for (const siteObj of this.sites.yieldSites( params.sortByCreationTime, params.priorityTarget, true // excludeNone )) { if (memo.includes(siteObj)) { continue; } if (siteObj.classes.includes('SpannerStorage')) { continue; } // let offset = this.getOffsetBySite(siteObj); // followDerivation; const offsetInStream = siteObj.elementOffset(this); const newOffset = offsetInStream + params.offsetAppend; const positionInStream = newOffset; const recursionType = siteObj.recursionType; yield [siteObj, positionInStream, recursionType]; memo.push(siteObj); const newParams = { callerFirst: params.callerFirst, memo, offsetAppend: positionInStream, // .offset returnSortTuples: true, // always! sortByCreationTime: params.sortByCreationTime, }; for (const [ topLevel, inStreamPos, recurType ] of siteObj.contextSites(newParams)) { const inStreamOffset = inStreamPos; // .offset; // const hypotheticalPosition = inStreamOffset; // more complex w/ sortTuples if (!memo.includes(topLevel)) { // if returnSortTuples... // else yield [topLevel, inStreamOffset, recurType]; memo.push(topLevel); } } } // if followDerivation... } } base.Music21Object = Music21Object; </pre> </article> </section> </div> <div class="clearfix"></div> <footer> <span class="copyright"> Music21j, Copyright © 2013-2018 Michael Scott Cuthbert and cuthbertLab. </span> <br /> <span class="jsdoc-message"> Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Wed Jul 4th 2018 using the <a href="https://github.com/terryweiss/docstrap">DocStrap template</a>. </span> </footer> </div> <br clear="both"> </div> </div> <!--<script src="scripts/sunlight.js"></script>--> <script src="scripts/docstrap.lib.js"></script> <script src="scripts/bootstrap-dropdown.js"></script> <script src="scripts/toc.js"></script> <script> $( function () { $( "[id*='$']" ).each( function () { var $this = $( this ); $this.attr( "id", $this.attr( "id" ).replace( "$", "__" ) ); } ); $( "#toc" ).toc( { anchorName : function ( i, heading, prefix ) { return $( heading ).attr( "id" ) || ( prefix + i ); }, selectors : "h1,h2,h3,h4", showAndHide : false, scrollTo : "100px" } ); $( "#toc>ul" ).addClass( "nav nav-pills nav-stacked" ); $( "#main span[id^='toc']" ).addClass( "toc-shim" ); $( '.dropdown-toggle' ).dropdown(); // $( ".tutorial-section pre, .readme-section pre" ).addClass( "sunlight-highlight-javascript" ).addClass( "linenums" ); $( ".tutorial-section pre, .readme-section pre" ).each( function () { var $this = $( this ); var example = $this.find( "code" ); exampleText = example.html(); var lang = /{@lang (.*?)}/.exec( exampleText ); if ( lang && lang[1] ) { exampleText = exampleText.replace( lang[0], "" ); example.html( exampleText ); lang = lang[1]; } else { lang = "javascript"; } if ( lang ) { $this .addClass( "sunlight-highlight-" + lang ) .addClass( "linenums" ) .html( example.html() ); } } ); Sunlight.highlightAll( { lineNumbers : true, showMenu : true, enableDoclinks : true } ); } ); </script> <!--Navigation and Symbol Display--> <!--Google Analytics--> </body> </html>