classdef FFMPEGDecoderAudioMetricItem < MetricItem
    
    methods (Abstract)
        m=calc_audio_metric(obj,y1,y2,fs)
    end
    
    
    methods
        function obj=FFMPEGDecoderAudioMetricItem(name)
            obj=obj@MetricItem(name);
        end
        
        function fl=getfilelist(obj,filemask)
            fl=dir(filemask);
        end
        
        function [Y1,Y2,fs]=import_wavs_to_matlab_and_align(obj,fname1,fname2)
            [Y1,FS1,NBITS1]=wavread(fname1);
            [Y2,FS2,NBITS2]=wavread(fname2);
            
            if FS1~=FS2
                error('%s and %s dont have the same sampling rates!',fname1,fname2);
            end
            
            fs=FS1;
            
            if NBITS1~=NBITS2
                error('%s and %s dont have the same bit depths!',fname1,fname2);
            end
            
            if size(Y1,2)~=size(Y2,2)
                error('%s and %s dont have the same number of channels!',fname1,fname2);
            end
            
            Y1mono=mean(Y1,2);
            Y2mono=mean(Y2,2);
            
            NCOMPMAX=3000;
            
            Y1mono=[zeros(NCOMPMAX,1); Y1mono; zeros(NCOMPMAX,1)];
            Y2mono=[zeros(NCOMPMAX,1); Y2mono; zeros(NCOMPMAX,1)];
            
            
            MINN=min(length(Y1mono),length(Y2mono));
            Y1mono=Y1mono(1:MINN);
            Y2mono=Y2mono(1:MINN);
            
            fprintf('Aligning %s and %s ...\n',fname1,fname2);
            
            minranges=round([32 64 128 256 512 1024]*0.95);
            maxranges=round([32 64 128 256 512 1024]*1.05);
            minranges=[-10 minranges];
            maxranges=[10 maxranges];
            
            mindiff=1E16;
            
            for irange=1:length(minranges)
                sstart=minranges(irange);
                send=maxranges(irange);
                
                
                for ipos=NCOMPMAX+sstart:NCOMPMAX+send
                    diff_l2=1/MINN*(sum(abs(Y1mono(NCOMPMAX:MINN-NCOMPMAX)- Y2mono(ipos:ipos+MINN-2*NCOMPMAX)).^2));
                    if diff_l2<mindiff
                        mindiff=diff_l2;
                        minpos=ipos;
                    end
                end
            end
            
            fprintf('Aligned by %d samples\n',minpos-NCOMPMAX);
            
            Y1=[zeros(NCOMPMAX,size(Y1,2)); Y1; zeros(NCOMPMAX,size(Y1,2))];
            Y2=[zeros(NCOMPMAX,size(Y1,2)); Y2; zeros(NCOMPMAX,size(Y1,2))];
            
            Y1=Y1(NCOMPMAX:MINN-NCOMPMAX,:);
            Y2=Y2(minpos:minpos+MINN-2*NCOMPMAX,:);
            
            if size(Y1,1)~=size(Y2,1)
                error('Aligned sizes are not the same, something went wrong');
            end
        end
        
        
        
        function val=calc(obj,item1,item2)
            [val,isCached]=obj.CheckCache(item1,item2);
            if ~isCached
                fprintf('Decoding audio .... \n');
                [item1decodedname,item2decodedname]=obj.decompressaudio(item1,item2);
                fprintf('Calculating audio metric .... \n');
                [Y1,Y2,fs]=obj.import_wavs_to_matlab_and_align(item1decodedname,item2decodedname);
                val=obj.calc_audio_metric(Y1,Y2,fs);
                obj.StoreToCache(item1,item2,val);
            end
        end
        
        
        function [item1decodedname,item2decodedname]=decompressaudio(obj,item1,item2)
            [fpathstr,fname1,fext] = fileparts(item1.getfilename);
            [fpathstr,fname2,fext] = fileparts(item2.getfilename);
            
            
            
            % TODO: check this !
            item1decodedname=sprintf('decodedaudio/decoded1_%s.wav',fname1);
            item2decodedname=sprintf('decodedaudio/decoded2_%s.wav',fname2);
            
            if ~exist('decodedaudio','dir')
                mkdir('decodedaudio');
            end
            
            if ~exist(item1decodedname,'file')
                dos(sprintf('ffmpeg -i %s %s',item1.getfilename,item1decodedname));
            end
            
            if ~exist(item2decodedname,'file')
                dos(sprintf('ffmpeg -i %s %s',item2.getfilename,item2decodedname));
            end
        end
    end
    
end