Calculate an attenuation roll-off curve, from a signal and its recording

    :param signal: ouput signal delivered to the generation hardware
    :type signal: numpy.ndarray    
    :param resp: recording of given signal, as recieved from microphone
    :type resp: numpy.ndarray
    :param fs: input and output samplerate (should be the same)
    :type fs: int
    :param smooth_pts: amount of averaging to use on the result
    :type smooth_pts: int
    :returns: numpy.ndarray -- attenuation vector

def attenuation_curve(signal, resp, fs, calf, smooth_pts=99):
    """
    Calculate an attenuation roll-off curve, from a signal and its recording

    :param signal: ouput signal delivered to the generation hardware
    :type signal: numpy.ndarray    
    :param resp: recording of given signal, as recieved from microphone
    :type resp: numpy.ndarray
    :param fs: input and output samplerate (should be the same)
    :type fs: int
    :param smooth_pts: amount of averaging to use on the result
    :type smooth_pts: int
    :returns: numpy.ndarray -- attenuation vector
    """
    # remove dc offset
    y = resp - np.mean(resp)
    x = signal

    # frequencies present in calibration spectrum
    npts = len(y)
    fq = np.arange(npts / 2 + 1) / (float(npts) / fs)

    # convert time signals to frequency domain
    Y = np.fft.rfft(y)
    X = np.fft.rfft(x)

    # take the magnitude of signals
    Ymag = np.sqrt(Y.real ** 2 + Y.imag ** 2)  # equivalent to abs(Y)
    Xmag = np.sqrt(X.real ** 2 + X.imag ** 2)

    # convert to decibel scale
    YmagdB = 20 * np.log10(Ymag)
    XmagdB = 20 * np.log10(Xmag)

    # now we can substract to get attenuation curve
    diffdB = XmagdB - YmagdB

    # may want to smooth results here?
    diffdB = smooth(diffdB, smooth_pts)

    # shift by the given calibration frequency to align attenutation
    # with reference point set by user
    fidx = (np.abs(fq - calf)).argmin()
    diffdB -= diffdB[fidx]

    return diffdB