function au2=vdFeaExtractFromFile(au, vdOpt, showPlot) % vdFeaExtractFromFile: Feature extraction for a wave file % % Usage: % au2=vdFeaExtractFromFile(au); % au2=vdFeaExtractFromFile(au, vdOpt); % au2=vdFeaExtractFromFile(au, vdOpt, showPlot); % [au2, frameClass]=vdFeaExtractFromFile(au...); % % Example: % auFile='D:/dataset/vibrato/female/combined-female.wav'; % vdOpt=vdOptSet; % fea=vdFeaExtractFromFile(auFile, vdOpt, 1); % Category: Feature extraction for vibrato detection % Roger Jang, 20130106 if nargin<1, selfdemo; return; end if nargin<2, vdOpt=vdOptSet; end if nargin<3, showPlot=0; end if ischar(au), au=waveFile2obj(au); end au.signal=au.signal(:,1); % Channel 2 is usually the computed pitch (for groundtruth labeling) % === Pitch computation ptOpt=ptOptSet(au.fs, au.nbits, vdOpt.pfType); ptOpt.frameSize=vdOpt.frameSize; ptOpt.overlap=vdOpt.overlap; ptOpt.mainFun='maxPickingOverPf'; ptOpt.usePitchSmooth=0; pitchObj=pitchTrack(au, ptOpt, showPlot); pitch=pitchObj.pitch; % Pitch vector pitchRate = ptOpt.fs/(ptOpt.frameSize-ptOpt.overlap); % === Volume computation opt=wave2volume('defaultOpt'); opt.frameSize=vdOpt.frameSize; opt.overlap=vdOpt.overlap; volume=wave2volume(au, opt); % === Label the pitch vector pitchLen=length(pitch); pitchTime=(frame2sampleIndex(1:pitchLen, vdOpt.frameSize, vdOpt.overlap)-1)/au.fs; % The first sample starts at time 0. sFrameSize=round(pitchRate*vdOpt.sFrameSizeInSec); % super (big) frame for detecting vibrato sOverlap=round(pitchRate*vdOpt.sOverlapInSec); pFrame=buffer2(pitch, sFrameSize, sOverlap); vFrame=buffer2(volume, sFrameSize, sOverlap); sFrameNum=size(pFrame,2); sFrameTime=pitchTime(frame2sampleIndex(1:sFrameNum, sFrameSize, sOverlap)); % === Find frames without zero pitch invalidIndex=any(pFrame==0); % === Feature extraction feature=zeros(length(vdOpt.featureName), sFrameNum); for j=1:sFrameNum if ~invalidIndex(j) feature(:,j)=vdFeaExtractFromFrame(pFrame(:,j), vFrame(:,j), vdOpt); end end % === Get the groundtruth (if it exists) cueTime=wavCueRead(au.file); if isempty(cueTime) feature=[]; frameClass=[]; else interval=rangeSearchBin(sFrameTime, cueTime); frameClass=2-mod(interval, 2); % 1: non-vibrato, 2: vibrato end other.pitch=pitch; other.pitchTime=pitchTime; other.volume=volume; other.pFrame=pFrame; other.sFrameTime=sFrameTime; other.vFrame=vFrame; other.invalidIndex=invalidIndex; other.cueTime=cueTime; % === Put everything together for output au2=au; au2.feature=feature; au2.tOutput=frameClass; au2.other=other; if showPlot figure; plot(pitchTime, pitch); for j=1:length(cueTime) if mod(j, 2)==1 line(cueTime(j)*[1, 1], [min(pitch), max(pitch)], 'color', 'g'); else line(cueTime(j)*[1, 1], [min(pitch), max(pitch)], 'color', 'r'); end end if ~isempty(frameClass) line(sFrameTime, frameClass-1, 'color', 'r', 'marker', '.', 'linestyle', 'none'); % Plot all training data line(sFrameTime(~invalidIndex), frameClass(~invalidIndex)-1, 'color', 'k', 'marker', 'o', 'linestyle', 'none'); % Plot training data without zero-pitch end end % ====== Self demo function selfdemo mObj=mFileParse(which(mfilename)); strEval(mObj.example);