def test2(): intermed = notesinterpret.IntermediateList((4, 4)) #tests ties, rests, notes rlist = [64, 64, 64, 64, 32, 32, 16, 16, 8, 8, 4, 4, 2, 2, 1, 1] noteList = [] curtime = 0 for i in range(len(rlist)): n = rlist[i] pitch = 60 + i % 3 if i % 2 == 1: pitch = 0 #a rest noteList.append( NotesRealtimeNoteEvent([pitch], curtime, curtime + old_div(4 * intermed.baseDivisions, n))) noteList[-1].isTied = False curtime += old_div(4 * intermed.baseDivisions, n) for i in range(len(rlist)): n = rlist[i] noteList.append( NotesRealtimeNoteEvent([70], curtime, curtime + old_div(4 * intermed.baseDivisions, n))) noteList[-1].isTied = True curtime += old_div(4 * intermed.baseDivisions, n) intermed.noteList = noteList intermed.bSharps = True return intermed
def createIntermediateList(listNotes, timesig, quantize, bIsTreble, bSharps): #inserts rests between notes, standardizes all durations to be whole,half,qtr,8th,and so on, tied notes if necessary divisions = old_div(quantize, 4) #because each pulse is a qtr note assert quantize >= 4 intermed = IntermediateList(timesig, bSharps=bSharps) fQtrnotespermeasure = float(timesig[0]) / (old_div(timesig[1], 4)) nTimestepspermeasure = int(fQtrnotespermeasure * intermed.baseDivisions) #insert rests between notes newlist = [] for i in range(len(listNotes)): if listNotes[i][1] == listNotes[i][2]: raise 'Cannot have note of length 0.' newlist.append(listNotes[i]) if i < len(listNotes) - 1: restLength = listNotes[i + 1][1] - listNotes[i][2] assert restLength >= 0 if restLength != 0: newlist.append(((0, ), listNotes[i][2], listNotes[i + 1][1])) #convert to a standard time base, where each unit is 1/baseDivisions of a qtr note. def qStepToTimeBase(x): return int((float(x) / (divisions) * intermed.baseDivisions)) #standardize durations, creating tied notes when necessary. currentMeasureTime = 0 for note in newlist: length = qStepToTimeBase(note[2] - note[1]) results = intermed.effectivelyTieLongNotesBarlines( currentMeasureTime, length, nTimestepspermeasure) for i in range(len(results)): duration = results[i] bIsTied = i != len(results) - 1 newnote = NotesRealtimeNoteEvent(pitch=note[0], start=currentMeasureTime, end=currentMeasureTime + duration) newnote.isTied = bIsTied intermed.noteList.append(newnote) currentMeasureTime += duration assert currentMeasureTime <= nTimestepspermeasure if currentMeasureTime == nTimestepspermeasure: # begin the next measure... currentMeasureTime = 0 return intermed
def test1(): intermed = notesinterpret.IntermediateList((4, 4)) #tests notes, sharps, different durations sampleList = [ 1, 2, 2, 4, 8, 4, 4, 8, 64, 64, 64, 64, 32, 32, 16, 16, 2, 4, 8, 8, 8, 8, 4, 4, 4, 4, 8, 8, 8, 8 ] noteList = [] curtime = 0 for n in sampleList: noteList.append( NotesRealtimeNoteEvent([60 + curtime % 7], curtime, curtime + old_div(4 * intermed.baseDivisions, n))) noteList[-1].isTied = False curtime += old_div(4 * intermed.baseDivisions, n) intermed.noteList = noteList intermed.bSharps = True return intermed
def convCoord(x): return int((old_div(x,maxx)) * w)
def draw(self,listPulses, listFinal ): im = Image.new('RGB', (w,h*3) , 0xffffff) listQuantize = self.listSteps listPulses = listPulses listNotes = self.listPrequantized listNotesQuantized = self.listPostquantized listFinal = listFinal maxx = listQuantize[-1] def convCoord(x): return int((old_div(x,maxx)) * w) def convCoordQ(x): return convCoord(listQuantize[x]) def convCoordQRegular(x): return int((float(x)/(len(listQuantize)-1)) * w) self.prevpitch=0; self.curlevel=0 def getnote(x): if x!=self.prevpitch: self.curlevel= (self.curlevel+1)%4 self.prevpitch=x return self.curlevel draw = ImageDraw.Draw(im) #~ draw.line((0, 0) + im.size, fill=128) #~ draw.line((0, im.size[1], im.size[0], 0), fill=128) for q in listQuantize: x= convCoord(q) draw.line( (x,0,x,h), fill=0xaaaaaa) for q in listPulses: x= convCoord(q) draw.line( (x,0,x,old_div(h,16)), fill=0x4444ff, width=4) for note in listNotes: start, stop = convCoord(note[1]),convCoord(note[2]) y=old_div(h,2) - (old_div(getnote(note[0])*h,8)) draw.rectangle( (start,y,stop,y+old_div(h,8)), fill=0x44ff44) for note in listNotesQuantized: start, stop = convCoordQ(note[1]),convCoordQ(note[2]) y=old_div(h,2) - (old_div(getnote(note[0])*h,8)) y+=old_div(h,2) draw.rectangle( (start,y,stop,y+old_div(h,8)), fill=0xff4444) #draw "final" version for q in range(len(listQuantize)): x= convCoordQRegular(q) draw.line( (x,h*2,x,h*3), fill=0xaaaaaa) for note in listFinal: start, stop = convCoordQRegular(note[1]),convCoordQRegular(note[2]) for pitch in note[0]: y=old_div(h,2) - (old_div(getnote(pitch)*h,8)) draw.rectangle( (start,y + h*2,stop,y+old_div(h,8)+ h*2), fill=0xffff44) del draw im.save('out.png', "PNG")
class IntermediateList(object): #an intermediate list of notes. timings in terms of baseDivisions. noteList = None # list of NotesRealtimeNoteEvent. bSharps = True timesig = None baseDivisions = 64 #each qtr note can be divided into this many pieces. 64 units always = 1 qtr note atomicnotes = [ int(old_div(baseDivisions, n)) for n in [0.25, 0.5, 1, 2, 4, 8, 16, 32] ] # whole, half, qtr, 8th, 16, 32, 64, 138 def __init__(self, timesig, bSharps=True): self.timesig = timesig self.bSharps = bSharps self.noteList = [] def effectivelyTieLongNotes(self, currentMeasureTime, length): #spell a long note on the beat. for example, turn something 3 beats long into halfnote tied to qtr # probably only looks well for duple times! #returns list of atoms results = [] lengthleft = length while lengthleft > 0: found = False for atom in self.atomicnotes: if atom <= lengthleft and isDivisible(currentMeasureTime, atom): results.append(atom) lengthleft -= atom currentMeasureTime += atom found = True break assert found assert lengthleft == 0 return results def effectivelyTieLongNotesBarlines(self, currentMeasureTime, length, measureLength): #spell a long note, taking measures into account (must tie across barlines) #returns list of atoms. results = [] if currentMeasureTime + length <= measureLength: return self.effectivelyTieLongNotes(currentMeasureTime, length) else: lengthleft = length firstnotelength = measureLength - currentMeasureTime results.extend( self.effectivelyTieLongNotes(currentMeasureTime, firstnotelength)) lengthleft -= firstnotelength currentMeasureTime += firstnotelength #add any full measures while lengthleft >= measureLength: results.extend( self.effectivelyTieLongNotes(currentMeasureTime, measureLength)) lengthleft -= measureLength currentMeasureTime += measureLength #add the rest if lengthleft != 0: results.extend( self.effectivelyTieLongNotes(currentMeasureTime, lengthleft)) lengthleft -= lengthleft currentMeasureTime += lengthleft return results
def createQuantizedList(objResults, quantize): #quantizes and eliminate overlapping notes if isinstance(objResults, NotesinterpretException): raise objResults if useVisualTest: vis = testdepiction.TestDepiction() listPulses, listNotes = objResults.listPulses, objResults.listNotes # how many subdivisions? divisions = old_div(quantize, 4) #because each pulse is a qtr note assert quantize >= 4 #for example, if quantize by 8th note, and each pulse is a qtr note, there are two possible values per pulse. #create quantization list (contains all acceptible times). #divides linearly. one might also smooth intra-pulse timing with a spline... listQuantize = [] listQuantize.append(0.0) prevTime = 0.0 for pulseTime in listPulses: inc = old_div((pulseTime - prevTime), divisions) for i in range(divisions): listQuantize.append(prevTime + i * inc) prevTime = pulseTime if useVisualTest: vis.addPreQuantize(listQuantize, listNotes) #quantize all of the times for note in listNotes: note.start = findclosest(listQuantize, note.start) note.end = findclosest(listQuantize, note.end) #now times are integers, corresponding to multiples of time unit. So if quantize=8, each unit is an 8th note if useVisualTest: vis.addQuantized(listNotes) #now get rid of overlapping notes, using some heuristics. #this logic is not currently used since polyphony no longer supported... #although could occur if two notes played rapidly listFinal = [] while listNotes: currentPitchGroup = [listNotes.pop(0)] currentPitchStartTime = currentPitchGroup[0].start while listNotes and listNotes[0].start == currentPitchStartTime: currentPitchGroup.append(listNotes.pop(0)) #length of this pitch group is the longest in the group... currentPitchEndTime = 0 for note in currentPitchGroup: if note.end > currentPitchEndTime: currentPitchEndTime = note.end #...unless it is interrupted by some other note. if listNotes and listNotes[0].start < currentPitchEndTime: currentPitchEndTime = listNotes[0].start #can't have a note of length 0. if currentPitchEndTime == currentPitchStartTime: currentPitchEndTime += 1 #quantize currentPitchEndTime to have it fill to next note? if listNotes and currentPitchEndTime != listNotes[0].start: if listNotes[0].start - currentPitchEndTime < quantize: currentPitchEndTime = listNotes[ 0].start #bleed into next note. assert currentPitchEndTime > currentPitchStartTime listFinal.append(([m.pitch for m in currentPitchGroup], currentPitchStartTime, currentPitchEndTime)) if useVisualTest: vis.draw(listPulses, listFinal) return listFinal