Notes and Chords#
[1]:
from manimusic import *
config.media_embed = True; config.media_width = "100%"
_RV = "-v WARNING -qm --progress_bar None --disable_caching Example"
_RI = "-v WARNING -s --progress_bar None --disable_caching Example"
_RV_mid = "-v WARNING -qm -r 1600,400 --progress_bar None --disable_caching Example"
_RI_mid = "-v WARNING -s -r 1600,400 --progress_bar None --disable_caching Example"
Manim Community v0.17.3
Notes#
Warning
Optional elements can be in any order, but the first two required elements must be in the specified order.
* Fist element [required] : "m" Minim or "c" Crotchet or "s" Semibreve
* Second element [required] : C,D,E,F,G,A,B
* Reference [default=0] : Positive or negative number
* Alteration [optional] : #,b,n
* Stem [default=d] : x,d,u
* Body shifted [optional] : r, l
* Note shifted [optional] : R, L <- Shift all note
* Alteration shifted [optional] : a, h, H, _
[2]:
class Example(Scene):
def construct(self):
staff = Staff(clefs="gfc", width=10)
pt = staff.partition
partitions = staff.get_ticks()
n_g = Note(staff, "mC#x", 6/pt, 0).set_color(RED)
n_f = Note(staff, "cCbu", 6/pt, 1).set_color(PURPLE)
n_c = Note(staff, "sCn", 6/pt, 2).set_color(TEAL)
self.add(staff, n_g, n_f, n_c, partitions)
%manim $_RI

Reference#
[3]:
class Example(Scene):
def construct(self):
staff = Staff(clefs="g", width=10)
pt = staff.partition
notes = VGroup(
Note(staff, "mC", 6 /pt).set_color(RED),
Note(staff, "cC1", 10/pt).set_color(TEAL),
Note(staff, "sC2", 14/pt).set_color(TEAL),
Note(staff, "sB-1", 18/pt).set_color(YELLOW),
)
self.add(staff, notes)
%manim $_RI_mid

Stems#
Note
The Semibreve note does not have a stem
, even if we explicitly define it.
[4]:
class Example(Scene):
def construct(self):
staff = Staff(clefs="g", width=10)
pt = staff.partition
notes = VGroup(
Note(staff, "mC", 6 /pt).set_color(RED),
Note(staff, "mC1u", 10/pt).set_color(RED),
Note(staff, "cC2u", 14/pt).set_color(TEAL),
Note(staff, "cB-1x", 18/pt).set_color(TEAL), # "x" to remove stem
Note(staff, "mA-1x", 22/pt).set_color(YELLOW),
Note(staff, "sBu", 26/pt).set_color(YELLOW), # <- "u" does nothing to Semibreve
)
self.add(staff, notes)
%manim $_RI_mid

Alterations#
Warning
The double sharp and double flat symbols were not included because I never used them. This library is geared towards Harmony and Counterpoint lectures, not writing sheet music. In case you need it, you can perfectly import the symbol with an SVG, change the scale and position using the methods you saw in Staffs
chapter.
[5]:
class Example(Scene):
def construct(self):
staff = Staff(clefs="g", width=10)
pt = staff.partition
notes = VGroup(
Note(staff, "mC", 6/pt).set_color(RED),
Note(staff, "mC1u#", 10/pt).set_color(RED),
Note(staff, "cCb2u", 14/pt).set_color(TEAL),
Note(staff, "cBn-1x", 18/pt).set_color(TEAL),
# Chords:
Note(staff, "sB-1br" , 22/pt).set_color(YELLOW),
Note(staff, "sA-1nh", 22/pt).set_color(YELLOW),
)
self.add(staff, notes)
%manim $_RI_mid

Note parts#
[6]:
class Example(Scene):
def construct(self):
staff = Staff(width=2).scale(1.4).shift(UP * 0.2)
note = Note(staff, "cA-1#u", 0.5)
note.stem.set_color(PURPLE)
note.body.set_color(RED)
note.alteration.set_color(TEAL)
note.additional_lines.set_color(YELLOW)
self.add(staff, note)
%manim $_RI_mid

