from dataclasses import dataclass header = """ """ footer = """ """ @dataclass class key: midi: int x: float black: bool name: str octave: int inoctave: int def includes(array,val): ret = False for aval in array: if val == aval: ret = True return ret keycount = 88 blackkeys = [1,3,6,8,10] spacing = [0,1,2,3,4,6,7,8,9,10,11,12] knames = ['C','Cs','D','Ds','E','F','Fs','G','Gs','A','As','B','C'] onames = ['0','1','2','3','4','5','6','7','8','9','10'] octave_spacing = 1.75 startkey = 60 - round((keycount - 8)/2) + 1 inote = startkey keys = [] # https://en.wikipedia.org/wiki/Piano_key_frequencies # midi note 21 is called A0, middle C is called C4 for i in range(0,keycount): (octave,key12) = divmod(inote,12) octave = octave -1 black = includes(blackkeys,key12) octave_x = spacing[key12]*.125 xpos = (octave-4)*octave_spacing + octave_x #print('i= '+i+' inote '+inote+' key12 '+key12+' octave '+octave+' xpos '+xpos); k = key(inote,x=xpos,black=black,name=knames[key12]+onames[octave],octave=octave,inoctave=key12) keys.append(k) print(k) inote = inote + 1 trans = """ """ routes = """ """ merger = """ """ obuf = "" tbuf = "" rbuf = "" inote = startkey lastoctave = -1 for i in range(88): (octave,key12) = divmod(inote,12) octave = octave -1 if octave != lastoctave: obuf = obuf + merger % (octave,octave,octave) lastoctave = octave kn = keys[i].name kcolor = 'WSHAPE' if keys[i].black: kcolor = 'BSHAPE' xpos = keys[i].x tbuf = tbuf + trans % (kn,xpos,kcolor,kn,kn,kn) rbuf = rbuf + routes % (kn,kn, kn,kn, kn,kn,kn,knames[key12],octave) inote = inote + 1 f = open("kb.x3d","w+"); f.write(header) f.write(obuf) f.write(tbuf) f.write(rbuf) f.write(footer) f.close()