2012-08-07 46 views
6

में प्रत्येक 1/4 सेकंड में ऑडियो फ़ाइल की आवृत्ति प्राप्त करें मेरे पास एक ध्वनि फ़ाइल (.3 जीपी) है और इसकी लगभग ~ 1 मिनट है। मैं हर 1/4 सेकंड में इस ध्वनि फ़ाइल की आवृत्ति प्राप्त करना चाहता हूं। मेरा विचार ऑडियो फ़ाइल से प्रत्येक 1/4 सेकंड में नमूने प्राप्त करना और एफएफटी I का उपयोग करना आवृत्ति मान प्राप्त हो सकता है। क्या इसे करने का कोई तरीका है?एंड्रॉइड

दरअसल मैं ध्वनि फ़ाइल को 1/4sec नमूने ध्वनि फ़ाइलों (अलवीस को पूर्ववत ओवरराइटिंग) में विभाजित करता हूं, फिर एफएफटी एल्गोरिदम का उपयोग करके आवृत्ति का पता लगाता हूं जहां मैग्निट्यूड सबसे बड़ा है। लेकिन आसान समाधान हो सकते हैं हालांकि मुझे कोई संकेत नहीं है कि यह कैसे करें।

*** अद्यतन 2 - नए कोड

मैं इस कोड अब तक का उपयोग करें:

public class RecordAudio extends AsyncTask<Void, double[], Void> { 

