Подтвердить что ты не робот

Android-аудио FFT для получения определенной величины частоты с использованием аудиозаписей

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

int channel_config = AudioFormat.CHANNEL_CONFIGURATION_MONO;
int format = AudioFormat.ENCODING_PCM_16BIT;
int sampleSize = 8000;
int bufferSize = AudioRecord.getMinBufferSize(sampleSize, channel_config, format);
AudioRecord audioInput = new AudioRecord(AudioSource.MIC, sampleSize, channel_config, format, bufferSize);

Затем звук читается в:

short[] audioBuffer = new short[bufferSize];
audioInput.startRecording();
audioInput.read(audioBuffer, 0, bufferSize);

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

FFT в Java и Сложный класс для этого

Затем я отправляю следующие значения:

Complex[] fftTempArray = new Complex[bufferSize];
for (int i=0; i<bufferSize; i++)
{
    fftTempArray[i] = new Complex(audio[i], 0);
}
Complex[] fftArray = fft(fftTempArray);

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

4b9b3361

Ответ 1

Сначала вам нужно убедиться, что полученный результат правильно преобразован в float/double. Я не уверен, как работает короткая [] версия, но версия byte [] возвращает только исходную байтовую версию. Этот массив байтов затем должен быть правильно преобразован в число с плавающей запятой. Код для преобразования должен выглядеть примерно так:

    double[] micBufferData = new double[<insert-proper-size>];
    final int bytesPerSample = 2; // As it is 16bit PCM
    final double amplification = 100.0; // choose a number as you like
    for (int index = 0, floatIndex = 0; index < bytesRecorded - bytesPerSample + 1; index += bytesPerSample, floatIndex++) {
        double sample = 0;
        for (int b = 0; b < bytesPerSample; b++) {
            int v = bufferData[index + b];
            if (b < bytesPerSample - 1 || bytesPerSample == 1) {
                v &= 0xFF;
            }
            sample += v << (b * 8);
        }
        double sample32 = amplification * (sample / 32768.0);
        micBufferData[floatIndex] = sample32;
    }

Затем вы используете micBufferData [] для создания сложного массива ввода.

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

Вам нужна частота дискретизации, чтобы преобразовать индексы массива в такие величины к частотам:

private double ComputeFrequency(int arrayIndex) {
    return ((1.0 * sampleRate) / (1.0 * fftOutWindowSize)) * arrayIndex;
}