%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% .m script of web demo "Insert title here" 
% Written for GNU Octave
% 
% INSTITUTE OF TELECOMMUNICATIONS  
% University of Stuttgart 
% www.inue-uni-stuttgart.de 
% author: Alexander Knaub  
% date: 05.10.2016
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% This example script just prints the values of the given parameters.
% Make sure that the function prototype matches the prototype defined
% in the XML config file. (Parameter names are arbitrary but should be the same
% for better readability)

function [oversampling_used, pdf_link] = ...
    inout_behav(...
	type,...
        range, ... 
        clipping, ...
        n_steps,... 
        zero_behav,... 
        round_opt,... 
        method,... 
        io_only,... 
        filename)

if is_octave()
    
end

tikz_ena = 0;

if ~tikz_ena
    % define formats
    landscape = '-S930,350';
    portrait  = '-S640,480';

    % select format
    output_format = portrait;

    % Create an invisible figure.
    fh = figure(1);
    set(fh, "visible", "off");

    % define style
    set(0, 'defaultlinelinewidth', 2);
    set(0, 'defaultaxesfontsize', 8);
    set(0, 'defaultaxesfontname', 'Helvetica');
    set(0, 'defaulttextfontsize', 8);
    set(0, 'defaulttextfontname', 'Helvetica');
end

magenta_my = [255,102,255]/255;
gray_my = [200,200,200]/255;

%  n_steps = 8;
n_samples = 2000;

x_in = linspace(-2*range,2*range, n_samples);

% do clipping if necessary:
x_clip = x_in;
x_clip(abs(x_in) > clipping) = sign(x_in(abs(x_in)>clipping)) * clipping;

% prepare the quantization parameters:
x_range = 2*max(abs(x_clip));
quantization_step = x_range/(n_steps);

if (~strcmp(method, 'round')  && ~strcmp(method, 'dn'))
    fprintf('Unknown method %s! Applying rounding.', method)
    method = 'round';
end



if strcmp(method, 'round')
%      x_norm = x_norm*(1 - eps * (1+eps));
%      x_quant = sign(x) .* floor(abs(x)/quantization_step)*quantization_step;
    fprintf('Quantization by rounding\n')
    
    if strcmp(zero_behav, 'riser')
        fprintf('Mid-riser behavior\n')
        
        
        if mod(n_steps, 2) == 0
            
            x_quant = floor((x_clip)/quantization_step)*quantization_step + 0.5*quantization_step;
            % make sure that we have correct number of steps:
            x_quant(x_quant > quantization_step*(n_steps/2 - 0.5))... 
                = quantization_step * (n_steps/2 - 0.5);
        else
            quantization_step = x_range/(n_steps+1)
            x_quant = floor((x_clip)/quantization_step)*quantization_step + 0.5*quantization_step;
            
            % make sure that we have correct number of steps:
            x_quant(x_quant > quantization_step*((n_steps-1)/2 - 0.5))... 
                = quantization_step*((n_steps-1)/2 - 0.5);
            if round_opt 
                scaling_factor = quantization_step * ((n_steps-1)/2) / clipping
                clipping = scaling_factor*clipping;
            end
        end
    else
        fprintf('Mid-tread behavior\n')
        
        if mod(n_steps, 2) == 0
            quantization_step = x_range/(n_steps+1)
            if round_opt % && mod(n_steps, 2) == 0
                fprintf('Rescaling for better rounding...\n');
                % renormalize the signal so that it lies within a smaller range:
                scaling_factor = quantization_step * (n_steps/2-0.5) / max(abs(x_clip))
%                  x_clip = x_clip * scaling_factor;
%                  x_in = x_in * scaling_factor;
                clipping = scaling_factor*clipping;
            end
            x_quant = floor((x_clip)/quantization_step+0.5)*quantization_step;
            % make sure, the range after quantizing is [-N/2 ... N/2-1]:
            x_quant(x_quant > quantization_step*(n_steps/2 - 1))... 
                = quantization_step * (n_steps/2 -1);
        else
            quantization_step = x_range/(n_steps)
            x_quant = floor((x_clip)/quantization_step+0.5)*quantization_step;
            % make sure, the range after quantizing is [-N/2 ... N/2-1]:
            x_quant(x_quant > quantization_step*(n_steps/2 - 0.5))... 
                = quantization_step * (n_steps/2 -0.5);
        end
    end
    
