175 lines
4.6 KiB
C#
175 lines
4.6 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
using System.Numerics;
|
|
|
|
public class Example01_time_to_frequency : MonoBehaviour
|
|
{
|
|
[Space]
|
|
[Header("[!] set fixed time to 0.01f [!]")]
|
|
[Header("TIME SIGNAL TO FREQUENCY FFT")]
|
|
[Space]
|
|
|
|
//samplingfrequency
|
|
public int samplingFrequency;
|
|
|
|
//input-output values for the FFT
|
|
double[] X_inputValues;
|
|
double[] Y_inputValues;
|
|
double[] Y_output;
|
|
|
|
//list with the input values
|
|
public List<double> Y_values;
|
|
|
|
//these are the frequencies, amplitude and phase of the sinus added to the signal
|
|
[Space(10)]
|
|
[Header("F,A and P must be same lenght")]
|
|
[Tooltip("Add different values of amplitude/frequency to change the time response")]
|
|
[Space]
|
|
public double[] freq;
|
|
public double[] Amp;
|
|
public double[] phase;
|
|
|
|
|
|
//this is the size of the window of data
|
|
public int windowSize = 1024;
|
|
|
|
//this is used to obtain the frequency with a peak
|
|
[Space(10)]
|
|
[Header("MOST IMPORTANT FREQUENCY")]
|
|
[Tooltip("This corresponds to the peak on the FFT")]
|
|
[Space]
|
|
public double maxf_obtained;
|
|
|
|
//counts the steps taken
|
|
long count = 0;
|
|
|
|
//the chart transforms for the time and frequency
|
|
[Space(10)]
|
|
[Header("CHARTS FOR DRAWING")]
|
|
[Space]
|
|
public Transform tfTime;
|
|
public Transform tfFreq;
|
|
|
|
|
|
void Start()
|
|
{
|
|
X_inputValues = new double[windowSize];
|
|
Y_inputValues = new double[windowSize];
|
|
|
|
samplingFrequency = (int)(1 / Time.fixedDeltaTime);
|
|
|
|
for (int ii = 0; ii < windowSize; ii++)
|
|
{
|
|
Y_values.Add(0);
|
|
}
|
|
|
|
StartCoroutine(time_to_frequency());
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// This corrutine obtains these steps in order:
|
|
/// 1) generates a time response using SIN() signals
|
|
/// 2) obtains a window of the signal
|
|
/// 3) applies the FFT
|
|
/// </summary>
|
|
|
|
IEnumerator time_to_frequency()
|
|
{
|
|
while (true)
|
|
{
|
|
|
|
// add point to the time chart
|
|
double signal = 0;
|
|
for (int jj = 0; jj < Amp.Length; jj++)
|
|
{
|
|
signal+= (double)( Amp[jj] * Mathf.Sin(2 * Mathf.PI * (float)freq[jj] * (float)count *1/(float)samplingFrequency + (float)phase[jj]) );
|
|
}
|
|
count++;
|
|
|
|
Y_values.Add(signal);
|
|
|
|
|
|
if (Y_values.Count >= windowSize)
|
|
{
|
|
//ONE IS THE INPUT VALUES
|
|
|
|
//this is the window size
|
|
for (int ii = 0; ii < windowSize; ii++)
|
|
{
|
|
X_inputValues[ii] = ii;
|
|
|
|
|
|
X_inputValues[ii] = ii;
|
|
Y_inputValues[ii] = (Y_values[ii + Y_values.Count - 1 - windowSize]);
|
|
|
|
}
|
|
|
|
|
|
|
|
//perform complex opterations and set up the arrays
|
|
Complex[] inputSignal_Time = new Complex[windowSize];
|
|
Complex[] outputSignal_Freq = new Complex[windowSize];
|
|
|
|
|
|
inputSignal_Time = FastFourierTransform.doubleToComplex(Y_inputValues);
|
|
|
|
|
|
//result is the iutput values once DFT has been applied
|
|
outputSignal_Freq = FastFourierTransform.FFT(inputSignal_Time,false);
|
|
|
|
|
|
|
|
Y_output = new double[windowSize];
|
|
//get module of complex number
|
|
for (int ii = 0; ii < windowSize; ii++)
|
|
{
|
|
//Debug.Log(ii);
|
|
Y_output[ii] = (double)Complex.Abs(outputSignal_Freq[ii]);
|
|
}
|
|
|
|
|
|
// find peak VALUES on the FFT
|
|
double MaxPeak = -1000;
|
|
int peakIndex = 0;
|
|
for (int i = 1; i < Y_output.Length/2 - 1; i++)
|
|
{
|
|
if (Y_output[i]>MaxPeak)
|
|
{
|
|
MaxPeak = Y_output[i];
|
|
peakIndex = i;
|
|
}
|
|
}
|
|
|
|
//store results
|
|
maxf_obtained = (double)peakIndex / (double)windowSize/2* (double)samplingFrequency;
|
|
|
|
}
|
|
|
|
|
|
yield return new WaitForFixedUpdate();
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void FixedUpdate()
|
|
{
|
|
//draw both charts: time-domain and frequency-domain
|
|
Drawing.drawChart(tfTime,X_inputValues, Y_inputValues, "time");
|
|
Drawing.drawChart(tfFreq, X_inputValues, Y_output, "frequency");
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|