# ----------------------------------------------------------------------------
#
#  Copyright (C) 2013-2020 Fons Adriaensen <fons@linuxaudio.org>
#    
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 3 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <http:#www.gnu.org/licenses/>.
#
# ----------------------------------------------------------------------------


import numpy as np
from math import pi, floor, atan2
from cmath import polar


def adjust_freq (freq, fsamp, nsamp):
    """ 
    Adjust 'freq' for an integer number of cycles in 'nsamp' samples.
    """
    t = nsamp / fsamp
    k = int (freq * t + 0.5)
    return k / t


def gen_sinewave (ampl, freq, fsamp, nsamp):
    """
    Generate sine wave test signal.
    """
    # Phase array, better use double precision for this.
    w = 2 * pi * freq / fsamp
    R = np.linspace (0, w * nsamp, nsamp, endpoint = False, dtype = np.float64)
    return ampl * np.sin (R)
        

def gen_complex (freq, fsamp, nsamp, window = True):
    """
    Generate windowed reference signal for selective measurement.
    """
    # Phase array, better use double precision for this.
    w = 2 * pi * freq / fsamp
    R = np.linspace (0, w * nsamp, nsamp, endpoint = False, dtype = np.float64)
    # Generate complex (cos(R), sin(R))
    S = np.exp ((0 + 1j) * R)
    if window:
        # Raised cosine window.
        W = np.linspace (0, 2 * pi, nsamp, endpoint = False, dtype = np.float32)
        S *= (1 - np.cos (W))
    return S


def sigdetect (Ainp, Aref):
    """
    Frequency selective measurement. Detect signal in Ainp at the
    frequency determined by Aref, generated by 'gen_complex' above.
    Equivalent to one bin of an FFT.
    Returns amplitude and phase in radians.
    """
    return polar (2 * np.dot (Ainp, Aref) / Aref.shape [0])


