2010-07-20 13 views
43

में के बाद से मैं अपने दम पर यह करने के लिए नहीं करना चाहते, मैं जावा के लिए एक अच्छा FFT कार्यान्वयन के लिए तलाश कर रहा हूँ। सबसे पहले मैंने इसे FFT Princeton पर इस्तेमाल किया लेकिन यह ऑब्जेक्ट्स का उपयोग करता है और मेरे प्रोफाइलर ने मुझे बताया कि यह वास्तव में इस तथ्य के कारण तेज़ नहीं है। तो मैंने फिर से गुमराह किया और इसे एक पाया: FFT Columbia जो तेज़ है। शायद आप में से एक को एक और एफएफटी कार्यान्वयन पता है? मैं क्योंकि मेरे एप्लिकेशन ध्वनि डेटा की एक बड़ी राशि को प्रोसेस करने में है "सर्वश्रेष्ठ" एक करना चाहते हैं, और उपयोगकर्ताओं को इंतजार कर ... ;-)विश्वसनीय और तेजी से FFT जावा

सादर पसंद नहीं है।

+11

बस मेरे दो सेंट, लेकिन मुझे वास्तव में उपकरण/पुस्तकालय/संसाधन अनुशंसाओं पर प्रतिबंध से नफरत है। –

+2

इस प्रश्न को दोबारा खोलें, क्योंकि यह महत्वपूर्ण है। – stackoverflowuser2010

उत्तर

28

FFTW 'सबसे तेजी से फूरियर पश्चिम में बदलना' है, और कुछ जावा रैपर है:

http://www.fftw.org/download.html

आशा है कि मदद करता है!

+0

दिलचस्प लग रहा है, मैं इसे बाद में देखता हूं। :) – InsertNickHere

+0

मैंने इसका जवाब स्वीकार कर लिया है भले ही मैं इसका उपयोग नहीं करता, लेकिन कई पेपोल इस lib को संदर्भित करते हैं। – InsertNickHere

+3

ध्यान दें कि एफएफटीडब्ल्यू जीपीएल लाइसेंस के तहत कवर किया गया है। (कम प्रतिबंधक लाइसेंस के साथ उपलब्ध गैर मुक्त संस्करण) –

3

मैं जावा में FFTs के लिए SSTJ का उपयोग करते हुए देख रहा हूँ। यदि पुस्तकालय उपलब्ध है या यदि शुद्ध नहीं है तो यह जेएनआई के माध्यम से FFTW पर रीडायरेक्ट कर सकता है।

+1

