2013-03-22 11 views
11

मैं इन सवाल पढ़ा है:आईओएस FFT ड्रा स्पेक्ट्रम

Using the Apple FFT and Accelerate Framework

How do I set up a buffer when doing an FFT using the Accelerate framework?

iOS FFT Accerelate.framework draw spectrum during playback

वे सब कैसे ढांचे में तेजी लाने के साथ सेटअप fft करने का वर्णन। उनकी मदद से मैं एफएफटी स्थापित करने और बुनियादी स्पेक्ट्रम विश्लेषक प्राप्त करने में सक्षम था। अभी, मैं एफएफटी से प्राप्त सभी मूल्यों को प्रदर्शित कर रहा हूं। हालांकि, मैं केवल कुछ आवृत्तियों को शांत करने वाले सलाखों के 10-15, या एक चर संख्या को दिखाना चाहता हूं। आईट्यून्स या विनएम्प लेवल मीटर की तरह। 1. क्या मुझे आवृत्तियों की एक श्रृंखला से औसत परिमाण मानों की आवश्यकता है? या क्या वे आपको विशिष्ट आवृत्ति पट्टी के लिए एक परिमाण दिखाते हैं? 2. साथ ही, क्या मुझे अपने परिमाण मान को डीबी में परिवर्तित करने की आवश्यकता है? 3. मैं अपने डेटा को किसी निश्चित सीमा पर कैसे मैप कर सकता हूं। क्या मैं अपनी आवाज बिटडिप के लिए अधिकतम डीबी रेंज के खिलाफ मैप करता हूं? बिन के लिए अधिकतम मान प्राप्त करने से अधिकतम मैपिंग मान कूदने लगेंगे।

मेरे RenderCallback:

static OSStatus PlaybackCallback(void *inRefCon, 
           AudioUnitRenderActionFlags *ioActionFlags, 
           const AudioTimeStamp *inTimeStamp, 
           UInt32 inBusNumber, 
           UInt32 inNumberFrames, 
           AudioBufferList *ioData) 
{ 
    UInt32 maxSamples = kAudioBufferNumFrames; 

    UInt32 log2n = log2f(maxSamples); //bins 
    UInt32 n = 1 << log2n; 

    UInt32 stride = 1; 
    UInt32 nOver2 = n/2; 

    COMPLEX_SPLIT A; 
    float   *originalReal, *obtainedReal, *frequencyArray, *window, *in_real; 

    in_real = (float *) malloc(maxSamples * sizeof(float)); 

    A.realp = (float *) malloc(nOver2 * sizeof(float)); 
    A.imagp = (float *) malloc(nOver2 * sizeof(float)); 
    memset(A.imagp, 0, nOver2 * sizeof(float)); 

    obtainedReal = (float *) malloc(n * sizeof(float)); 
    originalReal = (float *) malloc(n * sizeof(float)); 
    frequencyArray = (float *) malloc(n * sizeof(float)); 

    //-- window 

    UInt32 windowSize = maxSamples; 
    window = (float *) malloc(windowSize * sizeof(float)); 

    memset(window, 0, windowSize * sizeof(float)); 
    // vDSP_hann_window(window, windowSize, vDSP_HANN_DENORM); 

    vDSP_blkman_window(window, windowSize, 0); 

    vDSP_vmul(ioBuffer, 1, window, 1, in_real, 1, maxSamples); 

    //-- window 

    vDSP_ctoz((COMPLEX*)in_real, 2, &A, 1, maxSamples/2); 

    vDSP_fft_zrip(fftSetup, &A, stride, log2n, FFT_FORWARD); 
    vDSP_fft_zrip(fftSetup, &A, stride, log2n, FFT_INVERSE); 

    float scale = (float) 1.0/(2 * n); 

    vDSP_vsmul(A.realp, 1, &scale, A.realp, 1, nOver2); 
    vDSP_vsmul(A.imagp, 1, &scale, A.imagp, 1, nOver2); 

    vDSP_ztoc(&A, 1, (COMPLEX *) obtainedReal, 2, nOver2); 
    vDSP_zvmags(&A, 1, obtainedReal, 1, nOver2); 

    Float32 one = 1; 
    vDSP_vdbcon(obtainedReal, 1, &one, obtainedReal, 1, nOver2, 0); 

    for (int i = 0; i < nOver2; i++) { 
     frequencyArray[i] = obtainedReal[i]; 
    } 


    // Extract the maximum value 
    double fftMax = 0.0; 
    vDSP_maxmgvD((double *)obtainedReal, 1, &fftMax, nOver2); 

    float max = sqrt(fftMax); 
} 

