Android аудио БПФ для получения определенной частоты с использованием аудиозаписи
В настоящее время я пытаюсь реализовать некоторый код с помощью 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);
Исполнение БПФ - вот где я застреваю, так как у меня очень мало опыта в этой области. Я пытался использовать этот класс:
БПФ в Java и сложный класс, чтобы пойти с ним
Затем я отправляю следующие значения:
Complex[] fftTempArray = new Complex[bufferSize];
for (int i=0; i<bufferSize; i++)
{
fftTempArray[i] = new Complex(audio[i], 0);
}
Complex[] fftArray = fft(fftTempArray);
Это может быть моим неправильным пониманием того, как должен работать этот класс, но возвращаемые значения перепрыгивают повсеместно и не представляют постоянной частоты даже в тишине. Кто-нибудь знает способ выполнения этой задачи, или я слишком усложняю вопрос, пытаясь захватить только небольшое количество частотных диапазонов, а не нарисовать его в виде графического представления?
1 ответ
Во-первых, вы должны убедиться, что полученный результат правильно конвертируется в число с плавающей запятой / двойное число. Я не уверен, как работает версия short[], но версия 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;
}