Привет,
Я использую прорыв микрофона I2S MEMS Arduino MKR1000 и Adafruit SPH0645 для анализа звука.
Поскольку Arduino не способен рассчитывать БПФ в реальном времени с определеннымТочность, я хочу назначить разные размеры FFT для разных частотных интервалов.Существует библиотека ArduinoSound, которая выполняет операции FFT, но когда я выбираю частоту дискретизации 12 кГц (или более) и размер 128 FFT, Arduino прекращает вычисление.Я не уверен, что это связано с нехваткой памяти или скоростью процессора.
Я должен анализировать до 15 кГц (то есть с частотой дискретизации 30 кГц), но мне не нужен только один размер FFT.
До 1 кГц я хочу анализировать каждые 100 герц (или разные, но близкие могут быть 120-240 и т. Д.). Между 1 кГц и 10 кГц я хочу анализировать каждые 500 герц (или то же самое с частотой выше 600 Гц и т. Д.) И, наконец, до 15 кГц, яхочу анализировать каждые 800 герц (или 1200 Гц и т. д.)
Поэтому я хочу получить приблизительно эти частоты (не зацикливаясь на числах):
120-240-360-480-600-720-840-960-1400-1900-2300-2700-3100-3500-3900-4300-4700-5100-5500-5900-6300-6700-7100-7500-7900-8300-8700-9100-9500-9900-10800-11800-12800-13800-14800
Размер FFT от 0 до 1 кГц = 16
Размер FFT от 1 до 10 кГц = 32 (или 64)
Между 10-15 кГцFFTsize = 8 (или 16)
Мой начальный код:
#include <ArduinoSound.h>
// sample rate for the input
const int sampleRate = 8000;
// size of the FFT to compute
const int fftSize = 128;
// size of the spectrum output, half of FFT size
const int spectrumSize = fftSize / 2;
// array to store spectrum output
int spectrum[spectrumSize];
// create an FFT analyzer to be used with the I2S input
FFTAnalyzer fftAnalyzer(fftSize);
void setup() {
// Open serial communications and wait for port to open:
// A baud rate of 115200 is used instead of 9600 for a faster data rate
// on non-native USB ports
Serial.begin(115200);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
// setup the I2S audio input for the sample rate with 32-bits per sample
if (!AudioInI2S.begin(sampleRate, 32)) {
Serial.println("Failed to initialize I2S input!");
while (1); // do nothing
}
// configure the I2S input as the input for the FFT analyzer
if (!fftAnalyzer.input(AudioInI2S)) {
Serial.println("Failed to set FFT analyzer input!");
while (1); // do nothing
}
}
void loop() {
// check if a new analysis is available
if (fftAnalyzer.available()) {
// read the new spectrum
fftAnalyzer.read(spectrum, spectrumSize);
// print out the spectrum
for (int i = 0; i < spectrumSize; i++) {
Serial.print((i * sampleRate) / fftSize); // the starting frequency
Serial.print("\t"); //
Serial.println(spectrum[i]); // the spectrum value
}
}
}
Как вы видите в части void setup (), код конфигурирует образец I2Sоценить позначение в строке 4. Но я хочу использовать 3 различных sampleRate и fftSize.Если вам нужно больше разъяснений, пожалуйста, спросите.Я думал, что смогу решить эту проблему с 3 различными настройками и циклом, но я не знаю, как настроить мой код для достижения этой цели.Если вы также покажете, как каждый sampleRate может быть действительным только для определенного интервала (например, 1000-10000), я также уменьшу вычисления.Потому что sampleRate 2000 не будет игнорировать первые 1000 Гц в соответствии с моим кодом.
Я также загрузил свой модифицированный код, что неверно, но объясняет механизм.Мне нужно разделить его на несколько разделов.Я знаю, что могу сделать это с 3 различными кодами и Arduino, так как я могу сделать это только с одним.
#include <ArduinoSound.h>
// sample rate for the input
const int sampleRate1 = 2000;
const int sampleRate2 = 20000;
const int sampleRate3 = 30000;
// size of the FFT to compute
const int fftSize1 = 32;
const int fftSize2 = 64;
const int fftSize3 = 16;
// size of the spectrum output, half of FFT size
const int spectrumSize1 = fftSize1 / 2;
const int spectrumSize2 = fftSize2 / 2;
const int spectrumSize3 = fftSize3 / 2;
// array to store spectrum output
int spectrum1[spectrumSize1];
int spectrum2[spectrumSize2];
int spectrum3[spectrumSize3];
// create an FFT analyzer to be used with the I2S input
FFTAnalyzer fftAnalyzer1(fftSize1);
FFTAnalyzer fftAnalyzer2(fftSize2);
FFTAnalyzer fftAnalyzer3(fftSize3);
void setup() {
// Open serial communications and wait for port to open:
// A baud rate of 115200 is used instead of 9600 for a faster data rate
// on non-native USB ports
Serial.begin(115200);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
// setup the I2S audio input for the sample rate with 32-bits per sample
if (!AudioInI2S.begin(sampleRate1, 32)) {
Serial.println("Failed to initialize I2S input!");
while (1); // do nothing
}
if (!AudioInI2S.begin(sampleRate2, 32)) {
Serial.println("Failed to initialize I2S input!");
while (1); // do nothing
}
if (!AudioInI2S.begin(sampleRate3, 32)) {
Serial.println("Failed to initialize I2S input!");
while (1); // do nothing
}
// configure the I2S input as the input for the FFT analyzer
if (!fftAnalyzer1.input(AudioInI2S)) {
Serial.println("Failed to set FFT analyzer input!");
while (1); // do nothing
}
if (!fftAnalyzer2.input(AudioInI2S)) {
Serial.println("Failed to set FFT analyzer input!");
while (1); // do nothing
}
if (!fftAnalyzer3.input(AudioInI2S)) {
Serial.println("Failed to set FFT analyzer input!");
while (1); // do nothing
}
}
void loop() {
{
// check if a new analysis is available
if (fftAnalyzer1.available()) {
// read the new spectrum
fftAnalyzer1.read(spectrum1, spectrumSize1); }
// check if a new analysis is available
if (fftAnalyzer2.available()) {
// read the new spectrum
fftAnalyzer2.read(spectrum2, spectrumSize2); }
// check if a new analysis is available
if (fftAnalyzer3.available()) {
// read the new spectrum
fftAnalyzer3.read(spectrum3, spectrumSize3); }
// print out the spectrum
for (int i = 0; i < spectrumSize1; i++) {
Serial.print((i * sampleRate1) / fftSize1); // the starting frequency
Serial.print("\t"); //
Serial.println(spectrum1[i]); // the spectrum value
}
for (int i = 0; i < spectrumSize2; i++) {
Serial.print((i * sampleRate2) / fftSize2); // the starting frequency
Serial.print("\t"); //
Serial.println(spectrum2[i]); // the spectrum value
}
for (int i = 0; i < spectrumSize3; i++) {
Serial.print((i * sampleRate3) / fftSize3); // the starting frequency
Serial.print("\t"); //
Serial.println(spectrum3[i]); // the spectrum value
}
}
}