Android: основная частота

Я хочу найти основную частоту человеческого голоса в приложении для Android. Я вычисляю это с помощью этого класса FFT и этого Комплексный класс.

Мой код для расчета БПФ таков:

public double calculateFFT(byte[] signal)
        {           
        final int mNumberOfFFTPoints =1024;
        double mMaxFFTSample;

        double temp;
        Complex[] y;
        Complex[] complexSignal = new Complex[mNumberOfFFTPoints];
        double[] absSignal = new double[mNumberOfFFTPoints/2];

        for(int i = 0; i < mNumberOfFFTPoints; i++){
            temp = (double)((signal[2*i] & 0xFF) | (signal[2*i+1] << 8)) / 32768.0F;
            complexSignal[i] = new Complex(temp,0.0);
        }

        y = FFT.fft(complexSignal); 

        mMaxFFTSample = 0.0;
        int mPeakPos = 0;
        for(int i = 0; i < (mNumberOfFFTPoints/2); i++)
        {
            absSignal[i] = Math.sqrt(Math.pow(y[i].re(), 2) + Math.pow(y[i].im(), 2));

            if(absSignal[i] > mMaxFFTSample)
            {
                mMaxFFTSample = absSignal[i];
                mPeakPos = i;
            } 
        }


        return ((1.0 * sampleRate) / (1.0 * mNumberOfFFTPoints)) * mPeakPos;

    }

и у меня те же значения, что и Как мне получить частоты каждое значение в БПФ?

Можно ли по этим значениям найти основную частоту? Кто-нибудь может мне помочь?

Заранее спасибо.


person user3582433    schedule 26.05.2014    source источник
comment
Вы можете попробовать опубликовать это на Signal Processing StackExchange.   -  person Cobbles    schedule 26.05.2014
comment
Если вы хотите определить высоту голоса, прочитайте кепстральный анализ. - вам все еще нужно БПФ, но для извлечения основного тона требуется еще несколько операций.   -  person Paul R    schedule 26.05.2014


Ответы (4)


Похоже, вы уже выбрали решение (БПФ) для своей проблемы. Я не специалист по DSP, но рискну предположить, что таким образом вы не получите очень хороших результатов. Более подробное обсуждение см. здесь: Как вы анализируете основную частоту сэмпла PCM или WAV?

Если вы делаете решите придерживаться этого метода:

  1. Рассмотрите возможность использования более 1024 точек, если вам нужна точность на более низких частотах — помните, что (разговорный) человеческий голос удивительно низок .

  2. Грамотно выбирайте частоту дискретизации — примените фильтр нижних частот, если можете. Есть причина, по которой телефоны имеют полосу пропускания всего около 3 кГц, остальное на самом деле не нужно для того, чтобы слышать человеческие голоса.

  3. Затем изучите первую половину ваших выходных значений и выберите наименьшее из самых больших: здесь трудная часть — их может быть несколько (дальнейшие пики должны появиться на гармониках (фиксированные кратные) это тоже, но это трудно проверить, так как ваши ведра здесь не подходят). Мы надеемся, что это диапазон частот, в котором находится истинный фундаментальный сигнал.

Опять же, возможно, стоит подумать о других способах решения этой проблемы, поскольку БПФ может дать вам разочаровывающие результаты в реальном мире.

person declension    schedule 26.05.2014
comment
Я пытаюсь найти основную частоту с помощью автокорреляции с помощью edu.emory.mathcs.jtransforms.fft.DoubleFFT_1D; но я не знаю, является ли значение, которое возвращает частота=sampleRate*double)max_index/(double)mNumberOfFFTPoints;}, является основной частотой? - person user3582433; 26.05.2014

Обнаружение основной частоты человеческого голоса является активной областью исследований, как показывают приведенные ниже ссылки. Ваш подход должен быть тщательно разработан и должен зависеть от характера данных.

Например, если вашим источником является человек, поющий одну ноту, без музыки или других фоновых звуков в записи, модифицированный пиковый детектор может дать разумные результаты.

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

