यह बीट डिटेक्शन कोड कुछ बीट्स को ठीक से रजिस्टर करने में विफल क्यों है?


38

मैंने गानों में बीट्स का पता लगाने के लिए यह साउंडअनलीज़र क्लास बनाई:

class SoundAnalyzer
{
    public SoundBuffer soundData;
    public Sound sound;
    public List<double> beatMarkers = new List<double>();

    public SoundAnalyzer(string path)
    {
        soundData = new SoundBuffer(path);
        sound = new Sound(soundData);
    }

    // C = threshold, N = size of history buffer / 1024  B = bands
    public void PlaceBeatMarkers(float C, int N, int B)
    {
        List<double>[] instantEnergyList = new List<double>[B];
        GetEnergyList(B, ref instantEnergyList);
        for (int i = 0; i < B; i++)
        {
            PlaceMarkers(instantEnergyList[i], N, C);
        }
        beatMarkers.Sort();
    }

    private short[] getRange(int begin, int end, short[] array)
    {
        short[] result = new short[end - begin];
        for (int i = 0; i < end - begin; i++)
        {
            result[i] = array[begin + i];
        }
        return result;
    }

    // get a array of with a list of energy for each band
    private void GetEnergyList(int B, ref List<double>[] instantEnergyList)
    {
        for (int i = 0; i < B; i++)
        {
            instantEnergyList[i] = new List<double>();
        }
        short[] samples = soundData.Samples;

        float timePerSample = 1 / (float)soundData.SampleRate;
        int sampleIndex = 0;
        int nextSamples = 1024;
        int samplesPerBand = nextSamples / B;

        // for the whole song
        while (sampleIndex + nextSamples < samples.Length)
        {
            complex[] FFT = FastFourier.Calculate(getRange(sampleIndex, nextSamples + sampleIndex, samples));
            // foreach band
            for (int i = 0; i < B; i++)
            {
                double energy = 0;
                for (int j = 0; j < samplesPerBand; j++)
                    energy += FFT[i * samplesPerBand + j].GetMagnitude();

                energy /= samplesPerBand;
                instantEnergyList[i].Add(energy);

            }

            if (sampleIndex + nextSamples >= samples.Length)
                nextSamples = samples.Length - sampleIndex - 1;
            sampleIndex += nextSamples;
            samplesPerBand = nextSamples / B;
        }
    }

    // place the actual markers
    private void PlaceMarkers(List<double> instantEnergyList, int N, float C)
    {
        double timePerSample = 1 / (double)soundData.SampleRate;
        int index = N;
        int numInBuffer = index;
        double historyBuffer = 0;

        //Fill the history buffer with n * instant energy
        for (int i = 0; i < index; i++)
        {
            historyBuffer += instantEnergyList[i];
        }

        // If instantEnergy / samples in buffer < instantEnergy for the next sample then add beatmarker.
        while (index + 1 < instantEnergyList.Count)
        {
            if(instantEnergyList[index + 1] > (historyBuffer / numInBuffer) * C)
                beatMarkers.Add((index + 1) * 1024 * timePerSample); 
            historyBuffer -= instantEnergyList[index - numInBuffer];
            historyBuffer += instantEnergyList[index + 1];
            index++;
        }
    }
}

किसी कारण से यह केवल 637 सेकंड से लगभग 641 सेकंड तक बीट्स का पता लगा रहा है, और मुझे नहीं पता कि क्यों। मुझे पता है कि बीट को कई बैंड से डाला जा रहा है क्योंकि मुझे डुप्लिकेट मिल रहा है, और ऐसा लगता है कि यह उन मूल्यों के बीच प्रत्येक तात्कालिक ऊर्जा मूल्य को हरा दे रहा है।

इसके बाद इसका मॉडल तैयार किया गया है: http://www.flipcode.com/misc/BeatDetectionAlgorithms.pdf

तो धड़कन ठीक से रजिस्टर क्यों नहीं होगी?


2
क्या आप एक बैंड के लिए समय के साथ InstantEnergyList [सूचकांक + 1] और इतिहास के विकास की साजिश पोस्ट कर सकते हैं? दो रेखांकन एक दूसरे के ऊपर ओवरले हुए। इससे इस बात की जानकारी मिलेगी कि समस्या क्या हो सकती है। इसके अलावा, ऊर्जा परिमाण का वर्ग होना चाहिए, यह मत भूलना।
सीजय

आह हाँ जो इस समस्या का अनावरण कर सकता है, मुझे यह देखने दो कि क्या मैं किसी तरह कुछ रेखांकन बना सकता हूँ
क्विंसी

