Документация Engee

Printing into a Score using MuseScore

Страница в процессе перевода.

MuseScore is a wonderful and open source professional music score editor with a huge amount of capabilities. MusicManipulations provides a convenient interface that can instantly print any Notes or MIDIFile structure via MuseScore.

# MusicVisualizations.musescoreFunction

musescore(file, notes | midi; keywords...)

Use the open source software "MuseScore" to create a score and save the given notes (or an entire midi file) to file, which can be either a .pdf or a .png.If given a .png the actual file name will end with -1, -2 etc. for each page of the score.

MuseScore must be accessible from the command line for this to work (add the path to MuseScore.exe to your PATH environment variable (ask Google)).

The keyword display = true will also display the created file. Keyword rmmidi = true deletes the MIDI file that has to be created inbetween score convertion (use false to keep it). MuseScore is run by default with commands -n -T 10 -r 1200, but you can change the keyword c to be whatever command (enclosed in backticks) you want, see the command line options of MuseScore for details.

!!! tip "Quantize your notes!" Keep in mind that the score creation capabilities of MuseScore rely upon having well-defined notes. This means that you should use the function quantize to quantize both the position and duration of your notes!

Creating a Score out of some Notes

using FileIO # used for loading the midi files
using MusicManipulations # tools for manipulating notes in Julia
using MusicVisualizations # tools for visualizing these notes

We first load the test MIDI file "Doxy". The third track has the notes of the Bass:

midi = load(testmidi()) # read the "test" Doxy MIDI recording.
bass = getnotes(midi, 3)
basstrim = bass[1:50]
50 Notes with tpq=960
 Note A♯2 | vel = 95  | pos = 7680, dur = 690
 Note A♯2 | vel = 71  | pos = 9280, dur = 308
 Note G♯2 | vel = 52  | pos = 9600, dur = 668
 Note G♯2 | vel = 58  | pos = 11200, dur = 338
 Note G2  | vel = 71  | pos = 11520, dur = 701
 Note G♯2 | vel = 83  | pos = 13120, dur = 281
 Note G2  | vel = 73  | pos = 13440, dur = 855
  ⋮
 Note F2  | vel = 75  | pos = 53760, dur = 885
 Note A♯2 | vel = 80  | pos = 54720, dur = 930
 Note G♯2 | vel = 97  | pos = 55680, dur = 889
 Note D♯2 | vel = 80  | pos = 56640, dur = 930
 Note G2  | vel = 80  | pos = 57600, dur = 975
 Note B1  | vel = 88  | pos = 58560, dur = 952
 Note D2  | vel = 83  | pos = 59520, dur = 941

Because the notes of the Bass are already quantized we can already print them into a staff using MuseScore:

musescore("bass.png", basstrim)
Bass score

Amazingly MuseScore deduces automatically the clef and even the key of the piece!

Creating a full Score out of a MIDI file

You can also pass a full MIDI file to musescore.

piano = getnotes(midi, 4)
533 Notes with tpq=960
 Note F4  | vel = 69  | pos = 7427, dur = 181
 Note A♯4 | vel = 85  | pos = 7760, dur = 450
 Note D5  | vel = 91  | pos = 8319, dur = 356
 Note D4  | vel = 88  | pos = 8323, dur = 314
 Note G♯3 | vel = 88  | pos = 8327, dur = 358
 Note A♯4 | vel = 76  | pos = 8694, dur = 575
 Note G4  | vel = 66  | pos = 9281, dur = 273
  ⋮
 Note D5  | vel = 91  | pos = 189794, dur = 227
 Note D5  | vel = 106 | pos = 190725, dur = 610
 Note A4  | vel = 99  | pos = 190729, dur = 604
 Note D♯4 | vel = 101 | pos = 190742, dur = 720
 Note A3  | vel = 106 | pos = 190746, dur = 833
 Note D4  | vel = 106 | pos = 190746, dur = 837
 Note G4  | vel = 109 | pos = 190748, dur = 590

However, MuseScore has decent results only with quantized notes. Let’s quantize on a triplet grid using quantize.

