function [Wme, detectiontime] = Detection(watermarked_signal, filename);
% Detecting the watermark from the received signal and display it
% INPUT:  watermarked_signal - the watermarked signal

Common_para;
[temp_r,temp_c] = size(watermarked_signal);
if temp_r~=1
    watermarked_signal = watermarked_signal';
end
N = length(watermarked_signal);

% Get the necessary information for embedding
fid = fopen(['Para_', filename,'.dat'],'r');
N_em = fscanf(fid,'%d\n',1);     % The length of the embedding watermark
N_block = fscanf(fid,'%d\n',1);  % The number of blocks required for embedding
Nwm_diff = fscanf(fid,'%d\n',1); % redundant bits
fclose(fid);

% for pattern block synchronization
threshold = 36;

% Preparation
fid = fopen(['Positions_', filename,'.dat'],'r');
Positions = fscanf(fid,'%4d\n');
fclose(fid);

fid = fopen(['PNs_', filename,'.dat'],'r');
PNs = fscanf(fid,'%4d\n');
fclose(fid);

fid = fopen(['subbands_', filename,'.dat'],'r');
subbands = fscanf(fid,'%4d\n');
fclose(fid);

% Work on the configuration of MB and MPR
% For watermark bit
% Locate the slots for each watermark bit and find their PNs
count = 1;  
for i = 1 : N_bit
    for j = 1 : tiles_w
        P_wm(i,j) = Positions(count);
        PNs_wm(i,j) = PNs(count);
        count = count + 1;
    end
end

% For synchronization bit
% Locate the slots for sync bit and also fill in the corresonding PN in each position  
temp_sync = zeros( N_s, N_u );   
for i = 1 : tiles_s
    row    = ceil( Positions(count)/N_u  );
    column =  rem( Positions(count), N_u );
    if column == 0
        column = column + N_u;
    end
    temp_sync(row,column) = PNs(count);
    count = count + 1;
end

m = 1;
for i = 1 : N_u
    n = 1;
    for j = 1 : N_s
        if temp_sync(j,i) ~= 0
            % Each row of P_sync includes the positions of slots for sync bit per unit
            P_sync(m,n) = j; 
            % The corresponding PNs
            PNs_sync(m,n) = temp_sync(j,i);
            n = n + 1;
        end
    end
    % Each number of N_sync denotes for the number of slots for sync bits per unit
    N_sync(m) = length(find(P_sync(i,:)));   
    m = m + 1;
end  

% Detection starts. 
msgbox('Detection starts!', 'Monitoring Detection', 'replace');
tic;

halfsize = N_frame/2;
d_sync = [];
Nb_period = [ N_block ];
Q_period  = [ N_block+1 ];
period = [1, N];
for nb = 1 : length(Q_period)
    index = 1;          % for the first time
    flag  = 1;
    i = 1;              % for counting the frame
    j = 0;              % for counting the unit
    k = 1;              % for counting the pattern block
    p = period(nb,1);   % pointer
    m = 0;              % for counting the frames per period
    Pt_f = [];
    while flag == 1
        % Process frame by frame
        if index == 1   % the first frame is special                       
            temp  = watermarked_signal( p : p+N_frame-1);
            index = 0;
            frame = temp; 
        else
            temp  = watermarked_signal( p+halfsize : p+N_frame-1 );
            if length(temp) == 0
                disp('Finish!');
                break;
            end
            if length(temp) ~= halfsize
                flag = 0;
                disp('Sample are insufficient and zeros will be padded!');
                temp = [temp, zeros(1,halfsize-length(temp))];
            end
            for count = 1 : halfsize
                frame(count) = frame(halfsize + count);
                frame(count + halfsize) = temp(count);
            end
        end  
    
