Vai al contenuto principale
Ricetta numero 166

Ricettario · Capitolo 7 · Figure e immagini

Corali numerati in un metodo di armonia a due colonne

Corali a quattro voci scritti in Humdrum **kern diventano risorse partitura di tipo esempio: numerate Esempio 4.1, citate con :ref e mobili come le figure.

pp. 62–63 · 2–3 di 3

  • Esempio in inglese: non c’è ancora un’edizione italiana
  • Formato 210 × 280 mm
  • 2 colonne, Intercolonna di 7 mm
  • Crimson Pro 10,8/14,2
  • Fira Sans Condensed
  • Playfair Display
  • 3 pagine
  • Livello
  • Postext 1.54.0
  • Impaginato in 75 ms
  • 175 righe di codice

In breve

Un capitolo sulle cadenze di un libro di armonia per il conservatorio, su due colonne. I cinque esempi musicali sono scritti come testo, incisi come vere partiture, numerati come le figure e messi vicino al paragrafo che li cita.

Che cosa comporrai

Il capitolo 4 di Four-Part Harmony, un metodo per i primi anni di conservatorio, su una pagina di 210 × 280 mm in due colonne di Crimson Pro. La lezione tratta delle cadenze, e i suoi cinque esempi sono corali a quattro voci su due pentagrammi, con i gradi in numeri romani sotto il basso: le cinque cadenze di sol maggiore, tre versi di Nun danket alle Gott e il Salmo 134 di Ginevra (l’Old Hundredth) completo. Ognuno porta un numero, da Example 4.1 a 4.5 (Ejemplo nell’edizione spagnola), una didascalia nel carattere delle etichette con l’etichetta color vinaccia, e sta in testa o al piede della colonna che segue il paragrafo che lo cita; il salmo intero corre sulle due colonne in testa a pagina 63. Le armonizzazioni sono state scritte per questo metodo e controllate per quinte e ottave parallele, distanze tra le voci e risoluzione della sensibile.

Questa ricetta risponde a

  • Come numero gli esempi musicali e li faccio flottare come figure in un libro a due colonne?
  • Come aggiungo una figura con didascalia numerata e la cito nel testo («vedi Fig. 3.2»)?
  • Come decido dove va una figura: in testa alla pagina, su entrambe le colonne, esattamente qui o nel margine?

La risposta breve

script.js · righe 26–41nel codice completo
// In the Markdown, :ref{id="ex-old-hundredth" style="full"} prints 'Example 4.4' ('Ejemplo
// 4.4' in Spanish) and ::resource{id="…"} anchors the float after the paragraph that cites it.
const example = (id, source, placement, styleId) => {
  const [caption, note, altText] = CAPTIONS[id];
  return { id, typeId: 'example', kind: 'score', caption, note, altText, placement,
    score: { format: 'humdrum', source, styleId }, createdAt: 0, updatedAt: 0 };
};
// The **kern sources are in #region art-scores; captions in content.captions.<lang>.md.
const resources = () => [
  example('ex-cadences', CADENCES, { position: 'bottom' }, 'column'),
  example('ex-nun-danket', NUN_DANKET, { position: 'top' }, 'column'),
  example('ex-nun-danket-3', NUN_DANKET_3, { position: 'auto' }, 'column'),
  // Across both columns in the document's own score style: the whole tune in two systems.
  example('ex-old-hundredth', OLD_HUNDREDTH, { position: 'top', span: 'page' }),
  example('ex-deceptive', DECEPTIVE, { position: 'auto', span: 'page' }),
];

Ingredienti

Tipo
Crimson Pro, Playfair Display, Fira Sans Condensed (SIL OFL 1.1)
Risorse
Nessuna: ogni immagine è disegnata nel codice

Preparazione

#1 · Scrivi ogni corale in Humdrum **kern

script.js · righe 263–273nel codice completo
// Each example lists its spines as Humdrum wants them, lowest first: the bass staff split into
// tenor and bass, the **harm spine (printed under that staff), the treble staff split into
// soprano and alto. Writing them with spaces keeps the pen free of tab characters.
const kern = (meter, body) => [
  '**kern **harm **kern', '*clefF4 * *clefG2', '*k[f#] * *k[f#]', `*M${meter} * *M${meter}`,
  '*^ * *^', ...body.trim().split('\n'), '== == == == ==', '*- *- *- *- *-',
].map((row) => row.trim().split(/ +/)
  // Spanish harmony books write every degree in capitals: vi is VI, iib is IIb.
  .map((cell) => (LANG === 'es' && /^(?:i{1,3}|iv|vi{0,2})[bc7]?$/.test(cell)
    ? cell.replace(/^[iv]+/, (degree) => degree.toUpperCase()) : cell))
  .join('\t')).join('\n');

