% This function returns the signal values on a given time resolution. It also
% generates the noise on the same grid.
% the user can specify either the required time resolution (in sec) or the
% required number of points in the signal duration (in which case TimeRes=-1).

function [SignalAmp, NoiseAmp, TimeAxis] = GenerateSignalValues(Signal,TimeRes,Npts,handles)

% define the time-axis
% we don't plot the signal on its entire duration since it will consume too
% much time...
% Duration= getfield(Signal.Values, 'SignalDuration');  

TimeAxis = 0:TimeRes:((Npts-1)*TimeRes);  
dt = TimeRes;

% read signal parameters
N       = getfield(Signal.Structure, 'N');
B       = getfield(Signal.Structure, 'B');
fmax    = getfield(Signal.Structure, 'fmax');

SignalType = getfield(Signal.Structure, 'Type');
Carriers = getfield(Signal.Values, 'Carriers');

% generate signal amplitudes
SignalAmp = zeros(size(TimeAxis));
if (strmatch(SignalType, 'sinc'))
    Energy = getfield(Signal.Values, 'SincEnergies');
    Delay = getfield(Signal.Values, 'SincDelays');
    for n=1:(N/2)
        SignalAmp = SignalAmp+sqrt(Energy(n)) * sqrt(B)*sinc(B*(TimeAxis-Delay(n))) .* cos(2*pi*Carriers(n)*(TimeAxis-Delay(n)));
        updateProgBar(n,handles,N);
    end
elseif (strmatch(SignalType, 'bpsk'))
    Tsymbol = getfield(Signal.Structure, 'BPSK_Tsymbol');
    NumSymbols = getfield(Signal.Structure, 'BPSK_NumSymbols');
    BitStream = getfield(Signal.Values, 'BitStream');
    Energy = getfield(Signal.Values, 'BPSKEnergies');
    for n=1:(N/2)
        xBB = zeros(size(TimeAxis));
        for symInd = 1:NumSymbols   % can improve by creating only delat[n] and filtering with the sinc or rcosine functions
            symPoint = (symInd-1)*Tsymbol;
            xBB = xBB + BitStream(n,symInd)*sinc((TimeAxis-symPoint)/Tsymbol);
            if mod(symInd,10)==1
                updateProgBar((n-1)*NumSymbols+symInd,handles,N*NumSymbols);
            end
        end
        SignalAmp=SignalAmp+sqrt(2*Energy(n)*B)*xBB.*cos(2*pi*Carriers(n)*TimeAxis);
    end
elseif (strmatch(SignalType, 'qpsk'))
    Tsymbol = getfield(Signal.Structure, 'QPSK_Tsymbol');
    NumSymbols = getfield(Signal.Structure, 'QPSK_NumSymbols');
    BitStreamI = getfield(Signal.Values, 'BitStreamI');
    BitStreamQ = getfield(Signal.Values, 'BitStreamQ');
    Energy = getfield(Signal.Values, 'QPSKEnergies');
    for n=1:(N/2)
        xBBI = zeros(size(TimeAxis));
        xBBQ = zeros(size(TimeAxis));
        for symInd = 1:NumSymbols   % can improve by creating only delat[n] and filtering with the sinc or rcosine functions
            symPoint = (symInd-1)*Tsymbol;
            xBBI = xBBI + BitStreamI(n,symInd)*sinc((TimeAxis-symPoint)/Tsymbol);
            xBBQ = xBBQ + BitStreamQ(n,symInd)*sinc((TimeAxis-symPoint)/Tsymbol);
            if mod(symInd,10)==1
            updateProgBar((n-1)*NumSymbols+symInd,handles,N*NumSymbols);
            end
        end
        SignalAmp=SignalAmp+sqrt(2*Energy(n)*B)*(xBBI.*cos(2*pi*Carriers(n)*TimeAxis)+xBBQ.*sin(2*pi*Carriers(n)*TimeAxis));
    end
end

