/// <summary> /// This method duplicates exactly the function /// ifft(input) in MATLAB /// Requires a complex input number to be able to exactly /// transform back to an orginal signal /// i.e. x = ifft(fft(x)) /// </summary> /// <param name="input"></param> /// <param name="inputComplex">If true, the input array is a complex arrray. /// i.e. the array alternates between a real and an imaginary value. /// If false, the array contains only real values</param> /// <param name="returnComplex">If true, return a complex return arrray. /// i.e. the array alternates between a real and an imaginary value. /// If false, return only the positive real value /// </param> /// <returns>signal (complex or only positive real values)</returns> public static double[] IFFT(double[] input, bool inputComplex = true, bool returnComplex = true) { var fft = new LomontFFT(); double[] complexSignal; if (inputComplex) { complexSignal = input; } else { complexSignal = DoubleToComplexDouble(input); } fft.FFT(complexSignal, false); if (returnComplex) { return(complexSignal); } else { return(Real(complexSignal)); } }
private float[] GetFrecuencySampleFromAudioData(float[] audioData) { var frecuencySample = new float[SAMPLES / DIVISOR]; _values = new float[2 * SAMPLES]; for (var i = 0; i < SAMPLES; i++) { _values[2 * i] = audioData[i]; _values[2 * i + 1] = 0; } _fourierTransform = new LomontFFT(); _fourierTransform.FFT(_values, true); var maxValue = 0f; for (var i = 0; i < SAMPLES / DIVISOR; i++) { var value = Magnitude(_values[2 * i], _values[2 * i + 1]); if (maxValue < value) { maxValue = value; } } for (var i = 0; i < SAMPLES / DIVISOR; i++) { frecuencySample[i] = Magnitude(_values[2 * i], _values[2 * i + 1]) / maxValue; } return(frecuencySample); }
/// <summary> /// This method duplicates exactly the function /// fft(input) in MATLAB /// </summary> /// <param name="input">e.g. an audio signal</param> /// <returns>a complex array (the array alternates between a real and an imaginary value)</returns> public static double[] FFT(double[] input) { var fft = new LomontFFT(); var complexSignal = DoubleToComplexDouble(input); fft.FFT(complexSignal, true); return(complexSignal); }
/// <summary> /// Generate a spectrogram array spaced linearily /// </summary> /// <param name="samples">audio data</param> /// <param name="fftWindowsSize">fft window size</param> /// <param name="fftOverlap">overlap in number of samples (normaly half of the fft window size) [low number = high overlap]</param> /// <returns>spectrogram jagged array</returns> public static double[][] CreateSpectrogramLomont(float[] samples, int fftWindowsSize, int fftOverlap) { var fft = new LomontFFT(); int numberOfSamples = samples.Length; // overlap must be an integer smaller than the window size // half the windows size is quite normal double[] windowArray = FFTWindow.GetWindowFunction(FFTWindowType.HANNING, fftWindowsSize); // width of the segment - e.g. split the file into 78 time slots (numberOfSegments) and do analysis on each slot int numberOfSegments = (numberOfSamples - fftWindowsSize) / fftOverlap; var frames = new double[numberOfSegments][]; // since we are dealing with small buffer sizes (1024) but are trying to detect peaks at low frequency ranges // octaves 0 .. 2 for example, zero padding is nessessary to improve the interpolation resolution of the FFT // otherwise FFT bins will be quite large making it impossible to distinguish between low octave notes which // are seperated by only a few Hz in these ranges. //const int ZERO_PAD_MULTIPLIER = 4; // zero padding adds interpolation resolution to the FFT, it also dilutes the magnitude of the bins // TODO: figure out how to properly use zero_padding // even - Re, odd - Img var complexSignal = new double[2 * fftWindowsSize]; //var complexSignal = new double[2*fftWindowsSize*ZERO_PAD_MULTIPLIER*2]; // zero pad double lengthSqrt = Math.Sqrt(fftWindowsSize); for (int i = 0; i < numberOfSegments; i++) { // apply Hanning Window for (int j = 0; j < fftWindowsSize; j++) { // Weight by Hann Window complexSignal[2 * j] = (double)(windowArray[j] * samples[i * fftOverlap + j]); // need to clear out as fft modifies buffer (phase) complexSignal[2 * j + 1] = 0; } // FFT transform for gathering the spectrum fft.FFT(complexSignal, true); // get the ABS of the complex signal var band = new double[fftWindowsSize / 2]; for (int j = 0; j < fftWindowsSize / 2; j++) { double re = complexSignal[2 * j]; double img = complexSignal[2 * j + 1]; // do the Abs calculation and add with Math.Sqrt(audio_data.Length); // i.e. the magnitude spectrum band[j] = (double)(Math.Sqrt(re * re + img * img) * lengthSqrt); } frames[i] = band; } return(frames); }
public FFTThread(int w) { m_window = new FFTWindow(FFTWindowType.HANNING, w); m_w = w; m_rin = new double[m_w]; m_rout = new double[m_w]; m_iout = new double[m_w]; //m_fft = new FFTReal(m_w); m_fft = new LomontFFT(); }
void Awake() { if (AudioAnalyzer._instance != null) { Destroy(this); } _fft = new LomontFFT(); _instance = this; InitializeAnalyzer(); }
public double[] Spectrum(double[] input, bool scale) { var fft = new LomontFFT(); fft.RealFFT(input, true); var spectrum = Helper.ComputeSpectrum(input); fft.RealFFT(input, false); return(spectrum); }
/// /// <summary> * Create an FFT transformer for a given sample size. This preallocates /// * resources appropriate to that block size. A specified window /// * function will be applied to all input data. /// * </summary> /// * <param name="size"> The number of samples in a block that we will /// * be asked to transform. Must be a power of 2. </param> /// * <param name="window"> Window function to apply to all input data. /// * Its block size must be the same as the size /// * parameter. </param> /// * <exception cref="IllegalArgumentException"> Invalid parameter. </exception> /// public FFTTransformer(int size, Window window) { if (!IsPowerOf2(size)) { throw new System.ArgumentException("size for FFT must" + " be a power of 2 (was " + size + ")"); } windowFunc = window; transformer = new LomontFFT(); blockSize = size; // Allocate working data arrays. xre = new double[blockSize]; }
public NoteFinderFilter(int fftSize, double sampleRate, double cornerFrequency = 440.0) { _fftSize = fftSize; _sampleRate = sampleRate; _fftBufferTmp = new double[_fftSize * 2]; _hanWindow = new HanWindow(_fftSize); _soFilter = new SecondOrderLowPassFilter(_sampleRate, cornerFrequency); _frequencyNotes = new FrequencyNotes(_fftSize, _sampleRate); _fft = new LomontFFT { A = 1, B = -1 }; }
public FFT(FFTWindowType windowType, int winSize) { this.winSize = winSize; this.fftSize = 2 * winSize; fftwData = fftwf_malloc(fftSize * sizeof(float)); fftwPlan = fftwf_plan_r2r_1d(fftSize, fftwData, fftwData, FFTW_R2HC, FFTW_ESTIMATE | FFTW_DESTROY_INPUT); fft = new float[fftSize]; data = new float[fftSize]; lomonFFT = new LomontFFT(); win = new FFTWindow(windowType, winSize); }
public double[] Spectrum(double[] input, bool scale) { var fft = new LomontFFT(); var data = Helper.ToComplex(input); fft.FFT(data, true); var spectrum = Helper.ComputeSpectrum(data); fft.FFT(data, false); Helper.ToDouble(data, input); return(spectrum); }
/// <summary> /// Generate a spectrum graph array spaced linearily /// </summary> /// <param name="samples">audio data</param> /// <param name="fftWindowsSize">fft window size</param> /// <returns>spectrum graph array</returns> public static double[] CreateSpectrumAnalysisLomont(float[] samples, int fftWindowsSize) { var fft = new LomontFFT(); int numberOfSamples = samples.Length; // overlap must be an integer smaller than the window size // half the windows size is quite normal double[] windowArray = FFTWindow.GetWindowFunction(FFTWindowType.HANNING, fftWindowsSize); // even - Re, odd - Img var complexSignal = new double[2 * fftWindowsSize]; // apply Hanning Window // e.g. take 371 ms each 11.6 ms (2048 samples each 64 samples) for (int j = 0; (j < fftWindowsSize) && (samples.Length > j); j++) { // Weight by Hann Window complexSignal[2 * j] = (double)(windowArray[j] * samples[j]); // need to clear out as fft modifies buffer (phase) complexSignal[2 * j + 1] = 0; } // FFT transform for gathering the spectrum fft.FFT(complexSignal, true); var band = new double[fftWindowsSize / 2]; double lengthSqrt = Math.Sqrt(fftWindowsSize); for (int j = 0; j < fftWindowsSize / 2; j++) { double re = complexSignal[2 * j] * lengthSqrt; double img = complexSignal[2 * j + 1] * lengthSqrt; // do the Abs calculation and add with Math.Sqrt(audio_data.Length); // i.e. the magnitude spectrum band[j] = (double)(Math.Sqrt(re * re + img * img) * lengthSqrt); } return(band); }
public void Start() { var audioSource = GetComponent <AudioSource>(); _audioData = new float[audioSource.clip.samples * audioSource.clip.channels]; audioSource.clip.GetData(_audioData, 0); _values = new float[2 * SAMPLES]; for (var i = 0; i < SAMPLES; i++) { _values[2 * i] = _audioData[i]; _values[2 * i + 1] = 0; } _fourierTransform = new LomontFFT(); _fourierTransform.FFT(_values, true); var lineRenderer = GetComponent <LineRenderer>(); lineRenderer.useWorldSpace = false; var points = new Vector3[SAMPLES / DIVISOR]; var maxValue = 0f; for (var i = 0; i < SAMPLES / DIVISOR; i++) { var value = Magnitude(_values[2 * i], _values[2 * i + 1]); if (maxValue < value) { maxValue = value; } } for (var i = 0; i < SAMPLES / DIVISOR; i++) { points[i] = new Vector3(0.0004f * i, Magnitude(_values[2 * i], _values[2 * i + 1]) / maxValue, 0); } lineRenderer.positionCount = SAMPLES / DIVISOR; lineRenderer.SetPositions(points); }
Dictionary <int, bool> instantiatedBeatMap; //prevent duplicate beat creation // Use this for initialization void Start() { audioSource = GetComponent <AudioSource>(); clip = audioSource.clip; fft = new LomontFFT(); float[] samples = new float[clip.samples * clip.channels]; clip.GetData(samples, 0); //convert float to double double[] samplesD = new double[samples.Length]; for (int i = 0; i < samplesD.Length; i++) { samplesD[i] = (double)samples[i]; } Debug.Log("clip samples: " + clip.samples); //debug Debug.Log("clip channels: " + clip.channels); //debug Debug.Log("clip duration: " + clip.length); //debug steps = Mathf.RoundToInt(samplingInterval / secondInMilliseconds * clip.frequency); Debug.Log("steps: " + steps); //debug int n = samplingWindowSize; int k = 0; for (int j = 0; j < samplingWindowSize; j++) { n = n / 2; if (n <= 0) { break; } k++; } band = new float[k + 1]; g = new GameObject[k + 1]; positions = new Dictionary <int, Vector3[]>(); for (int i = 0; i < band.Length; i++) { band[i] = 0; g[i] = GameObject.CreatePrimitive(PrimitiveType.Sphere); g[i].GetComponent <Renderer>().material.SetColor("_Color", Color.cyan); g[i].transform.position = new Vector3(i, 0, 0); } for (int i = 0; i < samplesD.Length; i = i + steps) { double[] samplingWindow = new double[samplingWindowSize]; if (i > samplingWindowSize) { Array.Copy(samplesD, i - samplingWindowSize / 2, samplingWindow, 0, samplingWindowSize); } else //i = 0 { Array.Copy(samplesD, i, samplingWindow, 0, samplingWindowSize); } fft.FFT(samplingWindow, true); //convert double to float float[] samplingWindowF = new float[samplingWindow.Length]; for (int j = 0; j < samplingWindow.Length; j++) { samplingWindowF[j] = (float)samplingWindow[j]; } checkWindow(i, samplingWindowF); /* * if (i > 70000) * { * break; * }*/ } /* * using (System.IO.StreamWriter file = new System.IO.StreamWriter(@"C:\Users\wgwong\Desktop\out2.txt")) * { * foreach (var entry in positions) * { * file.WriteLine("position: " + entry.Key); * for (int i = 0; i < entry.Value.Length; i++) { * var element = entry.Value[i]; * file.WriteLine("element[" + i + "]: " + element.x + ", " + element.y + ", " + element.z); * } * file.WriteLine("\n"); * } * }*/ leftLaneBalls = new ArrayList(); midLaneBalls = new ArrayList(); rightLaneBalls = new ArrayList(); leftBumper = new Bumper(new Vector3(12, 0, 2), Color.red); midBumper = new Bumper(new Vector3(14, 0, 2), Color.blue); rightBumper = new Bumper(new Vector3(16, 0, 2), Color.green); beatMap = new Dictionary <int, bool[]>(); instantiatedBeatMap = new Dictionary <int, bool>(); createBeatMap(); audioSource.Play(); }
/// <summary> /// Performs the FFT on the provided samples. /// Will bin channels internally /// </summary> /// <returns>The FF.</returns> /// <param name="dAudioSamples">D audio samples.</param> /// <param name="fftType">Fft type.</param> /// <param name="forwardFFT">If set to <c>true</c> forward FF.</param> public double[] GetFFTOutputBins(ref double[] dAudioSamples, int fftType = 1, bool forwardFFT = true, bool applyHannWindowing = true) { if (!IsInitialized) { return(null); } if (_fftScript == null) { _fftScript = new LomontFFT(); _fftScript.A = 1; _fftScript.B = -1; } if (_fftBinsOutput == null || _fftBinsOutput.Length != FFTBinCount) { _fftBinsOutput = new double[FFTBinCount]; _fftBinsActual = new double[_fftBinsOutput.Length / ChannelCount]; } System.Array.Clear(_fftBinsOutput, 0, _fftBinsOutput.Length); for (int sampleIndex = 0; sampleIndex < _dAudioSamples.Length; sampleIndex += ChannelCount) { for (int channelIndex = 0; channelIndex < ChannelCount; ++channelIndex) { int binIndex = sampleIndex == 0 ? 0 : sampleIndex / ChannelCount; double valToAdd = Mathf.Pow((float)_dAudioSamples [sampleIndex + channelIndex], 4); //double valToAdd = _dAudioSamples [sampleIndex + channelIndex]; _fftBinsOutput [binIndex] += _dAudioSamples [sampleIndex + channelIndex]; } } for (int i = 0; i < _fftBinsOutput.Length; ++i) { _fftBinsOutput [i] /= ChannelCount; } //apply hanning window if (applyHannWindowing) { Utilities.Hann(ref _fftBinsOutput); } switch (fftType) { case 0: { Debug.LogWarning("COMPLEXFFT NOT SUPPORTED YET"); //_fftScript.FFT (_fftBinsOutput, forwardFFT); } break; case 1: { _fftScript.RealFFT(ref _fftBinsOutput, forwardFFT); _fftBinsOutput [0] = 0; _fftBinsOutput [1] = 0; for (int i = 2; i < _fftBinsOutput.Length; i += 2) { float real = (float)_fftBinsOutput [i]; float im = (float)_fftBinsOutput [i + 1]; float val = Mathf.Sqrt(Mathf.Pow(real, 2) + Mathf.Pow(im, 2)); if (i == 2) { _fftBinsActual [0] = val; } else { _fftBinsActual [(i / 2) - 1] = val; } } } break; case 2: { Debug.LogWarning("TABLEFFT NOT SUPPORTED YET"); //_fftScript.TableFFT (_fftBinsOutput, forwardFFT); } break; } return(_fftBinsActual); }
public AudioService() { lomonFFT = new Lomont.LomontFFT(); }
void saveFile() { float[] samples = new float[4096]; //aud.GetOutputData (samples, 0); aud.clip.GetData(samples, Microphone.GetPosition(Microphone.devices[0]) - 4096); float maxAmp = (float)samples.Max() * 2; if (maxAmp > 0.001f) { LomontFFT fftMe = new LomontFFT(); double[] sampleFFT = Array.ConvertAll(samples, x => (double)x); fftMe.RealFFT(sampleFFT, true); float[] frequences = new float[5]; frequences[0] = (float)sampleFFT.Take(25).Max(); frequences[1] = (float)sampleFFT.Skip(25).Take(50).Max(); frequences[2] = (float)sampleFFT.Skip(75).Take(75).Max(); frequences[3] = (float)sampleFFT.Skip(150).Take(100).Max(); frequences[4] = (float)sampleFFT.Skip(250).Take(125).Max(); float maxFreq = frequences.Max(); int maxFreqIndex = frequences.ToList().IndexOf(maxFreq); if (maxFreqIndex == 0) { //float noise = (UnityEngine.Random.value - 0.5f) / 5f; float noise = 0f; makeOrb(maxFreq, new Vector3(22 + noise, -5, 20)); makeOrb(maxFreq, new Vector3(-22 + noise, -5, 20)); } if (maxFreqIndex == 1) { //float noise = (UnityEngine.Random.value - 0.5f) / 5f; float noise = 0f; makeOrb(maxFreq, new Vector3(20 + noise, -2, 20)); makeOrb(maxFreq, new Vector3(-20 + noise, -2, 20)); //makeOrb (maxFreq, new Vector3 (-35+ noise, -1, -15)); //makeOrb (maxFreq, new Vector3 (35+ noise, -1, -15)); } if (maxFreqIndex == 2) { //float noise = (UnityEngine.Random.value - 0.5f) / 5f; float noise = 0f; makeOrb(maxFreq, new Vector3(15 + noise, 3, 20)); makeOrb(maxFreq, new Vector3(-15 + noise, 3, 20)); //makeOrb(maxFreq,new Vector3(-25+ noise,0,-25)); //makeOrb(maxFreq,new Vector3(25+ noise,0,-25)); } if (maxFreqIndex == 3) { //float noise = (UnityEngine.Random.value - 0.5f) / 5f; float noise = 0f; makeOrb(maxFreq, new Vector3(10 + noise, 7, 25)); makeOrb(maxFreq, new Vector3(-10 + noise, 7, 25)); //makeOrb (maxFreq, new Vector3 (-15+ noise, 1, -35)); //makeOrb (maxFreq, new Vector3 (15+ noise, 1, -35)); } if (maxFreqIndex == 4) { //float noise = (UnityEngine.Random.value - 0.5f) / 5f; float noise = 0f; makeOrb(maxFreq, new Vector3(0 + noise, 10, 30)); //makeOrb (maxFreq, new Vector3 (0+ noise, 2, -45)); } } }
public void UpdatePLP(ref double[] dAudioSamples, int channelCount, int sampleRate, bool applyHannWindow = true) { if (dAudioSamples == null) { return; } if (_fftScript == null) { _fftScript = new LomontFFT(); _fftScript.A = 1; _fftScript.B = -1; } System.Array.Clear(_fftBinsRaw, 0, _fftBinsRaw.Length); System.Array.Clear(_fftBinsActual, 0, _fftBinsActual.Length); //channel bin the data for (int sampleIndex = 0; sampleIndex < dAudioSamples.Length; sampleIndex += channelCount) { int binIndex = sampleIndex == 0 ? 0 : sampleIndex / channelCount; for (int channelIndex = 0; channelIndex < channelCount; ++channelIndex) { _fftBinsRaw [binIndex] = dAudioSamples [sampleIndex + channelIndex]; } _fftBinsRaw [binIndex] /= channelCount; } //apply hanning window on audio samples if (applyHannWindow) { Utilities.Hann(ref _fftBinsRaw); } //perform fft. _fftScript.RealFFT(ref _fftBinsRaw, true); //aggregate fft output into fftActual for (int i = 2; i < _fftBinsRaw.Length; i += 2) { float real = (float)_fftBinsRaw [i]; float im = (float)_fftBinsRaw [i + 1]; float val = Mathf.Sqrt(Mathf.Pow(real, 2) + Mathf.Pow(im, 2)); if (i == 2) { _fftBinsActual [0] = val; } else { _fftBinsActual [(i / 2) - 1] = val; } } //left shift the spectrogram for (int i = 1; i < _spectrogram.Length; ++i) { LeftShiftArray <float> (ref _spectrogram [i]); /*for (int j = 0; j < _spectrogram [i - 1].Length; ++j) { * _spectrogram [i - 1][j] = _spectrogram [i][j]; * }*/ } //apply logarithmic compression and fill in place float[] toFill = _spectrogram [_spectrogram.Length - 1]; for (int i = 0; i < toFill.Length; ++i) { toFill [i] = _fftBinsActual [i]; //Mathf.Log ((float)(1+_fftBinsActual [i])); } //compute discrete derivative if (_frameIndex > 0) { float[] prev = _frameIndex > _spectrogram.Length - 1? _spectrogram[_spectrogram.Length - 2]:_spectrogram [_frameIndex - 1]; float[] curr = _frameIndex > _spectrogram.Length - 1 ? _spectrogram [_spectrogram.Length - 1] : _spectrogram [_frameIndex]; for (int i = 0; i < curr.Length; ++i) { float diff = curr[i] - prev[i]; if (diff > 0) { curr[i] = diff; } else { curr[i] = 0; } } } ++_frameIndex; if (_frameIndex > _spectrogram.Length) { bool firstRun = _frameIndex == _spectrogram.Length + 1; ComputeNoveltyCurve(firstRun); ComputeTempogram(false, firstRun); UpdateBPM(); ComputePeriodicLocalPulse(firstRun); //CorrelateNoveltyCurveWithSinCurve (); LeftShiftArray <double> (ref _noveltyCurve); //LeftShiftArray<double> (ref _tempogramActual); for (int i = 1; i < _tempogramActual.Length; ++i) { LeftShiftArray <double> (ref _tempogramActual[i]); } LeftShiftArray <double> (ref _tempo); LeftShiftArray <double> (ref _tempoMaxCoeff); LeftShiftArray <double> (ref _plpCurve); } }