Note
You can use the Note.get_parts(attr1, attr2, ...)
method to get multiple parts of the note, if an attribute doesn’t exist it will be ignored.
[7]:
class Example(Scene):
def construct(self):
staff = Staff(width=2).scale(1.4).shift(UP * 0.2)
note = Note(staff, "cA-1#u", 0.5)
note.get_parts("body", "alteration").set_color(RED)
note.get_parts("stem", "additional_lines", "random_attr").set_color(TEAL)
self.add(staff, note)
%manim $_RI_mid

Additional lines#
Note
The additional lines are inside Staff
, not Note
, but they can also be accessed through Note
as an attribute.
[8]:
class Example(Scene):
def construct(self):
staff = Staff(clefs="gf", width=2)
note1 = Note(staff, "cA-1#u", 0.5, 0)
note2 = Note(staff, "cE1#u", 0.8, 1)
note1.additional_lines.set_color(RED)
staff.additional_lines[1][0].set_color(YELLOW)
staff.additional_lines[1][1].set_color(TEAL)
self.add(staff) # Note that we are not adding the notes
%manim $_RI_mid

Melodies and Chords#
Note
Points .
must be at the end.
[9]:
class Example(Scene):
def construct(self):
staff = Staff(clefs="gfc", width=10, bars=[*range(6,13)])
staff.bars_group.fade(0.6)
partitions = staff.get_ticks().set_color(YELLOW)
# staff, note1|note2|... ,prop,line
chord_line = ChordLine(staff, "C|Eb|G|Bbla|C1#h", 0.2, 0, merge_stems=True).set_color(RED)
chord_stems = ChordLine(staff, "Ed|Gu", 0.4, 0, glob="c").set_color(PURPLE)
melody = Melody(staff, "C|Eb|G|Bb |C1 ", 0.2, 1, increment=0.15, glob="cu").set_color(TEAL)
melody2 = Melody(staff, "C|Eb.|G...|Bb ", 0.2, 2, increment=1/30, glob="s").set_color(PINK)
# chord_line.stem.set_color(ORANGE).scale([1,0.8,1], about_edge=UP)
self.add(staff, partitions, chord_line, chord_stems, melody, melody2)
%manim $_RI

Note
If you have a Staff
with only one line you can omit it just like with notes.
[10]:
class Example(Scene):
def construct(self):
staff = Staff(width=3).scale(1.4)
chord_line = ChordLine(staff, "Cb|Eba|GbH_|Bblh|C1#h", 0.6, glob="m")
chord_line[0].set_color(RED)
chord_line[1].set_color(TEAL)
chord_line[2].set_color(YELLOW)
chord_line[3].set_color(ORANGE)
chord_line[4].set_color(PINK)
self.add(staff, chord_line)
%manim $_RI_mid

Additional lines#
Note
In the ChordLines
there can be several additional_lines
at the same time, so the lines that are unnecessary will be filtered. In the same way as the Note
, these lines do not belong to ChordLine
, but to Staff
.
[11]:
class Example(Scene):
def construct(self):
staff = Staff(clefs="g", width=12, height=0.8)
# 0|1 |2 |3 |4 |5 <-- Array order
chord = ChordLine(staff, "E|D-1|F-1|B-1|C2|A1", 0.3).set_color(RED)
chord.additional_lines.set_color(TEAL) # access with Chord
chord[1].set_color(BLUE)
chord[1].additional_lines.shift(LEFT) # access with Note (Down)
chord[4].set_color(BLUE)
chord[4].additional_lines.shift(RIGHT) # access with Note (Up)
chord_lines_up = ChordLine(staff, "C2|E2", 0.5).set_color(ORANGE)
chord_lines_up.additional_lines.set_color(PINK)
chord_lines_down = ChordLine(staff, "A-1|F-1", 0.8).set_color(YELLOW)
chord_lines_down.additional_lines.set_color(BLUE)
self.add(staff, chord, chord_lines_up, chord_lines_down)
%manim $_RI_mid