कुछ संगीत बजाना, मैं -96db से मूल्यों 0dB को मिलता है।

CGPointMake(i, kMaxSpectrumHeight * (1 - frequencyArray[i]/-96.)); 

मेरी एक नहीं बल्कि गोल वक्र दे रहा है: पर एक बिंदु साजिश

plot1

मैं db से मैं 10000 के आधार पर अपने सरणी मूल्य गुणा करके साजिश और प्राप्त कर सकते हैं परिवर्तित नहीं करते हैं अच्छा चोटियों।

plot2

Am मैं कुछ पूरी तरह से गलत कर? और मैं बार की एक चर संख्या दिखाने के लिए कैसे मिलता है?

+0

बस सोच रहा है: लेकिन क्या आपके पास अंतिम कोड है जो बार प्रदान करता है? मुझे यह जानने में कठिनाई हो रही है कि नीचे दिए गए उत्तर से कहां जाना है। – kezi

उत्तर

8
  1. मैं आवृत्तियों की एक रेंज से औसत परिमाण मूल्यों की जरूरत है? या क्या वे आपको विशिष्ट आवृत्ति पट्टी के लिए एक परिमाण दिखाते हैं?

हां, आपको निश्चित रूप से परिभाषित बैंडों में मूल्यों को औसत करने की आवश्यकता है। दिखा रहा है कि सिर्फ एक एफएफटी बिन पागलपन है।

  1. साथ ही, क्या मुझे अपने परिमाण मान को डीबी में परिवर्तित करने की आवश्यकता है?

हाँ: डीबी एक लॉग स्केल है। संयोग से नहीं, मानव सुनवाई भी लॉग पैमाने पर (मोटे तौर पर) काम करती है। इसलिए यदि आप उन्हें प्लॉट करने से पहले मूल्यों के लॉग 2() लेते हैं तो मूल्य मनुष्यों के लिए अधिक प्राकृतिक लगेंगे।

  1. मैं अपने डेटा को किसी निश्चित सीमा पर कैसे मैप कर सकता हूं। क्या मैं अपनी आवाज बिटडिप के लिए अधिकतम डीबी रेंज के खिलाफ मैप करता हूं? बिन के लिए अधिकतम मान प्राप्त करना अधिकतम मैपिंग मानों को कूदने के लिए नेतृत्व करेगा।

मुझे क्या करना (धारणात्मक कम से कम) एक 0..1, उदाहरण के लिए 'सामान्यीकृत और बढ़ाया' नाव मूल्य में जो कुछ भी प्रारूप से अपने मूल्यों कन्वर्ट करने के लिए है सबसे आसान काम लगता है। फिर वहां से आप प्लॉट करने के लिए आवश्यक कुछ चीज़ों के लिए जरूरी रूप से परिवर्तित कर सकते हैं। उदाहरण के लिए

SInt16 rawValue = fft[0]; // let's say this comes back as 12990 

float scaledValue = rawValue/32767.; // This is MAX_INT for 16-bit; 
     // dividing we get .396435438 which is much easier for most people 
     // to see conceptually as 39% of our max possible value 

float displayValue = log2(scaledValue); 

my_fft[0] = displayValue; 
संबंधित मुद्दे