% Now generate noise and scale to desired SNR
% This code works on 2009a
% savedState = getfield(Signal.Values, 'SavedRNDStateForNoiseGen');
% defaultStream = RandStream.getDefaultStream;
% defaultStream.State = savedState;
% for compatability we use instead the old method
randn('state',getfield(Signal.Values, 'SavedRandnStateForNoiseGen'));
rand('state',getfield(Signal.Values, 'SavedRandStateForNoiseGen'));

noise_wideband = randn(size(TimeAxis));
fnyquist = 2*fmax;
if (fnyquist < 1/dt)  % the time resolution is higher than the Nyquist rate, so we need to reject the noise beyond fmax
    noise_unscaled = filter(fir1(3500,2*fmax/(1/dt)),1,noise_wideband);
else
    noise_unscaled = noise_wideband;
end
NoiseEnergy = norm(noise_unscaled)^2;
SignalEnergy = norm(SignalAmp)^2;
CurrentSNR = SignalEnergy/NoiseEnergy;
SNR_dB = getfield(Signal.Structure, 'SNR');
SNR_val = 10^(SNR_dB/10);
NoiseAmp = noise_unscaled*sqrt(CurrentSNR/SNR_val);



% % This function returns the signal values on a given time resolution. It also
% % generates the noise on the same grid.
% % the user can specify either the required time resolution (in sec) or the
% % required number of points in the signal duration (in which case TimeRes=-1).
% 
% function [SignalAmp, NoiseAmp, TimeAxis] = GenerateSignalValues(Signal,TimeRes,Npts,handles)
% 
% % define the time-axis
% Duration= getfield(Signal.Values, 'SignalDuration');
% if (TimeRes > 0)
%     TimeAxis = 0:TimeRes:Duration;
% else
%     TimeAxis = linspace(0,Duration,Npts);
% end
% dt = TimeAxis(2)-TimeAxis(1);
% 
% % read signal parameters
% N       = getfield(Signal.Structure, 'N');
% B       = getfield(Signal.Structure, 'B');
% fmax    = getfield(Signal.Structure, 'fmax');
% 
% SignalType = getfield(Signal.Structure, 'Type');
% Carriers = getfield(Signal.Values, 'Carriers');
% 
% % generate signal amplitudes
% SignalAmp = zeros(size(TimeAxis));
% if (strmatch(SignalType, 'sinc'))
%     Energy = getfield(Signal.Values, 'SincEnergies');
%     Delay = getfield(Signal.Values, 'SincDelays');
%     for n=1:(N/2)
%         SignalAmp = SignalAmp+sqrt(Energy(n)) * sqrt(B)*sinc(B*(TimeAxis-Delay(n))) .* cos(2*pi*Carriers(n)*(TimeAxis-Delay(n)));
%         updateProgBar(n,handles,N);
%     end
% elseif (strmatch(SignalType, 'bpsk'))
%     Tsymbol = getfield(Signal.Structure, 'BPSK_Tsymbol');
%     NumSymbols = getfield(Signal.Structure, 'BPSK_NumSymbols');
%     BitStream = getfield(Signal.Values, 'BitStream');
%     Energy = getfield(Signal.Values, 'BPSKEnergies');
%     for n=1:(N/2)
%         xBB = zeros(size(TimeAxis));
%         for symInd = 1:NumSymbols   % can improve by creating only delat[n] and filtering with the sinc or rcosine functions
%             symPoint = (symInd-1)*Tsymbol;
%             xBB = xBB + BitStream(n,symInd)*sinc((TimeAxis-symPoint)/Tsymbol);
%         end
%         SignalAmp=SignalAmp+sqrt(2*Energy(n)*B)*xBB.*cos(2*pi*Carriers(n)*TimeAxis);
%     updateProgBar(n,handles,N);
%     end
% elseif (strmatch(SignalType, 'qpsk'))
%     Tsymbol = getfield(Signal.Structure, 'QPSK_Tsymbol');
%     NumSymbols = getfield(Signal.Structure, 'QPSK_NumSymbols');
%     BitStreamI = getfield(Signal.Values, 'BitStreamI');
%     BitStreamQ = getfield(Signal.Values, 'BitStreamQ');
%     Energy = getfield(Signal.Values, 'QPSKEnergies');
%     for n=1:(N/2)
%         xBBI = zeros(size(TimeAxis));
%         xBBQ = zeros(size(TimeAxis));
%         for symInd = 1:NumSymbols   % can improve by creating only delat[n] and filtering with the sinc or rcosine functions
%             symPoint = (symInd-1)*Tsymbol;
%             xBBI = xBBI + BitStreamI(n,symInd)*sinc((TimeAxis-symPoint)/Tsymbol);
%             xBBQ = xBBQ + BitStreamQ(n,symInd)*sinc((TimeAxis-symPoint)/Tsymbol);
%         end
%         SignalAmp=SignalAmp+sqrt(2*Energy(n)*B)*(xBBI.*cos(2*pi*Carriers(n)*TimeAxis)+xBBQ.*sin(2*pi*Carriers(n)*TimeAxis));
%         updateProgBar(n,handles,N);
%     end
% end
% 
% % Now generate noise and scale to desired SNR
% defaultStream.State = getfield(Signal.Values, 'SavedRNDStateForNoiseGen');
% noise_wideband = randn(size(TimeAxis));
% fnyquist = 2*fmax;
% if (fnyquist < 1/dt)  % the time resolution is higher than the Nyquist rate, so we need to reject the noise beyond fmax
%     noise_unscaled = filter(fir1(3500,2*fmax/(1/dt)),1,noise_wideband);
% else
%     noise_unscaled = noise_wideband;
% end
% NoiseEnergy = norm(noise_unscaled)^2;
% SignalEnergy = norm(SignalAmp)^2;
% CurrentSNR = SignalEnergy/NoiseEnergy;
% SNR_dB = getfield(Signal.Structure, 'SNR');
% SNR_val = 10^(SNR_dB/10);
% NoiseAmp = noise_unscaled*sqrt(CurrentSNR/SNR_val);
% 
% function updateProgBar(k,handles,N)
% loopsize=1:(N/2);
%     if k/length(loopsize) >=1/12 && k/length(loopsize) <2/12
%         set(handles.progressBarBoxaxes1,'Color',[0 0.4 0.6]);
%     elseif k/length(loopsize) >=2/12 && k/length(loopsize) <3/12
%         set(handles.progressBarBoxaxes2,'Color',[0 0.4 0.6]);
%     elseif k/length(loopsize) >=3/12 && k/length(loopsize) <4/12
%         set(handles.progressBarBoxaxes3,'Color',[0 0.4 0.6]);
%     elseif k/length(loopsize) >=4/12 && k/length(loopsize) <5/12
%         set(handles.progressBarBoxaxes4,'Color',[0 0.4 0.6]);
%     elseif k/length(loopsize) >=5/12 && k/length(loopsize) <6/12
%         set(handles.progressBarBoxaxes5,'Color',[0 0.4 0.6]);
%     elseif k/length(loopsize) >=6/12 && k/length(loopsize) <7/12
%         set(handles.progressBarBoxaxes6,'Color',[0 0.4 0.6]);
%     elseif k/length(loopsize) >=7/12 && k/length(loopsize) <8/12
%         set(handles.progressBarBoxaxes7,'Color',[0 0.4 0.6]);
%     elseif k/length(loopsize) >=8/12 && k/length(loopsize) <9/12
%         set(handles.progressBarBoxaxes8,'Color',[0 0.4 0.6]);
%     elseif k/length(loopsize) >=9/12 && k/length(loopsize) <10/12
%         set(handles.progressBarBoxaxes9,'Color',[0 0.4 0.6]);
%     elseif k/length(loopsize) >=10/12 && k/length(loopsize) <11/12
%         set(handles.progressBarBoxaxes10,'Color',[0 0.4 0.6]);
%     elseif k/length(loopsize) >=11/12 && k/length(loopsize) <12/12
%         set(handles.progressBarBoxaxes11,'Color',[0 0.4 0.6]);
%     elseif k/length(loopsize) >=12/12
%         set(handles.progressBarBoxaxes12,'Color',[0 0.4 0.6]);
%     end  
%    set(handles.uneditProgPrecent,'String',[num2str(100*k/length(loopsize)) '%']);     