/scala-music

Scala Music is a tool to work with music using the Scala programming language

Primary LanguageScalaMIT LicenseMIT

Scala Music

Scala Music is a library to work with music using the Scala programming language.

Copyright (c) 2020 Vincenzo Moreno Luna. Licensed MIT.

Overview

Scala Music is a library for defining music using functional programming.

Its structure is:

  • core - data structures and DSL for defining music;
  • audio - services for playback and storage;
  • performance - objects and functions for music interpretation ;
  • examples - example musics;

It uses Java MIDI to play musics, and it currently requires to specify the path of the soundfont to use.

Using Scala Music

There isn't a package available in online repositories yet. You have to build a JAR from this project and put it in your project. Once you do it, you can write songs as follows:

import scalamusic.core.Music._

val music: Music[Pitch] =
      c(7, en) :+: enr :+: c(7, en) :+: enr :+: c(7, en) :+: c(7, dqn) :+:
      qnr :+: g(6, qn) :+: f(6, en) :+: enr :+: e(6, qn)

Each note is expressed by its name, its octave, and its duration. For the sake of simplicity, durations are expressed using their initials.

For example:

  • hn - half note
  • dqn - dotted quarter note
  • qn - quarter note
  • den - dotted eighth note
  • en - eighth note

Rests are expressed with duration's naming convention and a final "r".

For example:

  • hnr - half note rest
  • qnr - quarter note rest
  • enr - eighth note rest

You can use ":+:" to define a sequence of notes, and ":=:" to define what has to be played at the same time. You can also wrap a music inside a Modification in order to modify it according to some Control.

See the example folder for more examples.

An alternative way to describe a music is by providing absolute pitches (i.e. numbers) and then convert them to Pitches using the pitch function. This can be useful for algorithmic composition.

To play a music you must first create a service providing the path of the soundfont to use:

val musicService: MusicService = new MusicService(soundfontPath)

You must also declare a starting Context for your music:

val context: Context[NoteWithAttributes] = Context(0, DefaultPlayer, AcousticGrandPiano, Metronome.tickedWholeNote(96), 0, 127, (C, Mode.Major))

The context define things like the starting speed, instrument, the player that will perform the music, and more.

You have to attach a context to each of your musics, defining the parts that make the music score:

val score: List[Part] =
    List(
      (context.copy(cVol = 75, cInst = Flute), fluteMusic),
      (context.copy(cVol = 60, cInst = AcousticGrandPiano), pianoMusic),
      (context.copy(cVol = 70, cInst = AcousticBass), bassMusic)
    )

Now you can play the score as follows:

musicService.play(score)

You can also save the score into a MIDI file:

musicService.write(score, "Score.mid")

At this stage, there isn't support for all the MIDI features. Everything that is not yet supported is silently ignored when playing a song.

Credits

This project is built upon the scala-music-school project, which is the playground I used while following the book The Haskell School Of Music. Scala Music, at this stage, is hence a kind of porting in Scala of the Haskell's library Euterpea. At least as it is described in the book. Here I want to give credit to Paul Hudak and Donya Quick for their work, as I really enjoyed the reading.