qpiano = quantize(piano, [0, 1//3, 2//3, 1])
533 Notes with tpq=960
 Note F4  | vel = 69  | pos = 7360, dur = 320
 Note A♯4 | vel = 85  | pos = 7680, dur = 320
 Note D5  | vel = 91  | pos = 8320, dur = 320
 Note D4  | vel = 88  | pos = 8320, dur = 320
 Note G♯3 | vel = 88  | pos = 8320, dur = 320
 Note A♯4 | vel = 76  | pos = 8640, dur = 640
 Note G4  | vel = 66  | pos = 9280, dur = 320
  ⋮
 Note D5  | vel = 91  | pos = 189760, dur = 320
 Note D5  | vel = 106 | pos = 190720, dur = 640
 Note A4  | vel = 99  | pos = 190720, dur = 640
 Note D♯4 | vel = 101 | pos = 190720, dur = 640
 Note A3  | vel = 106 | pos = 190720, dur = 960
 Note D4  | vel = 106 | pos = 190720, dur = 960
 Note G4  | vel = 109 | pos = 190720, dur = 640

and save both tracks into a midi file:

ptrack = MIDITrack()
addnotes!(ptrack, qpiano)
addtrackname!(ptrack, "Doxy")
smidi = MIDIFile(1, 960, [midi.tracks[3], ptrack])
MIDIFile (format=1, tpq=960) with tracks:
 Bass
 Doxy

and then save the full thing as .pdf or .png:

musescore("doxy.pdf", smidi)

The first page looks like this: Full score

When given multiple tracks MuseScore displays the name of the track (trackname), as well as the instrument it automatically chose to represent it.

Drum Notation

It is also possible to use MuseScore to create drum notation. The process for this is almost identical with the above, with two differences. Firstly, the pitch of each note must have a specific value that maps the the actual drum instrument, and secondly all notes must be written on channel 9.

The function DrumNote simplifies this process:

# MIDI.DrumNoteFunction

DrumNote(pitch, position, duration = 960; velocity = 100)

Shorthand constructor for a Note that is always on channel 9. It is possible to specify pitch as a String (e.g. "Acoustic Snare"), which will be converted to actual pitch using DRUMKEY.

And this is the drum key we use:

DRUMKEY
Dict{String, String} with 15 entries:
  "Crash Cymbal 2"     => "A3"
  "Closed Hi-Hat"      => "F#2"
  "Crash Cymbal 1"     => "C#3"
  "Acoustic Bass Drum" => "B1"
  "Acoustic Snare"     => "D2"
  "Tambourine"         => "F#3"
  "Ride Bell"          => "F3"
  "Side Stick"         => "C#2"
  "Low-Mid Tom"        => "B2"
  "Pedal Hi-Hat"       => "G#2"
  "Ride Cymbal"        => "D#3"
  "Open Hi-Hat"        => "A#2"
  "Cowbell"            => "G#3"
  "High Floor Tom"     => "G2"
  "Low Floor Tom"      => "F2"

Here is an example where we create the "basic rock groove" in drum notation:

tpq = 960; e = 960÷2 # eigth note = quarter note ÷ 2
bass = "Acoustic Bass Drum"
snare = "Acoustic Snare"
hihat = "Closed Hi-Hat"
"Closed Hi-Hat"

We make the 8 hihat notes

rock = [DrumNote(hihat, i*e, e) for i in 0:7]
8-element Vector{Note}:
 Note F♯2 | vel = 100 | pos = 0, dur = 480 | channel 9
 Note F♯2 | vel = 100 | pos = 480, dur = 480 | channel 9
 Note F♯2 | vel = 100 | pos = 960, dur = 480 | channel 9
 Note F♯2 | vel = 100 | pos = 1440, dur = 480 | channel 9
 Note F♯2 | vel = 100 | pos = 1920, dur = 480 | channel 9
 Note F♯2 | vel = 100 | pos = 2400, dur = 480 | channel 9
 Note F♯2 | vel = 100 | pos = 2880, dur = 480 | channel 9
 Note F♯2 | vel = 100 | pos = 3360, dur = 480 | channel 9

add 2 bass drums

push!(rock, DrumNote(bass, 0, e), DrumNote(bass, 4e, e))
10-element Vector{Note}:
 Note F♯2 | vel = 100 | pos = 0, dur = 480 | channel 9
 Note F♯2 | vel = 100 | pos = 480, dur = 480 | channel 9
 Note F♯2 | vel = 100 | pos = 960, dur = 480 | channel 9
 Note F♯2 | vel = 100 | pos = 1440, dur = 480 | channel 9
 Note F♯2 | vel = 100 | pos = 1920, dur = 480 | channel 9
 Note F♯2 | vel = 100 | pos = 2400, dur = 480 | channel 9
 Note F♯2 | vel = 100 | pos = 2880, dur = 480 | channel 9
 Note F♯2 | vel = 100 | pos = 3360, dur = 480 | channel 9
 Note B1  | vel = 100 | pos = 0, dur = 480 | channel 9
 Note B1  | vel = 100 | pos = 1920, dur = 480 | channel 9

and add 2 snare drums

push!(rock, DrumNote(snare, 2e, e), DrumNote(snare, 6e, e))
12-element Vector{Note}:
 Note F♯2 | vel = 100 | pos = 0, dur = 480 | channel 9
 Note F♯2 | vel = 100 | pos = 480, dur = 480 | channel 9
 Note F♯2 | vel = 100 | pos = 960, dur = 480 | channel 9
 Note F♯2 | vel = 100 | pos = 1440, dur = 480 | channel 9
 Note F♯2 | vel = 100 | pos = 1920, dur = 480 | channel 9
 Note F♯2 | vel = 100 | pos = 2400, dur = 480 | channel 9
 Note F♯2 | vel = 100 | pos = 2880, dur = 480 | channel 9
 Note F♯2 | vel = 100 | pos = 3360, dur = 480 | channel 9
 Note B1  | vel = 100 | pos = 0, dur = 480 | channel 9
 Note B1  | vel = 100 | pos = 1920, dur = 480 | channel 9
 Note D2  | vel = 100 | pos = 960, dur = 480 | channel 9
 Note D2  | vel = 100 | pos = 2880, dur = 480 | channel 9

and finally bundle the notes with the ticks per quarter note

rock = Notes(rock, tpq)
12 Notes with tpq=960
 Note F♯2 | vel = 100 | pos = 0, dur = 480 | channel 9
 Note F♯2 | vel = 100 | pos = 480, dur = 480 | channel 9
 Note F♯2 | vel = 100 | pos = 960, dur = 480 | channel 9
 Note F♯2 | vel = 100 | pos = 1440, dur = 480 | channel 9
 Note F♯2 | vel = 100 | pos = 1920, dur = 480 | channel 9
 Note F♯2 | vel = 100 | pos = 2400, dur = 480 | channel 9
 Note F♯2 | vel = 100 | pos = 2880, dur = 480 | channel 9
 Note F♯2 | vel = 100 | pos = 3360, dur = 480 | channel 9
 Note B1  | vel = 100 | pos = 0, dur = 480 | channel 9
 Note B1  | vel = 100 | pos = 1920, dur = 480 | channel 9
 Note D2  | vel = 100 | pos = 960, dur = 480 | channel 9
 Note D2  | vel = 100 | pos = 2880, dur = 480 | channel 9

and then call MuseScore to actually make the score

musescore("rock.png", rock)
rock 1