UNPKG

music21j-port

Version:

A toolkit for computer-aided musicology, Javascript version

952 lines (780 loc) 25 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Music21j Source: music21/key.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/key.js</h1> <section> <article> <pre class="sunlight-highlight-javascript linenums">/** * music21j -- Javascript reimplementation of Core music21p features. * music21/key -- KeySignature and Key objects * * Copyright (c) 2013-16, Michael Scott Cuthbert and cuthbertLab * Based on music21 (=music21p), Copyright (c) 2006–16, Michael Scott Cuthbert and cuthbertLab * */ import { Music21Exception } from './exceptions21.js'; import { base } from './base.js'; // import { common } from './common.js'; import { debug } from './debug.js'; import { interval } from './interval.js'; import { pitch } from './pitch.js'; import { scale } from './scale.js'; /* key and keysignature module. See {@link music21.key} namespace for details * * @exports music21/key */ /** * Key and KeySignature related objects and methods * * @namespace music21.key * @memberof music21 * @requires music21/base * @requires music21/pitch * @requires music21/interval * @requires music21/scale */ export const key = {}; key.modeSharpsAlter = { major: 0, minor: -3, dorian: -2, phrygian: -4, lydian: 1, mixolydian: -1, locrian: -5, }; key.convertKeyStringToMusic21KeyString = function convertKeyStringToMusic21KeyString( textString ) { if (textString === 'bb') { textString = 'b-'; } else if (textString === 'Bb') { textString = 'B-'; } else if (textString.endsWith('b') &amp;&amp; !textString.startsWith('b')) { textString = textString.replace(/b$/, '-'); } return textString; }; /** * @class KeySignature * @memberof music21.key * @description Represents a key signature * @param {int} [sharps=0] -- the number of sharps (negative for flats) * @property {Int} [sharps=0] -- number of sharps (negative for flats) * @extends music21.base.Music21Object * @example * var ks = new music21.key.KeySignature(-3); //E-flat major or c minor * var s = new music21.stream.Stream(); * s.keySignature = ks; * var n = new music21.note.Note('A-'); // A-flat * s.append(n); * s.appendNewDOM(); */ export class KeySignature extends base.Music21Object { constructor(sharps) { super(); this._sharps = sharps || 0; // if undefined this._alteredPitchesCache = undefined; // 12 flats/sharps enough for now... this.flatMapping = [ 'C', 'F', 'B-', 'E-', 'A-', 'D-', 'G-', 'C-', 'F-', 'B--', 'E--', 'A--', 'D--', ]; this.sharpMapping = [ 'C', 'G', 'D', 'A', 'E', 'B', 'F#', 'C#', 'G#', 'D#', 'A#', 'E#', 'B#', ]; } get sharps() { return this._sharps; } set sharps(s) { this._alteredPitchesCache = []; this._sharps = s; } /** * Gives the width in pixels necessary to represent the key signature. * * @memberof music21.key.KeySignature# * @var {number} width * @readonly */ get width() { if (this.sharps === 0) { return 0; } else { // add 6 to add extra space after the KS... return 12 * Math.abs(this.sharps) + 6; } } /** * An Array of Altered Pitches in KeySignature order (i.e., for flats, Bb, Eb, etc.) * * @memberof music21.key.KeySignature# * @var {Array&lt;music21.pitch.Pitch>} alteredPitches * @readonly * @example * var ks = new music21.key.KeySignature(3) * var ap = ks.alteredPitches * var apName = []; * for (var i = 0; i &lt; ap.length; i++) { * apName.push(ap[i].name); * } * apName * // ["F#", "C#", "G#"] */ get alteredPitches() { if (this._alteredPitchesCache !== undefined) { return this._alteredPitchesCache; } let transStr = 'P5'; let startPitch = 'B'; if (this.sharps &lt; 0) { transStr = 'P4'; startPitch = 'F'; } const transInterval = new interval.Interval(transStr); const post = []; let pKeep = new pitch.Pitch(startPitch); for (let i = 0; i &lt; Math.abs(this.sharps); i++) { pKeep = transInterval.transposePitch(pKeep); pKeep.octave = 4; post.push(pKeep); } this._alteredPitchesCache = post; return post; } /** * Return the name of the major key with this many sharps * * @memberof music21.key.KeySignature * @returns {(string|undefined)} name of key * @example * var ks = new music21.key.KeySignature(-3) * ks.majorName() * // "E-" */ majorName() { if (this.sharps >= 0) { return this.sharpMapping[this.sharps]; } else { return this.flatMapping[Math.abs(this.sharps)]; } } /** * Return the name of the minor key with this many sharps * @memberof music21.key.KeySignature * @returns {(string|undefined)} */ minorName() { const tempSharps = this.sharps + 3; if (tempSharps >= 0) { return this.sharpMapping[tempSharps]; } else { return this.flatMapping[Math.abs(tempSharps)]; } } /** * returns the vexflow name (just the `majorName()` with "b" for "-") for * the key signature. Does not create the object. * * Deprecated. * * @memberof music21.key.KeySignature * @returns {string} */ vexflow() { console.log('calling deprecated function KeySignature.vexflow'); const tempName = this.majorName(); return tempName.replace(/-/g, 'b'); } /** * Returns the accidental associated with a step in this key, or undefined if none. * * @memberof music21.key.KeySignature * @param {string} step - a valid step name such as "C","D", etc., but not "C#" etc. * @returns {(music21.pitch.Accidental|undefined)} */ accidentalByStep(step) { const aps = this.alteredPitches; for (let i = 0; i &lt; aps.length; i++) { if (aps[i].step === step) { if (aps[i].accidental === undefined) { return undefined; } // make a new accidental; return new pitch.Accidental(aps[i].accidental.alter); } } return undefined; } /** * Takes a pitch in C major and transposes it so that it has * the same step position in the current key signature. * * @memberof music21.key.KeySignature * @returns {music21.pitch.Pitch} * @example * var ks = new music21.key.KeySignature(-3) * var p1 = new music21.pitch.Pitch('B') * var p2 = ks.transposePitchFromC(p1) * p2.name * // "D" * var p3 = new music21.pitch.Pitch('G-') * var p4 = ks.transposePitchFromC(p3) * p4.name * // "B--" */ transposePitchFromC(p) { let transInterval; let transTimes; if (this.sharps === 0) { return new pitch.Pitch(p.nameWithOctave); } else if (this.sharps &lt; 0) { transTimes = Math.abs(this.sharps); transInterval = new interval.Interval('P4'); } else { transTimes = this.sharps; transInterval = new interval.Interval('P5'); } let newPitch = p; for (let i = 0; i &lt; transTimes; i++) { newPitch = transInterval.transposePitch(newPitch); if (i % 2 === 1) { newPitch.octave -= 1; } } return newPitch; } } key.KeySignature = KeySignature; /** * Create a Key object. Like a KeySignature but with ideas about Tonic, Dominant, etc. * * TODO: allow keyName to be a {@link music21.pitch.Pitch} * TODO: Scale mixin. * * @class Key * @memberof music21.key * @extends music21.key.KeySignature * @param {string} keyName -- a pitch name representing the key (w/ "-" for flat) * @param {string} [mode] -- if not given then the CASE of the keyName will be used ("C" => "major", "c" => "minor") */ export class Key extends KeySignature { constructor(keyName, mode) { if (keyName === undefined) { keyName = 'C'; } if (mode === undefined) { const lowerCase = keyName.toLowerCase(); if (keyName === lowerCase) { mode = 'minor'; } else { mode = 'major'; } } const sharpsArray = 'A-- E-- B-- F- C- G- D- A- E- B- F C G D A E B F# C# G# D# A# E# B#'.split( ' ' ); const sharpsIndex = sharpsArray.indexOf(keyName.toUpperCase()); if (sharpsIndex === -1) { throw new Music21Exception('Cannot find the key for ' + keyName); } const modeShift = key.modeSharpsAlter[mode] || 0; const sharps = sharpsIndex + modeShift - 11; if (debug) { console.log('Found sharps ' + sharps + ' for key: ' + keyName); } super(sharps); this.tonic = new pitch.Pitch(keyName); this.mode = mode; this._scale = this.getScale(); } /** * returns a {@link music21.scale.MajorScale} or {@link music21.scale.MinorScale} * object from the pitch object. * * @memberof music21.key.Key * @param {string|undefined} [scaleType=this.mode] - the type of scale, or the mode. * @returns {Object} A music21.scale.Scale subclass. */ getScale(scaleType) { if (scaleType === undefined) { scaleType = this.mode; } const pitchObj = this.tonic; if (scaleType === 'major') { return new scale.MajorScale(pitchObj); } else if (scaleType === 'minor') { return new scale.MinorScale(pitchObj); } else if (['harmonic minor', 'harmonic-minor'].includes(scaleType)) { return new scale.HarmonicMinorScale(pitchObj); } else if (['melodic minor', 'melodic-minor'].includes(scaleType)) { return new scale.AscendingMelodicMinorScale(pitchObj); } else { return new scale.ConcreteScale(pitchObj); } } // when scale.js adds functionality, it must be added here. get isConcrete() { return this._scale.isConcrete; } getPitches(...args) { return this._scale.getPitches(...args); } pitchFromDegree(...args) { return this._scale.pitchFromDegree(...args); } getScaleDegreeFromPitch(...args) { return this._scale.getScaleDegreeFromPitch(...args); } } key.Key = Key; </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>