Download python/demo.py from HY-2012/UniverSR.AXERA: direct link, hf CLI and curl.
- Browser
- Download file 2.74 kB
-
https://huggingface.co/HY-2012/UniverSR.AXERA/resolve/main/python/demo.py
- Command line
-
hf download hf://HY-2012/UniverSR.AXERA/python/demo.py
-
curl -L -o demo.py https://huggingface.co/HY-2012/UniverSR.AXERA/resolve/main/python/demo.py
2.74 kB
| import sys,time,argparse | |
| from pathlib import Path | |
| import numpy as np, torch, torchaudio, soundfile as sf, axengine | |
| ROOT=Path(__file__).resolve().parent; sys.path.insert(0,str(ROOT)) | |
| T=128; F_HR=432; HOP=512; NFFT=1024; SR=48000 | |
| WIN=torch.hann_window(NFFT) | |
| def stft(x): | |
| X=torch.stft(x.reshape(1,-1),NFFT,HOP,window=WIN,center=True,return_complex=True) | |
| A=X+1e-4; X=A.abs()**0.2*torch.exp(1j*A.angle()) | |
| r=torch.view_as_real(X).permute(0,3,1,2); return r[:,:,:-1,:] | |
| def istft(sp): | |
| sp=torch.nn.functional.pad(sp,[0,0,0,1],value=0).permute(0,2,3,1).contiguous() | |
| X=torch.view_as_complex(sp); X=X.abs()**5.0*torch.exp(1j*X.angle()) | |
| return torch.istft(X,NFFT,HOP,window=WIN,center=True,length=245760) | |
| def main(): | |
| p=argparse.ArgumentParser(); p.add_argument('input'); p.add_argument('output'); p.add_argument('--models',default=str(ROOT/'models')); p.add_argument('--seed',type=int,default=42); p.add_argument('--overlap',type=int,default=64); p.add_argument('--sr',type=int,default=8); a=p.parse_args() | |
| ce=axengine.InferenceSession(str(Path(a.models)/f'universr_split_{a.sr}k_condenc.axmodel')) | |
| mc=axengine.InferenceSession(str(Path(a.models)/f'universr_split_{a.sr}k_main_cond_actual.axmodel')) | |
| mu=axengine.InferenceSession(str(Path(a.models)/f'universr_split_{a.sr}k_main_uncond.axmodel')) | |
| x,sr=sf.read(a.input); x=torch.tensor(x,dtype=torch.float32).reshape(1,-1) | |
| x=torchaudio.functional.resample(x,sr,SR); x=torch.nn.functional.pad(x,(0,max(0,245760-x.shape[-1])))[...,:245760] | |
| Y=stft(x.unsqueeze(1)); total=Y.shape[-1]; lr=80 if a.sr==8 else 170; hf=512-432 | |
| pad=(T-total%T)%T | |
| Yp=torch.nn.functional.pad(Y,(0,pad),mode='constant') if pad else Y | |
| total=Yp.shape[-1] | |
| starts=list(range(0,total-T+1,T-a.overlap)) | |
| spec=torch.zeros_like(Yp); wsum=torch.zeros(total) | |
| rng=np.random.RandomState(a.seed); t0=time.time() | |
| for s in starts: | |
| y=Yp[:,:,:lr,s:s+T].numpy().astype(np.float32) | |
| z=ce.run(None,{'y':y})[0].astype(np.float32) # 1,384,1,T | |
| zz=rng.randn(1,2,F_HR,T).astype(np.float32) | |
| n=128 | |
| for i in range(4): | |
| t=np.array([i/4],np.float32); dt=0.25 | |
| def f(q,tt): | |
| vu=mu.run(None,{'x':q,'t':tt})[0]; vc=mc.run(None,{'x':q,'t':tt,'y_cond':z})[0] | |
| return (1-1.5)*vu+1.5*vc | |
| k1=f(zz,t); zm=zz+0.5*dt*k1; k2=f(zm,np.array([i/4+0.125],np.float32)); zz=zz+dt*k2 | |
| cut=max(0,lr-hf); full=np.concatenate([y,zz[:,:,cut:,:]],axis=2) # 1,2,512,T? | |
| full=torch.from_numpy(full) | |
| w=torch.ones(T) | |
| if s>0: w[:a.overlap]=torch.linspace(0,1,a.overlap) | |
| if s+T>total: w[-(s+T-total):]=0 | |
| spec[:,:,:,s:s+T]+=full*w; wsum[s:s+T]+=w | |
| spec=spec/wsum.clamp_min(1e-8); out=istft(spec).squeeze()[:245760] | |
| sf.write(a.output,out.numpy(),SR,subtype='PCM_16'); print('time',time.time()-t0,'shape',out.shape) | |
| if __name__=='__main__': main() | |