Source: music21/meter.js

/**
 * music21j -- Javascript reimplementation of Core music21p features.
 * music21/meter -- TimeSignature objects
 *
 *
 * Copyright (c) 2013-16, Michael Scott Cuthbert and cuthbertLab
 * Based on music21 (=music21p), Copyright (c) 2006–16, Michael Scott Cuthbert and cuthbertLab
 *
 */
import * as Vex from 'vexflow';
import { base } from './base';
import { duration } from './duration';

/**
 * meter module. See {@link music21.meter} namespace for details.
 *
 * @exports music21/meter
 */

/**
 * Meter and TimeSignature Classes (esp. {@link music21.meter.TimeSignature} ) and methods.
 *
 * @namespace music21.meter
 * @memberof music21
 * @requires music21/base
 * @requires music21/duration
 */
export const meter = {};


/**
 * A MUCH simpler version of the music21p TimeSignature object.
 *
 * @class TimeSignature
 * @memberof music21.meter
 * @param {string} meterString - a string ("4/4", "3/8" etc.) to initialize the TimeSignature.
 * @property {Int} [numerator=4]
 * @property {Int} [denominator=4]
 * @property {Array<Array<Int>>} beatGroups - groupings of beats; inner arrays are numerator, denominator
 * @property {string} ratioString - a string like "4/4"
 * @property {music21.duration.Duration} barDuration - a Duration object representing the expressed total length of the TimeSignature.
 */
export class TimeSignature extends base.Music21Object {
    constructor(meterString) {
        super();
        this.classes.push('TimeSignature');
        this._numerator = 4;
        this._denominator = 4;
        this.beatGroups = [];
        if (typeof (meterString) === 'string') {
            this.ratioString = meterString;
        }
    }
    get numerator() {
        return this._numerator;
    }
    set numerator(s) {
        this._numerator = s;
    }
    get denominator() {
        return this._denominator;
    }
    set denominator(s) {
        this._denominator = s;
    }
    get ratioString() {
        return this.numerator.toString() + '/' + this.denominator.toString();
    }
    set ratioString(meterString) {
        const meterList = meterString.split('/');
        this.numerator = parseInt(meterList[0]);
        this.denominator = parseInt(meterList[1]);
    }
    get barDuration() {
        const ql = 4.0 * this._numerator / this._denominator;
        return new duration.Duration(ql);
    }
    /**
     * Compute the Beat Group according to this time signature.
     *
     * @memberof music21.meter.TimeSignature
     * @returns {Array<Array<Int>>} a list of numerator and denominators, find a list of beat groups.
     */
    computeBeatGroups() {
        const tempBeatGroups = [];
        let numBeats = this.numerator;
        let beatValue = this.denominator;
        if (beatValue < 8 && numBeats >= 5) {
            const beatsToEighthNoteRatio = 8 / beatValue; // hopefully Int -- right Brian Ferneyhough?
            beatValue = 8;
            numBeats *= beatsToEighthNoteRatio;
        }

        if (beatValue >= 8) {
            while (numBeats >= 5) {
                tempBeatGroups.push([3, beatValue]);
                numBeats -= 3;
            }
            if (numBeats === 4) {
                tempBeatGroups.push([2, beatValue]);
                tempBeatGroups.push([2, beatValue]);
            } else if (numBeats > 0) {
                tempBeatGroups.push([numBeats, beatValue]);
            }
        } else if (beatValue === 2) {
            tempBeatGroups.push([1, 2]);
        } else if (beatValue <= 1) {
            tempBeatGroups.push([1, 1]);
        } else { // 4/4, 2/4, 3/4, standard stuff
            tempBeatGroups.push([2, 8]);
        }
        return tempBeatGroups;
    }
    /**
     * Compute the Beat Group according to this time signature for VexFlow. For beaming.
     *
     * @memberof music21.meter.TimeSignature
     * @param {Vex} Vex - a reference to the Vex object
     * @returns {Array<Vex.Flow.Fraction>} a list of numerator and denominator groups, for VexFlow
     */
    vexflowBeatGroups() {
        let tempBeatGroups;
        if (this.beatGroups.length > 0) {
            tempBeatGroups = this.beatGroups;
        } else {
            tempBeatGroups = this.computeBeatGroups();
        }
        // console.log(tempBeatGroups);
        const vfBeatGroups = [];
        for (let i = 0; i < tempBeatGroups.length; i++) {
            const bg = tempBeatGroups[i];
            vfBeatGroups.push(new Vex.Flow.Fraction(bg[0], bg[1]));
        }
        return vfBeatGroups;

        //  if (numBeats % 3 == 0 && beatValue < 4) {
        //  // 6/8, 3/8, 9/8, etc.
        //  numBeats = numBeats / 3;
        //  beatValue = beatValue / 3;
        //  }
    }
}

meter.TimeSignature = TimeSignature;
Music21j, Copyright © 2013-2016 Michael Scott Cuthbert and cuthbertLab.
Documentation generated by JSDoc 3.4.3 on Wed Jul 26th 2017 using the DocStrap template.