Où puis-je trouver une implémentation gratuite, très rapide et fiable de la FFT en C# ?
Qui peuvent être utilisés dans un produit ? Ou y a-t-il des restrictions ?
Où puis-je trouver une implémentation gratuite, très rapide et fiable de la FFT en C# ?
Qui peuvent être utilisés dans un produit ? Ou y a-t-il des restrictions ?
Le gars qui a fait AForge a fait un assez bon travail mais ce n'est pas de la qualité commerciale. C'est un bon outil d'apprentissage, mais on peut voir qu'il apprenait lui aussi et qu'il a commis de graves erreurs, comme supposer la taille d'une image au lieu d'utiliser le nombre correct de bits par pixel.
Je ne le critique pas, je lui voue un grand respect pour avoir appris tout cela et nous avoir montré comment le faire. Je pense qu'il a un doctorat maintenant ou du moins qu'il est sur le point de l'obtenir, donc il est vraiment intelligent, mais ce n'est pas une bibliothèque utilisable commercialement.
La bibliothèque Math.Net a ses propres bizarreries lorsqu'elle travaille avec des transformées de Fourier et des images/nombres complexes. Par exemple, si je ne me trompe pas, elle produit la transformée de Fourier dans un format visible par l'homme, ce qui est bien pour les humains si vous voulez regarder une image de la transformée, mais ce n'est pas si bien quand vous attendez que les données soient dans un certain format (le format normal). Je peux me tromper, mais je me souviens juste qu'il y avait une certaine bizarrerie, alors j'ai utilisé le code original qu'ils ont utilisé pour la transformation de Fourier et cela a bien mieux fonctionné. (ExocortexDSP v1.2 http://www.exocortex.org/dsp/ )
Math.net avait également d'autres particularités que je n'aimais pas lorsqu'il s'agissait de traiter les données de la FFT. Je ne me souviens plus de ce que c'était, mais je sais qu'il était beaucoup plus facile d'obtenir ce que je voulais avec la bibliothèque DSP ExoCortex. Je ne suis ni mathématicien ni ingénieur ; pour ces personnes, cela peut être parfaitement logique.
J'utilise donc le code FFT extrait d'ExoCortex, sur lequel Math.Net est basé, sans rien d'autre et cela fonctionne très bien.
Enfin, je sais que ce n'est pas du C#, mais j'ai commencé à envisager d'utiliser FFTW ( http://www.fftw.org/ ). Et ce type a déjà créé un wrapper C#, alors j'allais y jeter un coup d'œil, mais je ne l'ai pas encore utilisé. ( http://www.sdss.jhu.edu/~tamas/bytes/fftwcsharp.html )
OH ! Je ne sais pas si vous faites cela pour l'école ou pour le travail, mais dans tous les cas, il existe une excellente série de conférences gratuites données par un professeur de Stanford sur iTunes University.
https://podcasts.apple.com/us/podcast/the-fourier-transforms-and-its-applications/id384232849
J'aimerais avoir plus de détails sur la bizarrerie de l'implémentation fft de Math.NET Iridium - afin que nous puissions y remédier !) Est-ce lié à la façon dont les nombres complexes sont traités ? Je n'ai aucune idée de ce que vous voulez dire par "format visible par l'homme". Échantillons : mathnet.opensourcedotnet.info/doc/IridiumFFT.ashx
Fftw a une sorte de licence problématique ; regardez ça : "Des licences non libres pour la FFTW sont également disponibles et permettent des conditions d'utilisation différentes de celles de la GPL."
C'est une question à Mike Bethany. J'essaie d'apprendre comment convertir des données du domaine temporel au domaine fréquentiel. Votre lien exocortex est-il le bon moyen de le faire ?
AForge.net est une bibliothèque gratuite (open-source) qui supporte la Transformée de Fourier Rapide. (Voir Sources/Imaging/ ComplexImage.cs pour l'usage, Sources/Math/ FourierTransform.cs pour la mise en œuvre)
Math.NET Bibliothèque Iridium fournit une collection rapide et régulièrement mise à jour de fonctions mathématiques, dont la FFT. Il est sous licence LGPL et vous êtes donc libre de l'utiliser dans des produits commerciaux.
Je vois que c'est un vieux fil de discussion, mais pour ce que ça vaut, voici une implémentation FFT 1-D puissance-de-2-longueur-seule en C#, gratuite (licence MIT), que j'ai écrite en 2010.
Je n'ai pas comparé ses performances à d'autres implémentations C# FFT. Je l'ai écrit principalement pour comparer les performances de Flash/ActionScript et de Silverlight/C#. Ce dernier est beaucoup plus rapide, au moins pour le calcul des chiffres.
/**
* Performs an in-place complex FFT.
*
* Released under the MIT License
*
* Copyright (c) 2010 Gerald T. Beauregard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
public class FFT2
{
// Element for linked list in which we store the
// input/output data. We use a linked list because
// for sequential access it's faster than array index.
class FFTElement
{
public double re = 0.0; // Real component
public double im = 0.0; // Imaginary component
public FFTElement next; // Next element in linked list
public uint revTgt; // Target position post bit-reversal
}
private uint m_logN = 0; // log2 of FFT size
private uint m_N = 0; // FFT size
private FFTElement[] m_X; // Vector of linked list elements
/**
*
*/
public FFT2()
{
}
/**
* Initialize class to perform FFT of specified size.
*
* @param logN Log2 of FFT length. e.g. for 512 pt FFT, logN = 9.
*/
public void init(
uint logN )
{
m_logN = logN;
m_N = (uint)(1 << (int)m_logN);
// Allocate elements for linked list of complex numbers.
m_X = new FFTElement[m_N];
for (uint k = 0; k < m_N; k++)
m_X[k] = new FFTElement();
// Set up "next" pointers.
for (uint k = 0; k < m_N-1; k++)
m_X[k].next = m_X[k+1];
// Specify target for bit reversal re-ordering.
for (uint k = 0; k < m_N; k++ )
m_X[k].revTgt = BitReverse(k,logN);
}
/**
* Performs in-place complex FFT.
*
* @param xRe Real part of input/output
* @param xIm Imaginary part of input/output
* @param inverse If true, do an inverse FFT
*/
public void run(
double[] xRe,
double[] xIm,
bool inverse = false )
{
uint numFlies = m_N >> 1; // Number of butterflies per sub-FFT
uint span = m_N >> 1; // Width of the butterfly
uint spacing = m_N; // Distance between start of sub-FFTs
uint wIndexStep = 1; // Increment for twiddle table index
// Copy data into linked complex number objects
// If it's an IFFT, we divide by N while we're at it
FFTElement x = m_X[0];
uint k = 0;
double scale = inverse ? 1.0/m_N : 1.0;
while (x != null)
{
x.re = scale*xRe[k];
x.im = scale*xIm[k];
x = x.next;
k++;
}
// For each stage of the FFT
for (uint stage = 0; stage < m_logN; stage++)
{
// Compute a multiplier factor for the "twiddle factors".
// The twiddle factors are complex unit vectors spaced at
// regular angular intervals. The angle by which the twiddle
// factor advances depends on the FFT stage. In many FFT
// implementations the twiddle factors are cached, but because
// array lookup is relatively slow in C#, it's just
// as fast to compute them on the fly.
double wAngleInc = wIndexStep * 2.0*Math.PI/m_N;
if (inverse == false)
wAngleInc *= -1;
double wMulRe = Math.Cos(wAngleInc);
double wMulIm = Math.Sin(wAngleInc);
for (uint start = 0; start < m_N; start += spacing)
{
FFTElement xTop = m_X[start];
FFTElement xBot = m_X[start+span];
double wRe = 1.0;
double wIm = 0.0;
// For each butterfly in this stage
for (uint flyCount = 0; flyCount < numFlies; ++flyCount)
{
// Get the top & bottom values
double xTopRe = xTop.re;
double xTopIm = xTop.im;
double xBotRe = xBot.re;
double xBotIm = xBot.im;
// Top branch of butterfly has addition
xTop.re = xTopRe + xBotRe;
xTop.im = xTopIm + xBotIm;
// Bottom branch of butterly has subtraction,
// followed by multiplication by twiddle factor
xBotRe = xTopRe - xBotRe;
xBotIm = xTopIm - xBotIm;
xBot.re = xBotRe*wRe - xBotIm*wIm;
xBot.im = xBotRe*wIm + xBotIm*wRe;
// Advance butterfly to next top & bottom positions
xTop = xTop.next;
xBot = xBot.next;
// Update the twiddle factor, via complex multiply
// by unit vector with the appropriate angle
// (wRe + j wIm) = (wRe + j wIm) x (wMulRe + j wMulIm)
double tRe = wRe;
wRe = wRe*wMulRe - wIm*wMulIm;
wIm = tRe*wMulIm + wIm*wMulRe;
}
}
numFlies >>= 1; // Divide by 2 by right shift
span >>= 1;
spacing >>= 1;
wIndexStep <<= 1; // Multiply by 2 by left shift
}
// The algorithm leaves the result in a scrambled order.
// Unscramble while copying values from the complex
// linked list elements back to the input/output vectors.
x = m_X[0];
while (x != null)
{
uint target = x.revTgt;
xRe[target] = x.re;
xIm[target] = x.im;
x = x.next;
}
}
/**
* Do bit reversal of specified number of places of an int
* For example, 1101 bit-reversed is 1011
*
* @param x Number to be bit-reverse.
* @param numBits Number of bits in the number.
*/
private uint BitReverse(
uint x,
uint numBits)
{
uint y = 0;
for (uint i = 0; i < numBits; i++)
{
y <<= 1;
y |= x & 0x0001;
x >>= 1;
}
return y;
}
}
Je suis désolé. J'ai supprimé mon blog il y a quelques années car il attirait trop de spam. Malheureusement, le code est un peu trop gros pour être inséré dans un commentaire ici. Envoyez-moi un message à g.<mysurname>@ieee.org, et je serai heureux de vous envoyer le code.
Vous pouvez mettre à jour votre réponse, ajouter le code et supprimer votre lien mort. Partager votre code via des canaux privés serait contraire à l'esprit de Stack Overflow.
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.