Issue with AudioAnalyzeRMS and AudioAnalyzeFFT1024 Staying at 0 After a Certain Period of Time

Typicalcow

New member
Hello everyone,

I’m working on a project with a Teensy 4.1 where I’m trying to detect audio events using the PJRC Audio Library. I’ve tried using both the AudioAnalyzeRMS and AudioAnalyzeFFT1024 objects, but I’m encountering an issue where the RMS amplitude stays at 0 after about 10 minutes of operation. When I tried the AudioAnalyzeFFT1024, the .available() function keeps returning false after about the same amount of time as the RMS function stops working. These are the most important parts of my code I think, but the full code can be delivered if needed...

I’m using FreeRTOS with three tasks and a queue as follows:

/
C++:
/ Create the queue
sdCardQueue = xQueueCreate(200, sizeof(SDCardData));
// Create the tasks
xTaskCreate(sdCardTask, "SD Card", 3000, NULL, 3, NULL);
xTaskCreate(audioTask, "Audio", 3000, NULL, 2, NULL);
xTaskCreate(sensorTask, "Sensor", 1500, NULL, 2, NULL);

The task calling the function looks like this:

C++:
// Audio task
void audioTask(void *pvParameters) {
  while (1) {
    if (!recording) {
      // Check FFT output to detect an event based on any bin exceeding the threshold
      if (detectAudioEvent()) {
        Serial.println(F("Started recording..."));
        queue1.begin();
        recording = true;
        recordingStartTime = millis();
        taskYIELD();
      } else {
        vTaskDelay(pdMS_TO_TICKS(250));  // Delay for 0.25 seconds}
      }
    } else {
      SDCardData data;
      data.file = &audioFile;
      data.isAudio = true;

      if (queue1.available() >= 2) {
        memcpy(data.audio, queue1.readBuffer(), 256);
        queue1.freeBuffer();
        memcpy(data.audio + 256, queue1.readBuffer(), 256);
        queue1.freeBuffer();
        if (xQueueSend(sdCardQueue, &data, 0) != pdTRUE) {
          Serial.println("Queue full!");
          taskYIELD();
        }

        if (millis() - recordingStartTime >= recordingDuration) {
          queue1.end();
          recording = false;
          Serial.println(F("Recording stopped..."));
        }
      }
      taskYIELD();
    }
  }
}

And the audio objects are imported and initialized like this:

C++:
// Audio
// GUItool: begin automatically generated code
AudioInputI2S2 i2s2_2;             // xy=322.1999816894531,316.1999816894531
AudioFilterStateVariable filter1;  // xy=490.1999816894531,317.1999816894531
AudioAmplifier amp1;               // xy=635.1999740600586,329.1999683380127
AudioRecordQueue queue1;           // xy=786.2000312805176,329.1999855041504
AudioAnalyzeRMS rms1;              //xy=744.1999969482422,246.1999969482422
AudioConnection patchCord1(i2s2_2, 0, filter1, 0);
AudioConnection patchCord2(filter1, 2, amp1, 0);
AudioConnection patchCord3(amp1, queue1);
AudioConnection patchCord4(amp1, rms1);  // Connect audio to RMS
// GUItool: end automatically generated code

      // Initialize audio library (happens in the setup)
      AudioMemory(60);
      filter1.frequency(60);  // filter out DC & extremely low frequencies
      amp1.gain(15);          // amplify the signal to a useful range

Here’s the actual function I’ve implemented in my code (this is where I get the problems):

C++:
// Counter for unavailable RMS data
int rmsUnavailableCount = 0;

// Function to detect audio events based on RMS amplitude
bool detectAudioEvent() {
  // Check if new RMS data is available
  if (rms1.available()) {
    rmsUnavailableCount = 0;  // Reset the counter when RMS data is available

    // Read the RMS amplitude
    float rmsAmplitude = rms1.read();
    Serial.print(F("RMS ampl:"));
    Serial.println(rmsAmplitude);

    // Update the RMS threshold based on the noise floor
    const float alpha = 0.1;            // Smoothing factor between 0 and 1
    static float RMS_THRESHOLD = 0.015;  // Initial RMS threshold
    RMS_THRESHOLD = alpha * rmsAmplitude + (1 - alpha) * RMS_THRESHOLD;

    // Ensure the threshold stays within a certain range
    const float MIN_THRESHOLD = 0.015;
    const float MAX_THRESHOLD = 0.05;
    if (RMS_THRESHOLD < MIN_THRESHOLD) {
      RMS_THRESHOLD = MIN_THRESHOLD;
    } else if (RMS_THRESHOLD > MAX_THRESHOLD) {
      RMS_THRESHOLD = MAX_THRESHOLD;
    }
    Serial.print(F("Thresh:"));
    Serial.println(RMS_THRESHOLD);

    // Compare the RMS amplitude to the threshold
    if (rmsAmplitude > RMS_THRESHOLD) {
      return true;  // Audio event detected
    } else {
      return false;  // No audio event detected
    }
  } else {
    rmsUnavailableCount++;
    if (rmsUnavailableCount > 10) {
      Serial.println(F("RMS unavailable"));
      while (!rms1.available()) {
        vTaskDelay(pdMS_TO_TICKS(250));  // Delay for 0.25 seconds}
      }
    }
    return false;
  }
}

I’ve checked the audio input and it seems to be working correctly (I was still able to record audio when the issues happened). I’ve also tried resetting the RMS and FFT objects when they’re not available, but this doesn’t seem to solve the issue. The rms1.available() function always returns true, but the RMS amplitude stays at 0.

Has anyone encountered a similar issue or have any suggestions on what might be causing this? Any help would be greatly appreciated!

Kind regards,
Typicalcow

PS: Sorry for the long post!
 
Back
Top