%         % Windowing & DFT 
%         frame_w = frame .* hanning(N_frame)';   
%         % Get the magnitude
%         FD_frame = abs(fft(frame_w));    
        FD_frame = [];    % initialise
        FD_frame = abs( fft(frame.*hanning(N_frame)') );
        
        FD_frame = FD_frame(1:halfsize);

        % Normalization by the average
        factor = 0;
        for count = 1 : halfsize
            factor = factor + FD_frame(count) ;
        end
        factor = factor/halfsize;
        
        if factor ~= 0 
            m = m + 1; 
        
            % Calculate the logarithmic magnitude 
            % NB: If there are zeros in FD_frame, warning will occur.
            Pt_f(m,:) = 20 * log10(FD_frame/factor); 
            
            % Per unit
            if i >= 4         
                i = 0;
                j = j+1; 
            end
            i = i + 1; 
            p = p + halfsize;
        else
            p = p + N_frame;
        end
                    
        % Per pattern block
        if j >= N_u  
            if IsDsiplay
%                 fprintf('The %dth pattern block is finished. \n', k);
                msgbox(['Processing the' num2str(k), 'th pattern block'], 'Monitoring Detection', 'replace');
            end
            j = 0;
            k = k + 1;
            % Per period
            if k > Q_period(nb) 
                if IsDsiplay
%                     disp('Finish calculating Pt,f!');
                    msgbox('Finish calculating Pt,f!', 'Monitoring Detection', 'replace');
                end
                break;
            end
        end
    end
    
    dPt_f = [];
    [rP, cP] = size(Pt_f);
    % Calculate dt_f for amplifying the effect of modulus operator
    for i = 1 : rP
        if i <= rP - 2
            dPt_f(:,i) = [Pt_f(i,:) - Pt_f(i+2,:)]';
        else
            dPt_f(:,i) = Pt_f(i,:)';
        end
    end
    if IsDsiplay
%         disp('Finish calculating dPt,f!');
        msgbox('Finish calculating dPt,f!', 'Monitoring Detection', 'replace');
    end

    % Calculate the magnitude of tiles
    [rdP, cdP] = size(dPt_f);
    Qt_b = zeros(N_s, cdP);
    for i = 1 : N_s
        for j = subbands(2*i-1) : subbands(2*i)   % fl : fh
            Qt_b(i,:) = Qt_b(i,:) + dPt_f(j,:); 
        end
        Qt_b(i,:)= Qt_b(i,:)/( subbands(2*i)-subbands(2*i-1)+1 ); 
    end
    if IsDsiplay
%         disp('Finish calculating Qt,b!');
        msgbox('Finish calculating Qt,b!', 'Monitoring Detection', 'replace');
    end
    [Qr, Qc] = size(Qt_b);
        
    % Pattern block synchronization
    if IsDsiplay
%         disp('Pattern block synchronization begins!');
        msgbox('Pattern block synchronization begins', 'Monitoring Detection', 'replace');
    end
    flag_s = 0;
    count_s = 1;
    misalign = [];             % the amount of misalignment
    m_position = [];           % the position where misalignment happens
    n = 1;
    while n <= Nb_period(nb)
        if IsDsiplay
%             fprintf('The %dth pattern block starts. \n', n);
            msgbox(['Processing the' num2str(n), 'th pattern block ... '], 'Monitoring Detection', 'replace');
        end
        count = 1;
        for m = 1 : N_u        % Per unit
            for i = 1 : N_bit  % Per watermark bit
                aver_Q = 0.0;
                p = 1;
                q = 1;
                for j = 1 : N_u    
                    for k = 1 : N_sync(j) 
                        row = P_sync(j,k);
                        column = p + i - 1 + ( m-1 ) * 4 + (n-1) * (4*N_u);
                        if flag_s
                            column = column - sum(misalign);
%                             column = column + sum(misalign);  % for positive PITS
                        end
                        if column < 1 || column > Qc            % If exceed the dimension, take zero.
                            Qtb = 0;
                        else
                            Qtb = Qt_b(row,column);
                        end
                        aver_Q = aver_Q + Qtb;
                        Qt_b_temp(q) = Qtb;
                        PNs_sync_temp(q) = PNs_sync(j,k);
                        q = q + 1;
                    end
                    p = p + 4;
                end
                aver_Q = aver_Q/tiles_s;
                temp1 = 0.0;
                temp2 = 0.0;
                for r = 1 : tiles_s
                    temp1 = temp1 + PNs_sync_temp(r) * ( Qt_b_temp(r) - aver_Q );
                    temp2 = temp2 + ( PNs_sync_temp(r) * ( Qt_b_temp(r) - aver_Q ) )^2;
                end
                Sd(count) = temp1/sqrt(temp2);
                count = count + 1;
            end
        end
        Sd_max(nb,n) = max(Sd);
        d_sync(nb,n) = find( Sd==max(Sd) );            % the maximum sychronization strength
        % For cropping, the starting frame becomes the (Nu_frames - d_sync(nb,n) + 1)th frame
        % For zeros inserting, don't care.
        if d_sync(nb,n) >= threshold                   % cropping occurs
            flag_s = 1;
            misalign(count_s) = Nu_frames - d_sync(nb,n) + 1;
            m_position(count_s) = n;                     
            count_s = count_s + 1;
            n = n - 1 ;                                % repeat for this block untill meet the requirement
        end
        n = n + 1;
    end 
    
    % Try to find out where the croppings occur from m_position[]
    % So only keep the transitions and put in temp_tmp[]
    temp_tmp = [];
    count1 = 1;                                        % a temporary counter
    for i = 1 : length(m_position)
        if i == 1
            temp_tmp(count1) = m_position(i);
            count1 = count1 + 1;
        else 
            if m_position(i) ~= temp_tmp(count1-1)
                temp_tmp(count1) = m_position(i);
                count1 = count1 + 1;
            end
        end
    end
    
    % Accumulate the misalignment of one position
    count1 = 1;
    count2 = 1;
    temp_ma = [];
    temp_mp = [];
    i = 1;
    while i <= length(m_position)
        if m_position(i) == temp_tmp(count1)
            temp_ma(count2) = misalign(i);
            count2 = count2 + 1;
        else
            count2 = 1;
            temp_mp(count1) = sum(temp_ma);
            temp_ma = [];
            count1 = count1 + 1;
            i = i - 1;
        end
        i = i + 1;
    end   
    temp_mp(count1) = sum(temp_ma);
    misalign = [];
    misalign = temp_mp;

    m_position = [];
    m_position = temp_tmp;
    N_mp = length(m_position);
    
    % Initialise
    flag_s = 0;
    count_s = 1;
    i = 1;
    
    % Bit detection
    while i <= ( Nb_period(nb))                        % process every bit
        if count_s <= N_mp
            if i == m_position(count_s)
                flag_s = 1;
                count_s = count_s + 1;
            end
        end            
        for j = 1 : N_bit
            aver_Q = 0.0;
            for k = 1 : tiles_w                        % find all the tiles assigned to one bit
                row = ceil(P_wm(j,k)/N_u);         
                column_temp = rem( P_wm(j,k) , N_u );     
                if column_temp == 0
                    column_temp = column_temp + N_u;
                end
                column = (i-1)*N_u*4 + (column_temp-1)*4 + d_sync(nb,i);
                if flag_s
                    column = column - sum(misalign(1:count_s-1));
                end 
                if column < 1 || column > Qc
                    Qtb = 0;
                else
                    Qtb = Qt_b(row,column);
                end
                aver_Q = aver_Q + Qtb;
                Qt_b_temp(k) = Qtb;
            end
            aver_Q = aver_Q/tiles_w; 
            temp1 = 0.0;
            temp2 = 0.0;
            for k = 1 : tiles_w
                temp1 = temp1 + PNs_wm(j,k)*( Qt_b_temp(k) - aver_Q );
                temp2 = temp2 + (  PNs_wm(j,k) * (Qt_b_temp(k) - aver_Q)  )^2;
            end
            G(nb,(i-1)*4+j) = temp1/sqrt(temp2);
            if G(nb,(i-1)*4+j) < 0
                Bit_temp(nb,(i-1)*4+j) = 0;
            else
                Bit_temp(nb,(i-1)*4+j) = 1;
            end
        end
        i = i + 1;
    end
end

detectiontime = toc;
msgbox(['Detection has completed!' ], 'Monitoring Detection', 'replace');

% Combine all the recovered bits
Bit = [];
for i = 1 : length(Nb_period)
    Bit = [Bit,Bit_temp(i,1:Nb_period(i)*4)];
end

% For some redundant bits probably were added in the embedding, 
% we only take the first N_em bits 
Wme = Bit( 1:(N_em-Nwm_diff) );
% fid = fopen('Wm_detected.dat','w');
% fprintf(fid,'%d\n',Wme);
% fclose(fid);

return;
