speaking-midi / tests /test_dense.py
k-l-lambda's picture
Deploy dense piano fitting in both Space input modes
f97fef1
Raw History Blame Contribute Delete
1.82 kB
import tempfile
import unittest
from pathlib import Path
import numpy as np
from speaking_midi.core import Piano, Note, SR, write_midi, read_midi, metrics
from speaking_midi.dense import decode_activations, fit_dense
class DenseFitting(unittest.TestCase):
def test_calibration_and_nonoverlapping_midi_grid(self):
coefficients=np.array([[0.,.3,.6,.15],[.9,0.,0.,0.]])
calibration=np.array([[0.,.1,.2,.4,1.],[0.,.2,.4,.8,2.]])
notes=decode_activations(coefficients,calibration,[60,64],[1,4,8,16,32],.02,2,.08)
self.assertEqual([(n.pitch,n.velocity) for n in notes],[(60,12),(60,21),(64,17)])
with tempfile.TemporaryDirectory() as d:
path=Path(d)/'control.mid';write_midi(notes,path)
decoded=read_midi(path)
self.assertEqual(len(decoded),3)
for n in decoded:
self.assertGreaterEqual(n.start,0)
self.assertLessEqual(n.start+n.duration,.08+1e-9)
def test_single_piano_note_recovery_on_cpu(self):
piano=Piano()
try:
y=piano.render([Note(60,64,.06,.02)],.3)
notes,report,_=fit_dense(y,piano,device='cpu',steps=150)
self.assertEqual(report['optimization']['device'],'cpu')
self.assertLess(report['loss_history'][-1][1],report['loss_history'][0][1])
self.assertTrue(any(n.pitch==60 and abs(n.start-.06)<=.02 for n in notes))
rendered=piano.render(notes,.8)
self.assertLess(metrics(y,rendered)['log_band_mae'],metrics(y,np.zeros_like(y))['log_band_mae'])
finally:piano.close()
def test_reject_overlapping_gate(self):
with self.assertRaises(ValueError):
fit_dense(np.ones(SR,dtype=np.float32),None,gate=.04,grid_frames=2)
if __name__=='__main__':unittest.main()