def test_transpose_out_of_range(self): song_lines = ("*song: transpose = 0\n*track.melody: octave = 8\n c") parse_string = StringToParse('test_string', song_lines) song = Song.parse(parse_string) song_lines = ("*song: transpose = 100\n*track.melody: octave = 8\n c") parse_string = StringToParse('test_string', song_lines) song = Song.parse(parse_string) track_visitor = MidiTrackVisitor(transpose=song.transpose) note_items = [item for item in song.items if isinstance(item, Note)] with self.parse_exception('Note number 208 > 127', 'c'): for note in note_items: note.visit_midi_track(track_visitor)
def test_parse_2_2_ticks_error(self): song_lines = "*song: time_signature = 2/2, ticks_per_beat = 1\n" + " e | d e f g | d" parse_string = StringToParse('test_string', song_lines) with self.parse_exception( 'ticks per beat of 1 has to be a multiple of crotchets per beat of 2', 'ticks_per_beat'): song = Song.parse(parse_string)
def test_invalid_transpose_value(self): song_lines = ("*song: transpose = 310\nc c") parse_string = StringToParse('test_string', song_lines) with self.parse_exception( 'Invalid value for transpose: 310 - must be an integer from -127 to 127', '310'): song = Song.parse(parse_string)
def test_parse_song_scale(self): song_lines = "*song: scale = C2 major\n*track.melody: octave = 2\n c e | d e f g | c, d'' " parse_string = StringToParse('test_string', song_lines) song = Song.parse(parse_string) self.assertEquals( song.scale, Scale(ScaleNote(0, octave=2), RelativeScale('major', [0, 2, 4, 5, 7, 9, 11]))) note_items = [item for item in song.items if isinstance(item, Note)] scale_positions = [ song.scale.get_position(note.midi_note) for note in note_items ] self.assertEquals(scale_positions, [0, 2, 1, 2, 3, 4, 0, 8])
def test_subticks(self): song_lines = """ *song: tempo_bpm=120, ticks_per_beat=4, subticks_per_tick = 5 | [C] c """ parse_string = StringToParse('test_string', song_lines) song = Song.parse(parse_string) self.assertEqualsDisplaying( song, Song([ SongValuesCommand([ SetSongTempoBpm(120), SetSongTicksPerBeat(4), SetSongSubTicksPerTick(5) ]), BarLine(), Chord(ScaleNote(0), descriptor=''), Note(0, duration=(1, 1)) ]))
def test_parse_song_cut(self): song_lines = """ *song: tempo_bpm=120, ticks_per_beat=4 | [C] c e [:FAC] e ! c | [G] r2 """ parse_string = StringToParse('test_string', song_lines) song = Song.parse(parse_string) self.assertEqualsDisplaying( song, Song([ SongValuesCommand( [SetSongTempoBpm(120), SetSongTicksPerBeat(4)]), Note(0, duration=(1, 1)), BarLine(), Chord(ScaleNote(4), descriptor=''), Rest((2, 1)) ]))
def test_transpose(self): song_lines = ( "*song: transpose = 3\n*track.melody: octave = 2\n*track.chord: octave = 1\n*track.bass:octave = 0\n" + "c c [C]") parse_string = StringToParse('test_string', song_lines) song = Song.parse(parse_string) note_items = [item for item in song.items if isinstance(item, Note)] first_note = note_items[0] self.assertEquals(first_note.midi_note, 36) track_visitor = MidiTrackVisitor(transpose=song.transpose) first_note.visit_midi_track(track_visitor) self.assertEquals(track_visitor.midi_notes[0], 39) chord_items = [item for item in song.items if isinstance(item, Chord)] first_chord = chord_items[0] self.assertEquals(first_chord.midi_notes, [24, 28, 31]) first_chord.visit_midi_track(track_visitor) self.assertEquals(track_visitor.midi_notes[1], [27, 31, 34]) self.assertEquals(first_chord.bass_midi_note, 12) bass_note = song.tracks['bass'].items[0] bass_note.visit_midi_track(track_visitor) self.assertEquals(track_visitor.midi_notes[2], 15)
def test_parse_song(self): parse_string = StringToParse('test_string', self.song_lines) song = Song.parse(parse_string) self.assertEqualsDisplaying( song, Song([ SongValuesCommand( [SetSongTempoBpm(120), SetSongTicksPerBeat(4)]), TrackValuesCommand('chord', [SetTrackOctave(2), SetTrackInstrument(40)]), TrackValuesCommand( 'bass', [SetTrackOctave(1), SetTrackVolume(90)]), Chord(ScaleNote(0), descriptor=''), Note(0, duration=(1, 1)), Note(2, duration=(1, 1)), Chord(ScaleNote(3), other_notes=[ScaleNote(5), ScaleNote(0)]), Note(2, duration=(1, 1)), Note(0, duration=(1, 2)), Note(0, duration=(1, 2)), BarLine(), Chord(ScaleNote(4), descriptor=''), Note(4, duration=(1, 1)), Rest((2, 1)) ])) chord_track = song.tracks['chord'] self.assertEquals(chord_track.instrument, 40) self.assertEquals(song.tracks['bass'].volume, 90) self.assertEquals(len(chord_track.items), 3) self.assertEquals(len(song.tracks['melody'].items), 6) self.assertEquals(chord_track.items[0].midi_notes, [36, 40, 43]) self.assertEquals(chord_track.items[1].bass_midi_note, 29) self.assertEquals(song.bar_ticks, [0, 16, 32])
def test_note_too_low(self): song_lines = """*track.melody: octave = 4\n c c, c, c, | c, d, e, f, """ parse_string = StringToParse('test_string', song_lines) with self.parse_exception('Note number -8 < 0', "e, f, "): song = Song.parse(parse_string)
def test_note_too_high(self): song_lines = """*track.melody: octave = 5\n c c' c' c' | c' d d' e'""" parse_string = StringToParse('test_string', song_lines) with self.parse_exception('Note number 134 > 127', "d' e'"): song = Song.parse(parse_string)
def _continuation_song(self, string): song_lines = "*song: ticks_per_beat=1, time_signature = 4/4\n%s" % string parse_string = StringToParse('test_string', song_lines) return Song.parse(parse_string)
def test_parse_3_8(self): song_lines = "*song: time_signature = 3/8\n" + "ch e | dh e f | ch" parse_string = StringToParse('test_string', song_lines) song = Song.parse(parse_string)
def test_parse_3_4(self): song_lines = "*song: time_signature = 3/4\n" + "c e | d e f | c" parse_string = StringToParse('test_string', song_lines) song = Song.parse(parse_string)