2
लेकिन यह कथानक सिर्फ इतिहास है बफ़र, या इतिहास बफ़र / अंकइन्फ़र * सी? ऐसा लगता है कि आपके पास वहां एक विशाल सी है। कोड को देखते हुए, हिस्ट्रीबफ़र के पास तात्कालिकता के समान मूल्य होने चाहिए, वह ग्राफ़ केवल तभी हो सकता है जब सी बहुत अधिक हो या न्यूमबफ़र बहुत कम हो (1 से नीचे का रास्ता), जो मुझे लगता है कि ऐसा नहीं है।
सिजय

7
सवाल यह है कि मर नहीं होगा ...
इंजीनियर

3
यह सवाल dsp.stackexchange.com
Atav32

जवाबों:


7

मैंने उस पर एक छुरा लिया, जो गूंगा था क्योंकि मैं फूरियर रूपांतरण या संगीत सिद्धांत से परिचित नहीं था। इसलिए, कुछ अध्ययन के बाद मेरे पास कोई हल नहीं है, लेकिन मुझे कई परेशान करने वाली चीजें दिखाई देती हैं:

  • साउंड और साउंडबफ़र के लिए कोड गायब है और आसानी से अपराधी हो सकता है
  • फूरियर रूपांतरण
    • मैं नाम और पद्धति के नामों को गुगली करके एक ही फूरियर ट्रांसफॉर्म लाइब्रेरी को नहीं खोज सका, जिसका अर्थ है कि कोड कस्टम हो सकता है और समस्या का स्रोत हो सकता है
    • तथ्य यह है कि FastFourier.Calculate संक्षिप्त की एक सरणी लेता है असामान्य है
  • विधि GetEnergyList एक रेफरी सूची लेता है, लेकिन इस सूची का फिर से उपयोग नहीं किया जाता है?
  • कई स्थानों पर आप नमूना को 1024 में हार्ड कोडित करते हुए देखते हैं, लेकिन यह स्पष्ट नहीं है कि हमेशा ऐसा ही होता है।
  • यह परेशान कर रहा है कि PlaceBeatMarkers के लिए टिप्पणी है कि N को 1024 से विभाजित किया जाना चाहिए, शायद कॉलिंग कोड ऐसा करना भूल गया?
  • मुझे उस तरह से बहुत संदेह है जिस तरह से हिस्ट्रीबफ़र को प्लेसमैकर्स में हेरफेर किया गया है, खासकर जब से एन पास हुआ है और तब हिस्ट्रीबफ़र को हेरफेर करने के लिए इस्तेमाल किया गया था।
  • टिप्पणी *// Fill the history buffer with n * instant energy*और कोड है कि पीछा नहीं करता है।

थोड़ी देर बाद मुझे लगा कि कोड वास्तव में अच्छी तरह से व्यवस्थित नहीं है और इसे ठीक करने की कोशिश में समय की बर्बादी होगी। अगर आपको लगता है कि यह इसके लायक है, तो मैं जो अगला कदम उठाऊंगा, वह है:

  1. इसे सबसे सरल भाग तक तोड़ दें
  2. सबसे वर्बोज़ तरीके से कोड को फिर से लिखें, सभी छिपे हुए चर नाम दें
  3. यह सुनिश्चित करने के लिए इकाई परीक्षण लिखें कि कोड का थोड़ा हिस्सा सही ढंग से काम करता है
  4. कोड का एक और छोटा खंड जोड़ें और तब तक दोहराएं जब तक कि आपको पूरी चीज सही काम न कर ले

टिप्स

  • आप लूप लॉजिक को आसान बनाने के लिए निश्चित संख्या में बैंड बनाना चाहते हैं
  • N, C और B जैसे नाम अच्छे दें जो स्पष्ट और संक्षिप्त हों, इससे आपको तार्किक त्रुटियों को आसानी से देखने में मदद मिलेगी
  • कोड के बड़े वर्गों को कई तथाकथित तरीकों से तोड़ें जो प्रत्येक बड़ी प्रक्रिया का एक छोटा संक्षिप्त चरण करते हैं और यह सुनिश्चित करने के लिए यूनिट परीक्षण लिखा हो सकता है कि यह सही ढंग से काम कर रहा है।

मैं कोड पहेलियों को हल करने का प्रशंसक हूं, जब तक कि पहेली अच्छी है। इसलिए इनाम। मुझे खुशी है कि आप इसे ले गए, और कोड में त्रुटियों को खोजने के लिए आपके उत्तर एक कोड पहेली प्राप्त कर सकते हैं सबसे अच्छा जवाब है।
सेठ बैटन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.