Skip to content

Commit 8b51a44

Browse files
authored
Read and write names of midi tracks #99
2 parents 701e7d0 + dabfeda commit 8b51a44

File tree

2 files changed

+91
-1
lines changed

2 files changed

+91
-1
lines changed

src/miditrack.jl

+64-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export getnotes, addnote!, addnotes!, addevent!
1+
export getnotes, addnote!, addnotes!, addevent!, trackname, addtrackname!
22
export MIDITrack
33

44
"""
@@ -211,3 +211,66 @@ function programchange(track::MIDITrack, time::Integer, channel::UInt8, program:
211211
program -= 1
212212
addevent!(track, time, MIDIEvent(0, PROGRAMCHANGE | channel, UInt8[program]))
213213
end
214+
215+
"""
216+
trackname(track::MIDI.MIDITrack)
217+
218+
Return the name of the given [`MIDITrack`](@ref) as a string,
219+
by finding the "track name" [`MetaEvent`](@ref).
220+
"""
221+
function trackname(track::MIDI.MIDITrack)
222+
223+
pos = findnameevent(track)
224+
if pos == 0
225+
return "No track name found"
226+
# check if there really is a name
227+
elseif length(track.events[pos].data) == 0
228+
return "No track name found"
229+
else
230+
event = track.events[pos]
231+
# extract the name (string(Char()) takes care of ASCII encoding)
232+
trackname = string(Char(event.data[1]))
233+
for c in event.data[2:end]
234+
trackname *= string(Char(c))
235+
end
236+
return trackname
237+
end
238+
end
239+
240+
"""
241+
addtrackname!(track::MIDI.MIDITrack, name::String)
242+
243+
Add a name of the given [`MIDITrack`](@ref) by attaching the correct
244+
"track name" [`MetaEvent`](@ref) to the track.
245+
"""
246+
function addtrackname!(track::MIDI.MIDITrack, name::String)
247+
# construct fitting name event
248+
data = UInt8[]
249+
for i = 1:length(name)
250+
push!(data, UInt8(name[i]))
251+
end
252+
meta = MetaEvent(0,0x03,data)
253+
254+
# remove existing name
255+
prev = findnameevent(track)
256+
if prev != 0
257+
deleteat!(track.events, prev)
258+
end
259+
260+
# add event to track
261+
addevent!(track, 0, meta)
262+
end
263+
264+
function findnameevent(track::MIDI.MIDITrack)
265+
# find track name MetaEvent
266+
# (has dt zero and occurs before any other event with nonzero dt)
267+
position = 0
268+
for (i,event) in enumerate(track.events)
269+
if event.dT != 0
270+
break
271+
elseif event.dT == 0 && isa(event, MIDI.MetaEvent) && event.metatype == 0x03
272+
position = i
273+
end
274+
end
275+
return position
276+
end

test/miditrack.jl

+27
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,31 @@ invalidtestvalues = [
7373
@test n1 == n2
7474
end
7575
end
76+
77+
@testset "Track names" begin
78+
79+
# correct tracks
80+
midi = readMIDIfile("doxy.mid")
81+
@test trackname(midi.tracks[2]) == "Drums"
82+
@test trackname(midi.tracks[3]) == "Bass"
83+
@test trackname(midi.tracks[4]) == "ORIGINAL"
84+
85+
# broken track
86+
midi.tracks[2].events = midi.tracks[2].events[10:end]
87+
@test trackname(midi.tracks[2]) == "No track name found"
88+
89+
# add track name
90+
addtrackname!(midi.tracks[2],"Uagadugu")
91+
@test trackname(midi.tracks[2]) == "Uagadugu"
92+
93+
# replace track name
94+
addtrackname!(midi.tracks[2],"Overwrite")
95+
@test trackname(midi.tracks[2]) == "Overwrite"
96+
97+
# save and reopen
98+
writeMIDIfile("changedname.mid",midi)
99+
midi = readMIDIfile("changedname.mid")
100+
@test trackname(midi.tracks[2]) == "Overwrite"
101+
rm("changedname.mid")
102+
end
76103
end

0 commit comments

Comments
 (0)