Objectif du TP

Construire en OCaml un langage de composition musicale fonctionnel, capable de representer des melodies, les transformer (transposition, retrograde, inversion), les compiler en code ABC jouable, et les visualiser en ASCII art.

Concepts du cours utilises

ConceptApplication musicale
Types algebriques (Seance 2)Notation des notes, octaves, durees
Pattern matching (Seance 1)Interpretation d'une melody
Fonctions d'ordre superieur (Seance 2)Transposition, retrograde, inversion
Fold (Seance 2)Comptage, somme des durees, extraction
Arbres syntaxiques (Seance 3)AST d'une melody, compilation vers ABC
Interpretation (Seance 3)Generer du code ABC jouable

Le format ABC

Syntaxe ABC
  • Lettres A-G : notes de la gamme (C = Do, D = Re, E = Mi...)
  • Lettres minuscules : octave 5 (aigue)
  • Chiffres apres la lettre : duree (2 = double, /2 = demi)
  • z : silence

Partie A — Types et compilation ABC (1h)

Types de donnees

type note = C | D | E | F | G | A | B
type octave = int   (* 4 = central, 5 = aigu, 3 = grave *)
type duree = float  (* 1.0 = noire, 0.5 = croche, 2.0 = blanche *)

type melody =
  | Silence of duree
  | Note    of note * octave * duree
  | Seq     of melody * melody       (* sequence *)
  | Rep     of melody * int          (* repetition *)

Operateurs de construction

(* Sequence : mel1 puis mel2 *)
let (++) m1 m2 = Seq (m1, m2)

(* Silence avant/apres *)
let (|>) m d = Seq (m, Silence d)
let (|>>) d m = Seq (Silence d, m)

(* Repeter un motif n fois *)
let rep n m = Rep (m, n)

(* Octave par defaut = 4 *)
let n note duree = Note (note, 4, duree)

Le compilateur ABC

let rec to_abc = function
  | Silence d ->
    "z" ^ duree_to_string d
  | Note (note, oct, d) ->
    note_to_string note ^ octave_to_string oct ^ duree_to_string d
  | Seq (m1, m2) ->
    to_abc m1 ^ " " ^ to_abc m2
  | Rep (m, n) ->
    let motif = to_abc m in
    String.concat " " (List.init n (fun _ -> motif))

let to_abc_complete titre auteur melody =
  Printf.sprintf "X:1\nT:%s\nC:%s\nM:4/4\nL:1/4\nK:C\n%s"
    titre auteur (to_abc melody)
Verifier

Compilez et copiez la sortie sur abcnotation.com, puis cliquez sur "Play" !

Partie B — Transformations musicales (1.5h)

Transposition

let note_to_semitone = function
  | C -> 0 | D -> 2 | E -> 4 | F -> 5 | G -> 7 | A -> 9 | B -> 11

let rec transpose st = function
  | Silence d       -> Silence d
  | Note (no, o, d) ->
    let (no', o') = transpose_note (no, o) st in
    Note (no', o', d)
  | Seq (m1, m2)    -> Seq (transpose st m1, transpose st m2)
  | Rep (m, n)      -> Rep (transpose st m, n)

Retrograde

let rec retrograde = function
  | Silence d    -> Silence d
  | Note _ as n -> n
  | Seq (m1, m2) -> Seq (retrograde m2, retrograde m1)
  | Rep (m, n)   -> Rep (retrograde m, n)

(* Le retrograde est une involution : *)
(* retrograde (retrograde m) = m *)

Inversion et augmentation

(* Inversion autour d'un centre *)
let rec invert centre = function
  | Silence d       -> Silence d
  | Note (no, o, d) ->
    let s_diff = note_to_semitone centre - note_to_semitone no in
    let new_s = (note_to_semitone centre + s_diff) mod 12 in
    Note (semitone_to_note new_s, o, d)
  | Seq (m1, m2)    -> Seq (invert centre m1, invert centre m2)
  | Rep (m, n)      -> Rep (invert centre m, n)

(* Augmentation : doubler la duree *)
let rec augmenter facteur = function
  | Silence d       -> Silence (d *. facteur)
  | Note (no, o, d) -> Note (no, o, d *. facteur)
  | Seq (m1, m2)    -> Seq (augmenter facteur m1, augmenter facteur m2)
  | Rep (m, n)      -> Rep (augmenter facteur m, n)

Partie C — Visualisation ASCII (0.5h)

(* Visualisation ASCII (piano-roll en texte) *)
let ascii_art melody =
  let pts = positions 0.0 melody in
  (* ... construit une chaine avec des '*' aux bonnes positions ... *)

(* Conversion texte-musique : chaque lettre = une note *)
let text_to_melody texte =
  (* ... convertit "bonjour" en melody ... *)

Partie D — Composons ! (1h)

Mission Composition
  1. Creez un theme de 4 a 8 notes.
  2. Generez 3 variations : transposition (+5 demi-tons), retrograde, inversion.
  3. Assemblez votre theme et ses variations.
  4. Jouez : exportez en ABC et ecoutez sur abcnotation.com.
  5. Visualisez : affichez l'ASCII art.
(* Twinkle Twinkle Little Star *)
let twinkle =
  n C 1.0 ++ n C 1.0 ++ n G 1.0 ++ n G 1.0 ++
  n A 1.0 ++ n A 1.0 ++ n G 2.0 ++
  n F 1.0 ++ n F 1.0 ++ n E 1.0 ++ n E 1.0 ++
  n D 1.0 ++ n D 1.0 ++ n C 2.0

(* Mes variations *)
let var_transpose = transpose 5 mon_theme
let var_retro     = retrograde mon_theme
let var_invert    = invert E mon_theme
Rendu

Envoyez votre fichier music.ml et un fichier ma_composition.abc avec votre meilleur morceau.