    @Override 
    protected Void doInBackground(Void... arg0) { 

     try { 
      int bufferSize = AudioRecord.getMinBufferSize(frequency, 
      AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT); 


      //int bufferSize = AudioRecord.getMinBufferSize(frequency, 
        // channelConfiguration, audioEncoding); 

      AudioRecord audioRecord = new AudioRecord( 
        MediaRecorder.AudioSource.MIC, frequency, 
        channelConfiguration, audioEncoding, bufferSize); 

      short[] buffer = new short[blockSize]; 
      //double[] toTransform = new double[blockSize]; 


      audioRecord.startRecording(); 


      // started = true; hopes this should true before calling 
      // following while loop 

      while (started) { 
       sampling++; 

       double[] re = new double[blockSize]; 
       double[] im = new double[blockSize]; 

       double[] newArray = new double[blockSize*2]; 
       double[] magns = new double[blockSize]; 

       double MaxMagn=0; 
       double pitch = 0; 

       int bufferReadResult = audioRecord.read(buffer, 0, 
         blockSize); 


       for (int i = 0; i < blockSize && i < bufferReadResult; i++) { 
        re[i] = (double) buffer[i]/32768.0; // signed 16bit 
        im[i] = 0; 
       }  

       newArray = FFTbase.fft(re, im,true); 

       for (int i = 0; i < newArray.length; i+=2) { 

        re[i/2]=newArray[i]; 
        im[i/2]=newArray[i+1]; 
        magns[i/2] = Math.sqrt(re[i/2]*re[i/2]+im[i/2]*im[i/2]); 
       } 

       // I only need the first half  

       for (int i = 0; i < (magns.length)/2; i++) { 
        if (magns[i]>MaxMagn) 
        { 
         MaxMagn = magns[i]; 
         pitch=i; 
        } 
       }           
       if (sampling > 50) { 
        Log.i("pitch and magnitude", "" + MaxMagn + " " + pitch*15.625f); 
        sampling=0; 
        MaxMagn=0;pitch=0; 
        }     


      } 

      audioRecord.stop(); 

     } catch (Throwable t) { 
      t.printStackTrace(); 
      Log.e("AudioRecord", "Recording Failed"); 
     } 
     return null; 
    } 

मैं इस का उपयोग करें: http://www.wikijava.org/wiki/The_Fast_Fourier_Transform_in_Java_%28part_1%29

गिटार तार सही लगते हैं, लेकिन अपने ही ध्वनि नहीं है इस वजह से अच्छा:

enter image description here

दो चोटियों की परिमाण ज्यादातर समय बदलती है और मुझे मौलिक आवृत्ति प्राप्त करने के लिए हमेशा सबसे बड़ी मिलती है।

+0

हाय, मुझे एक ही समस्या है, मुझे ध्वनि वास्तविक समय रिकॉर्ड करने और हर 4ms में आवृत्ति की गणना करने की आवश्यकता है, आपने इसे कैसे प्राप्त किया? आपके साथ कोई नमूना कोड? –

+0

हाय, मैं समस्या से निपटने में सफल नहीं हुआ, हालांकि मेरी गिटार की आवाज 10 में से 9 थी, लेकिन मेरी आवाज शायद 10 में से 7 थी .. –

उत्तर

7

पिच FFT के साथ ट्रैकिंग तो अक्सर स्टैक ओवरफ़्लो पर पूछा जाता है मैं एक blog entry with sample code लिखा था। कोड सी में है, लेकिन स्पष्टीकरण और लिंक के साथ आप जो भी चाहते हैं उसे करने में सक्षम होना चाहिए।

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

+0

उत्तर के लिए धन्यवाद, मेरे कोड के साथ मेरी खोज को अपडेट किया गया। मैंने एक नमूना काउंटर शुरू करने के साथ 1/4 सेकेंड हल किए और जब यह किसी दिए गए मान तक पहुंच जाता है तो यह फिर से शुरू होता है। लेकिन उच्च आवृत्तियों पर पिच का पता लगाने इतना अच्छा नहीं है।अगर मैं जोर से उच्च आवाज करता हूं, तो ऊपरी हार्मोनिक्स पूरी चीज को गलत बनाता है और अगर मैं 3khz के बजाय लगभग 13khz मिलता हूं। हालांकि उदाहरण के लिए मुझे 1kz का 600hz insted मिलता है, इसलिए मुझे नहीं पता कि समस्या क्या है। –

+0

समस्या यह है कि यदि आपके पास ऐसी ध्वनि है जिसमें हार्मोनिक्स (यानी कोई संगीत वाद्य यंत्र, या कोई शोर जो शुद्ध साइन लहर नहीं है) तो बस एफएफटी की चोटी को ढूंढने से आपको पिच नहीं मिलेगी। पिच से संबंधित आवृत्ति हार्मोनिक्स की तुलना में कम आयाम हो सकती है। आपको [पिच अनुमान एल्गोरिदम] पर पढ़ना होगा (http://en.wikipedia.org/wiki/Pitch_detection_algorithm) –

+0

यह सच है कि _mandrill ने क्या कहा, लेकिन यह स्पष्ट है कि आपको अन्य समस्याएं हैं क्योंकि आप जो आवृत्तियों को प्राप्त कर रहे हैं वे गुणक नहीं हैं और इसलिए हार्मोनिक्स नहीं हैं। अगर मुझे बाद में मौका मिलेगा, तो मैं आपके कोड पर अधिक बारीकी से देखूंगा, लेकिन पहले स्किम पर ऐसा लगता है कि आप कुछ गलतियां कर रहे हैं: 1. निचले आधे की बजाय पूरे रूपांतरित डेटा को देखते हुए 2. खिड़की नहीं आपका डेटा। यह सब और अधिक मेरे ब्लॉग एंट्री ट्यूटोरियल में शामिल है। –

1

AsyncTask का प्रयास करें:

class GetFrequency extends AsyncTask<String, Void, Void> { 
    public Void doInBackground(String... params) { 
      while (true) { 

      // Apply Logic Here 

      try { 
       Thread.sleep(250); 
       } catch (Exception ie) { 
        // TODO Auto-generated catch block 
       e.printStackTrace(); 
       } 
     } 
    } 
} 

करके अपने MainActivity में इस कॉल,

frequencyButtonListener.setOnClickListener(new OnClickListener() { 

     @Override 
     public void onClick(View v) { 

     new GetFrequency.execute(params); 

     } 
    }); 
+0

हाय, उत्तर के लिए धन्यवाद। मुझे कुछ त्रुटि मिली है जिसे मैं ठीक नहीं कर सकता। onPostExecute, onPreExecute और ऑन प्रोग्रेस अपडेट मुझे sytax त्रुटियां देता है। –

+0

यदि आप उन्हें नहीं चाहते हैं, तो बस उन्हें हटा दें !! –

+0

मैंने उन्हें हटा दिया। वाकई, मुझे समझ में नहीं आता कि इसे कैसे काम करना चाहिए। मेरे पास /sdcard/music.3gp में .3gp फ़ाइल है और इसका विश्लेषण करना चाहते हैं। तो मैंने नए GetFrequency.execute (पैरा) के साथ एक बटन बनाया; लेकिन यह मुझे एक त्रुटि देता है GetFrequency.execute को किसी प्रकार से हल नहीं किया जा सकता है। –