else
    % Only 'dn' as method remains 
    if strcmp(zero_behav, 'riser')
        fprintf('Mid-riser behavior\n')
        x_quant = floor((x_clip)/quantization_step)*quantization_step;
        if mod(n_steps, 2) == 0
            x_quant(x_quant > quantization_step*(n_steps/2 - 1))... 
                = quantization_step * (n_steps/2 - 1);
        else
            x_quant(x_quant < -quantization_step*((n_steps-1)/2))... 
                = -quantization_step * ((n_steps-1)/2);
        end
    else
        fprintf('Mid-tread behavior\n');
        x_quant = floor((x_clip)/quantization_step+0.5)*quantization_step - 0.5*quantization_step; 
        if mod(n_steps, 2) == 0 
            x_quant(x_quant > quantization_step*(n_steps/2 - 0.5))... 
                = quantization_step * (n_steps/2 - 0.5);
            x_quant(x_quant < -quantization_step*(n_steps/2 - 0.5))... 
                = -quantization_step * (n_steps/2 - 0.5);
        else
            x_quant(x_quant > quantization_step*(n_steps/2 - 1))... 
                = quantization_step * (n_steps/2 - 1);
        end
    end
    
end

%p_signal = (clipping^2)/12;

used_signal = x_in(abs(x_in) <= clipping);
p_signal  = mean(used_signal.^2);

quantization_error = x_quant-x_in;
noise = quantization_error(abs(x_in) <= clipping);
p_noise = mean(noise.^2);


if tikz_ena
    tic
    toc
else
    pdf_link = '';
    % Plot into the figure
    tic
    
    outside_color = gray_my;
    plot(0,0,'color', [1 1 1]);
    
    hold all; axis equal; grid on; 
    xlim([[-range, range]]);
    ylim([[-range, range]]);
    xlabel('Input x_k')
    ylabel('Output y_k=q(x_k)')
    
    if ~io_only
        rectangle('Position', [-range, -range, -clipping+range, 2*range], ...
                'FaceColor', outside_color, 'EdgeColor', outside_color)
        rectangle('Position', [clipping, -range, range, 2*range], ...
                'FaceColor', outside_color, 'EdgeColor', outside_color)
        rectangle('Position', [-range, -range, 2*range, -clipping+range], ...
                'FaceColor', outside_color, 'EdgeColor', outside_color)
        rectangle('Position', [-range, clipping, 2*range, range], ...
                'FaceColor', outside_color, 'EdgeColor', outside_color)
        
        in_plot = plot(x_in, x_in, 'g');
        
        err_plot = plot(x_in, quantization_error, 'r');
        
        clip_plot = plot(x_in, x_clip, 'b:');
        
        quant_plot = plot(x_in, x_quant, 'k');
        legend([in_plot, clip_plot, quant_plot, err_plot],... 
                {'input', 'clipped', 'output', 'error'},...
                'location', 'southeastoutside')
    else
        quant_plot = plot(x_in, x_quant, 'k');
    end
    
    
    
    
    
    
    
    
    title(sprintf('Quantization step: q=%0.2f; SQNR = %0.2fdB',... 
                quantization_step, 10*log10(p_signal/p_noise)))
    toc


    % Create an image file. This png image is displayed on the webpage. Its size 
    % must be 640x480.

    print(filename, '-dpng', output_format);
    %  print(filename, '-dpng');
    %  print([filename '.pdf'], '-dpdf', '-color');
end

end

%% subfunction that checks if we are in octave
function r = is_octave()
  persistent x;
  if (isempty (x))
    x = exist ('OCTAVE_VERSION', 'builtin');
  end
  r = x;
end
