annotate code Kat/spsmodel.m @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents 881c3acf1164
children
rev   line source
katkost@1 1 function [y,yh,ys] = spsmodel(x,fs,w,N,t,maxnS,stocf)
katkost@1 2 %=> analysis/synthesis of a sound using the sinusoidal harmonic model
katkost@1 3 % x: input sound, fs: sampling rate, w: analysis window (odd size),
katkost@1 4 % N: FFT size (minimum 512), t: threshold in negative dB,
katkost@1 5 % maxnS: maximum number of sinusoids,
katkost@1 6 % stocf: decimation factor of mag spectrum for stochastic analysis
katkost@1 7 % y: output sound, yh: harmonic component, ys: stochastic component
katkost@1 8 M = length(w); % analysis window size
katkost@1 9 Ns = 1024; % FFT size for synthesis
katkost@1 10 H = 256; % hop size for analysis and synthesis
katkost@1 11 N2 = N/2+1; % half-size of spectrum
katkost@1 12 soundlength = length(x); % length of input sound array
katkost@1 13 hNs = Ns/2; % half synthesis window size
katkost@1 14 hM = (M-1)/2; % half analysis window size
katkost@1 15 pin = max(N2,1+hM) % initialize sound pointer to middle of analysis window
katkost@1 16 pend = soundlength-max(N2,hM); % last sample to start a frame
katkost@1 17 fftbuffer = zeros(N,1); % initialize buffer for FFT
katkost@1 18 yh = zeros(soundlength+Ns/2,1); % output sine component
katkost@1 19 ys = zeros(soundlength+Ns/2,1); % output residual component
katkost@1 20 w = w/sum(w); % normalize analysis window
katkost@1 21 sw = zeros(Ns,1);
katkost@1 22 ow = triang(2*H-1); % overlapping window
katkost@1 23 ovidx = Ns/2+1-H+1:Ns/2+H; % overlap indexes
katkost@1 24 sw(ovidx) = ow(1:2*H-1);
katkost@1 25 bh = blackmanharris(Ns); % synthesis window
katkost@1 26 bh = bh ./ sum(bh); % normalize synthesis window
katkost@1 27 wr = bh; % window for residual
katkost@1 28 sw(ovidx) = sw(ovidx) ./ bh(ovidx);
katkost@1 29 sws = H*hanning(Ns)/2; % synthesis window for stochastic
katkost@1 30 lastysloc = zeros(maxnS,1); % initialize synthesis harmonic locations
katkost@1 31 ysphase = 2*pi*rand(maxnS,1); % initialize synthesis harmonic phases
katkost@1 32 fridx = 0;
katkost@1 33
katkost@1 34
katkost@1 35
katkost@1 36
katkost@1 37
katkost@1 38 while pin<pend
katkost@1 39 %-----analysis-----%
katkost@1 40 xw = x(pin-hM:pin+hM).*w(1:M); % window the input sound
katkost@1 41 fftbuffer = fftbuffer*0; % reset buffer;
katkost@1 42 fftbuffer(1:(M+1)/2) = xw((M+1)/2:M); % zero-phase window in fftbuffer
katkost@1 43 fftbuffer(N-(M-1)/2+1:N) = xw(1:(M-1)/2);
katkost@1 44 X = fft(fftbuffer); % compute the FFT
katkost@1 45 mX = 20*log10(abs(X(1:N2))); % magnitude spectrum
katkost@1 46 pX = unwrap(angle(X(1:N/2+1))); % unwrapped phase spectrum
katkost@1 47 ploc = 1 + find((mX(2:N2-1)>t) .* (mX(2:N2-1)>mX(3:N2)) ...
katkost@1 48 .* (mX(2:N2-1)>mX(1:N2-2))); % find peaks
katkost@1 49 [ploc,pmag,pphase] = peakinterp(mX,pX,ploc); % refine peak values
katkost@1 50 % sort by magnitude
katkost@1 51 [smag,I] = sort(pmag(:),1,'descend');
katkost@1 52 nS = min(maxnS,length(find(smag>t)));
katkost@1 53 sloc = ploc(I(1:nS));
katkost@1 54 sphase = pphase(I(1:nS));
katkost@1 55 if (fridx==0)
katkost@1 56 % update last frame data for first frame
katkost@1 57 lastnS = nS;
katkost@1 58 lastsloc = sloc;
katkost@1 59 lastsmag = smag;
katkost@1 60 lastsphase = sphase;
katkost@1 61 end
katkost@1 62 % connect sinusoids to last frame lnS (lastsloc,lastsphase,lastsmag)
katkost@1 63 sloc(1:nS) = (sloc(1:nS)~=0).*((sloc(1:nS)-1)*Ns/N); % synth. locs
katkost@1 64 lastidx = zeros(1,nS);
katkost@1 65 for i=1:nS
katkost@1 66 [dev,idx] = min(abs(sloc(i) - lastsloc(1:lastnS)));
katkost@1 67 lastidx(i) = idx;
katkost@1 68 end
katkost@1 69 ri= pin-hNs; % input sound pointer for residual analysis
katkost@1 70 xr = x(ri:ri+Ns-1).*wr(1:Ns); % window the input sound
katkost@1 71 Xr = fft(fftshift(xr)); % compute FFT for residual analysis
katkost@1 72 Xh = genspecsines(sloc,smag,sphase,Ns); % generate sines
katkost@1 73 Xr = Xr-Xh; % get the residual complex spectrum
katkost@1 74 mXr = 20*log10(abs(Xr(1:Ns/2+1))); % magnitude spectrum of residual
katkost@1 75 mXsenv = decimate(max(-200,mXr),stocf); % decimate the magnitude spectrum
katkost@1 76 % and avoid -Inf
katkost@1 77 %-----synthesis data-----%
katkost@1 78 ysloc = sloc; % synthesis locations
katkost@1 79 ysmag = smag(1:nS); % synthesis magnitudes
katkost@1 80 mYsenv = mXsenv; % synthesis residual envelope
katkost@1 81
katkost@1 82
katkost@1 83 %-----transformations-----%
katkost@1 84
katkost@1 85 %-----time mapping-----%
katkost@1 86 outsoundlength = soundlength*2;
katkost@1 87 TM=[ 0 soundlength/fs; % input time (sec)
katkost@1 88 0 outsoundlength/fs ]; % output time (sec)
katkost@1 89
katkost@1 90 %%-----frequency stretch-----%
katkost@1 91 %fstretch = 1.1;
katkost@1 92 %ysloc = ysloc .* (fstretch.^[0:length(ysloc)-1]');
katkost@1 93
katkost@1 94 %-----synthesis-----%
katkost@1 95 if (fridx==0)
katkost@1 96 lastysphase = ysphase;
katkost@1 97 end
katkost@1 98 if (nS>lastnS)
katkost@1 99 lastysphase = [ lastysphase ; zeros(nS-lastnS,1) ];
katkost@1 100 lastysloc = [ lastysloc ; zeros(nS-lastnS,1) ];
katkost@1 101 end
katkost@1 102 ysphase = lastysphase(lastidx(1:nS)) + 2*pi*(lastysloc(lastidx(1:nS))+ysloc)/2/Ns*H; % propagate phases
katkost@1 103 lastysloc = ysloc;
katkost@1 104 lastysphase = ysphase;
katkost@1 105 lastnS = nS; % update last frame data
katkost@1 106 lastsloc = sloc; % update last frame data
katkost@1 107 lastsmag = smag; % update last frame data
katkost@1 108 lastsphase = sphase; % update last frame data
katkost@1 109 Yh = genspecsines(ysloc,ysmag,ysphase,Ns); % generate sines
katkost@1 110 mYs = interp(mYsenv,stocf); % interpolate to original size
katkost@1 111 roffset = ceil(stocf/2)-1; % interpolated array offset
katkost@1 112 mYs = [ mYs(1)*ones(roffset,1); mYs(1:Ns/2+1-roffset) ];
katkost@1 113 mYs = 10.^(mYs/20); % dB to linear magnitude
katkost@1 114 pYs = 2*pi*rand(Ns/2+1,1); % generate phase spectrum with random values
katkost@1 115 mYs1 = [mYs(1:Ns/2+1); mYs(Ns/2:-1:2)]; % create complete magnitude spectrum
katkost@1 116 pYs1 = [pYs(1:Ns/2+1); -1*pYs(Ns/2:-1:2)]; % create complete phase spectrum
katkost@1 117 Ys = mYs1.*cos(pYs1)+1i*mYs1.*sin(pYs1); % compute complex spectrum
katkost@1 118 yhw = fftshift(real(ifft(Yh))); % sines in time domain using inverse FFT
katkost@1 119 ysw = fftshift(real(ifft(Ys))); % stochastic in time domain using IFFT
katkost@1 120 yh(ri:ri+Ns-1) = yh(ri:ri+Ns-1)+yhw(1:Ns).*sw; % overlap-add for sines
katkost@1 121 ys(ri:ri+Ns-1) = ys(ri:ri+Ns-1)+ysw(1:Ns).*sws; % overlap-add for stochastic
katkost@1 122 pin = pin+H; % advance the sound pointer
katkost@1 123 fridx = fridx+1;
katkost@1 124 end
katkost@1 125 y= yh+ys; % sum sines and stochastic