piccal/NoteTester.py

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)