কেন এই বীট সনাক্তকরণ কোডটি কিছু মারাকে সঠিকভাবে নিবন্ধকরণ করতে ব্যর্থ হচ্ছে?


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++;
        }
    }
}

কোনও কারণে এটি কেবল 63৩7 সেকেন্ড থেকে প্রায় 1৪১ সেকেন্ড পর্যন্ত মারধর সনাক্ত করে এবং কেন তা আমার কোনও ধারণা নেই। আমি জানি যে আমি নকলগুলি খুঁজে পাচ্ছি বলে একাধিক ব্যান্ড থেকে বীটগুলি sertedোকানো হচ্ছে এবং মনে হচ্ছে এটি সেই মানগুলির মধ্যে প্রতিটি তাত্ক্ষণিক শক্তি মানকে একটি বিট বরাদ্দ করেছে।

এটি এর পরে মডেল করা হয়েছে: http://www.flipcode.com/misc/BeatDetectionAlgorithms.pdf

তাহলে মার কেন ঠিকমতো নিবন্ধন করবে না?


2
আপনি কি একটি ব্যান্ডের জন্য সময়ের সাথে সাথে ইনস্ট্যান্টনারজিলিস্ট [সূচক + 1] এবং ইতিহাসের বাফারের বিবর্তনের প্লট পোস্ট করতে পারেন? দুটি গ্রাফ একে অপরের উপরে ওভারলেড হয়েছে। সমস্যা কী হতে পারে সে সম্পর্কে এটি ক্লু দেবে। এছাড়াও, শক্তি অবশ্যই দৈর্ঘ্যের বর্গ হতে হবে, এটি ভুলে যাবেন না।
সিজেজে

আহ্ হ্যাঁ সমস্যাটি উন্মোচন করতে পারে, আমাকে দেখতে দিন আমি কোনওরকম কিছু গ্রাফ তৈরি করতে পারি কিনা
কুইন্সি

2
তবে এই প্লটটি কেবল ইতিহাসের বাফার, বা ইতিহাসবাফার / নাম্বইনফার * সি? দেখে মনে হচ্ছে আপনার সেখানে বিশাল সি আছে। কোডটি দেখলে, ইতিহাসবাফারের ইনস্ট্যান্টনারির সাথে একই মান থাকতে হবে, সেই গ্রাফটি কেবল তখনই হতে পারে যদি সি খুব বেশি বা নাম্বারনফার খুব কম হয় (1 এর নীচে), যা আমি অনুমান করি এটি ক্ষেত্রে নয় not
সিজেজে

7
যে প্রশ্নটি মারা যায় না ...
ইঞ্জিনিয়ার

3
এই প্রশ্নটি dsp.stackex
بدل.

উত্তর:


7

আমি এতে ছুরিকাঘাত করেছিলাম, যা বোবা ছিল কারণ আমি ফুরিয়ার ট্রান্সফর্ম বা সংগীত তত্ত্বের সাথে পরিচিত নই। সুতরাং, কিছু অধ্যয়নের পরে আমার কাছে কোনও সমাধান নেই, তবে আমি বেশ কয়েকটি উদ্বেগজনক জিনিস দেখছি:

  • সাউন্ড এবং সাউন্ডবফারের কোডটি অনুপস্থিত এবং সহজেই অপরাধী হতে পারে
  • ফুরিয়ার রূপান্তর
    • নেমস্পেস এবং পদ্ধতির নাম গুগল করে আমি একই ফুরিয়ার লাইব্রেরিটি খুঁজে পাইনি, যার অর্থ কোডটি কাস্টম হতে পারে এবং সমস্যার উত্স হতে পারে
    • ফাস্টফুরিয়ার.ক্যালকুলেট সংক্ষেপে একটি অ্যারে নেয় তা অস্বাভাবিক
  • GetEnergyList পদ্ধতিটি একটি রেফ তালিকা নিয়েছে তবে এই তালিকাটি আবার ব্যবহার করা হচ্ছে না?
  • বেশ কয়েকটি স্পটে আপনি দেখতে পেয়েছেন যে স্যাম্পল সাইজ হার্ড 1024 তে কোডড হয়েছে, তবে এটি স্পষ্ট নয় যে সবসময় এটি হয়।
  • প্লেসবিটমার্কার্সের জন্য মন্তব্য নোট করে যে এনকে 1024 দ্বারা ভাগ করা উচিত, এটি কলিং কোডটি করতে ভুলে গেছে?
  • আমি প্লেমারমার্কগুলিতে ইতিহাসের বাফারকে যেভাবে চালিত করা হয় তা সম্পর্কে আমি খুব সন্দেহজনক, বিশেষত যেহেতু এন পাস করা হয়েছে এবং তারপরে ইতিহাসের বাফারটি ব্যবহার করতে ব্যবহৃত হয়েছিল।
  • মন্তব্য *// Fill the history buffer with n * instant energy*এবং কোড অনুসরণ করে যে jive না।

কিছুক্ষণ পরে আমি অনুভূতিটি পেয়েছি কোডটি আসলেই ভালভাবে সংগঠিত হয় না এবং এটি ঠিক করার চেষ্টা করা সময় নষ্ট হবে। আপনি যদি এটির মূল্যবান বলে মনে করেন তবে আমি পরবর্তী পদক্ষেপ গ্রহণ করব:

  1. এটি সবচেয়ে সহজ অংশে ভেঙে দিন
  2. কোডটি সবচেয়ে ভার্বোজ উপায়ে আবার লিখুন, সমস্ত লুকানো ভেরিয়েবলের নাম দিন
  3. কোডের সামান্য অংশটি সঠিকভাবে কাজ করে তা নিশ্চিত করার জন্য ইউনিট পরীক্ষা লিখুন
  4. কোডের আরেকটি ছোট বিভাগ যুক্ত করুন এবং পুরো জিনিসটি সঠিকভাবে কাজ না করা পর্যন্ত পুনরাবৃত্তি করুন

পরামর্শ

  • লুপ যুক্তিটি সহজ করার জন্য আপনি ব্যান্ডের সংখ্যা স্থির করতে চাইতে পারেন
  • N, C এবং B এর মতো ভাল নামগুলি পরিষ্কার এবং সংক্ষিপ্ত রূপ দিন, এটি আপনাকে যৌক্তিক ত্রুটিগুলি আরও সহজভাবে মনে করতে সহায়তা করবে
  • কোডের বড় অংশগুলিকে একাধিক নামক পদ্ধতিতে ভাঙ্গা করুন যা প্রত্যেকে বড় প্রক্রিয়াটির একটি ছোট সংক্ষিপ্ত পদক্ষেপ করে এবং এটি সঠিকভাবে কাজ করছে কিনা তা নিশ্চিত করার জন্য ইউনিট টেস্ট লিখিত থাকতে পারে।

আমি কোড ধাঁধা সমাধান করার ভক্ত, যতক্ষণ ধাঁধা ভাল। অতএব অনুগ্রহ। আমি খুশি হয়েছি যে আপনি এটি গ্রহণ করেছেন এবং কোডে ত্রুটিগুলি খুঁজে পাওয়ার জন্য আপনার উত্তরগুলি কোনও কোড ধাঁধা পেতে পারে answer
শেঠ ব্যাটিন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.