বীট সনাক্তকরণ এবং এফএফটি


13

আমি একটি প্লাটফর্মার গেমের সাথে কাজ করছি যাতে বিট সনাক্তকরণ সহ সংগীত অন্তর্ভুক্ত রয়েছে। বর্তমান প্রশস্ততা যখন কোন historicalতিহাসিক নমুনা ছাড়িয়েছে তখন তা পরীক্ষা করে আমি বীটগুলি সনাক্ত করছি। এটি রক এর মতো জেনারগুলির সাথে জেনারগুলির সাথে ভাল কাজ করে না, যা বেশ ধ্রুবক প্রশস্ততাযুক্ত।

সুতরাং আমি আরও তাকাতে এবং এফএফটি ব্যবহার করে একাধিক ব্যান্ডে শব্দটি বিভক্ত অ্যালগরিদমগুলি দেখতে পেলাম ... তারপরে আমি কুলি-টুকি এফএফটি অ্যালগরিদমকে পেয়েছি

আমার একটাই সমস্যা হ'ল আমি অডিওতে বেশ নতুন এবং সিগন্যালটিকে একাধিক সংকেতে বিভক্ত করতে কীভাবে এটি ব্যবহার করব তা আমার কোনও ধারণা নেই।

সুতরাং আমার প্রশ্নটি হ'ল:

সিগন্যালটিকে একাধিক ব্যান্ডে বিভক্ত করতে আপনি কীভাবে এফএফটি ব্যবহার করবেন?

আগ্রহী ছেলেদের জন্যও এটি সি # তে আমার অ্যালগোরিদম is

// C = threshold, N = size of history buffer / 1024
    public void PlaceBeatMarkers(float C, int N)
    {
        List<float> instantEnergyList = new List<float>();
        short[] samples = soundData.Samples;

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

        // Calculate instant energy for every 1024 samples.
        while (sampleIndex + nextSamples < samples.Length)
        {

            float instantEnergy = 0;

            for (int i = 0; i < nextSamples; i++)
            {
                instantEnergy += Math.Abs((float)samples[sampleIndex + i]);
            }

            instantEnergy /= nextSamples;
            instantEnergyList.Add(instantEnergy);

            if(sampleIndex + nextSamples >= samples.Length)
                nextSamples = samples.Length - sampleIndex - 1;

            sampleIndex += nextSamples;
        }


        int index = N;
        int numInBuffer = index;
        float 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++;
        }
    }

আমার ধারণা, উইকিপিডিয়া এর এফএফটি এবং ডিএসপি এন্ট্রিগুলি একটি ভাল সূচনা পয়েন্ট । বীট সনাক্তকরণ এন্ট্রি অপ্রয়োজনীয় তবে গেমদেভ.টনে একটি নিবন্ধের
টোবিয়াস কেইনজলার

উত্তর:


14

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

সূত্রে, যদি এক্স [কে] = এফএফটি (এক্স [এন]), আপনি এটিকে ভেক্টর দিন i [n] = x [n], এবং একটি আউটপুট পাবেন [এম], তারপরে

X[k] = o[2k] + j·o[2k+1]

(যদিও মাঝে মাঝে আপনি এক্স [কে] = ও [কে] + জ · ও [কে + কে / ২] পান, যেখানে কে আপনার উইন্ডোর দৈর্ঘ্য, উদাহরণ হিসাবে 1024)। যাইহোক, জে কল্পিত ইউনিট, বর্গ (-1)।

একটি ব্যান্ডের তীব্রতাটিকে এই ব্যান্ডের জটিল সংমিশ্রণের সাথে মূল হিসাবে গণনা করা হয়:

|X[k]| = sqrt( X[k] · X[k]* )

এবং শক্তিটি দৈর্ঘ্যের বর্গ হিসাবে সংজ্ঞায়িত করা হয়।

আমরা যদি একটি = ও [2 কে] এবং বি = ও [2 কে + 1] কল করি, আমরা পাই

X[k] = a + j·b

অতএব

E[k] = |X[k]|^2 = (a+j·b)·(a-j·b) = a·a + b·b

পুরো বিষয়টিকে আনرول করা, যদি আপনি এফএফটি অ্যালগরিদম থেকে আউটপুট হিসাবে [এম] পেয়ে থাকেন তবে ব্যান্ড কে-তে শক্তিটি হ'ল:

E[k] = o[2k] · o[2k] + o[2k+1] · o[2k+1]

(দ্রষ্টব্য: কনজুগেশন অপারেটরের সাথে বিভ্রান্তি এড়াতে আমি স্বাভাবিকের পরিবর্তে গুণকে নির্দেশ করতে the চিহ্নটি ব্যবহার করেছি)

ব্যান্ড কে এর ফ্রিকোয়েন্সি, 44.1Khz এর নমুনা ফ্রিকোয়েন্সি এবং 1024 নমুনার একটি উইন্ডো ধরে রেখে

freq(k) = k / 1024 * 44100 [Hz]

সুতরাং, উদাহরণস্বরূপ, আপনার প্রথম ব্যান্ড কে = 0 0 হার্জ উপস্থাপন করে, কে = 1 হ'ল 43 হার্জেড, এবং শেষের কে = 511 22KHz (নাইকুইস্ট ফ্রিকোয়েন্সি)।

