ScoreScript Language wiki

Music objects: scales that fit the player

A music object is a passage defined once and applied by name. The definition claims no bars; every application prints the object's bars in the part that applied it, moved to a tonic and — under fit — slid into that player's range. One definition of a one-octave scale becomes fifteen keys on twelve instruments, each in the register that instrument reads.

Define, then apply

ScoreScript sourceDownload source
scorescript 0.3
score "Two scales, one definition" {
  meter 4/4
  key open

  allstate = {
    4C4 8D E F G A B | 4C 8B A G F E D | 1C ||
  }

  parts {
    tpt F#3-C6
    tbn E2-Bb4
  }

  all written fit {
    @allstate F
    @allstate Bb
  }
}
Generated notationNotation for the preceding Music objects: scales that fit the player example
Canonical spelling
scorescript 0.3
score "Two scales, one definition" {
  meter 4/4
  key open

  allstate = {
    4C4 8D E F G A B | 4C 8B A G F E D | 1C ||
  }

  parts {
    tpt F#3-C6
    tbn E2-Bb4
  }

  all written fit {
    @allstate F
    @allstate Bb
  }
}

allstate = { … } defines the object in C, with its own bar lines and its closing double bar. @allstate F applies it at the tonic F: the object's C becomes F and every other note moves with it. all names every part on the roster; written says the head works on the player's page — the tonic, the range and the printed notes are all what the player reads, and the bars carry the instrument's transposition so the engine never derives them again; fit slides each application by whole octaves to the lowest position on or above the player's floor and refuses one whose top passes the ceiling. The trumpet, held to written F#3–C6, reads F major from F4; the trombone, held to E2–B♭4, reads it from F2. Each application opens with the key it was moved to and a label — F Allstate - 1 octave — derived from the object's name and its compass.

title "Major" on the body's first line is the word the label prints — Bb Major - 2 octaves — where a bare object prints its name (allstate2 → "Allstate2"). A \n or \p line between two applications opens the next object on a new system or page, exactly as the same mark before a measure group does; an All-State sheet is one \n between every scale.

A name is a word: letters, digits, hyphens. A name shaped like a chord symbol (am7, F7) is refused where it is defined, because @am7 would otherwise be ambiguous with the harmony label.

An object may also be moved by an interval (@allstate +P4) or an octave (@allstate F', @allstate F,), and applied inside a single part's body without a head — in which case the part's own range and concert pitch apply.

Choose by what fits

ScoreScript sourceDownload source
scorescript 0.3
score "What fits" {
  meter 4/4
  key open

  one = {
    4C4 8D E F G A B | 4C 8B A G F E D | 1C ||
  }

  two = {
    4C4 8D E F G A B | 4C 8D E F G A B | 4C 8B A G F E D | 4C 8B A G F E D | 1C ||
  }

  parts {
    fl C4-C7
    tbn E2-Bb4
  }

  all written fit {
    first { @two C, @one C }
    fits { @two G, @one G }
    if range contains @two D {
      @two D
      @one D
    } else {
      @one D
    }
  }
}
Generated notationNotation for the preceding Music objects: scales that fit the player example
Canonical spelling
scorescript 0.3
score "What fits" {
  meter 4/4
  key open

  one = {
    4C4 8D E F G A B | 4C 8B A G F E D | 1C ||
  }

  two = {
    4C4 8D E F G A B | 4C 8D E F G A B | 4C 8B A G F E D | 4C 8B A G F E D | 1C ||
  }

  parts {
    fl C4-C7
    tbn E2-Bb4
  }

  all written fit {
    first { @two C, @one C }
    fits { @two G, @one G }
    if range contains @two D {
      @two D
      @one D
    } else {
      @one D
    }
  }
}

Three doors, one rule. first { @two C, @one C } prints the FIRST object that fits — the flute gets two octaves of C, the trombone (whose written E2–B♭4 holds one octave of C but not two) gets one. fits { @two G, @one G } prints EVERY object that fits, in order: the flute prints both, the trombone the one. if range contains @two D { … } else { … } is the same question asked as logic, for a packet whose branches print different things.

The failure rule is strict. An object that does not fit is not cut short and not swapped for a smaller one: it is omitted and named in an error (object.no-fit) with the range in force, so the packet is never quietly wrong. A first or fits with nothing that fits is the same error.

The range in force is the declared contract (the roster line, a range statement, or bounds on the head — ob written C4-C6 { … }), else the catalog's practical band for the instrument, else nothing constrains the application at all. See declared ranges.

Built-in scales

ScoreScript sourceDownload source
scorescript 0.3
score "Built in" {
  meter 4/4
  key open

  parts {
    cl E3-G6
  }

  cl written fit {
    @scale-major G
    @scale-harmonic-minor A
    @scale-dorian D
    @scale-chromatic
  }
}
Generated notationNotation for the preceding Music objects: scales that fit the player example
Canonical spelling
scorescript 0.3
score "Built in" {
  meter 4/4
  key open

  parts {
    cl E3-G6
  }

  cl written fit {
    @scale-major G
    @scale-harmonic-minor A
    @scale-dorian D
    @scale-chromatic
  }
}

The compiler builds in the scales and modes: @scale-major, @scale-minor, @scale-harmonic-minor, @scale-melodic-minor, @scale-dorian, @scale-phrygian, @scale-lydian, @scale-mixolydian, @scale-aeolian, @scale-locrian, @scale-whole-tone, @scale-pentatonic, @scale-minor-pentatonic, @scale-blues, and @scale-chromatic. Each seven-note scale is one octave in the audition pattern — a quarter on the tonic, six eighths, the top tonic, and back — and prints the signature its tonic asks for (a mode prints its parent major's). @scale-chromatic runs from the bottom to the top of the reader's range and back, sharps up and flats down, the last note filling its bar, so it needs a range. scorescript scales prints the whole list with each scale's octave in C; hosts read the same list as the scorescript://catalog/scales resource.

A built-in name cannot be redefined; an authored object of the same name is refused. An unknown @name is object.unknown.

What the expanded score shows

Objects are a desugaring: the analyzer turns every application into ordinary bars before anything downstream sees the score, so a part that applied three scales is a part with three scales' bars, numbered after its last written bar. scorescript format --normalize expand writes that expanded score out, which is how to see — or hand to a tool that knows nothing of objects — exactly what each player was given.