Recorder Example Queue Object

Status
Not open for further replies.

jono_ph

Member
Hi all, I hope this message finds you well...

I am recording using the Examples > Audio > Recorder (to be more specific, I am actually using the WavFilerWriter from Foaly https://github.com/Foaly/WavFileWriter)... I am trying to implement a digital filter using this equation in order to high pass at a cutoff frequency of 100 Hz to eliminate the low frequency components(0-100Hz) which causes noise in my recordings.
1.png
In my code, I am taking the contents of m_buffer ( size m_buffer[512]) and applying the formula, but I am not getting the expected results.
2.JPG
I suspect that I am not applying the formula the right way or to the right values from the queue object. All that I get out is extreme harsh noise. Any advice?

Thanks in advance!
 
Posting code as an image makes it extremely difficult to help you.
Cut and paste it as text into your message, preferably within code tags (use the # icon).

Have you tried the unmodified WavFileWriter code to make sure that it is creating the file correctly using unmodified data?

Pete
 
Dear Pete
Firstly, thank you for the response!
Have you tried the unmodified WavFileWriter code to make sure that it is creating the file correctly using unmodified data?

Pete
Could you elaborate more on this? I ran WavFilerWriter.ino and it worked, but since then I have only been modifying WavFileWriter.Ino. The picture up there (apologies) is from WavFileWriter.cpp which I am trying to change... I will post the code now!
Code:
/*
  - PROJECT (E) 448 (SKIPSIE == FINAL YEAR PROJECT)
  - Jonathan Paul Hendricks, University of Stellenbosch, 2020
  - TOPIC: Long term-low cost acoustic monitor
  - Monitor dolphin sounds and other marine fauna.
*/

//Includes & Declarations & Constants

#include "WavFileWriter.hpp"
#include <SerialFlash.h>
#include <Audio.h>
#include <Wire.h>
#include <TimeLib.h>
#define FILE_BASE_NAME "REC"
#include <OpenAudio_ArduinoLibrary.h>


const int Fs = 44100;       // Frequency to sample
const int myMic = AUDIO_INPUT_MIC;        // Mic input
unsigned long prevMil = 0;
unsigned long prevMil2 = 0;
unsigned long prevMil3 = 0;
const long interval = 15000;
const long a = 12000;
int flag;
int flag2;
int flag3;
const uint8_t BASE_NAME_SIZE = sizeof(FILE_BASE_NAME) - 1;
char fileName[] = FILE_BASE_NAME "00.wav";
int buttonState = 0;
const int buttonPin = 1;

AudioPlaySdWav        kingSD;        //Kingston SD Card
AudioInputI2S         audioIn;       //Audio Connection
AudioOutputI2S        audioOut;      //Audio Connection
AudioRecordQueue      queue1;        //To write data to SD Card
AudioConnection       patchCord1(audioIn, 0, queue1, 0);   //-Record data and queue it
AudioConnection       patchCord2(kingSD, 0, audioOut, 0);  //-perform read/write functions to save
AudioConnection       patchCord3(kingSD, 0, audioOut, 1);  // data and play through Audio Connection output
AudioControlSGTL5000_Extended  AudioShield;

WavFileWriter wavWriter(queue1);



// ---------------

// Initial setup run at start of program

void setup() {

  SdFile::dateTimeCallback(dateTime);
  Serial.begin(9600);
  AudioMemory(60);
  AudioShield.enable();
  AudioShield.inputSelect(myMic);
  AudioShield.micGain(63);          //0-63
  AudioShield.volume(0.75);         //0-1
  AudioShield.adcHighPassFilterDisable();
  AudioShield.micBiasEnable(1.25);
  setSyncProvider(getTeensy3Time); //Initialise this
  Serial.println("Powered up & Ready to go!");
  pinMode(buttonPin, INPUT);


}

// ---------------

//loop function

void loop() {

  if (digitalRead(buttonPin) == LOW) {
    unsigned long currMil = millis();
    if (flag3 == 0) {
      flag3 = 1;
      Serial.println("Start Recording");
      wavWriter.open(fileName, Fs, 1);
    }
    if (currMil - prevMil >= interval) {
      while (SD.exists(fileName)) {
        if (fileName[BASE_NAME_SIZE + 1] != '9') {
          fileName[BASE_NAME_SIZE + 1]++;
        } else if (fileName[BASE_NAME_SIZE] != '9') {
          fileName[BASE_NAME_SIZE + 1] = '0';
          fileName[BASE_NAME_SIZE]++;
        } else {
          Serial.println(F("Can't create file name"));
          return;
        }
      }
      prevMil = currMil;
      Serial.println("Start Recording!");
      wavWriter.open(fileName, Fs, 1);
    }
    if (currMil - prevMil2 >= a + interval) {
      prevMil2 = currMil - a;
      wavWriter.close();
      Serial.println("Stop Recording");
      digitalClockDisplay();
    }
    if ((currMil - prevMil3) >= a && flag2 == 1) {

      Serial.println("Stop recording");
      wavWriter.close();
      flag2 = 0;
      digitalClockDisplay();
    }
    if (wavWriter.isWriting()) {
      wavWriter.update();
    }
  } else {
    unsigned long currMil = millis();
    prevMil = currMil;
    prevMil2 = currMil;
    prevMil3 = currMil;
    flag2 = 1;
    flag3 = 0;
    wavWriter.close();
    delay(500);
  }
}


// ---------------

/*Additional functions for implementation of acoustic monitor*/

//Timing functions

time_t getTeensy3Time() {
  return Teensy3Clock.get();
}

void digitalClockDisplay() {
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(" ");
  Serial.print(day());
  Serial.print(" ");
  Serial.print(month());
  Serial.print(" ");
  Serial.print(year());
  Serial.println();
}

/*  code to process time sync messages from the serial port   */
#define TIME_HEADER  "T"   // Header tag for serial time sync message

unsigned long processSyncMessage() {
  unsigned long pctime = 0L;
  const unsigned long DEFAULT_TIME = 1357041600; // Jan 1 2013

  if (Serial.find(TIME_HEADER)) {
    pctime = Serial.parseInt();
    return pctime;
    if ( pctime < DEFAULT_TIME) { // check the value is a valid time (greater than Jan 1 2013)
      pctime = 0L; // return 0 to indicate that the time is not valid
    }
  }
  return pctime;
}

void printDigits(int digits) {
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(":");
  if (digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

void dateTime(uint16_t* date, uint16_t* time)
{
  *date = FAT_DATE(year(), month(), day());
  *time = FAT_TIME(hour(), minute(), second());
}
That is my code for WavFileWriter.Ino, where I simply do some scheduling operations to be able to record every interval for a certain amount of time and store the data to an SD card in wav format (process starts when pressing a lock-button).

Code:
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
//
// This code was inspired by the Recorder example of Paul Stoffregens Audio library
// and the SFML SoundFileWriterWav class
// Copyright (C) 2018 Maximilian Wagenbach (aka Foaly)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
//    you must not claim that you wrote the original software.
//    If you use this software in a product, an acknowledgment
//    in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
//    and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////

#include "WavFileWriter.hpp"

#include <SPI.h>

namespace {

// Teensy Audio Shield Defaults
const uint8_t SDcard_CS_Pin    = 10;
const uint8_t SDcard_MOSI_Pin  =  11;
const uint8_t SDcard_SCK_Pin   = 13;

// Use these with the Teensy 3.5 & 3.6 SD card (Should work, but not yet tested)
//const uint8_t SDcard_CS_Pin    = BUILTIN_SDCARD
//const uint8_t SDcard_MOSI_Pin  = 11  // not actually used
//const uint8_t SDcard_SCK_Pin   = 13  // not actually used

// Use these for the SD+Wiz820 or other adaptors (Should work, but not yet tested)
//const uint8_t SDcard_CS_Pin    =  4
//const uint8_t SDcard_MOSI_Pin  = 11
//const uint8_t SDcard_SCK_Pin   = 13

// The following functions takes integers in host byte order
// and writes them to a stream as little endian

void encode(File& file, uint16_t value) {
  uint8_t bytes[] =
  {
    static_cast<uint8_t>(value & 0xFF),
    static_cast<uint8_t>(value >> 8)
  };
  file.write(reinterpret_cast<const uint8_t*>(bytes), sizeof(bytes));
}

void encode(File& file, uint32_t value) {
  uint8_t bytes[] =
  {
    static_cast<uint8_t> (value & 0x000000FF),
    static_cast<uint8_t>((value & 0x0000FF00) >>  8),
    static_cast<uint8_t>((value & 0x00FF0000) >> 16),
    static_cast<uint8_t>((value & 0xFF000000) >> 24),
  };
  file.write(reinterpret_cast<const uint8_t*>(bytes), sizeof(bytes));
}
}


WavFileWriter::WavFileWriter(AudioRecordQueue& queue) :
  m_isWriting(false),
  m_queue(queue)
{

}


bool WavFileWriter::open(const char *fileName, unsigned int sampleRate, unsigned int channelCount) {
  if (m_isWriting) {
    Serial.println("Cannot write WAV file. Already writing one.");
    return false;
  }


  // Initialize the SD card
  SPI.setMOSI(SDcard_MOSI_Pin);
  SPI.setSCK(SDcard_SCK_Pin);
  if (!(SD.begin(SDcard_CS_Pin))) {
    Serial.println("Unable to access the SD card while trying to write WAV file.");
    return false;
  }

  if (SD.exists(fileName)) {
    SD.remove(fileName);
  }

  m_file = SD.open(fileName, FILE_WRITE);
  if (!m_file) {
    Serial.println("Could not open file while trying to write WAV file.");
    return false;
  }

  m_queue.begin();
  m_isWriting = true;
  m_totalBytesWritten = 0;

  writeHeader(sampleRate, channelCount);
  return true;
}


bool WavFileWriter::isWriting() {
  return m_isWriting;
}


void WavFileWriter::writeHeader(unsigned int sampleRate, unsigned int channelCount) {
  // Write the main chunk ID
  uint8_t mainChunkId[4] = {'R', 'I', 'F', 'F'};
  m_file.write(mainChunkId, sizeof(mainChunkId));

  // Write the main chunk header
  uint32_t mainChunkSize = 0; // placeholder, will be written on closing
  encode(m_file, mainChunkSize);
  uint8_t mainChunkFormat[4] = {'W', 'A', 'V', 'E'};
  m_file.write(mainChunkFormat, sizeof(mainChunkFormat));

  // Write the sub-chunk 1 ("format") id and size
  uint8_t fmtChunkId[4] = {'f', 'm', 't', ' '};
  m_file.write(fmtChunkId, sizeof(fmtChunkId));
  uint32_t fmtChunkSize = 16;
  encode(m_file, fmtChunkSize);

  // Write the format (PCM)
  uint16_t format = 1;
  encode(m_file, format);

  // Write the sound attributes
  encode(m_file, static_cast<uint16_t>(channelCount));
  encode(m_file, static_cast<uint32_t>(sampleRate));
  uint32_t byteRate = sampleRate * channelCount * 2;
  encode(m_file, byteRate);
  uint16_t blockAlign = channelCount * 2;
  encode(m_file, blockAlign);
  uint16_t bitsPerSample = 16;
  encode(m_file, bitsPerSample);

  // Write the sub-chunk 2 ("data") id and size
  uint8_t dataChunkId[4] = {'d', 'a', 't', 'a'};
  m_file.write(dataChunkId, sizeof(dataChunkId));
  uint32_t dataChunkSize = 0; // placeholder, will be written on closing
  encode(m_file, dataChunkSize);

  m_totalBytesWritten += 44;
}


bool WavFileWriter::update() {
  if (!m_isWriting)
    return false;

  if (m_queue.available() < 2)
    return false;

  // Fetch 2 blocks from the audio library and copy
  // into a 512 byte buffer.  The Arduino SD library
  // is most efficient when full 512 byte sector size
  // writes are used.
  memcpy(m_buffer, m_queue.readBuffer(), 256);
  m_queue.freeBuffer();
  memcpy(m_buffer + 256, m_queue.readBuffer(), 256);
  m_queue.freeBuffer();
  for (int k = 0; k < 512; k++) {
    m_smooth = 0.985f * (m_smooth + m_buffer[k] - m_buffer[k - 1]) ;
    m_out[k] = m_smooth;
  }
  // write all 512 bytes to the SD card
  //elapsedMicros usec = 0;

  m_file.write(m_out, 512);
  // Uncomment these lines to see how long SD writes
  // are taking. A pair of audio blocks arrives every
  // 5802 microseconds, so hopefully most of the writes
  // take well under 5802 us. Some will take more, as
  // the SD library also must write to the FAT tables
  // and the SD card controller manages media erase and
  // wear leveling. The m_queue object can buffer
  // approximately 301700 us of audio, to allow time
  // for occasional high SD card latency, as long as
  // the average write time is under 5802 us.
  //Serial.print("SD write, us=");
  //    Serial.println(usec);

  m_totalBytesWritten += 512;
  return true;
}


bool WavFileWriter::close() {
  if (!m_isWriting)
    return false;

  m_queue.end();
  while (m_queue.available() > 0) {
    m_file.write(reinterpret_cast<const uint8_t*>(m_queue.readBuffer()), 256);
    m_queue.freeBuffer();
    m_totalBytesWritten += 256;
  }

  Serial.print("Done! Max no. of audio blocks used: ");
  Serial.println(AudioMemoryUsageMax());
  Serial.print("Bytes written: ");
  Serial.println(m_totalBytesWritten);

  m_file.flush();

  // Update the main chunk size and data sub-chunk size
  uint32_t mainChunkSize = m_totalBytesWritten - 8;  // 8 bytes RIFF header
  uint32_t dataChunkSize = m_totalBytesWritten - 44; // 44 bytes RIFF + WAVE headers
  m_file.seek(4);
  encode(m_file, mainChunkSize);
  m_file.seek(40);
  encode(m_file, dataChunkSize);

  m_file.close();

  m_isWriting = false;
  return true;
}
And that is the code I am currently trying to work on, specifically at "WavFileWriter::update() " where I want to alter the data before saving it to the SD card. I was busy trying to do the peak detection in order to vary the gain as well, but I first want to figure out how to alter the data received in the queue object... I hope it makes sense now? Let me know if I can provide more?

EDIT: Here is my WavFilerWriter.hpp
Code:
#include <SD.h>

////////////////////////////////////////////////////////////
//
// This code was inspired by the Recorder example of Paul Stoffregens Audio library
// and the SFML SoundFileWriterWav class
// Copyright (C) 2018 Maximilian Wagenbach (aka Foaly)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
//    you must not claim that you wrote the original software.
//    If you use this software in a product, an acknowledgment
//    in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
//    and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////

#ifndef WAVFILEWRITER_INCLUDE
#define WAVFILEWRITER_INCLUDE

#include <SD.h>
#include <SD_t3.h>
#include "utility/SdFat.h"
#include <record_queue.h>

class WavFileWriter
{
public:
    WavFileWriter(AudioRecordQueue& queue);
    bool open(const char *fileName, unsigned int sampleRate, unsigned int channelCount);
    bool isWriting();
    bool update();
    bool close();

private:
    void writeHeader(unsigned int sampleRate, unsigned int channelCount);

    bool                  m_isWriting;
    File                  m_file;
    AudioRecordQueue&     m_queue;
    uint32_t              m_totalBytesWritten;
    uint8_t               m_buffer[512];
    uint8_t               m_out[512];
    float                 m_smooth;
};

#endif // WAVFILEWRITER_INCLUDE
 
Last edited:
Posting code as an image makes it extremely difficult to help you.
Cut and paste it as text into your message, preferably within code tags (use the # icon).

Pete
I should've used the hashtag! Great stuff:D Also, to be more clear, everything works, just the part where I now want to apply a digital filter at WavFileWriter.cpp is where I am getting headaches... Feel free to comment out the for loop after the second "freebuffer()" at the "WavFileWriter::update()" to test it...

EDIT: I am not using Utils.hpp
 
Last edited:
I can also send you a version of WavFilerWriter.ino where I use the serial monitor instead of a lock-button? Just to demonstrate the recording process
 
Code:
    uint8_t               m_buffer[512];
That is your biggest problem. Samples are int16_t. When you calculate this:
Code:
    m_smooth = 0.985f * (m_smooth + m_buffer[k] - m_buffer[k - 1]) ;
it is done with the wrong datatype.
It should be:
Code:
    int16_t               m_buffer[AUDIO_BLOCK_SAMPLES * 2];

The rest of your code then has to be adjusted to use the correct number of samples or bytes as appropriate.
Something like this:
Code:
  // Copy AUDIO_BLOCK_SAMPLES samples (= AUDIO_BLOCK_SAMPLES * 2 BYTES) into m_buffer.
  memcpy(m_buffer, m_queue.readBuffer(), AUDIO_BLOCK_SAMPLES * 2);
  m_queue.freeBuffer();
  memcpy(m_buffer + 256, m_queue.readBuffer(), AUDIO_BLOCK_SAMPLES * 2);
  m_queue.freeBuffer();
  for (int k = 0; k < AUDIO_BLOCK_SAMPLES * 2; k++) {
    m_smooth = 0.985f * (m_smooth + m_buffer[k] - m_buffer[k - 1]) ;
    m_out[k] = m_smooth;
  }
  // write all 512 bytes to the SD card
  //elapsedMicros usec = 0;
  // Write TWO buffers of AUDIO_BLOCK_SAMPLES samples each
  m_file.write(m_out, AUDIO_BLOCK_SAMPLES * 2 * 2);

There's another problem in the for loop
Code:
    m_smooth = 0.985f * (m_smooth + m_buffer[k] - m_buffer[k - 1]) ;
When k is zero m_buffer[k-1] references m_buffer[-1] which is outside the buffer.
You should be saving the last sample in the buffer and passing it in to be used in place of m_buffer[-1].
It will probably not cause any major noise in the signal so, for now, let's get the basic sample processing working. Then we can refine it.

Pete
 
P.S. You can also speed up things by changing the floating point computations to use int16_t instead. We'll also handle that once the basic code works.

Pete
 
Hi, I've updated the code...
Code:
////////////////////////////////////////////////////////////
//
// This code was inspired by the Recorder example of Paul Stoffregens Audio library
// and the SFML SoundFileWriterWav class
// Copyright (C) 2018 Maximilian Wagenbach (aka Foaly)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
//    you must not claim that you wrote the original software.
//    If you use this software in a product, an acknowledgment
//    in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
//    and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////

#include "WavFileWriter.hpp"

#include <SPI.h>

namespace {

// Teensy Audio Shield Defaults
const uint8_t SDcard_CS_Pin    = 10;
const uint8_t SDcard_MOSI_Pin  =  11;
const uint8_t SDcard_SCK_Pin   = 13;

// Use these with the Teensy 3.5 & 3.6 SD card (Should work, but not yet tested)
//const uint8_t SDcard_CS_Pin    = BUILTIN_SDCARD
//const uint8_t SDcard_MOSI_Pin  = 11  // not actually used
//const uint8_t SDcard_SCK_Pin   = 13  // not actually used

// Use these for the SD+Wiz820 or other adaptors (Should work, but not yet tested)
//const uint8_t SDcard_CS_Pin    =  4
//const uint8_t SDcard_MOSI_Pin  = 11
//const uint8_t SDcard_SCK_Pin   = 13

// The following functions takes integers in host byte order
// and writes them to a stream as little endian

void encode(File& file, uint16_t value) {
  uint8_t bytes[] =
  {
    static_cast<uint8_t>(value & 0xFF),
    static_cast<uint8_t>(value >> 8)
  };
  file.write(reinterpret_cast<const uint8_t*>(bytes), sizeof(bytes));
}

void encode(File& file, uint32_t value) {
  uint8_t bytes[] =
  {
    static_cast<uint8_t> (value & 0x000000FF),
    static_cast<uint8_t>((value & 0x0000FF00) >>  8),
    static_cast<uint8_t>((value & 0x00FF0000) >> 16),
    static_cast<uint8_t>((value & 0xFF000000) >> 24),
  };
  file.write(reinterpret_cast<const uint8_t*>(bytes), sizeof(bytes));
}
}


WavFileWriter::WavFileWriter(AudioRecordQueue& queue) :
  m_isWriting(false),
  m_queue(queue)
{

}


bool WavFileWriter::open(const char *fileName, unsigned int sampleRate, unsigned int channelCount) {
  if (m_isWriting) {
    Serial.println("Cannot write WAV file. Already writing one.");
    return false;
  }


  // Initialize the SD card
  SPI.setMOSI(SDcard_MOSI_Pin);
  SPI.setSCK(SDcard_SCK_Pin);
  if (!(SD.begin(SDcard_CS_Pin))) {
    Serial.println("Unable to access the SD card while trying to write WAV file.");
    return false;
  }

  if (SD.exists(fileName)) {
    SD.remove(fileName);
  }

  m_file = SD.open(fileName, FILE_WRITE);
  if (!m_file) {
    Serial.println("Could not open file while trying to write WAV file.");
    return false;
  }

  m_queue.begin();
  m_isWriting = true;
  m_totalBytesWritten = 0;

  writeHeader(sampleRate, channelCount);
  return true;
}


bool WavFileWriter::isWriting() {
  return m_isWriting;
}


void WavFileWriter::writeHeader(unsigned int sampleRate, unsigned int channelCount) {
  // Write the main chunk ID
  uint8_t mainChunkId[4] = {'R', 'I', 'F', 'F'};
  m_file.write(mainChunkId, sizeof(mainChunkId));

  // Write the main chunk header
  uint32_t mainChunkSize = 0; // placeholder, will be written on closing
  encode(m_file, mainChunkSize);
  uint8_t mainChunkFormat[4] = {'W', 'A', 'V', 'E'};
  m_file.write(mainChunkFormat, sizeof(mainChunkFormat));

  // Write the sub-chunk 1 ("format") id and size
  uint8_t fmtChunkId[4] = {'f', 'm', 't', ' '};
  m_file.write(fmtChunkId, sizeof(fmtChunkId));
  uint32_t fmtChunkSize = 16;
  encode(m_file, fmtChunkSize);

  // Write the format (PCM)
  uint16_t format = 1;
  encode(m_file, format);

  // Write the sound attributes
  encode(m_file, static_cast<uint16_t>(channelCount));
  encode(m_file, static_cast<uint32_t>(sampleRate));
  uint32_t byteRate = sampleRate * channelCount * 2;
  encode(m_file, byteRate);
  uint16_t blockAlign = channelCount * 2;
  encode(m_file, blockAlign);
  uint16_t bitsPerSample = 16;
  encode(m_file, bitsPerSample);

  // Write the sub-chunk 2 ("data") id and size
  uint8_t dataChunkId[4] = {'d', 'a', 't', 'a'};
  m_file.write(dataChunkId, sizeof(dataChunkId));
  uint32_t dataChunkSize = 0; // placeholder, will be written on closing
  encode(m_file, dataChunkSize);

  m_totalBytesWritten += 44;
}


bool WavFileWriter::update() {
  if (!m_isWriting)
    return false;

  if (m_queue.available() < 2)
    return false;

  // Fetch 2 blocks from the audio library and copy
  // into a 512 byte buffer.  The Arduino SD library
  // is most efficient when full 512 byte sector size
  // writes are used.
  memcpy(m_buffer, m_queue.readBuffer(), AUDIO_BLOCK_SAMPLES * 2);
  m_queue.freeBuffer();
  memcpy(m_buffer + 256, m_queue.readBuffer(), AUDIO_BLOCK_SAMPLES * 2);
  m_queue.freeBuffer();
  for (int k = 0; k < AUDIO_BLOCK_SAMPLES * 2; k++) {
    m_smooth = 0.985f * (m_smooth + m_buffer[k] - m_buffer[k - 1]) ;
    m_out[k] = m_smooth;
  }
  // write all 512 bytes to the SD card
  //elapsedMicros usec = 0;

  m_file.write(m_out, AUDIO_BLOCK_SAMPLES * 2 * 2);
  // Uncomment these lines to see how long SD writes
  // are taking. A pair of audio blocks arrives every
  // 5802 microseconds, so hopefully most of the writes
  // take well under 5802 us. Some will take more, as
  // the SD library also must write to the FAT tables
  // and the SD card controller manages media erase and
  // wear leveling. The m_queue object can buffer
  // approximately 301700 us of audio, to allow time
  // for occasional high SD card latency, as long as
  // the average write time is under 5802 us.
  //Serial.print("SD write, us=");
  //    Serial.println(usec);

  m_totalBytesWritten += 512;
  return true;
}


bool WavFileWriter::close() {
  if (!m_isWriting)
    return false;

  m_queue.end();
  while (m_queue.available() > 0) {
    m_file.write(reinterpret_cast<const uint8_t*>(m_queue.readBuffer()), 256);
    m_queue.freeBuffer();
    m_totalBytesWritten += 256;
  }

  Serial.print("Done! Max no. of audio blocks used: ");
  Serial.println(AudioMemoryUsageMax());
  Serial.print("Bytes written: ");
  Serial.println(m_totalBytesWritten);

  m_file.flush();

  // Update the main chunk size and data sub-chunk size
  uint32_t mainChunkSize = m_totalBytesWritten - 8;  // 8 bytes RIFF header
  uint32_t dataChunkSize = m_totalBytesWritten - 44; // 44 bytes RIFF + WAVE headers
  m_file.seek(4);
  encode(m_file, mainChunkSize);
  m_file.seek(40);
  encode(m_file, dataChunkSize);

  m_file.close();

  m_isWriting = false;
  return true;
}
that is .cpp where I did the recommendations...
Code:
#include <SD.h>

////////////////////////////////////////////////////////////
//
// This code was inspired by the Recorder example of Paul Stoffregens Audio library
// and the SFML SoundFileWriterWav class
// Copyright (C) 2018 Maximilian Wagenbach (aka Foaly)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
//    you must not claim that you wrote the original software.
//    If you use this software in a product, an acknowledgment
//    in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
//    and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////

#ifndef WAVFILEWRITER_INCLUDE
#define WAVFILEWRITER_INCLUDE

#include <SD.h>
#include <SD_t3.h>
#include "utility/SdFat.h"
#include <record_queue.h>

class WavFileWriter
{
  public:
    WavFileWriter(AudioRecordQueue& queue);
    bool open(const char *fileName, unsigned int sampleRate, unsigned int channelCount);
    bool isWriting();
    bool update();
    bool close();

  private:
    void writeHeader(unsigned int sampleRate, unsigned int channelCount);

    bool                  m_isWriting;
    File                  m_file;
    AudioRecordQueue&     m_queue;
    uint32_t              m_totalBytesWritten;
    int16_t               m_buffer[AUDIO_BLOCK_SAMPLES * 2];
    uint8_t               m_out[512];
    float                 m_smooth;
};

#endif // WAVFILEWRITER_INCLUDE
that is .hpp where I did the recommendations... Things started happening;) Not the best though... Still noise, but in between that noise I can hear my whistle that I do at the start(before it was just noise)... You can listen here(just dont put it too loud or immediately against your ear) https://www.dropbox.com/s/4xb9b1f710djjb6/REC00.WAV?dl=0
 
P.S. You can also speed up things by changing the floating point computations to use int16_t instead. We'll also handle that once the basic code works.

Pete

Thanks for the help so far:D I am trying that now!

EDIT: I changed "float m_smooth" to "int16_t m_smooth" on WavFileWriter.hpp(not posting the full code again since I did above with the other recommendations), still similar noise but I can hear myself whisteling!
 
I missed (at least) one thing. The m_out array also needs to be int16_t;
Code:
    int16_t               m_out[AUDIO_BLOCK_SAMPLES * 2];

Which Teensy are you using? (T3.2 ?)

Pete
 
I tried that the first time around, but it gave me an error so I left it.. This is the error when I change m_out from
Code:
    uint8_t               m_out[512]
to
Code:
int16_t               m_out[AUDIO_BLOCK_SAMPLES * 2]
3.jpg
 
Try this:
Code:
  m_file.write((const char *)m_out, AUDIO_BLOCK_SAMPLES * 2 * 2);

And, you can also copy and paste error messages as text too.

Pete
 
Code:
When k is zero m_buffer[k-1] references m_buffer[-1] which is outside the buffer.
You should be saving the last sample in the buffer and passing it in to be used in place of m_buffer[-1].
It will probably not cause any major noise in the signal so, for now, let's get the basic sample processing working. Then we can refine it.

Pete[/QUOTE]

I am working on this now.. Hopefully this is what needs refinement for the recording to sound better? But it doesn't sound to great at the moment but I have made more progress in a few hours than a full two days (not proud of that..)
 
Fixing the m_buffer[-1] problem and changing floating point to fixed-point arithmetic won't make significant changes to the audio.
There is something else that is having a more profound effect.
One thing that looks odd is that you appear to be processing audio input from the microphone (via a queue) and writing it to the SD card, while at the same time reading a file from the SD card and playing it. If so, that will make the SD card too busy.

Post all three files again so I can see the current "state of the art" :)

Pete
 
Code:
/*
  - PROJECT (E) 448 (SKIPSIE == FINAL YEAR PROJECT)
  - Jonathan Paul Hendricks, University of Stellenbosch, 2020
  - TOPIC: Long term-low cost acoustic monitor
  - Monitor dolphin sounds and other marine fauna.
*/

//Includes & Declarations & Constants

#include "WavFileWriter.hpp"
#include <SerialFlash.h>
#include <Audio.h>
#include <Wire.h>
#include <TimeLib.h>
#define FILE_BASE_NAME "REC"
#include <OpenAudio_ArduinoLibrary.h>


const int Fs = 44100;       // Frequency to sample
const int myMic = AUDIO_INPUT_MIC;        // Mic input
unsigned long prevMil = 0;
unsigned long prevMil2 = 0;
unsigned long prevMil3 = 0;
const long interval = 15000;
const long a = 12000;
int flag;
int flag2;
int flag3;
const uint8_t BASE_NAME_SIZE = sizeof(FILE_BASE_NAME) - 1;
char fileName[] = FILE_BASE_NAME "00.wav";
int buttonState = 0;
const int buttonPin = 1;

AudioPlaySdWav        kingSD;        //Kingston SD Card
AudioInputI2S         audioIn;       //Audio Connection
AudioOutputI2S        audioOut;      //Audio Connection
AudioRecordQueue      queue1;        //To write data to SD Card
AudioConnection       patchCord1(audioIn, 0, queue1, 0);   //-Record data and queue it
AudioConnection       patchCord2(kingSD, 0, audioOut, 0);  //-perform read/write functions to save
AudioConnection       patchCord3(kingSD, 0, audioOut, 1);  // data and play through Audio Connection output
AudioControlSGTL5000_Extended  AudioShield;

WavFileWriter wavWriter(queue1);



// ---------------

// Initial setup run at start of program

void setup() {

  SdFile::dateTimeCallback(dateTime);
  Serial.begin(9600);
  AudioMemory(60);
  AudioShield.enable();
  AudioShield.inputSelect(myMic);
  AudioShield.micGain(63);          //0-63
  AudioShield.volume(0.75);         //0-1
  AudioShield.adcHighPassFilterDisable();
  AudioShield.micBiasEnable(1.25);
  setSyncProvider(getTeensy3Time); //Initialise this
  Serial.println("Powered up & Ready to go!");
  pinMode(buttonPin, INPUT);


}

// ---------------

//loop function

void loop() {

  if (digitalRead(buttonPin) == LOW) {
    unsigned long currMil = millis();
    if (flag3 == 0) {
      flag3 = 1;
      Serial.println("Start Recording");
      wavWriter.open(fileName, Fs, 1);
    }
    if (currMil - prevMil >= interval) {
      while (SD.exists(fileName)) {
        if (fileName[BASE_NAME_SIZE + 1] != '9') {
          fileName[BASE_NAME_SIZE + 1]++;
        } else if (fileName[BASE_NAME_SIZE] != '9') {
          fileName[BASE_NAME_SIZE + 1] = '0';
          fileName[BASE_NAME_SIZE]++;
        } else {
          Serial.println(F("Can't create file name"));
          return;
        }
      }
      prevMil = currMil;
      Serial.println("Start Recording!");
      wavWriter.open(fileName, Fs, 1);
    }
    if (currMil - prevMil2 >= a + interval) {
      prevMil2 = currMil - a;
      wavWriter.close();
      Serial.println("Stop Recording");
      digitalClockDisplay();
    }
    if ((currMil - prevMil3) >= a && flag2 == 1) {

      Serial.println("Stop recording");
      wavWriter.close();
      flag2 = 0;
      digitalClockDisplay();
    }
    if (wavWriter.isWriting()) {
      wavWriter.update();
    }
  } else {
    unsigned long currMil = millis();
    prevMil = currMil;
    prevMil2 = currMil;
    prevMil3 = currMil;
    flag2 = 1;
    flag3 = 0;
    wavWriter.close();
    delay(500);
  }
}


// ---------------

/*Additional functions for implementation of acoustic monitor*/

//Timing functions

time_t getTeensy3Time() {
  return Teensy3Clock.get();
}

void digitalClockDisplay() {
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(" ");
  Serial.print(day());
  Serial.print(" ");
  Serial.print(month());
  Serial.print(" ");
  Serial.print(year());
  Serial.println();
}

/*  code to process time sync messages from the serial port   */
#define TIME_HEADER  "T"   // Header tag for serial time sync message

unsigned long processSyncMessage() {
  unsigned long pctime = 0L;
  const unsigned long DEFAULT_TIME = 1357041600; // Jan 1 2013

  if (Serial.find(TIME_HEADER)) {
    pctime = Serial.parseInt();
    return pctime;
    if ( pctime < DEFAULT_TIME) { // check the value is a valid time (greater than Jan 1 2013)
      pctime = 0L; // return 0 to indicate that the time is not valid
    }
  }
  return pctime;
}

void printDigits(int digits) {
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(":");
  if (digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

void dateTime(uint16_t* date, uint16_t* time)
{
  *date = FAT_DATE(year(), month(), day());
  *time = FAT_TIME(hour(), minute(), second());
}
that is my WavFileWriter.ino
Code:
////////////////////////////////////////////////////////////
//
// This code was inspired by the Recorder example of Paul Stoffregens Audio library
// and the SFML SoundFileWriterWav class
// Copyright (C) 2018 Maximilian Wagenbach (aka Foaly)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
//    you must not claim that you wrote the original software.
//    If you use this software in a product, an acknowledgment
//    in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
//    and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////

#include "WavFileWriter.hpp"

#include <SPI.h>

namespace {

// Teensy Audio Shield Defaults
const uint8_t SDcard_CS_Pin    = 10;
const uint8_t SDcard_MOSI_Pin  =  11;
const uint8_t SDcard_SCK_Pin   = 13;

// Use these with the Teensy 3.5 & 3.6 SD card (Should work, but not yet tested)
//const uint8_t SDcard_CS_Pin    = BUILTIN_SDCARD
//const uint8_t SDcard_MOSI_Pin  = 11  // not actually used
//const uint8_t SDcard_SCK_Pin   = 13  // not actually used

// Use these for the SD+Wiz820 or other adaptors (Should work, but not yet tested)
//const uint8_t SDcard_CS_Pin    =  4
//const uint8_t SDcard_MOSI_Pin  = 11
//const uint8_t SDcard_SCK_Pin   = 13

// The following functions takes integers in host byte order
// and writes them to a stream as little endian

void encode(File& file, uint16_t value) {
  uint8_t bytes[] =
  {
    static_cast<uint8_t>(value & 0xFF),
    static_cast<uint8_t>(value >> 8)
  };
  file.write(reinterpret_cast<const uint8_t*>(bytes), sizeof(bytes));
}

void encode(File& file, uint32_t value) {
  uint8_t bytes[] =
  {
    static_cast<uint8_t> (value & 0x000000FF),
    static_cast<uint8_t>((value & 0x0000FF00) >>  8),
    static_cast<uint8_t>((value & 0x00FF0000) >> 16),
    static_cast<uint8_t>((value & 0xFF000000) >> 24),
  };
  file.write(reinterpret_cast<const uint8_t*>(bytes), sizeof(bytes));
}
}


WavFileWriter::WavFileWriter(AudioRecordQueue& queue) :
  m_isWriting(false),
  m_queue(queue)
{

}


bool WavFileWriter::open(const char *fileName, unsigned int sampleRate, unsigned int channelCount) {
  if (m_isWriting) {
    Serial.println("Cannot write WAV file. Already writing one.");
    return false;
  }


  // Initialize the SD card
  SPI.setMOSI(SDcard_MOSI_Pin);
  SPI.setSCK(SDcard_SCK_Pin);
  if (!(SD.begin(SDcard_CS_Pin))) {
    Serial.println("Unable to access the SD card while trying to write WAV file.");
    return false;
  }

  if (SD.exists(fileName)) {
    SD.remove(fileName);
  }

  m_file = SD.open(fileName, FILE_WRITE);
  if (!m_file) {
    Serial.println("Could not open file while trying to write WAV file.");
    return false;
  }

  m_queue.begin();
  m_isWriting = true;
  m_totalBytesWritten = 0;

  writeHeader(sampleRate, channelCount);
  return true;
}


bool WavFileWriter::isWriting() {
  return m_isWriting;
}


void WavFileWriter::writeHeader(unsigned int sampleRate, unsigned int channelCount) {
  // Write the main chunk ID
  uint8_t mainChunkId[4] = {'R', 'I', 'F', 'F'};
  m_file.write(mainChunkId, sizeof(mainChunkId));

  // Write the main chunk header
  uint32_t mainChunkSize = 0; // placeholder, will be written on closing
  encode(m_file, mainChunkSize);
  uint8_t mainChunkFormat[4] = {'W', 'A', 'V', 'E'};
  m_file.write(mainChunkFormat, sizeof(mainChunkFormat));

  // Write the sub-chunk 1 ("format") id and size
  uint8_t fmtChunkId[4] = {'f', 'm', 't', ' '};
  m_file.write(fmtChunkId, sizeof(fmtChunkId));
  uint32_t fmtChunkSize = 16;
  encode(m_file, fmtChunkSize);

  // Write the format (PCM)
  uint16_t format = 1;
  encode(m_file, format);

  // Write the sound attributes
  encode(m_file, static_cast<uint16_t>(channelCount));
  encode(m_file, static_cast<uint32_t>(sampleRate));
  uint32_t byteRate = sampleRate * channelCount * 2;
  encode(m_file, byteRate);
  uint16_t blockAlign = channelCount * 2;
  encode(m_file, blockAlign);
  uint16_t bitsPerSample = 16;
  encode(m_file, bitsPerSample);

  // Write the sub-chunk 2 ("data") id and size
  uint8_t dataChunkId[4] = {'d', 'a', 't', 'a'};
  m_file.write(dataChunkId, sizeof(dataChunkId));
  uint32_t dataChunkSize = 0; // placeholder, will be written on closing
  encode(m_file, dataChunkSize);

  m_totalBytesWritten += 44;
}


bool WavFileWriter::update() {
  if (!m_isWriting)
    return false;

  if (m_queue.available() < 2)
    return false;

  // Fetch 2 blocks from the audio library and copy
  // into a 512 byte buffer.  The Arduino SD library
  // is most efficient when full 512 byte sector size
  // writes are used.
  memcpy(m_buffer, m_queue.readBuffer(), AUDIO_BLOCK_SAMPLES * 2);
  m_queue.freeBuffer();
  memcpy(m_buffer + 256, m_queue.readBuffer(), AUDIO_BLOCK_SAMPLES * 2);
  m_queue.freeBuffer();
  for (int k = 0; k < AUDIO_BLOCK_SAMPLES * 2; k++) {
    m_smooth = 0.995f * (m_smooth + m_buffer[k] - m_buffer[k - 1]) ;
    m_out[k] = m_smooth;
  }
  // write all 512 bytes to the SD card
  //elapsedMicros usec = 0;

   m_file.write((const char *)m_out, AUDIO_BLOCK_SAMPLES * 2 * 2);
  // Uncomment these lines to see how long SD writes
  // are taking. A pair of audio blocks arrives every
  // 5802 microseconds, so hopefully most of the writes
  // take well under 5802 us. Some will take more, as
  // the SD library also must write to the FAT tables
  // and the SD card controller manages media erase and
  // wear leveling. The m_queue object can buffer
  // approximately 301700 us of audio, to allow time
  // for occasional high SD card latency, as long as
  // the average write time is under 5802 us.
  //Serial.print("SD write, us=");
  //    Serial.println(usec);

  m_totalBytesWritten += 512;
  return true;
}


bool WavFileWriter::close() {
  if (!m_isWriting)
    return false;

  m_queue.end();
  while (m_queue.available() > 0) {
    m_file.write(reinterpret_cast<const uint8_t*>(m_queue.readBuffer()), 256);
    m_queue.freeBuffer();
    m_totalBytesWritten += 256;
  }

  Serial.print("Done! Max no. of audio blocks used: ");
  Serial.println(AudioMemoryUsageMax());
  Serial.print("Bytes written: ");
  Serial.println(m_totalBytesWritten);

  m_file.flush();

  // Update the main chunk size and data sub-chunk size
  uint32_t mainChunkSize = m_totalBytesWritten - 8;  // 8 bytes RIFF header
  uint32_t dataChunkSize = m_totalBytesWritten - 44; // 44 bytes RIFF + WAVE headers
  m_file.seek(4);
  encode(m_file, mainChunkSize);
  m_file.seek(40);
  encode(m_file, dataChunkSize);

  m_file.close();

  m_isWriting = false;
  return true;
}
That is my WavFileWriter.cpp
Code:
#include <SD.h>

////////////////////////////////////////////////////////////
//
// This code was inspired by the Recorder example of Paul Stoffregens Audio library
// and the SFML SoundFileWriterWav class
// Copyright (C) 2018 Maximilian Wagenbach (aka Foaly)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
//    you must not claim that you wrote the original software.
//    If you use this software in a product, an acknowledgment
//    in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
//    and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////

#ifndef WAVFILEWRITER_INCLUDE
#define WAVFILEWRITER_INCLUDE

#include <SD.h>
#include <SD_t3.h>
#include "utility/SdFat.h"
#include <record_queue.h>

class WavFileWriter
{
  public:
    WavFileWriter(AudioRecordQueue& queue);
    bool open(const char *fileName, unsigned int sampleRate, unsigned int channelCount);
    bool isWriting();
    bool update();
    bool close();

  private:
    void writeHeader(unsigned int sampleRate, unsigned int channelCount);

    bool                  m_isWriting;
    File                  m_file;
    AudioRecordQueue&     m_queue;
    uint32_t              m_totalBytesWritten;
    int16_t               m_buffer[AUDIO_BLOCK_SAMPLES * 2];
    int16_t               m_out[AUDIO_BLOCK_SAMPLES * 2];
    int16_t               m_smooth;
};

#endif // WAVFILEWRITER_INCLUDE
That is my WavFileWriter.hpp

Thanks for still helping so far :)

Jono
 
One thing that looks odd is that you appear to be processing audio input from the microphone (via a queue) and writing it to the SD card, while at the same time reading a file from the SD card and playing it. If so, that will make the SD card too busy.
Pete
What part of the code are you referring to here?

Jono
 
I've been playing with the filter and produced this sketch which you might find useful.
It generates a tonesweeep from 100-10000Hz over 5 seconds. The output of the sweep is fed to the queue so that the sketch can apply your filter and then put it back in the queue. That is then passed into the FFT. The code just adds each successive FFT scan into an array and sends the data to the Serial Plotter when the tonesweep ends. There are probably much better ways of processing the final data ready for display.

Code:
/* Derived from the FFT audio example and heavily
    modified by Pete (El Supremo)

This outputs to Serial PLOTTER
                       ^^^^^^^
201025
_4
  - Clean up to post to forum.
  
201024
_3
  - Output a graph to Serial Plotter
_2
  - In theory, modify to send the tonesweep
    output through the queue and play, so
    that the filter can process the tonesweep
    and then let the FFT have it.
    THEN improve the display
_1
  - Modify FFT example to use tonesweep as
    input and stop once the sweep is done.
  - Not pretty, but IT WORKS
*/

// FFT Test
// This example code is in the public domain.

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// Create the Audio components.  These should be created in the
// order data flows, inputs/sources -> processing -> outputs
//
AudioInputI2S          audioInput;  // audio shield: mic or line-in NOT USED
AudioSynthToneSweep    ts;          // tonesweep object
AudioRecordQueue       Q_in_L;      // sample blocks input to the sketch
AudioAnalyzeFFT1024    myFFT;       // 1024 point FFT
AudioPlayQueue         Q_out_L;     // sample blocks sent to audio device
AudioOutputI2S         audioOutput; // audio shield: headphones & line-out

// Connect output of tonesweep to the queue
AudioConnection patchCord1(ts, 0, Q_in_L, 0);
// Connect the queue to FFT
AudioConnection patchCord3(Q_out_L, 0, myFFT, 0);
AudioControlSGTL5000 audioShield;

// Intermediate buffer for queue processing
short buf_L[AUDIO_BLOCK_SAMPLES];
int16_t l_smooth = 0;
int16_t l_lastsample = 0;

// Final output from FFT
float sumbins[512];

// When defined, use the floating point version
#define ALPHA f_alpha

// When defined, use the integer version which
// DOES NOT WORK YET
//#define ALPHA alpha

const float f_alpha = 0.9f;
const int16_t alpha = (32767)*f_alpha;
const float bin_width = 44100./1024.;

void setup()
{
  Serial.begin(9600);
  while(!Serial);
  // Audio connections require memory to work.  For more
  // detailed information, see the MemoryAndCpuUsage example
  AudioMemory(12);

  // Enable the audio shield and set the output volume.
  audioShield.enable();
  audioShield.volume(0.5);

  // Configure the FFT window algorithm to use
  myFFT.windowFunction(AudioWindowHanning1024);

  // Start the tonesweep
  if(!ts.play(.5,100,10000,5.0)) {
    Serial.println("AudioSynthToneSweep - begin failed");
    while(1);
  }
  // Make sure the tonesweep has started
  while(!ts.isPlaying());
  Q_in_L.begin();
  for(int i = 0; i < 512; i++)sumbins[i] = 0;
}

void loop()
{
  float n;
  int i;
  short *bp_L;
  
  if(ts.isPlaying()) {
    if(Q_in_L.available() >= 1) {
      bp_L = Q_in_L.readBuffer();

      // Copy the audio buffer to our memory
      for(int i = 0; i < AUDIO_BLOCK_SAMPLES; i++) {
        buf_L[i] = bp_L[i];
      }
      // Free the input audio buffer
      Q_in_L.freeBuffer();
      // Get a pointer to an "empty" output buffer
      bp_L = Q_out_L.getBuffer();
      // Do the first sample in the buffer which requires
      // input from the last sample in the previous buffer
      l_smooth = ALPHA * (l_smooth + buf_L[0] - l_lastsample);
      bp_L[0] = l_smooth;
      // Do the rest of the buffer
      for (int k = 1; k < AUDIO_BLOCK_SAMPLES; k++) {
        l_smooth = ALPHA * (l_smooth + buf_L[k] - buf_L[k - 1]);
        bp_L[k] = l_smooth;
      }
      // Save the last sample for the next pass
      l_lastsample = buf_L[AUDIO_BLOCK_SAMPLES-1];
      Q_out_L.playBuffer();
    }
    if (myFFT.available()) {
      for(int j = 0; j < 512; j++) {
        float sample = myFFT.read(j); 
//        if(sample > sumbins[j]) sumbins[j] = sample;
        sumbins[j] += sample;
      }
    }
  } else {
    // tonesweep has finished.
    for(i = 0; i < 512; i++) {
      // Output to Serial Plotter
      Serial.printf("%2d\n",(int)(sumbins[i]*100));    
    }
    // Nothing more to be done
    while(1);
  }
}

The attached image shows the Serial Plotter graph for alpha = 0.9 which corresponds to a corner frequency of 780Hz.
FFT_tonesweep_4_screencap.jpg
I tested this on a T4.0 (T4.1 will work too) - but T3.x won't because this uses floating point computations.

Pete
 
Hi Pete

This looks interesting, I will give it a shout and get back to you. The output looks pretty neat :cool: I am still having problems with my audio board so I am hoping to get a new one this week and then I will try and implement it. For now I will play around with the example :)

Jono
 
Status
Not open for further replies.
Back
Top