На приведенном ниже графике показана простая проблема обнаружения. На нем показан частотный спектр женского сопрано с нотой си-бемоль-3 (си-бемоль 3). Основная частота Bb3 составляет 233 Гц, но на самом деле сопрано поет основную частоту 236 Гц (самый левый и самый высокий пик). В этом случае простой детектор пиков дает правильную основную частоту.

Частотный спектр женского сопрано, поющего ноту Си-бемоль-3. Sooeet.com БПФ-калькулятор

На приведенном ниже графике показана одна из проблем определения основной частоты даже для отдельных спетых нот, не говоря уже об общей человеческой речи. На нем показан частотный спектр женского сопрано, держащего ноту F4. Основная частота F4 составляет 349 Гц, но на самом деле сопрано поет основную частоту 360 Гц (крайний левый пик).

Частотный спектр женского сопрано, поющего ноту F4. Sooeet.com FFT калькулятор

Однако в этом случае самый высокий пик является не основной, а первой гармоникой на частоте 714 Гц. Ваш модифицированный пиковый детектор должен работать с этими случаями.

В обобщенной человеческой речи понятие основной частоты на самом деле неприменимо к какому-либо подмножеству большей продолжительности, чем каждая отдельная форманта в речи. Это связано с тем, что частотный спектр обобщенной человеческой речи сильно зависит от времени.

См. эти ссылки:

Анализ речевого сигнала

Форманты человеческой речи

Обнаружение основной частоты

БПФ, графики и аудиоданные из калькулятора БПФ Sooeet.com

person Babson    schedule 26.05.2014

Мой код для автокорреляции в этом:

    public double calculateFFT(double[] signal)

     {
      final int mNumberOfFFTPoints =1024;

      double[] magnitude = new double[mNumberOfFFTPoints/2];
      DoubleFFT_1D fft = new DoubleFFT_1D(mNumberOfFFTPoints);
      double[] fftData = new double[mNumberOfFFTPoints*2];
      double max_index=-1;
      double max_magnitude=-1;


      final float sampleRate=44100;
      double frequency;

      for (int i=0;i<mNumberOfFFTPoints;i++){

       //fftData[2 * i] = buffer[i+firstSample];
       fftData[2 * i] = signal[i];  //da controllare
       fftData[2 * i + 1] = 0;

       fft.complexForward(fftData);
      }

      for(int i = 0; i < mNumberOfFFTPoints/2; i++){

       magnitude[i]=Math.sqrt((fftData[2*i] * fftData[2*i]) + (fftData[2*i + 1] * fftData[2*i + 1]));



       if (max_magnitude<magnitude[i]){
        max_magnitude=magnitude[i];
        max_index=i;
       }
      }


      return frequency=sampleRate*(double)max_index/(double)mNumberOfFFTPoints;

 }

Значение «возврата» — это моя основная частота?

person user3582433    schedule 26.05.2014
comment
в некоторых случаях быть не может! - person ederwander; 26.05.2014
comment
Зачем? Я заметил, что fft.complexForward(fftData) не работает, и я не знаю, потому что это происходит. - person user3582433; 26.05.2014

Максимумы БПФ возвращают пиковую частоту бина, которая может быть не основной частотой, а бином результата БПФ, ближайшим к обертону или гармонике основной частоты. Более длительное БПФ с использованием большего количества данных даст вам более близко расположенные интервалы результатов БПФ, и, таким образом, интервал, вероятно, будет ближе к пиковой частоте. Вы также можете интерполировать пик, если он находится между интервалами. Но если вы имеете дело с сигналом с сильным гармоническим содержанием, таким как голос или музыка, вам может потребоваться использовать алгоритм обнаружения/оценки основного тона вместо пикового алгоритма БПФ.

person hotpaw2    schedule 26.05.2014
comment
Я пробую это: как получить основную частоту сигнала с помощью автокорреляции">dsp.stackexchange.com/questions/8432/ с автокорреляцией, но она не очень хорошо работает, она не вычисляет fft.ComplexForward(fftData) - person user3582433; 26.05.2014