एसएसटीजे लिंक पुराना है ... आपका मतलब है जावा में साझा वैज्ञानिक टूलबॉक्स, अब [caromyr.github.io] पर होस्ट किया गया है (http://carsomyr.github.io/shared/) –

+0

@ जेसनएस मैंने अपना लिंक – alcor

15

पार्टी के लिए देर - यहाँ उन लोगों के लिए एक शुद्ध जावा समाधान के रूप में जब JNI एक विकल्प नहीं है। JTransforms

+0

को सही किया JTransforms में Apache Commons FastFourierTransformer के रूप में अच्छा एपीआई नहीं है लेकिन यह बहुत तेज़ है। –

10

मैं जावा में FFT के लिए एक समारोह लिखा है: http://www.wikijava.org/wiki/The_Fast_Fourier_Transform_in_Java_%28part_1%29

यह तो आप उन कार्यों हर जगह (व्यक्तिगत या व्यावसायिक परियोजनाओं भी) का उपयोग कर सकते पब्लिक डोमेन में है। बस मुझे क्रेडिट में उद्धृत करें और मुझे अपने काम का एक लिंक भेजें, और आप ठीक हैं।

यह पूरी तरह से विश्वसनीय है। मैंने गणित के एफएफटी के खिलाफ अपने आउटपुट की जांच की है और वे 15 वें दशमलव अंक तक हमेशा सही थे। मुझे लगता है कि यह जावा के लिए एक बहुत अच्छा एफएफटी कार्यान्वयन है। मैंने इसे जे 2 एसई 1.6 संस्करण पर लिखा, और इसे जे 2 एसई 1.5-1.6 संस्करण पर परीक्षण किया।

आप अनुदेश की संख्या की गिनती तो आप स्पष्ट रूप से देख सकते हैं इस संस्करण महान है कि भले ही यह बिल्कुल अनुकूल नहीं है (यह एक बहुत एक आदर्श कम्प्यूटेशनल जटिलता समारोह आकलन तुलना में बहुत सरल है)। यदि पर्याप्त अनुरोध हैं तो मैं अनुकूलित संस्करण प्रकाशित करने की योजना बना रहा हूं।

मुझे पता है अगर यह उपयोगी था, और मुझे आप की तरह किसी भी टिप्पणी बताओ।

/** 
* @author Orlando Selenu 
* 
*/ 
public class FFTbase { 
/** 
* The Fast Fourier Transform (generic version, with NO optimizations). 
* 
* @param inputReal 
*   an array of length n, the real part 
* @param inputImag 
*   an array of length n, the imaginary part 
* @param DIRECT 
*   TRUE = direct transform, FALSE = inverse transform 
* @return a new array of length 2n 
*/ 
public static double[] fft(final double[] inputReal, double[] inputImag, 
          boolean DIRECT) { 
    // - n is the dimension of the problem 
    // - nu is its logarithm in base e 
    int n = inputReal.length; 

    // If n is a power of 2, then ld is an integer (_without_ decimals) 
    double ld = Math.log(n)/Math.log(2.0); 

    // Here I check if n is a power of 2. If exist decimals in ld, I quit 
    // from the function returning null. 
    if (((int) ld) - ld != 0) { 
     System.out.println("The number of elements is not a power of 2."); 
     return null; 
    } 

    // Declaration and initialization of the variables 
    // ld should be an integer, actually, so I don't lose any information in 
    // the cast 
    int nu = (int) ld; 
    int n2 = n/2; 
    int nu1 = nu - 1; 
    double[] xReal = new double[n]; 
    double[] xImag = new double[n]; 
    double tReal, tImag, p, arg, c, s; 

    // Here I check if I'm going to do the direct transform or the inverse 
    // transform. 
    double constant; 
    if (DIRECT) 
     constant = -2 * Math.PI; 
    else 
     constant = 2 * Math.PI; 

    // I don't want to overwrite the input arrays, so here I copy them. This 
    // choice adds \Theta(2n) to the complexity. 
    for (int i = 0; i < n; i++) { 
     xReal[i] = inputReal[i]; 
     xImag[i] = inputImag[i]; 
    } 

    // First phase - calculation 
    int k = 0; 
    for (int l = 1; l <= nu; l++) { 
     while (k < n) { 
      for (int i = 1; i <= n2; i++) { 
       p = bitreverseReference(k >> nu1, nu); 
       // direct FFT or inverse FFT 
       arg = constant * p/n; 
       c = Math.cos(arg); 
       s = Math.sin(arg); 
       tReal = xReal[k + n2] * c + xImag[k + n2] * s; 
       tImag = xImag[k + n2] * c - xReal[k + n2] * s; 
       xReal[k + n2] = xReal[k] - tReal; 
       xImag[k + n2] = xImag[k] - tImag; 
       xReal[k] += tReal; 
       xImag[k] += tImag; 
       k++; 
      } 
      k += n2; 
     } 
     k = 0; 
     nu1--; 
     n2 /= 2; 
    } 

    // Second phase - recombination 
    k = 0; 
    int r; 
    while (k < n) { 
     r = bitreverseReference(k, nu); 
     if (r > k) { 
      tReal = xReal[k]; 
      tImag = xImag[k]; 
      xReal[k] = xReal[r]; 
      xImag[k] = xImag[r]; 
      xReal[r] = tReal; 
      xImag[r] = tImag; 
     } 
     k++; 
    } 

    // Here I have to mix xReal and xImag to have an array (yes, it should 
    // be possible to do this stuff in the earlier parts of the code, but 
    // it's here to readibility). 
    double[] newArray = new double[xReal.length * 2]; 
    double radice = 1/Math.sqrt(n); 
    for (int i = 0; i < newArray.length; i += 2) { 
     int i2 = i/2; 
     // I used Stephen Wolfram's Mathematica as a reference so I'm going 
     // to normalize the output while I'm copying the elements. 
     newArray[i] = xReal[i2] * radice; 
     newArray[i + 1] = xImag[i2] * radice; 
    } 
    return newArray; 
} 

/** 
* The reference bitreverse function. 
*/ 
private static int bitreverseReference(int j, int nu) { 
    int j2; 
    int j1 = j; 
    int k = 0; 
    for (int i = 1; i <= nu; i++) { 
     j2 = j1/2; 
     k = 2 * k + j1 - 2 * j2; 
     j1 = j2; 
    } 
    return k; 
    } 
} 
+0

क्या आप वेबपृष्ठ पर लाइसेंस बता सकते हैं? साथ ही, कृपया बताएं कि आप कैसे उद्धृत करना चाहते हैं। – stackoverflowuser2010

+1

हाय @ stackoverflowuser2010, लाइसेंस http://www.wikijava.org/wiki/WikiJava:GFDL पर है, इसलिए बस कोड से लिंक करें, और मेरा नाम लिखें (ऑरलैंडो सेलेनू) :) आपकी परियोजना क्या है? – alcor

+0

धन्यवाद। एंड्रॉइड पर काम करना और एक एफएफटी कार्यान्वयन की आवश्यकता है। – stackoverflowuser2010

3

मैं इसे आप क्या कार्रवाई कर रहे हैं पर निर्भर करता है लगता है:

मैं एक ही कोड यहीं साझा करें। यदि आप बड़ी अवधि में एफएफटी की गणना कर रहे हैं तो आप पाएंगे कि आप कितने आवृत्ति बिंदु चाहते हैं इस पर निर्भर करते हुए इसमें कुछ समय लगता है। हालांकि, ज्यादातर मामलों में ऑडियो के लिए इसे गैर-स्थिर माना जाता है (यह सिग्नल का मतलब है और अधिक समय में भिन्न परिवर्तन), इसलिए एक बड़ा एफएफटी (Periodogram PSD अनुमान) लेना एक सटीक प्रतिनिधित्व नहीं है। वैकल्पिक रूप से आप शॉर्ट-टाइम फूरियर ट्रांसफॉर्म का उपयोग कर सकते हैं, जिससे आप सिग्नल को छोटे फ्रेम में तोड़ते हैं और एफएफटी की गणना करते हैं। फ्रेम आकार इस बात पर निर्भर करता है कि आंकड़े कितनी जल्दी बदलते हैं, भाषण के लिए आमतौर पर 20-40ms होता है, संगीत के लिए मुझे लगता है कि यह थोड़ा अधिक है।

यह विधि अच्छी है यदि आप माइक्रोफ़ोन से नमूना कर रहे हैं, क्योंकि यह आपको एक समय में प्रत्येक फ्रेम को बफर करने की अनुमति देता है, एफएफटी की गणना करता है और उपयोगकर्ता को क्या लगता है "वास्तविक समय" बातचीत है। क्योंकि 20ms जल्दी है, क्योंकि हम वास्तव में छोटे अंतर को समझ नहीं सकते हैं।

मैंने भाषण संकेत पर एफएफटीडब्ल्यू और किसएफएफटी सी-पुस्तकालयों के बीच अंतर का परीक्षण करने के लिए एक छोटा बेंच मार्क विकसित किया। हां एफएफटीडब्ल्यू अत्यधिक अनुकूलित है, लेकिन जब आप केवल लघु-फ्रेम ले रहे हैं, उपयोगकर्ता के लिए डेटा अपडेट कर रहे हैं, और केवल एक छोटे से एफएफटी आकार का उपयोग कर रहे हैं, तो वे दोनों बहुत समान हैं। Badlogic गेम द्वारा LibGdx का उपयोग करके KissFFT libraries in Android को कार्यान्वित करने के तरीके पर एक उदाहरण दिया गया है। मैंने एंड्रॉइड ऐप में ओवरलैपिंग फ्रेम का उपयोग करके इस लाइब्रेरी को कार्यान्वित किया है जिसे मैंने कुछ महीने पहले विकसित किया था जिसे Speech Enhancement for Android कहा जाता है।

संबंधित मुद्दे