আমি আশা করি এটি কীভাবে আপনি এফএফটি ব্যবহার করে প্রতি ব্যান্ডের সিগন্যালের শক্তি পাবেন সে সম্পর্কে আপনার প্রশ্নের উত্তর দেয়।

সংযোজন : মন্তব্যে আপনার প্রশ্নের উত্তর দেওয়া, এবং ধরে নেওয়া যে আপনি প্রশ্নটিতে পোস্ট করা লিঙ্কটি থেকে কোডটি ব্যবহার করছেন (দ্য কুলি-টুকি অ্যালগোরিদম সি তে): আসুন বলি যে আপনার শর্ট ইনসটির ভেক্টর হিসাবে আপনার ইনপুট ডেটা রয়েছে:

// len is 1024 in this example.  It MUST be a power of 2
// centerFreq is given in Hz, for example 43.0
double EnergyForBand( short *input, int len, double centerFreq)
{
  int i;
  int band;
  complex *xin;
  complex *xout;
  double magnitude;
  double samplingFreq = 44100.0; 

  // 1. Get the input as a vector of complex samples
  xin = (complex *)malloc(sizeof(struct complex_t) * len);

  for (i=0;i<len;i++) {
    xin[i].re = (double)input[i];
    xin[i].im = 0;
  }

  // 2. Transform the signal
  xout = FFT_simple(xin, len);

  // 3. Find the band ( Note: floor(x+0.5) = round(x) )
  band = (int) floor(centerFreq * len / samplingFreq + 0.5); 

  // 4. Get the magnitude
  magnitude = complex_magnitude( xout[band] );

  // 5. Don't leak memory
  free( xin );
  free( xout );

  // 6. Return energy
  return magnitude * magnitude;
}

আমার সি কিছুটা মরিচা (আমি আজকাল বেশিরভাগ সি ++ তে কোডিং করছি), তবে আমি আশা করি এই কোডটি দিয়ে আমি কোনও বড় ভুল করিনি। অবশ্যই আপনি যদি অন্য ব্যান্ডের শক্তিতে আগ্রহী হন তবে তাদের প্রতিটিটির জন্য পুরো উইন্ডোটি রূপান্তরিত করার কোনও মানে হয় না, এটি সিপিইউ সময় নষ্ট হবে। সেক্ষেত্রে একবার রূপান্তর করুন এবং এক্সআউট থেকে আপনার প্রয়োজনীয় সমস্ত মান পান।


ওহ, আপনি যে কোডটি সংযুক্ত করেছেন সে সম্পর্কে আমি কেবল একবার দেখেছি, এটি ইতিমধ্যে আপনাকে "জটিল" আকারে ফলাফল দেয় এবং এমনকি একটি জটিল সংখ্যার परिमाण গণনা করার জন্য একটি ফাংশন সরবরাহ করে। তারপরে আপনাকে কেবল আউটপুট ভেক্টরের প্রতিটি উপাদানগুলির জন্য সেই মাত্রার বর্গাকার গণনা করতে হবে, ফলাফলগুলি বাছাই করার বিষয়ে চিন্তা করার দরকার নেই।
সিজেজে

উদাহরণস্বরূপ যদি আমার উইন্ডো 0-1024 থেকে সমস্ত 1024 নমুনা থাকে এবং আমি সেগুলিকে আসল মান হিসাবে পাই, সুতরাং কোনও জটিল অংশ নেই। এবং আমি সেখানে ফ্রিকোয়েন্সি ব্যান্ড 43Hz এ শক্তি গণনা করতে চাই। আমি কীভাবে তখন এটি সংহত করব? (আমার কেবল আসল অংশটি ফিরে আসতে হবে, ইতিবাচক অংশটি) আপনি যদি কিছু সিউডোকোডে করতে পারতেন তবে আমি চিরকাল আপনার গভীরতা
কুইন্সি

আমার লেখা কোডটি আপনার লিঙ্ক করা সি লাইব্রেরিটি ব্যবহার করছে যা ইতিমধ্যে একটি "জটিল" কাঠামো ধারণ করে। এটি আমার প্রশ্নে বর্ণিত মোড়ককে অযৌক্তিক করে তোলে (এবং কোডটি এটি প্রতিফলিত করে)
সিজেজে


0

আমি নিজে এটি করেছি বা এ সম্পর্কে খুব বেশি কিছু পড়িনি, তবে আমার প্রথম শটটি এরকমই:

প্রথমত, আপনাকে এফএফটি সহ সময় নির্ভর নির্ভর বর্ণালী পেতে একটি উইন্ডো ফাংশন প্রয়োগ করতে হবে। বীটটি সাধারণত নিম্ন ফ্রিকোয়েন্সিগুলিতে থাকে, সুতরাং এর কয়েকটি ফ্রিকোয়েন্সিগুলির তীব্রতার উপর আরও বড় টাইম উইন্ডো সহ অন্য একটি এফএফটি প্রয়োগ করুন (সরলতার জন্য শুরুতে উদাহরণস্বরূপ কেবলমাত্র 100 হার্জ প্রতি 1 দিয়ে শুরু করুন এবং দেখুন যে এটি যথেষ্ট নির্ভরযোগ্য কিনা)। এই বর্ণালীতে শীর্ষটি সন্ধান করুন এবং সেই ফ্রিকোয়েন্সিটি বীটের জন্য অনুমান।


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