Почему этот код обнаружения биений не позволяет правильно зарегистрировать некоторые биты?

Я сделал этот класс SoundAnalyzer для обнаружения ударов в песнях:

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

Итак, почему биты не регистрируются должным образом?

39 голосов | спросил Quincy 17 MarpmThu, 17 Mar 2011 19:10:07 +03002011-03-17T19:10:07+03:0007 2011, 19:10:07

1 ответ


7

Я принял удар, который был глупым, потому что я не знаком с преобразованиями Фурье или теорией музыки. Итак, после некоторого исследования у меня нет решения, но я вижу несколько тревожных вещей:

  • Код для Sound и Soundbuffer отсутствует и может быть легко виновником
  • Преобразования Фурье
    • Я не мог найти одну и ту же библиотеку преобразований Фурье, перейдя по именам имен имен и имен методов, что означает, что код может быть обычным и может быть источником проблемы.
    • Тот факт, что FastFourier.Calculate принимает короткий набор, необычен
  • Метод GetEnergyList принимает список ссылок, но этот список больше не используется?
  • В нескольких местах вы видите, что SampleSize жестко закодирован до 1024, но не совсем ясно, что это всегда так.
  • Вызывает беспокойство, что комментарий для PlaceBeatMarkers отмечает, что N следует разделить на 1024, может быть, вызывающий код забыл это сделать?
  • Я очень подозрительно отношусь к тому, как historyBuffer манипулирует в PlaceMarkers, тем более, что N передается, а затем используется для управления буфером history.
  • Комментарий *// Fill the history buffer with n * instant energy*, а следующий код не jive.

Через некоторое время у меня появилось ощущение, что код не очень хорошо организован, и это будет пустая трата времени на исправление. Если вы считаете, что это того стоит, следующий шаг, который я сделал бы:

  1. Разбить его на самую простую часть
  2. Перепишите код в самый верный способ, назовите все скрытые переменные
  3. Блок записи тесты, чтобы убедиться, что небольшая часть кода работает правильно.
  4. Добавьте еще один небольшой раздел кода и повторите, пока не получите целое вещь работает правильно

Советы

  • Возможно, вы захотите сделать число полос фиксированным, чтобы упростить логику цикла
  • Дайте переменные, такие как хорошие, понятные и сжатые имена N, C и B, это поможет вам легче видеть логические ошибки.
  • Разделите большие части кода на несколько вызываемых методов, каждый из которых выполняет небольшой краткий шаг для более крупного процесса и может иметь блок-тесты, чтобы гарантировать, что он работает правильно.
ответил MrPhil 30 +04002012-10-30T09:23:04+04:00312012bEurope/MoscowTue, 30 Oct 2012 09:23:04 +0400 2012, 09:23:04

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132