Note
So that you don’t get confused when selecting notes of a chord, define the chords in an ascending or descending way, so identifying the index of each note will be easier.
[12]:
class Example(Scene):
def construct(self):
staff = Staff(clefs="g", width=3, height=0.8).scale(2).shift(UP)
chord = ChordLine(staff, "D-1l|E-1|A-1l|B-1|C2l|D2", 0.4, merge_stems=True)
# chord.stem.scale([1,0.9,1],about_edge=UP)
self.add(staff, chord)
%manim $_RI

Multi-Chords#
[13]:
class Example(Scene):
def construct(self):
staff = Staff(clefs="gf", width=12, height=0.7)
multi_chords = VGroup(
MultiChord(staff, "m|Cd,G#u|A-1d#,C1u", 0.2, [1, 0]), # order matters [0, 1] or [1, 0]
MultiChord(staff, "s|C,G", 0.3, [0]) .set_color(RED),
MultiChord(staff, "c|C,G", 0.3, [1], glob="x").set_color(TEAL),
MultiChord(staff, "m|C,G|A-1b,C2", 0.5, [1, 0]) .set_color(YELLOW),
MultiChord(staff, "m|C,G|A-1b,C1", 0.7, [1, 0], glob="u#").set_color(PURPLE),
MultiChord(staff, "m|C,G|A-1b,C1d", 0.9, [1, 0], glob="u") .set_color(GOLD),
)
multi_chords[3].additional_lines.shift(LEFT*0.2)
multi_chords[4].additional_lines.shift(RIGHT*0.2)
multi_chords[-1][0].set_color(PINK) # From GOLD to PINK
self.add(staff, multi_chords)
%manim $_RI_mid

Intervals#
[14]:
class Example(Scene):
def construct(self):
staff = Staff(clefs="gf", width=3, height=0.7)
multi_chord = MultiChord(staff, "m|Cd,G#u|A-1d#,C1u", 0.6)
vi1 = VInterval(
multi_chord[0][0],
multi_chord[0][1],
buff=0.1,
direction=LEFT # Default: RIGHT
).set_color(BLUE)
tex_interval = vi1.get_text("X", background_buff=0.08, font_size=30, color=BLUE, buff=0.2)
self.add(staff, multi_chord, vi1, tex_interval)
%manim $_RI_mid