Humdrum scrive le voci in colonne separate da tabulazioni, dalla più grave alla più acuta. Ogni pentagramma è una colonna (spine) divisa in due con *^: tenore e basso in chiave di basso, soprano e contralto in chiave di violino, così l’incisore mette due voci per pentagramma con i gambi separati (la voce di sinistra in su, quella di destra in giù). Una colonna **harm dopo il pentagramma del basso stampa i gradi sotto di esso; Ib è il primo rivolto, Ic la quarta e sesta. Lo script scrive le colonne con spazi e le trasforma in tabulazioni, così nessun editor può rovinare il file, e l’edizione spagnola riceve i gradi in maiuscolo (VI, IIb), come li scrivono i manuali di armonia spagnoli.

#2 · Fai di ogni esempio una risorsa di tipo esempio

La risposta breve costruisce le cinque risorse. typeId: 'example' prende il tipo Esempio integrato, che il motore aggiunge ai tipi di risorsa del libro quando una risorsa lo usa, con il nome nella lingua del documento (locale: 'es' dà Ejemplo) e numerato per capitolo: il primo esempio del capitolo 4 è il 4.1. Una risorsa partitura resta intera e si sposta come una figura: position: 'top' o 'bottom' prende la testa o il piede della colonna successiva con spazio dopo la citazione, e span: 'page' stende l’Old Hundredth sulle due colonne. Didascalie, crediti e testi alternativi vengono da un secondo file Markdown per edizione.

#3 · Dai agli esempi di colonna un pentagramma più piccolo

script.js · righe 45–53nel codice completo
const scoreStyle = {
  staffSize: mm(5.4), musicFont: 'Bravura', barNumbers: 'system', color: col('ink'),
  textFont: TEXT, // the Roman numerals under the bass, in the text face
  marginTop: pt(4), marginBottom: pt(2),
};
const scoreStyles = [ // rastral 4.6 mm: four staves of a chorale fit a column in two systems
  { id: 'column', name: t({ en: 'Column examples', es: 'Ejemplos de columna' }),
    staffSize: mm(4.6), barNumbers: 'none', spacing: 0.8 },
];

I due corali a tutta pagina usano lo scoreStyle del documento, con pentagrammi di 5,4 mm e numeri di battuta all’inizio di ogni sistema. Gli esempi di colonna scelgono lo stile con nome column: pentagrammi di 4,6 mm, niente numeri di battuta e spaziatura 0,8, che tiene le cinque battute dell’esempio 4.2 in un solo sistema invece di lasciare l’ultima da sola in un secondo.

#4 · Avvia l’incisore prima della composizione

script.js · righe 398–404nel codice completo
await initMusicEngine(); // until it runs, every score is laid out as a grey box
const continuation = { pageNumbering: { startAt: 61 }, // odd: the opener is a recto
  headings: { h1: 3, h2: 0, h3: 0, h4: 0, h5: 0, h6: 0 } }; // the next # is chapter 4
const doc = await buildDocumentWithFonts({ markdown, resources: resources(), continuation },
  config, kitFonts(FONTS));
showPages(doc, { title: t({ en: 'Numbered chorale examples in a harmony method',
  es: 'Corales numerados en un método de armonía' }) });

initMusicEngine() carica Verovio, l’incisore, dal pacchetto; finché non parte, ogni partitura viene impaginata come un riquadro grigio. La continuation fa di questo il capitolo 4 di un libro più lungo, così gli esempi vanno da 4.1 a 4.5 e i numeri di pagina partono da 61, su una pagina dispari.

#5 · Apri il capitolo sulle due colonne

script.js · righe 57–77nel codice completo
const label = { fontFamily: LABEL, fontWeight: 600, textTransform: 'uppercase' };
const opener = {
  enabled: true, minHeight: mm(46),
  slot: { elements: [
      { kind: 'text', id: 'kicker', content: '{attr.kicker}', ...label, fontSize: pt(9),
        letterSpacing: pt(1.8), color: col('accent'), align: 'left',
        placement: { anchor: { to: 'container', edge: 'top-left' },
          offset: { x: mm(0), y: mm(6) } } },
      { kind: 'text', id: 'title', content: '{titleText}', fontFamily: DISPLAY, fontSize: pt(36),
        lineHeight: 1.05, fontWeight: 400, color: col('ink'), align: 'left',
        placement: { anchor: { to: '#kicker', edge: 'below' }, offset: { x: mm(0), y: mm(3) },
          size: { width: mm(150), height: 'auto' } } },
      { kind: 'text', id: 'deck', content: '{attr.deck}', fontFamily: TEXT, fontSize: pt(13),
        lineHeight: 1.25, italic: true, color: col('muted'), align: 'left',
        placement: { anchor: { to: '#title', edge: 'below' }, offset: { x: mm(0), y: mm(3) },
          size: { width: mm(120), height: 'auto' } } },
      { kind: 'rule', id: 'rule', direction: 'horizontal', thickness: pt(1.5), color: col('accent'),
        placement: { anchor: { to: '#deck', edge: 'below' }, offset: { x: mm(0), y: mm(5) },
          size: { width: mm(18) } } },
  ] },
};

L’apertura occupa le due colonne (span: 'page' sul titolo di primo livello) e prende occhiello e sommario dagli attributi del titolo. minHeight abbassa il testo di 46 mm, così le due colonne cominciano sulla stessa riga sotto il filetto.

La ricetta completa

