MIDI Mixup source code

Combine the original note order without randomization, repeat shorter inputs to match the longest input, and start the output at time zero.

# MIDI Mixup
#
# Read 3 MIDI files, and use the pitches from the first one, the channels
# from the second one, and the durations from the third one.

function mixup(fname1,fname2,fname3,longest) {
	if ( nargs() < 4 )
		longest = 0
	f1 = readmf(fname1)
	f2 = readmf(fname2)
	f3 = readmf(fname3)
	f1.length = latest(f1)
	f2.length = latest(f2)
	f3.length = latest(f3)
	p = mixitup(f1,f2,f3,longest)
	writemf(p,"www.mid")
	writelines(p,"www.lines")
}

function mixitup(f1,f2,f3,longest) {

	f1 = onlynotes(f1)
	f2 = onlynotes(f2)
	f3 = onlynotes(f3)
	s1 = sizeof(f1)
	s2 = sizeof(f2)
	s3 = sizeof(f3)
	if ( s1 == 0 || s2 == 0 || s3 == 0 ) {
		print("Each selected MIDI file must contain notes.")
		return('')
	}
	if ( longest ) {
		nnotes = s1
		if ( s2 > nnotes )
			nnotes = s2
		if ( s3 > nnotes )
			nnotes = s3
		while ( sizeof(f1) < nnotes ) {
			f1 = f1+f1
		}
		while ( sizeof(f2) < nnotes ) {
			f2 = f2+f2
		}
		while ( sizeof(f3) < nnotes ) {
			f3 = f3+f3
		}
	} else {
		nnotes = s1
		if ( s2 < nnotes )
			nnotes = s2
		if ( s3 < nnotes )
			nnotes = s3
	}
	# Combine the inputs in their original note order; no randomization.
	r = ''
	for ( n=0; n<nnotes; n++ ) {
		nt = 'a'
		nt.pitch = (f1%(n+1)).pitch

		# we use the time and channel from the second midi file
		nt.time = (f2%(n+1)).time
		nt.chan = (f2%(n+1)).chan

		nt.duration = (f3%(n+1)).duration
		r |= nt
	}
	# Remove only the leading silence, preserving relative note timing.
	r.time -= (r%1).time
	r.length = latest(r)
	return(r)
}