All files / src/pipeline step1parts.js

100% Statements 4/4
100% Branches 2/2
100% Functions 3/3
100% Lines 4/4

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95                          1x         14x                                     2x                         70x                                                                                        
import { Step } from "./step.js";
 
/**
 * Step 1: macro-structure as a sequence of parts rho_1 ... rho_m.
 * Each rho_i is formally a 9-tuple (lambda, iota, zeta, eta, kappa, mu, pi, psi, omega);
 * Step 1 fills the first four (label, bars, numerator, denominator) plus global tempo.
 */
export class Step1Parts extends Step {
  /**
   * @override
   * @return {Object[]} UI descriptors: parts (m), tempo, and fields 1-4 per part (rho).
   */
  schema() {
    return SCHEMA;
  }
}
 
/** @private */
const SCHEMA = [
  {
    name: "parts",
    type: "stepper",
    label: "Number of Parts",
    tooltip: "Number of musical sections (e.g. A-B-A)",
    default: 1,
    min: 1,
    max: 5,
  },
  {
    name: "tempo",
    type: "int",
    label: "Tempo",
    tooltip: "Playback speed (MIDI BPM, always based on quarter notes)",
    default: 120,
    min: 30,
    max: 210,
    step: 1,
    format: (v) => `${v} <abbr title="Beats Per Minute">BPM</abbr>`,
  },
  {
    name: "part",
    type: "nested",
    label: "Part",
    tooltip: "Same label => copied part",
    firstColumn: {
      type: "select",
      key: "label",
      options: ["A", "B", "C", "D", "E"],
    },
    counter: "parts",
    defaults: ["A", "B", "A", "C", "A"].map((label) => ({
      label,
      bars: { B: 5, C: 6 }[label] ?? 4,
      numerator: 4,
      denominator: 4,
    })),
    template: [
      {
        name: "bars",
        type: "int",
        label: "Bars",
        tooltip: "Number of measures in this part",
        default: 4,
        min: 2,
        max: 16,
      },
      {
        name: "numerator",
        type: "int",
        label: "Beats/Bar",
        tooltip: "e.g. 3 (beats) in 3/4 time",
        default: 4,
        min: 1,
        max: 12,
      },
      {
        name: "denominator",
        type: "select",
        label: "Beat Value",
        tooltip: "e.g. 4 (quarter note) in 3/4 time",
        default: 4,
        options: [1, 2, 4, 8, 16, 32],
        labels: [
          "1 (whole note)",
          "2 (half note)",
          "4 (quarter note)",
          "8 (eighth note)",
          "16 (sixteenth note)",
          "32 (thirty-second note)",
        ],
      },
    ],
  },
];