music21j-port
Version:
A toolkit for computer-aided musicology, Javascript version
973 lines (785 loc) • 27.2 kB
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 < useSite.length; i++) {
const indexOffset = useSite._elementOffsets[i];
const thisElement = useSite._elements[i];
const matchClass = thisElement.isClassOrSubclass(classList);
if (flatten === false && !matchClass) {
continue;
} else if (!thisElement.isStream && !matchClass) {
continue;
}
// is a stream or an element of the appropriate class...
// first check normal elements
if (
getElementMethod.includes('Before')
&& indexOffset >= positionStart
) {
if (
getElementMethod.includes('At')
&& lastElement === undefined
) {
lastElement = thisElement;
} else if (matchClass) {
return lastElement;
}
} else {
lastElement = thisElement;
}
if (
getElementMethod.includes('After')
&& indexOffset > positionStart
&& 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 && !(className instanceof Array)) {
className = [className];
}
if (
getElementMethod.includes('At')
&& this.isClassOrSubclass(className)
) {
return this;
}
for (const [site, positionStart, searchType] of this.contextSites({
returnSortTuples: true,
sortByCreationTime,
})) {
if (
getElementMethod.includes('At')
&& 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')
&& (className === undefined
|| site.isClassOrSubclass(className))
) {
if (
!getElementMethod.includes('NotSelf')
&& this !== site
) {
return site;
}
}
const contextEl = payloadExtractor(
site,
'semiFlat',
positionStart,
getElementMethod,
className
);
if (contextEl !== undefined) {
contextEl.activeSite = site;
return contextEl;
}
if (
getElementMethod.includes('Before')
&& (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 && !(this in memo)) {
const recursionType = this.recursionType;
yield [this, 0.0, recursionType];
}
memo.push(this);
}
if (params.priorityTarget === undefined && !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>