function X = synthesize_chroma(Chroma,Times,SR) % X = synthesize_chroma(Chroma,Times,SR,npks) % Resynthesize a chroma feature vector to audio % Chroma is 12 rows x some number of columns, one per beat % Times is vector of beat times % SR is the sampling rate of the output waveform % X is returned as a 12 semitone-spaced Shepard tones modulated % by Chroma. % 2010-04-07 dpwe@ee.columbia.edu after chromsynth2.m if nargin < 2; Times = 0.5; end % 120 bpm if nargin < 3; SR = 22050; end [nchr,nbts] = size(Chroma); if length(Times) == 1 % just period, not times Times = cumsum(Times * ones(1,nbts)); end % Select only local maxima, with wrapping around edges Xm = (Chroma > Chroma([2:nchr,1],:)) & (Chroma >= Chroma([nchr,1:nchr-1],:)); Chroma = Xm.*Chroma; if length(Times) < (nbts+1) % +1 to have end time of final note(s) ? medbt = median(diff(Times)); Times = [Times, Times(end)+medbt*[1:((nbts+1)-length(Times))]]; end % crossfade overlap time dt = 0.01; dtsamp = round(dt*SR); % Generate 12 basic shepard tones dur = max(diff([0,Times])); % max duration dursamp = round(dur*SR); nchr = 12; octs = 10; basefrq = 27.5*(2^(3/12)); % A1+3 semis = C2; tones = zeros(nchr, dursamp + 2*dtsamp + 1); tt = [0:(size(tones,2)-1)]/SR; % what bin is the center freq? f_ctr = 880; f_sd = 1; f_bins = basefrq*2.^([0:(nchr*octs - 1)]/nchr); f_dist = log(f_bins/f_ctr)/log(2)/f_sd; % Gaussian weighting centered of f_ctr, with f_sd %if (dowt) f_wts = exp(-0.5*f_dist.^2); %else % % flat weights % f_wts = ones(1,length(f_dist)); %end % Sum up sinusoids for i = 1:nchr for j = 1:octs bin = nchr*(j-1) + i; omega = 2* pi * f_bins(bin); tones(i,:) = tones(i,:)+f_wts(bin)*sin(omega*tt); end end % resynth X = zeros(1,round(max(Times)*SR)); ee = round(SR*Times(1)); for b = 1:nbts-1 ss = ee+1; ee = round(SR * Times(b+1)); twin = 0.5*(1-cos([0:dtsamp-1]/(dtsamp-1)*pi)); twin = [twin,ones(1,ee-ss+1),fliplr(twin)]; sss = ss - dtsamp; eee = ee + dtsamp; if eee > length(X) twin = twin(1:end-(eee-length(X))); eee = length(X); end if sss < 1 twin = twin((2-sss):end); sss = 1; end ll = 1+eee-sss; dd = zeros(1,ll); for i = 1:nchr if Chroma(i,b)>0 dd = dd + Chroma(i,b)*tones(i,1:ll); end end X(sss:eee) = X(sss:eee) + twin .* dd; end