Sandbox
// ═══ Postext Cookbook · Nº 166 · Numbered chorale examples in a harmony method ══
// https://postext.dev/en/cookbook/conservatory-method-chorales
// Code: MIT · Text and four-part settings: original (CC BY 4.0) · Melodies: public domain
// Fonts: Crimson Pro, Playfair Display, Fira Sans Condensed (OFL 1.1) · Needs postext ≥ 1.54.0
import {
  buildDocumentWithFonts, renderPageToCanvas, defaultResourceTypes, initMusicEngine,
} from 'https://esm.sh/postext';

const LANG = 'en'; // @lang: the language of the sample document ('en' | 'es')
const RECIPE = 'conservatory-method-chorales';

// ─── 1 · Design ─────────────────────────────────────────────────────────────
// A claret accent on warm paper tones, every colour linked by id.
const palette = { ink: '#1f1a17', accent: '#7a2531', tint: '#f5eee6', rule: '#cdbfb2',
  muted: '#6a5f57', paper: '#ffffff' };
const col = (id) => ({ hex: palette[id], model: 'hex', paletteId: id });
const colorPalette = [
  ...Object.entries(palette).map(([id, hex]) => ({ id, name: id, value: { hex, model: 'hex' } })),
  { id: 'main-color', name: 'accent (defaults)', value: { hex: palette.accent, model: 'hex' } },
];
const [TEXT, DISPLAY, LABEL] = ['Crimson Pro', 'Playfair Display', 'Fira Sans Condensed'];
const OUTER = 16; // outer margin in mm: running heads and folios align to it
const LEAD = 14.2; // body leading in pt

// #region answer: score resources typed 'example', floated and numbered like figures
// In the Markdown, :ref{id="ex-old-hundredth" style="full"} prints 'Example 4.4' ('Ejemplo
// 4.4' in Spanish) and ::resource{id="…"} anchors the float after the paragraph that cites it.
const example = (id, source, placement, styleId) => {
  const [caption, note, altText] = CAPTIONS[id];
  return { id, typeId: 'example', kind: 'score', caption, note, altText, placement,
    score: { format: 'humdrum', source, styleId }, createdAt: 0, updatedAt: 0 };
};
// The **kern sources are in #region art-scores; captions in content.captions.<lang>.md.
const resources = () => [
  example('ex-cadences', CADENCES, { position: 'bottom' }, 'column'),
  example('ex-nun-danket', NUN_DANKET, { position: 'top' }, 'column'),
  example('ex-nun-danket-3', NUN_DANKET_3, { position: 'auto' }, 'column'),
  // Across both columns in the document's own score style: the whole tune in two systems.
  example('ex-old-hundredth', OLD_HUNDREDTH, { position: 'top', span: 'page' }),
  example('ex-deceptive', DECEPTIVE, { position: 'auto', span: 'page' }),
];
// #endregion

// #region scores: one score style for the page-wide chorale, a smaller one for the columns
const scoreStyle = {
  staffSize: mm(5.4), musicFont: 'Bravura', barNumbers: 'system', color: col('ink'),
  textFont: TEXT, // the Roman numerals under the bass, in the text face
  marginTop: pt(4), marginBottom: pt(2),

Lo script.js composto funziona così com’è: incollalo nello script modulo di qualsiasi pagina, oppure apri la ricetta su CodePen. Cartella della ricetta su GitHub ↗ (si apre in una nuova scheda)

Varianti

#Metti un esempio senza numero nel testo

Un blocco di codice tiene nel testo una partitura che il testo non cita, come una formula in display: niente numero né didascalia.

- ::resource{id="ex-cadences"}
+ ```humdrum {style="column" alt="Le cinque cadenze in sol maggiore"}
+ **kern	**harm	**kern
+ …
+ ```

#Chiamali esempi musicali

Definisci un tipo tuo per un altro nome e fai puntare typeId su di esso.

- resourceTypes: defaultResourceTypes(LANG),
+ resourceTypes: [...defaultResourceTypes(LANG), { id: 'musex', name: 'Esempio musicale',
+   shortLabel: 'Es. mus.', captionPrefix: 'Esempio musicale', numberingTemplate: '{h1}.{n}',
+   resetOn: 'h1', counterFormat: 'decimal' }],

Errori frequenti

Errore frequente

::resource{id="…"} accetta solo virgolette doppie

Un inserimento a blocco viene riconosciuto solo come ::resource{id="…"} con virgolette doppie; qualsiasi altra forma resta nel testo come riga visibile. Figure proprio qui →

  • Una risorsa partitura non si spezza mai tra colonne o pagine. Tieni gli esempi mobili a poche battute e metti un brano più lungo in un blocco di codice, che si spezza tra i sistemi.
  • L’incisore riempie ogni sistema fino alla larghezza del suo spazio, e l’ultimo conserva la sua larghezza naturale. Se un esempio lascia una battuta sola in un secondo sistema, abbassa lo spacing o la grandezza del pentagramma del suo stile.

Crediti

Testo
Font
Crimson Pro (SIL OFL 1.1) · Playfair Display (SIL OFL 1.1) · Fira Sans Condensed (SIL OFL 1.1)
Sandbox