Noise in Recording using Teensy4.0 + Audio Shield

Danny12

New member
Hi all,

I would like to do a simple record project which is recording an audio, saving the file to an sd card and playing the recorded file. Therefor I am using a Teensy 4.0 and Audio Shield.
I have an electret microphone directly connected to the audio shield. I am supplying the Teensy by an external power supply.
The overall setup looks like this:

IMG_20220730_150841.jpg

This is the code I am using:

Code:
// Record sound as raw data to a SD card, and play it back.
//
// Requires the audio shield:
//   http://www.pjrc.com/store/teensy3_audio.html
//
// Three pushbuttons need to be connected:
//   Record Button: pin 0 to GND
//   Stop Button:   pin 1 to GND
//   Play Button:   pin 2 to GND
//
// This example code is in the public domain.


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

// GUItool: begin automatically generated code

AudioInputI2S            i2s2;           //xy=105,63
AudioAnalyzePeak         peak1;          //xy=278,108
AudioRecordQueue         queue1;         //xy=281,63
AudioPlaySdWav           playWav1;       //xy=302,157
AudioOutputI2S           i2s1;           //xy=470,120
AudioConnection          patchCord1(i2s2, 0, queue1, 0);
AudioConnection          patchCord2(i2s2, 0, peak1, 0);
//AudioConnection          patchCord3(playWav1, 0, i2s1, 0);
AudioConnection          patchCord4(playWav1, 0, i2s1, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=265,212

// GUItool: end automatically generated code

// For a stereo recording version, see this forum thread:
// https://forum.pjrc.com/threads/46150?p=158388&viewfull=1#post158388

// A much more advanced sound recording and data logging project:
// https://github.com/WMXZ-EU/microSoundRecorder
// https://github.com/WMXZ-EU/microSoundRecorder/wiki/Hardware-setup
// https://forum.pjrc.com/threads/52175?p=185386&viewfull=1#post185386



const int myInput = AUDIO_INPUT_MIC;
//const int myInput = AUDIO_INPUT_LINEIN;

//write wav
unsigned long ChunkSize = 0L;
unsigned long Subchunk1Size = 16;
unsigned int AudioFormat = 1;
unsigned int numChannels = 1;
unsigned long sampleRate = 44100;
unsigned int bitsPerSample = 16;
unsigned long byteRate = sampleRate*numChannels*(bitsPerSample/8);// samplerate x channels x (bitspersample / 8)
unsigned int blockAlign = numChannels*bitsPerSample/8;
unsigned long Subchunk2Size = 0L;
unsigned long recByteSaved = 0L;
unsigned long NumSamples = 0L;
byte byte1, byte2, byte3, byte4;
elapsedMicros usec = 0;
unsigned int lastTime=0;
unsigned int enableSerial=0;
// Use these for the Audio Shield
#define SDCARD_CS_PIN    10
#define SDCARD_MOSI_PIN  11
#define SDCARD_SCK_PIN   12


// Remember which mode we're doing
int mode = 0;  // 0=stopped, 1=recording, 2=playing

// The file where data is recorded
File frec;

void setup() {

   if(enableSerial>0)
   {
    Serial.begin(9600);
   }
    // Audio connections require memory, and the record queue
    // uses this memory to buffer incoming audio.
   AudioMemory(60);
   sgtl5000_1.enable();
   sgtl5000_1.inputSelect(myInput);
   sgtl5000_1.volume(0.5);
    sgtl5000_1.micGain(36);
   
  // Initialize the SD card
  SPI.setMOSI(SDCARD_MOSI_PIN);
  SPI.setSCK(SDCARD_SCK_PIN);
  if (!(SD.begin(SDCARD_CS_PIN))) {
    // stop here if no SD card, but print a message
    while (1) {
      if(enableSerial>0)
      {
        Serial.println("Unable to access the SD card");
      }
      delay(500);
    }
  }
}

int timeLast = millis();
int state=1;

void loop() 
{

 int TimeWait=1000; // Wait time before Record starts
 int TimeRecord=2000;  // Time to record
 int TimeWaitBeforePlaying=200; // Wait Time to record
 int TimePlay=2500; // Playback Time
   
  int ActTime=millis();
  if ((ActTime-timeLast)>TimeWait+TimeRecord+TimeWaitBeforePlaying+TimePlay && state==4) 
  {
    timeLast=millis()-TimeWait-TimeRecord;
    if (mode == 2) stopPlaying();
    state=3;

  }
  else if ((ActTime-timeLast)>TimeWait+TimeRecord+TimeWaitBeforePlaying && state==3) 
  {
    if (mode == 1) stopRecording();
    if (mode == 0) startPlaying();
    if(enableSerial>0) Serial.println(ActTime);
    state=4;
  }
  else if ((ActTime-timeLast)>TimeWait+TimeRecord && state==2) 
  {

    if (mode == 1) stopRecording();
    if (mode == 2) stopPlaying();
    if(enableSerial>0) Serial.println(ActTime);
    state=3;
  }
  else  if((ActTime-timeLast)>TimeWait && state==1)
  {
    if (mode == 2) stopPlaying();
    if (mode == 0) startRecording();
    if(enableSerial>0) Serial.println(ActTime);
    state=2;
  }

  // If we're playing or recording, carry on...
  if (mode == 1) 
  {
    continueRecording();
  }
  if (mode == 2) 
  {
    continuePlaying();
  }
}


void startRecording() {
  if(enableSerial>0) Serial.println("startRecording");
  if (SD.exists("RECORD.WAV")) {
    // The SD library writes new data to the end of the
    // file, so to start a new recording, the old file
    // must be deleted before new data is written.
    SD.remove("RECORD.WAV");
  }
  frec = SD.open("RECORD.WAV", FILE_WRITE);
  if (frec) {
    queue1.begin();
    mode = 1;
    recByteSaved = 0L;
  }
}

void continueRecording() {
  if (queue1.available() >= 2) {
    byte buffer[512];
    // 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(buffer, queue1.readBuffer(), 256);
    queue1.freeBuffer();
    memcpy(buffer+256, queue1.readBuffer(), 256);
    queue1.freeBuffer();
    // write all 512 bytes to the SD card

    frec.write(buffer, 512);
    recByteSaved += 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 queue1 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-lastTime);
    lastTime=usec;
  }
}

