Значения амплитуды в пределах быстрого преобразования Фурье FFT отличаются постоянным входным сигналом?

В моем Beat-Detection я использую быстрое преобразование Фурье, чтобы обнаружить низкие частоты в звуковом сигнале. Я записываю сольный барабан, не двигая ни звук, ни громкость. После построения значений со временем. Я получаю непостоянные значения. Они отличаются очень сильно. Может быть, у вас есть идея, почему это происходит? Я могу только догадываться, но, может быть, я не использую правильный размер буфера или WindowSize для FFT?

Вниз графическое изображение и исходный код

закрытый класс RecordingThread расширяет тему {

    private boolean mShallContinue = true;

    @Override
    public void run() {
// Compute the minimum required audio buffer size and allocate the
    // buffer.
    mBufferSize = 4096;// AudioRecord.getMinBufferSize(SAMPLING_RATE,
                        // //4096;//
                        // AudioFormat.CHANNEL_IN_MONO,

    mAudioBuffer = new short[1024];// [mBufferSize / 2];
    bufferDouble2 = new int[mBufferSize / 2];
    bufferDouble = new int[(blockSize - 1) * 2];
    camera = Camera.open();

}
        AudioRecord record = new AudioRecord(
                MediaRecorder.AudioSource.DEFAULT, SAMPLING_RATE,
                AudioFormat.CHANNEL_IN_MONO,
                AudioFormat.ENCODING_PCM_16BIT, mBufferSize);

        short[] buffer = new short[blockSize];
        double[] audioDataDoubles = new double[(blockSize * 2)];
        double[] re = new double[blockSize];
        double[] im = new double[blockSize];
        double[] magnitude = new double[blockSize];

        // start collecting data
        record.startRecording();

        DoubleFFT_1D fft = new DoubleFFT_1D(blockSize);
        synchronized (this) {
            while (shallContinue()) {

                /** decibels */
                record.read(mAudioBuffer, 0, 1024);
                // updateDecibelLevel();

                /** frequency */
                // /windowing!?
                for (int i = 0; i < mAudioBuffer.length; i++) {
                    bufferDouble2[i] = (int) mAudioBuffer[i];
                }

                for (int i = 0; i < blockSize - 1; i++) {
                    double x = -Math.PI + 2 * i * (Math.PI / blockSize);
                    double winValue = (1 + Math.cos(x)) / 2.0;
                    bufferDouble[i] = (int) (bufferDouble2[i] * winValue);
                }

                int bufferReadResult = record.read(buffer, 0, blockSize);

                // Read in the data from the mic to the array
                for (int i = 0; i < blockSize && i < bufferReadResult; i++) {
                    audioDataDoubles[2 * i] = (double) buffer[i] / 32768.0; // signed
                                                                            // 16
                                                                            // bit
                    audioDataDoubles[(2 * i) + 1] = 0.0;
                }

                // audiodataDoubles now holds data to work with
                fft.complexForward(audioDataDoubles); // complexForward

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

                    // real is stored in first part of array
                    re[i] = audioDataDoubles[i * 2];
                    // imaginary is stored in the sequential part
                    im[i] = audioDataDoubles[(i * 2) + 1];

                    // magnitude is calculated by the square root of
                    // (imaginary^2 + real^2)
                    magnitude[i] = Math.sqrt((re[i] * re[i])
                            + (im[i] * im[i]));
                }
                magnitude[0] = 0.0;

                magnitude2 = magnitude[2];
                magnitude3 = magnitude[3];
                magnitude4 = magnitude[4];

                updateShortBuffer();
                bufferCount++;
                updateLongBuffer();

                // if (detectedRoomRMS == 200)
                updateFrequency();
                System.out.println(System.currentTimeMillis() + " M2: "
                        + magnitude2 + " M3: " + magnitude3 + " M4: "
                        + magnitude4 + " M5: " + magnitude[5] + " M10: "
                        + magnitude[10] + " M20: " + magnitude[20] + " M24: "
                        + magnitude[24] + " M48: " + magnitude[48] + " LONG20: "
                        + rms_Long_Buffer_five + " LONNG: "
                        + rms_Long_Buffer);
            }
            record.stop(); // stop recording please.
            record.release(); // Destroy the recording, PLEASE!
        }
    }

    /**
     * true if the thread should continue running or false if it should stop
     */
    private synchronized boolean shallContinue() {
        return mShallContinue;
    }

    /**
     * Notifies the thread that it should stop running at the next
     * opportunity.
     */
    private synchronized void stopRunning() {
        mShallContinue = false;
    }

}

// / post the output frequency to TextView
private void updateFrequency() {
    tvfreq.post(new Runnable() {

        String RoomRMS;
        String s;

        public void run() {

            if (RMSMessureDone == false) {
                String l = "..";
                String KK = "...";
                tvfreq.setTextColor(Color.WHITE);
                if ((rmsCounter > 10))
                    tvfreq.setText(KK); //
                else
                    tvfreq.setText(l);
            } else {
                BPM = round(BPM, 1);
                s = Double.toString(BPM);
                s = s + " bpm";
                tvfreq.setTextColor(Color.WHITE);
                tvfreq.setText((s));

                RoomRMS = Double.toString(detectedRoomRMS);
                tvdb.setText(RoomRMS);
            }
        }

    });

}

1 ответ

Я предполагаю, что несоответствия, которые вы видите, связаны с отношением начала к окну, используемому для БПФ.

По сути, подход, который вы используете, является неправильным для этой проблемы:

1: Характер сигнала: сигнал от басового барабана (и этим я предполагаю, что вы, вероятно, имеете в виду ударный барабан?), Имеет резкое начало (его только что сильно ударили), с быстрым затуханием. Начальный пик не связан с широкой полосой пропускания; это по сути белый шум. Хотя там будет много низкочастотного контента, он не будет доминировать. После первоначальной атаки оболочка барабана вибрирует с собственной частотой, с выходом, намного меньшим, чем начальный пик.

2: Просмотр квадратного окна. В настоящее время вы применяете функцию квадратного окна к своим сэмплам. Это не выигрышный выбор, так как он разбрызгивает энергию на места, которые вам не нужны. Окна Хэмминга и Блэкмана являются обычным выбором для БПФ.

3: разрешение: фундаментальный недостаток использования БПФ состоит в том, что он является оконным. Результатом ДПФ является просто вклад каждого частотного бина в течение периода окна. Период окна ограничивает ваше временное разрешение (вы знаете только, что событие с диапазоном частот произошло где-то в окне). С другой стороны, если вы хотите получить значимые результаты от низкочастотных бинов БПФ, теория Найквиста применяется в отношении частоты окна относительно измеренного сигнала. Допустим, вы производите выборку на частоте 44,1 кГц, это означает, что вам нужно 2048 точек DFT, если вы хотите получить значимые результаты, скажем, на 50 Гц. Каждое окно теперь имеет период 0,047 с (или около 1/20 с). Это ваш предел погрешности при каждом временном измерении.

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

Другие вопросы по тегам