120 lines
3.6 KiB
Python
120 lines
3.6 KiB
Python
|
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)
|
||
|
|
||
|
|