void stopRecording() {
  if(enableSerial>0) Serial.println("stopRecording");
  queue1.end();
  if (mode == 1) {
    while (queue1.available() > 0) {
      frec.write((byte*)queue1.readBuffer(), 256);
      queue1.freeBuffer();
      recByteSaved += 256;
    }
    writeOutHeader();
    frec.close();
  }
  mode = 0;
}


void startPlaying() {
  if(enableSerial>0) Serial.println("startPlaying");
  playWav1.play("RECORD.WAV");
  mode = 2;
}

void continuePlaying() {
  if (!playWav1.isPlaying()) {
    playWav1.stop();
    mode = 0;
  }
}

void stopPlaying() {
  if(enableSerial>0) Serial.println("stopPlaying");
  if (mode == 2) playWav1.stop();
  mode = 0;
}

void adjustMicLevel() {
  // TODO: read the peak1 object and adjust sgtl5000_1.micGain()
  // if anyone gets this working, please submit a github pull request :-)
}

void writeOutHeader() { // update WAV header with final filesize/datasize

//  NumSamples = (recByteSaved*8)/bitsPerSample/numChannels;
//  Subchunk2Size = NumSamples*numChannels*bitsPerSample/8; // number of samples x number of channels x number of bytes per sample
  Subchunk2Size = recByteSaved;
  ChunkSize = Subchunk2Size + 36;
  frec.seek(0);
  frec.write("RIFF");
  byte1 = ChunkSize & 0xff;
  byte2 = (ChunkSize >> 8) & 0xff;
  byte3 = (ChunkSize >> 16) & 0xff;
  byte4 = (ChunkSize >> 24) & 0xff;  
  frec.write(byte1);  frec.write(byte2);  frec.write(byte3);  frec.write(byte4);
  frec.write("WAVE");
  frec.write("fmt ");
  byte1 = Subchunk1Size & 0xff;
  byte2 = (Subchunk1Size >> 8) & 0xff;
  byte3 = (Subchunk1Size >> 16) & 0xff;
  byte4 = (Subchunk1Size >> 24) & 0xff;  
  frec.write(byte1);  frec.write(byte2);  frec.write(byte3);  frec.write(byte4);
  byte1 = AudioFormat & 0xff;
  byte2 = (AudioFormat >> 8) & 0xff;
  frec.write(byte1);  frec.write(byte2); 
  byte1 = numChannels & 0xff;
  byte2 = (numChannels >> 8) & 0xff;
  frec.write(byte1);  frec.write(byte2); 
  byte1 = sampleRate & 0xff;
  byte2 = (sampleRate >> 8) & 0xff;
  byte3 = (sampleRate >> 16) & 0xff;
  byte4 = (sampleRate >> 24) & 0xff;  
  frec.write(byte1);  frec.write(byte2);  frec.write(byte3);  frec.write(byte4);
  byte1 = byteRate & 0xff;
  byte2 = (byteRate >> 8) & 0xff;
  byte3 = (byteRate >> 16) & 0xff;
  byte4 = (byteRate >> 24) & 0xff;  
  frec.write(byte1);  frec.write(byte2);  frec.write(byte3);  frec.write(byte4);
  byte1 = blockAlign & 0xff;
  byte2 = (blockAlign >> 8) & 0xff;
  frec.write(byte1);  frec.write(byte2); 
  byte1 = bitsPerSample & 0xff;
  byte2 = (bitsPerSample >> 8) & 0xff;
  frec.write(byte1);  frec.write(byte2); 
  frec.write("data");
  byte1 = Subchunk2Size & 0xff;
  byte2 = (Subchunk2Size >> 8) & 0xff;
  byte3 = (Subchunk2Size >> 16) & 0xff;
  byte4 = (Subchunk2Size >> 24) & 0xff;  
  frec.write(byte1);  frec.write(byte2);  frec.write(byte3);  frec.write(byte4);
  frec.close();
  if(enableSerial>0) Serial.println("header written"); 
  if(enableSerial>0) Serial.print("Subchunk2: "); 
  if(enableSerial>0) Serial.println(Subchunk2Size); 
}


The Problem is that I am always getting high noise which is sounding terrible.

The frequency spectrum from Audacity looks like this:

Screenshot 2022-07-30 152459.jpg

It seems like I have Problems with 172Hz and multiple frequencies.
This is exactly the frequency for the SD Card Write operations. Every 5802µs...

I am using a SanDisk Ultra 16Gb Class 10 Micro SD.


Any Ideas what I am doing wrong and how I can get rid of these frequencies?

I already tired to power the teensy from a battery. This is only reduicing the 50Hz and multiple Frequencies from the mains, but has no significant impact on the hearable noise.

Saw a similar issue in this thread but could not find a solution there:

https://forum.pjrc.com/threads/41706-Teensy-Microphone-Module/page6
 
Last edited:
Back
Top