Note progression#
[15]:
class Example(Scene):
def construct(self):
staff = Staff(clefs="g", width=10)
pt = staff.partition
notes = VGroup(
Note(staff, "mB-1b",6 /pt).set_color(RED),
Note(staff, "mC#", 10/pt).set_color(BLUE),
Note(staff, "cA#", 14/pt).set_color(GREEN),
Note(staff, "cE1", 18/pt).set_color(TEAL),
Note(staff, "mA1n", 22/pt).set_color(YELLOW),
)
self.play(ShowStaff(staff))
self.play(
# Write(notes[0]),
# Write(notes[0].additional_lines),
# Or
notes[0].show_note(Write)
)
for i in range(1,len(notes)):
base_note = notes[i-1]
target_note = notes[i]
self.play(
TransformFromCopy(
base_note.get_parts("body", "stem"),
target_note.get_parts("body", "stem")
),
# ShowAdditionLinesNote creates the alteration and
# additional lines for the Note in case they exist
*ShowAdditionLinesNote(target_note, Write)
)
self.wait()
%manim $_RV_mid
This can be simplified if we use Melody
.
[16]:
class Example(Scene):
def construct(self):
staff = Staff(clefs="g", width=10)
pt = staff.partition
# 0 |1 |2 |3 |4
notes = Melody(staff, "mB-1b.|mC#u|sA#|cE1|mA1n", 6/pt, increment=2/pt)
notes[0].set_color(RED)
notes[3].set_color(TEAL)
self.play(ShowStaff(staff))
self.play(notes[0].show_note(Write))
for i in range(1,len(notes)):
base_note = notes[i-1]
target_note = notes[i]
self.play(
TransformFromCopy(
base_note.get_parts("body", "stem"),
target_note.get_parts("body", "stem")
),
# ShowAdditionLinesNote creates the alteration and
# additional lines for the next Note in case they exist
*ShowAdditionLinesNote(target_note, Write),
run_time=1
)
self.wait()
%manim $_RV_mid
Chord progression#
[17]:
class Example(Scene):
def construct(self):
staff = Staff(clefs="g", width=10)
pt = staff.partition
chords = VGroup(
ChordLine(staff, "C|G|Bba|C1r#", 0.2, glob="s"),
ChordLine(staff, "A-1b|F|C1#|F1", 0.4, glob="s"),
ChordLine(staff, "B-1ba|D#|Bb|E1", 0.6, glob="s"),
)
self.play(ShowStaff(staff))
self.play(chords[0].show_chord(Write))
for i in range(1,len(chords)):
base_chord = chords[i-1]
target_chord = chords[i]
self.play(
*[
TransformFromCopy(
base_note.get_parts("body", "stem"),
target_note.get_parts("body", "stem"),
run_time=2
)
for base_note, target_note in zip(base_chord, target_chord)
],
LaggedAnim(
0.8, # <- Start animation after 0.8 secs
*ShowAdditionLinesChord(target_chord, Write),
)
)
self.wait()
%manim $_RV_mid
Multi-chord progression#
[18]:
class Example(Scene):
def construct(self):
staff = Staff(clefs="gf", width=10)
pt = staff.partition
chords = VGroup(
MultiChord(staff, "m|Cd , G#u|A-1d#,C1u", 0.2),
MultiChord(staff, "m|GdR#H,Abua_|B-1b ,C1u", 0.4),
MultiChord(staff, "m|G-1d , Gbu|B-1b ,Bbu", 0.6),
MultiChord(staff, "m|C-1d , G0u|Ebd ,C1u", 0.8),
)
self.play(ShowStaff(staff))
self.play(chords[0].show_chord(Write))
for i in range(1,len(chords)):
base = chords[i-1]
target = chords[i]
self.play(
*[
TransformFromCopy(
note_base.get_parts("body", "stem"),
note_target.get_parts("body", "stem"),
run_time=2
)
for chord_base, chord_target in zip(base, target)
for note_base, note_target in zip(chord_base, chord_target)
],
LaggedAnim(
1.2, # <- Start animation after 1.2 secs
*ShowAdditionLinesMultiChord(target, Write),
)
)
self.wait()
%manim $_RV
Same but with HarmonyProgression
#
[19]:
class Example(Scene):
def construct(self):
staff = Staff(clefs="gf", width=12, height=1)
chords = HarmonyProgression(
staff,
"m|Cd , G#u|A-1d#,C1u",
"m|GdR#H,Abua_|B-1b ,C1u",
"m|G-1d , Gbu|B-1b ,Bbu",
"m|C-1d , G0u|Ebd ,C1u",
)
self.play(ShowStaff(staff))
self.play( chords.show_chord(0, Write) )
for i in range(1,len(chords)):
self.play(
*chords.transform(i-1, i, run_time=2),
)
self.wait()
%manim $_RV
[20]:
class Example(Scene):
def construct(self):
staff = Staff(clefs="g", width=10)
chords = HarmonyProgression(
staff,
"s|C,G,Bba,C1r#",
"s|A-1b,F,C1#,F1",
"s|B-1ba,D#,Bb,E1",
)
self.play(ShowStaff(staff))
self.play(chords[0].show_chord(Write))
for i in range(1,len(chords)):
self.play(*chords.transform(i-1, i, run_time=2))
self.wait()
%manim $_RV_mid