% This function takes a structure defining the parameters of the signal,
% and generate another structure which determine the values of the signal
% (analytically).

function Signal = GenerateSignal(SigStruct)
Signal = struct;

% embed the structure
Signal = setfield(Signal, 'Structure', SigStruct); %#ok<*SFLD>

% draw/update values
Values = struct;

N = getfield(SigStruct, 'N');
B = getfield(SigStruct, 'B');
fmax = getfield(SigStruct, 'fmax');
if (strmatch(getfield(SigStruct,'Type'), 'sinc'))
    if (strmatch(getfield(SigStruct,'SincEnergies'), 'random'))
        Energies = DrawUniform([N/2 1],1,3);
    elseif (strmatch(getfield(SigStruct,'SincEnergies'), 'specify'))
        EnergiesStr = getfield(SigStruct,'SincEnergiesString');
        Energies = str2num(EnergiesStr);
    end
    Values = setfield(Values, 'SincEnergies', Energies);
    
    SignalDuration = getfield(SigStruct,'SincDuration');
    Values = setfield(Values, 'SignalDuration', SignalDuration);
    
    if (strmatch(getfield(SigStruct,'SincDelays'), 'random'))
        Delays = DrawUniform([N/2 1],0,SignalDuration);
    elseif (strmatch(getfield(SigStruct,'SincDelays'), 'specify'))
        DelayString = getfield(SigStruct,'SincDelayString');
        Delays = str2num(DelayString);
    end
    Values = setfield(Values, 'SincDelays', Delays);
elseif (strmatch(getfield(SigStruct,'Type'), 'bpsk'))
    NumSymbols = getfield(SigStruct, 'BPSK_NumSymbols');
    BitStream = RandSource(N/2,NumSymbols);
    Values = setfield(Values, 'BitStream', BitStream);
    if (strmatch(getfield(SigStruct,'BPSKEnergies'), 'random'))
        Energies = DrawUniform([N/2 1],1,3);
    elseif (strmatch(getfield(SigStruct,'BPSKEnergies'), 'specify'))
        EnergiesStr = getfield(SigStruct,'BPSKEnergiesString');
        Energies = str2num(EnergiesStr);
    end
    Values = setfield(Values, 'BPSKEnergies', Energies);
    Tsymbol = getfield(SigStruct,'BPSK_Tsymbol');
    Values = setfield(Values, 'SignalDuration', NumSymbols*Tsymbol);    
elseif (strmatch(getfield(SigStruct,'Type'), 'qpsk'))
    NumSymbols = getfield(SigStruct, 'QPSK_NumSymbols');
    BitStreamI = RandSource(N/2,NumSymbols);
    BitStreamQ = RandSource(N/2,NumSymbols);
    Values = setfield(Values, 'BitStreamI', BitStreamI);    
    Values = setfield(Values, 'BitStreamQ', BitStreamQ);    
    if (strmatch(getfield(SigStruct,'QPSKEnergies'), 'random'))
        Energies = DrawUniform([N/2 1],1,3);
    elseif (strmatch(getfield(SigStruct,'QPSKEnergies'), 'specify'))
        EnergiesStr = getfield(SigStruct,'QPSKEnergiesString');
        Energies = str2num(EnergiesStr);
    end
    Values = setfield(Values, 'QPSKEnergies', Energies);
    Tsymbol = getfield(SigStruct,'QPSK_Tsymbol');
    Values = setfield(Values, 'SignalDuration', NumSymbols*Tsymbol);    
end

% Carriers
if (strmatch(getfield(SigStruct, 'Carriers'), 'random'))
    Carriers = DrawUniform([N/2 1],B,fmax-B);
elseif (strmatch(getfield(SigStruct, 'Carriers'), 'specify'))
    Carriers = str2num(getfield(SigStruct, 'CarrierString'));
end
Values = setfield(Values, 'Carriers', Carriers);

% Get the state of the random generator, so that can reproduce the same
% noise in repeated simulations. however, if pressing GenerateSignal again,
% the noise is also changed (by taking a new state).
% The reason for saving the state (rather than the actual noise signal)
% since we don't know yet the resolution of the signal, which depends on
% the parameters of the next stages.

% This code works on 2009a
%defaultStream = RandStream.getDefaultStream;
%Values = setfield(Values, 'SavedRNDStateForNoiseGen', defaultStream.State);
% for compatability we use instead the old method
Values = setfield(Values, 'SavedRandnStateForNoiseGen', randn('state'));
Values = setfield(Values, 'SavedRandStateForNoiseGen', rand('state'));

Signal = setfield(Signal, 'Values', Values); %#ok<*SFLD>

