123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- import sys,os,types,json
- from random import randrange
-
- class NoteTester:
- def __init__( self, cfg, api ):
- self.cfg = cfg
- self.api = api
-
- r = types.SimpleNamespace(**cfg.NoteTester)
-
- self.durMsL = [ randrange(r.minNoteDurMs, r.maxNoteDurMs) for _ in range(r.noteCount) ]
- self.pauseMsL = [ randrange(r.minPauseDurMs, r.maxPauseDurMs) for _ in range(r.noteCount) ]
- self.eventL = []
- self.nextMs = 0 # next transition time
- self.eventIdx = 0 # next event to play
- self.noteOnFl = False # True if note is currently sounding
- self.pitch = r.pitch #
- self.filename = r.filename
- self.isStartedFl = False
- self.minAttackUsec = r.minAttackUsec
- self.maxAttackUsec = r.maxAttackUsec
-
- def start( self ):
- self.eventIdx = 0
- self.noteOnFl = False
- self.nextMs = 0
- self.isStartedFl = True
-
- def stop( self ):
- self.isStartedFl = False
- self.write()
-
- def tick( self, ms ):
-
- if self.isStartedFl and ms > self.nextMs:
-
- offsMs = 0
-
- if self.noteOnFl:
- self.noteOnFl = False
- self.api.note_off( self.pitch )
- offsMs = self.pauseMsL[ self.eventIdx ]
- self.eventIdx += 1
- print("off:%i ms" % (offsMs))
-
-
- else:
- usec = self.minAttackUsec + (int(self.eventIdx * 250) % int(self.maxAttackUsec - self.minAttackUsec))
- decay_level = self.api.calc_decay_level( usec )
-
- self.api.note_on_us( self.pitch, usec, decay_level )
- offsMs = self.durMsL[ self.eventIdx ]
- print("usec:%i %i dcy:%i" % (usec,offsMs, decay_level) )
- self.noteOnFl = True
-
-
- self.eventL.append( (ms, self.noteOnFl) )
- self.nextMs = ms + offsMs
-
- if self.eventIdx >= len(self.durMsL):
- self.write();
- self.isStartedFl = False
- print("done % i" % (len(self.eventL)))
-
-
-
- def write( self ):
-
- with open(self.filename,"w") as f:
- json.dump({ "eventL":self.eventL },f )
-
-
-
- def note_tester_compare( nt_fn, logica_fn ):
-
- eventL = []
- logicaL = []
-
- with open(nt_fn,"r") as f:
- r = json.load(f)
- eventL = r['eventL']
- eventL = [ (ms-eventL[0][0], level ) for ms,level in eventL ]
-
- with open(logica_fn,"r") as f:
- logicaL = [ ( d['count']/16e3,d['level']) for d in json.load(f) if d['signal'] == 0 ]
- logicaL = [ (ms-logicaL[0][0], level!=0 ) for ms,level in logicaL ]
-
-
- print(len(eventL))
- print(len(logicaL))
-
- #edL = [ eventL[i][0] - eventL[i-1][0] for i in range(2,len(eventL)) ]
- #ldL = [ logicaL[i][0] - logicaL[i-1][0] for i in range(2,len(logicaL)) ]
-
- #print(edL[:10])
- #print(ldL[:10])
-
-
- durMs = 0
- ms = 0
- for i,(t0,t1) in enumerate(zip(eventL,logicaL)):
- t = t0[0] # eventL[] time
- dt = int(t - t1[0]) # diff between eventL[] and logicaL[] time
- fl = ' ' if t0[1] == t1[1] else '*' # mark level mismatch with '*'
- print("%5i %7i %4i %i %s" % (i,durMs,dt,t0[1],fl))
- durMs = t-ms
- ms = t
-
-
- if __name__ == "__main__":
-
- nt_fn = "note_tester.json"
- logica_fn = sys.argv[1]
- if len(sys.argv) > 2:
- nt_fn = sys.argv[2]
-
- note_tester_compare( nt_fn, logica_fn)
-
-
|