Teensy 4.0 - based Audio Guestbook

I believe that @KurtE mentioned here: https://forum.pjrc.com/threads/6813...ng-MTP-and-MSC?p=293743&viewfull=1#post293743, that MACs don't natively support MTP. He had to download the free version of something called OpenMTP. I personally dont use MACs so cant be of much further help but maybe someone else will jump in.

I do have a MAC, but I don't use it very much. It is about a 10-year-old notebook.

As @mjs513 mentioned, I have experimented some with OpenMTP. Also have played iwth Android File Transfer:
https://www.android.com/filetransfer/

But I am no expert in this. I primarily used Windows. Secondarily use Ubuntu and when I need to have the MAC to try things out on.
 
I do have a MAC, but I don't use it very much. It is about a 10-year-old notebook.

As @mjs513 mentioned, I have experimented some with OpenMTP. Also have played iwth Android File Transfer:
https://www.android.com/filetransfer/

But I am no expert in this. I primarily used Windows. Secondarily use Ubuntu and when I need to have the MAC to try things out on.

Thanks, @KurtE and @mjs513 , I will give this a try! I figured mac was the main issue. I have a couple of old Surface Pros I can pull out if needed!
 
Missing parts to record

I have used the codes and the phone is now recording:), however, while recording the wav files, small parts are failing to record at a regular interval.. for example, while recoding counting number (1-30) - 13 & 26 missing... any suggestion to fix this?



Code:
/**
 * Audio Guestbook, Copyright (c) 2022 Playful Technologyhttps://forum.pjrc.com/images/smilies/smile.png
 * 
 * Tested using a Teensy 4.0 with Teensy Audio Shield, although should work 
 * with minor modifications on other similar hardware
 * 
 * When handset is lifted, a pre-recorded greeting message is played, followed by a tone.
 * Then, recording starts, and continues until the handset is replaced.
 * Playback button allows all messages currently saved on SD card through earpiece 
 * 
 * follow the detailed instructions here:
 * https://github.com/DD4WH/audio-guestbook/blob/main/README.md
 * 
 * 
 *   the sketch only works with the latest Teensyduino 1.57 version, so please update your Arduino IDE AND your Teensyduino to Arduino version 1.8.19 and the latest Teensyduino version 1.57
 *   download the following library, unzip it and put it into your local Arduino folder (on my computer, the local Arduino folder is: "C:/Users/DD4WH/Documents/Arduino/libraries/"): https://github.com/KurtE/MTP_Teensy
 *   compile with option: "Serial + MTP Disk (Experimental)"" and with option "CPU speed: 150MHz" (this can save about 70% of battery power)
 *
 * Modifications by Frank DD4WH, August 2022
 * - now uses a Teensy 4.1 with built-in SD card (faster via SDIO), if you want to use a Teensy 4.0, uncomment in the USER CONFIGURATION below
 * - Files are saved on SD card as 44.1kHz, 16-bit mono WAV audio files 
 * - if you plug in the telephones´ USB cable into your computer, the telephone is mounted as a drive and you can acess the recordings 
 * - if there is no "greeting.wav" message on the SD card, the telephone automatically plays an invitation to record this message and then you can record the greeting message 
 * - if you want to record the greeting message again, just delete it from the telephone and lift the handheld again to record the greeting message  
 * --> if your handheld contact switch opens on lifting, simply uncomment in the USER CONFIGURATION below, everything else is done by the software
 * 
 * GNU GPL v3.0 license
 * 
 */

#include <Bounce.h>
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <TimeLib.h>
#include <MTP_Teensy.h>  // this library has to be downloaded separately (https://github.com/KurtE/MTP_Teensy)
// unzip the downloaded file and its content into your local Arduino folder (on my computer, the local Arduino folder is: "C:/Users/DD4WH/Documents/Arduino/libraries/")

/***************************************************************************************************************************************************/
/**USER CONFIGURATION ******************************************************************************************************************************/
/**COMMENT / UNCOMMENT ACCORDING TO YOUR HARDWARE **************************************************************************************************/
/***************************************************************************************************************************************************/

// comment this out, if your handheld OPENS the contact on lift
// use a digital voltmeter to find out
#define HANDHELD_CLOSES_ON_LIFT

// comment this out, if you want to record your greeting message with an external recorder
// leave as-is if you want to have the telephone automatically switch to recording the greeting message, in case there is no "greeting.wav" on the SD card 
#define AUTO_GREETING_MESSAGE

// comment out, if you use a Teensy 4.0 (and thus the SD card slot on the audio board)
// if you leave this as-is, you have to use the built-in SD card slot on the Teensy 4.1, NOT the SD card slot on the audio board 
//#define TEENSY_41

/***************************************************************************************************************************************************/
/**END OF USER CONFIGURATION ***********************************************************************************************************************/
/***************************************************************************************************************************************************/
/***************************************************************************************************************************************************/

// Define pins used by Teensy Audio Shield
#ifdef TEENSY_41
#define SDCARD_CS_PIN    BUILTIN_SDCARD
#else
#define SDCARD_CS_PIN    10
#endif
#define SDCARD_MOSI_PIN  7
#define SDCARD_SCK_PIN   14
// And those used for inputs
// You can choose the pins you use here:
//#define HOOK_PIN 40
//#define PLAYBACK_BUTTON_PIN 41
#define HOOK_PIN 0              // this is the default
#define PLAYBACK_BUTTON_PIN 1   // this is the default


// GLOBALS
// Audio initialisation code can be generated using the GUI interface at https://www.pjrc.com/teensy/gui/
// Inputs
AudioSynthWaveform          waveform1; // To create the "beep" sfx
AudioInputI2S               i2s2; // I2S input from microphone on audio shield
AudioPlaySdWav              playWav1; // Play 44.1kHz 16-bit PCM greeting WAV file
AudioRecordQueue            queue1; // Creating an audio buffer in memory before saving to SD
AudioMixer4                 mixer; // Allows merging several inputs to same output
AudioOutputI2S              i2s1; // I2S interface to Speaker/Line Out on Audio shield
AudioConnection patchCord1(waveform1, 0, mixer, 0); // wave to mixer 
AudioConnection patchCord3(playWav1, 0, mixer, 1); // wav file playback mixer
AudioConnection patchCord4(mixer, 0, i2s1, 0); // mixer output to speaker (L)
AudioConnection patchCord6(mixer, 0, i2s1, 1); // mixer output to speaker (R)
AudioConnection patchCord5(i2s2, 0, queue1, 0); // mic input to queue (L)
AudioControlSGTL5000      sgtl5000_1;

// Filename to save audio recording on SD card
char filename[15];
// The file object itself
File frec;

// Use long 40ms debounce time on both switches
Bounce buttonRecord = Bounce(HOOK_PIN, 40);
Bounce buttonPlay = Bounce(PLAYBACK_BUTTON_PIN, 40);

// Keep track of current state of the device
enum Mode {Initialising, Ready, Prompting, Recording, Playing, Recording_Greeting};
Mode mode = Mode::Initialising;

float beep_volume = 0.04f; // not too loud :-)

// variables for writing to WAV file
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;


void setup() {

  Serial.begin(9600);
  while (!Serial && millis() < 5000) {
    // wait for serial port to connect.
  }
  Serial.println("Serial set up correctly");
  print_mode();
  // Configure the input pins
  pinMode(HOOK_PIN, INPUT_PULLUP);
  pinMode(PLAYBACK_BUTTON_PIN, INPUT_PULLUP);

  // Audio connections require memory, and the record queue
  // uses this memory to buffer incoming audio.
  AudioMemory(60);

  // Enable the audio shield, select input, and enable output
  sgtl5000_1.enable();
  // Define which input on the audio shield to use (AUDIO_INPUT_LINEIN / AUDIO_INPUT_MIC)
  sgtl5000_1.inputSelect(AUDIO_INPUT_MIC);
  sgtl5000_1.adcHighPassFilterDisable(); //
  sgtl5000_1.volume(0.85);

  mixer.gain(0, 1.0f);
  mixer.gain(1, 1.0f);

  // Play a beep to indicate system is online
  waveform1.begin(beep_volume, 440, WAVEFORM_SINE);
  wait(1000);
  waveform1.amplitude(0);
  delay(1000);

  // Initialize the SD card
#ifndef TEENSY_41   // assumes that you are using the SD card slot of the AUDIO BOARD
  SPI.setMOSI(SDCARD_MOSI_PIN);
  SPI.setSCK(SDCARD_SCK_PIN);
#endif  
  if (!(SD.begin(SDCARD_CS_PIN))) 
  {
    // stop here if no SD card, but print a message
    while (1) {
      Serial.println("Unable to access the SD card");
      delay(500);
    }
  }
    else Serial.println("SD card correctly initialized");

  // mandatory to begin the MTP session.
    MTP.begin();

  // Add SD Card
    MTP.addFilesystem(SD, "Gruenkohls Audio guestbook"); // choose a nice name for the SD card volume to appear in your file explorer
    Serial.println("Added SD card via MTP");
    
    // Value in dB
//  sgtl5000_1.micGain(15);
  sgtl5000_1.micGain(8); // much lower gain is required for the AOM5024 electret capsule

  // Synchronise the Time object used in the program code with the RTC time provider.
  // See https://github.com/PaulStoffregen/Time
  setSyncProvider(getTeensy3Time);
  
  // Define a callback that will assign the correct datetime for any file system operations
  // (i.e. saving a new audio recording onto the SD card)
  FsDateTime::setCallback(dateTime);

  mode = Mode::Ready; print_mode();
}

void loop() { //1
  // First, read the buttons
  buttonRecord.update();
  buttonPlay.update();

  switch(mode)
  { //2
    case Mode::Ready:
      // Falling edge occurs when the handset is lifted --> 611 telephone
#if defined(HANDHELD_CLOSES_ON_LIFT)
      if (buttonRecord.fallingEdge()) 
#else
      if (buttonRecord.risingEdge()) 
#endif
      {
        Serial.println("Handset lifted");
        mode = Mode::Prompting; print_mode();
      } //3
      else if(buttonPlay.fallingEdge()) 
      { //4
        //playAllRecordings();
        playLastRecording();
      } //4
      break;

    case Mode::Prompting:
      // Wait a second for users to put the handset to their ear
      wait(1000);

#if defined(AUTO_GREETING_MESSAGE)

    if (!SD.exists("greeting.wav")) 
    { //5
      mode = Mode::Recording_Greeting;
      break;
    } //5
#endif
     
      // Play the greeting inviting them to record their message
      playWav1.play("greeting.wav");    
      // Wait until the  message has finished playing
//      while (playWav1.isPlaying()) {
      while (!playWav1.isStopped()) 
      { //6
        // Check whether the handset is replaced
        buttonRecord.update();
        buttonPlay.update();
        // Handset is replaced
#if defined(HANDHELD_CLOSES_ON_LIFT)
      if (buttonRecord.risingEdge()) 
#else
      if (buttonRecord.fallingEdge())
#endif
        {
          playWav1.stop();
          mode = Mode::Ready; print_mode();
          return;
        } //7
        if(buttonPlay.fallingEdge()) 
        { //8
          playWav1.stop();
          //playAllRecordings();
          playLastRecording();
          return;
        } //8
        
      }  // 
      
      // Debug message
      Serial.println("Starting Recording");
      // Play the tone sound effect
      waveform1.begin(beep_volume, 440, WAVEFORM_SINE);
      wait(1250);
      waveform1.amplitude(0);
      // Start the recording function
      startRecording();
      break;

    case Mode::Recording:
      // Handset is replaced
#if defined(HANDHELD_CLOSES_ON_LIFT)
      if (buttonRecord.risingEdge()) 
#else
      if (buttonRecord.fallingEdge())
#endif
      { //9  
      // Debug log
        Serial.println("Stopping Recording");
        // Stop recording
        stopRecording();
        // Play audio tone to confirm recording has ended
        end_Beep();
      } //9
      else 
      { //10
        continueRecording();
      } // 10
      break;

    case Mode::Playing: // to make compiler happy
      break;  

    case Mode::Initialising: // to make compiler happy
      break;  

    case Mode::Recording_Greeting: // to make compiler happy
      startRecordingGreeting();
      mode = Mode::Recording;
      break;  
      } // 2 end switch   
  MTP.loop();  //This is mandatory to be placed in the loop code.
} // 1 end loop

void startRecordingGreeting() {
    if (SD.exists("greeting.wav")) {
      return;
    }
    // play message "Please record Greeting message now !" 
    playWav1.play("invitation_greeting.wav");
    while (!playWav1.isStopped()) { // this works for playWav
      buttonPlay.update();
      buttonRecord.update();
      // Button is pressed again
#if defined(HANDHELD_CLOSES_ON_LIFT)
      if(buttonPlay.fallingEdge() || buttonRecord.risingEdge())  
#else
      if(buttonPlay.fallingEdge() || buttonRecord.fallingEdge())  
#endif
      { 
        playWav1.stop();
        mode = Mode::Ready; print_mode();
        return;
      }   
    }
    // play beep
    two_tone_Beep();
  frec = SD.open("greeting.wav", FILE_WRITE);
  Serial.println("Opened Greeting file !");
  if(frec) {
    Serial.print("Recording to greeting.wav");
    queue1.begin();
    mode = Mode::Recording; print_mode();
    recByteSaved = 0L;
  }
  else {
    Serial.println("Couldn't open file to record!");
  }
}

void startRecording() {
  // Find the first available file number
//  for (uint8_t i=0; i<9999; i++) { // BUGFIX uint8_t overflows if it reaches 255  
  for (uint16_t i=0; i<9999; i++) {   
    // Format the counter as a five-digit number with leading zeroes, followed by file extension
    snprintf(filename, 11, " %05d.wav", i);
    // Create if does not exist, do not open existing, write, sync after write
    if (!SD.exists(filename)) {
      break;
    }
  }
  frec = SD.open(filename, FILE_WRITE);
  Serial.println("Opened file !");
  if(frec) {
    Serial.print("Recording to ");
    Serial.println(filename);
    queue1.begin();
    mode = Mode::Recording; print_mode();
    recByteSaved = 0L;
  }
  else {
    Serial.println("Couldn't open file to record!");
  }
}

void continueRecording() {
  // Check if there is data in the queue
  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;
  }
}

void stopRecording() {
  // Stop adding any new data to the queue
  queue1.end();
  // Flush all existing remaining data from the queue
  while (queue1.available() > 0) {
    // Save to open file
    frec.write((byte*)queue1.readBuffer(), 256);
    queue1.freeBuffer();
    recByteSaved += 256;
  }
  writeOutHeader();
  // Close the file
  frec.close();
  Serial.println("Closed file");
  mode = Mode::Ready; print_mode();
}


void playAllRecordings() {
  // Recording files are saved in the root directory
  File dir = SD.open("/");
  
  while (true) {
    File entry =  dir.openNextFile();
    if (strstr(entry.name(), "greeting"))
    {
       entry =  dir.openNextFile();
    }
    if (!entry) {
      // no more files
      entry.close();
      end_Beep();
      break;
    }
    //int8_t len = strlen(entry.name()) - 4;
//    if (strstr(strlwr(entry.name() + (len - 4)), ".raw")) {
//    if (strstr(strlwr(entry.name() + (len - 4)), ".wav")) {
    // the lines above throw a warning, so I replace them with this (which is also easier to read):
    if (strstr(entry.name(), ".wav") || strstr(entry.name(), ".WAV")) {
      Serial.print("Now playing ");
      Serial.println(entry.name());
      // Play a short beep before each message
      waveform1.amplitude(beep_volume);
      wait(750);
      waveform1.amplitude(0);
      // Play the file
      playWav1.play(entry.name());
      mode = Mode::Playing; print_mode();
    }
    entry.close();

//    while (playWav1.isPlaying()) { // strangely enough, this works for playRaw, but it does not work properly for playWav
    while (!playWav1.isStopped()) { // this works for playWav
      buttonPlay.update();
      buttonRecord.update();
      // Button is pressed again
#if defined(HANDHELD_CLOSES_ON_LIFT)
      if(buttonPlay.fallingEdge() || buttonRecord.risingEdge())  
#else
      if(buttonPlay.fallingEdge() || buttonRecord.fallingEdge())  
#endif
      { 
        playWav1.stop();
        mode = Mode::Ready; print_mode();
        return;
      }   
    }
  }
  // All files have been played
  mode = Mode::Ready; print_mode();
}

void playLastRecording() { // 1
  // Find the first available file number
  uint16_t idx = 0; 
  for (uint16_t i=0; i<9999; i++) { // 2
    // Format the counter as a five-digit number with leading zeroes, followed by file extension
    snprintf(filename, 11, " %05d.wav", i);
    // check, if file with index i exists
    if (!SD.exists(filename)) { // 3
     idx = i - 1;
     break;
      } // 3
  } // 2
      // now play file with index idx == last recorded file
      snprintf(filename, 11, " %05d.wav", idx);
      Serial.println(filename);
      playWav1.play(filename);
      mode = Mode::Playing; print_mode();
      while (!playWav1.isStopped()) 
      { // 5 // this works for playWav
          buttonPlay.update();
          buttonRecord.update();
          // Button is pressed again
    #if defined(HANDHELD_CLOSES_ON_LIFT)
          if(buttonPlay.fallingEdge() || buttonRecord.risingEdge())  
    #else
          if(buttonPlay.fallingEdge() || buttonRecord.fallingEdge()) 
    #endif
          {
            playWav1.stop();
            mode = Mode::Ready; print_mode();
            return;
          }   //4
      } // 5 end while
      // file has been played
  mode = Mode::Ready; print_mode();  
  end_Beep();
} // 1 end playLastRecording


// Retrieve the current time from Teensy built-in RTC
time_t getTeensy3Time(){
  return Teensy3Clock.get();
}

// Callback to assign timestamps for file system operations
void dateTime(uint16_t* date, uint16_t* time, uint8_t* ms10) {

  // Return date using FS_DATE macro to format fields.
  *date = FS_DATE(year(), month(), day());

  // Return time using FS_TIME macro to format fields.
  *time = FS_TIME(hour(), minute(), second());

  // Return low time bits in units of 10 ms.
  *ms10 = second() & 1 ? 100 : 0;
}

// Non-blocking delay, which pauses execution of main program logic,
// but while still listening for input 
void wait(unsigned int milliseconds) {
  elapsedMillis msec=0;

  while (msec <= milliseconds) {
    buttonRecord.update();
    buttonPlay.update();
    if (buttonRecord.fallingEdge()) Serial.println("Button (pin 0) Press");
    if (buttonPlay.fallingEdge()) Serial.println("Button (pin 1) Press");
    if (buttonRecord.risingEdge()) Serial.println("Button (pin 0) Release");
    if (buttonPlay.risingEdge()) Serial.println("Button (pin 1) Release");
  }
}


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();
  Serial.println("header written"); 
  Serial.print("Subchunk2: "); 
  Serial.println(Subchunk2Size); 
}

void end_Beep(void) {
        waveform1.frequency(523.25);
        waveform1.amplitude(beep_volume);
        wait(250);
        waveform1.amplitude(0);
        wait(250);
        waveform1.amplitude(beep_volume);
        wait(250);
        waveform1.amplitude(0);
        wait(250);
        waveform1.amplitude(beep_volume);
        wait(250);
        waveform1.amplitude(0);
        wait(250);
        waveform1.amplitude(beep_volume);
        wait(250);
        waveform1.amplitude(0);
}

void two_tone_Beep(void) {
        waveform1.frequency(523.25);
        waveform1.amplitude(beep_volume);
        wait(250);
        waveform1.amplitude(0);
        waveform1.frequency(375.0);
        wait(250);
        waveform1.amplitude(beep_volume);
        wait(250);
        waveform1.amplitude(0);
        waveform1.frequency(523.25);
        wait(250);
        waveform1.amplitude(beep_volume);
        wait(250);
        waveform1.amplitude(0);
        waveform1.frequency(375.0);
        wait(250);
        waveform1.amplitude(beep_volume);
        wait(250);
        waveform1.amplitude(0);
}

void print_mode(void) { // only for debugging
  Serial.print("Mode switched to: ");
  // Initialising, Ready, Prompting, Recording, Playing
  if(mode == Mode::Ready)           Serial.println(" Ready");
  else if(mode == Mode::Prompting)  Serial.println(" Prompting");
  else if(mode == Mode::Recording)  Serial.println(" Recording");
  else if(mode == Mode::Playing)    Serial.println(" Playing");
  else if(mode == Mode::Initialising)  Serial.println(" Initialising");
  else if(mode == Mode::Recording_Greeting)  Serial.println(" Recording Greeting");
  else Serial.println(" Undefined");
}
 
while recording the wav files, small parts are failing to record at a regular interval.. for example, while recoding counting number (1-30) - 13 & 26 missing...

Could you explain in detail what that means? What is "small parts", what is "recoding counting number" ? I do not understand what is going right and what is going wrong in your setup.
 
I'm having some issues with getting the code to compile each time it throws more errors my way. It used to tell me multiple libraries were found for SD.h but I finally solved that issue I could really use some help because I am stuck on this. Below are the errors it is giving me any help is appreciated also I am using the correct versions of TD and Arduino I have checked multiple times.









In file included from C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Storage.h:35:0,
from C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Teensy.h:45,
from C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:37:
C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/FS.h:37:0: warning: "FILE_READ" redefined
#define FILE_READ 0
^
In file included from C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Audio/play_sd_raw.h:32:0,
from C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Audio/Audio.h:127,
from C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:32:
C:\Program Files (x86)\Arduino\libraries\SD\src/SD.h:23:0: note: this is the location of the previous definition
#define FILE_READ O_READ
^
In file included from C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Storage.h:35:0,
from C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Teensy.h:45,
from C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:37:
C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/FS.h:38:0: warning: "FILE_WRITE" redefined
#define FILE_WRITE 1
^
In file included from C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Audio/play_sd_raw.h:32:0,
from C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Audio/Audio.h:127,
from C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:32:
C:\Program Files (x86)\Arduino\libraries\SD\src/SD.h:24:0: note: this is the location of the previous definition
#define FILE_WRITE (O_READ | O_WRITE | O_CREAT | O_APPEND)
^
In file included from C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Storage.h:35:0,
from C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Teensy.h:45,
from C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:37:
C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/FS.h:75:10: error: reference to 'File' is ambiguous
virtual File openNextFile(uint8_t mode=0) = 0;
^
C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/FS.h:47:7: note: candidates are: class File
class File;
^
In file included from C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Audio/play_sd_raw.h:32:0,
from C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Audio/Audio.h:127,
from C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:32:
C:\Program Files (x86)\Arduino\libraries\SD\src/SD.h:28:9: note: class SDLib::File
class File : public Stream {
^
In file included from C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Storage.h:35:0,
from C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Teensy.h:45,
from C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:37:
C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/FS.h: In member function 'File File::eek:penNextFile(uint8_t)':
C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/FS.h:213:19: error: 'class FileImpl' has no member named 'openNextFile'
return (f) ? f->openNextFile(mode) : *this;
^
C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/FS.h: At global scope:
C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/FS.h:273:10: error: reference to 'File' is ambiguous
virtual File open(const char *filename, uint8_t mode = FILE_READ) = 0;
^
C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/FS.h:101:7: note: candidates are: class File
class File final : public Stream {
^
In file included from C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Audio/play_sd_raw.h:32:0,
from C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Audio/Audio.h:127,
from C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:32:
C:\Program Files (x86)\Arduino\libraries\SD\src/SD.h:28:9: note: class SDLib::File
class File : public Stream {
^
In file included from C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Storage.h:35:0,
from C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Teensy.h:45,
from C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:37:
C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/FS.h:287:2: error: reference to 'File' is ambiguous
File open(const String &filepath, uint8_t mode = FILE_READ) {
^
C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/FS.h:101:7: note: candidates are: class File
class File final : public Stream {
^
In file included from C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Audio/play_sd_raw.h:32:0,
from C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Audio/Audio.h:127,
from C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:32:
C:\Program Files (x86)\Arduino\libraries\SD\src/SD.h:28:9: note: class SDLib::File
class File : public Stream {
^
In file included from C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Teensy.h:45:0,
from C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:37:
C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Storage.h:178:2: error: reference to 'File' is ambiguous
File open(uint32_t store, const char *filename, uint32_t mode) {
^
In file included from C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Storage.h:35:0,
from C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Teensy.h:45,
from C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:37:
C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/FS.h:101:7: note: candidates are: class File
class File final : public Stream {
^
In file included from C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Audio/play_sd_raw.h:32:0,
from C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Audio/Audio.h:127,
from C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:32:
C:\Program Files (x86)\Arduino\libraries\SD\src/SD.h:28:9: note: class SDLib::File
class File : public Stream {
^
In file included from C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Teensy.h:45:0,
from C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:37:
C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Storage.h:287:2: error: reference to 'File' is ambiguous
File index_;
^
In file included from C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Storage.h:35:0,
from C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Teensy.h:45,
from C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:37:
C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/FS.h:101:7: note: candidates are: class File
class File final : public Stream {
^
In file included from C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Audio/play_sd_raw.h:32:0,
from C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Audio/Audio.h:127,
from C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:32:
C:\Program Files (x86)\Arduino\libraries\SD\src/SD.h:28:9: note: class SDLib::File
class File : public Stream {
^
In file included from C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Teensy.h:45:0,
from C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:37:
C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Storage.h:288:2: error: reference to 'File' is ambiguous
File file_;
^
In file included from C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Storage.h:35:0,
from C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Teensy.h:45,
from C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:37:
C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/FS.h:101:7: note: candidates are: class File
class File final : public Stream {
^
In file included from C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Audio/play_sd_raw.h:32:0,
from C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Audio/Audio.h:127,
from C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:32:
C:\Program Files (x86)\Arduino\libraries\SD\src/SD.h:28:9: note: class SDLib::File
class File : public Stream {
^
In file included from C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Teensy.h:45:0,
from C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:37:
C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Storage.h:289:2: error: reference to 'File' is ambiguous
File child_;
^
In file included from C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Storage.h:35:0,
from C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Teensy.h:45,
from C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:37:
C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/FS.h:101:7: note: candidates are: class File
class File final : public Stream {
^
In file included from C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Audio/play_sd_raw.h:32:0,
from C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Audio/Audio.h:127,
from C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:32:
C:\Program Files (x86)\Arduino\libraries\SD\src/SD.h:28:9: note: class SDLib::File
class File : public Stream {
^
In file included from C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:37:0:
C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Teensy.h: In member function 'uint32_t MTP_class::addFilesystem(SDLib::SDClass&, const char*)':
C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Teensy.h:78:55: error: no matching function for call to 'MTP_class::addFilesystem(SDLib::SDClass&, const char*&, mtp_fstype_t)'
return addFilesystem(disk, diskname, MTP_FSTYPE_SD);
^
C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Teensy.h:76:12: note: candidate: uint32_t MTP_class::addFilesystem(SDLib::SDClass&, const char*)
uint32_t addFilesystem(SDClass &disk, const char *diskname) {
^
C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Teensy.h:76:12: note: candidate expects 2 arguments, 3 provided
C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Teensy.h:82:12: note: candidate: uint32_t MTP_class::addFilesystem(FS&, const char*, mtp_fstype_t)
uint32_t addFilesystem(FS &disk, const char *diskname, mtp_fstype_t fstype = MTP_FSTYPE_UNKNOWN);
^
C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Teensy.h:82:12: note: no known conversion for argument 1 from 'SDLib::SDClass' to 'FS&'
C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino: At global scope:
C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:97:1: error: reference to 'File' is ambiguous
File frec;
^
In file included from C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Storage.h:35:0,
from C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Teensy.h:45,
from C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:37:
C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/FS.h:101:7: note: candidates are: class File
class File final : public Stream {
^
In file included from C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Audio/play_sd_raw.h:32:0,
from C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Audio/Audio.h:127,
from C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:32:
C:\Program Files (x86)\Arduino\libraries\SD\src/SD.h:28:9: note: class SDLib::File
class File : public Stream {
^
C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino: In function 'void setup()':
C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:64:26: error: 'BUILTIN_SDCARD' was not declared in this scope
#define SDCARD_CS_PIN BUILTIN_SDCARD
^
C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:161:18: note: in expansion of macro 'SDCARD_CS_PIN'
if (!(SD.begin(SDCARD_CS_PIN)))
^
C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:188:3: error: 'FsDateTime' has not been declared
FsDateTime::setCallback(dateTime);
^
C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino: In function 'void startRecordingGreeting()':
C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:329:3: error: 'frec' was not declared in this scope
frec = SD.open("greeting.wav", FILE_WRITE);
^
C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino: In function 'void startRecording()':
C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:353:3: error: 'frec' was not declared in this scope
frec = SD.open(filename, FILE_WRITE);
^
C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino: In function 'void continueRecording()':
C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:380:5: error: 'frec' was not declared in this scope
frec.write(buffer, 512);
^
C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino: In function 'void stopRecording()':
C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:391:5: error: 'frec' was not declared in this scope
frec.write((byte*)queue1.readBuffer(), 256);
^
C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:397:3: error: 'frec' was not declared in this scope
frec.close();
^
C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino: In function 'void playAllRecordings()':
C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:405:3: error: reference to 'File' is ambiguous
File dir = SD.open("/");
^
In file included from C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Storage.h:35:0,
from C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Teensy.h:45,
from C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:37:
C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/FS.h:101:7: note: candidates are: class File
class File final : public Stream {
^
In file included from C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Audio/play_sd_raw.h:32:0,
from C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Audio/Audio.h:127,
from C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:32:
C:\Program Files (x86)\Arduino\libraries\SD\src/SD.h:28:9: note: class SDLib::File
class File : public Stream {
^
C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:408:5: error: reference to 'File' is ambiguous
File entry = dir.openNextFile();
^
In file included from C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Storage.h:35:0,
from C:\Users\Jonah\OneDrive\Documents\Arduino\libraries\MTP_Teensy-main\src/MTP_Teensy.h:45,
from C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:37:
C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/FS.h:101:7: note: candidates are: class File
class File final : public Stream {
^
In file included from C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Audio/play_sd_raw.h:32:0,
from C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Audio/Audio.h:127,
from C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:32:
C:\Program Files (x86)\Arduino\libraries\SD\src/SD.h:28:9: note: class SDLib::File
class File : public Stream {
^
C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:409:16: error: 'entry' was not declared in this scope
if (strstr(entry.name(), "greeting"))
^
C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:411:17: error: 'dir' was not declared in this scope
entry = dir.openNextFile();
^
C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:413:10: error: 'entry' was not declared in this scope
if (!entry) {
^
C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:423:16: error: 'entry' was not declared in this scope
if (strstr(entry.name(), ".wav") || strstr(entry.name(), ".WAV")) {
^
C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:434:5: error: 'entry' was not declared in this scope
entry.close();
^
C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino: In function 'void dateTime(uint16_t*, uint16_t*, uint8_t*)':
C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:505:41: error: 'FS_DATE' was not declared in this scope
*date = FS_DATE(year(), month(), day());
^
C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:508:45: error: 'FS_TIME' was not declared in this scope
*time = FS_TIME(hour(), minute(), second());
^
C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino: In function 'void writeOutHeader()':
C:\Users\Jonah\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:536:3: error: 'frec' was not declared in this scope
frec.seek(0);
^
Error compiling for board Teensy 4.1.
 
In my github, I stated very clearly, that the code only works with T4.0 and T4.1

I now have a Teensy 4.1. I have now compiled your unaltered code found on your Github and it compiles with no errors. I can see that the errors I was getting stopped immediately after I stopped targeting a Teensy LC board and instead started targeting Teensy 4.0 and 4.1. I have now loaded the code onto the Teensy SD card (using the SD card slot on the Teensy rather than the audio shield). However, nothing happens when I pick up the receiver. I have no idea what I'm supposed to hear. Is there some kind of robot voice that's supposed to prompt me to record a greeting? I hear no such prompt when I pick up my receiver. I also hear nothing when I move a file named "greeting.wav" from my computer onto the SD card. Am I supposed to power the phone separately? It's a digital phone we bought on Amazon. It's the "Rotary Phone, MCHEETA Retro Rotary Dial Phone, 80s Vintage Old Telephone for Landline, Corded Landline Phones for Home(Yellow)."
 
Could you explain in detail what that means? What is "small parts", what is "recoding counting number" ? I do not understand what is going right and what is going wrong in your setup.

View attachment 00015.zip

@DD4WH Thanks for your response, If you can manage to hear the attached WAV file (Zip), you will find what I mean. Your help to fix this will be highly appreciated.
 
hear the attached WAV file (Zip), you will find what I mean.

That is pretty normal behaviour! By using the standard Teensy audio lib modules, it is not possible to record audio without such glitches. A better SD card might help, but in most cases you have got to live with that.
 
A fast card really helps. You just can't use the alle the labels on the card to know it is fast or not.
There are some threads here where you can find a fast card. Don't trust benchmarks on PCs.
 
Long story short, I improved the connections between phone and Teensy/Audio shield. I am now getting a "beep" tone after I pick up the handset. After I put it down and then pick it up, I hear no beep. I do hear the beep again if I power cycle the Teensy and then pick up the handset. It doesn't appear to be playing the greeting wav file I moved to the SD card, and it doesn't appear to be prompting a new recording or recording anything new. I'm using Teensy 4.1.
 
Also, on the Arduino IDE 1.8.19, I have either the ability to compile with Serial or with MTP Disk (Experimental) but not both. Is there a config file I need to change to fix this?
 
I've installed the 1.57 TD final. I'm still only getting a beep when I lift the handset after a fresh power cycle. When I press the pushbutton for message playback, I get 4 beeps that sound identical to each other and different from the other beep that plays after I pick up the handset.
 
That is pretty normal behaviour! By using the standard Teensy audio lib modules, it is not possible to record audio without such glitches. A better SD card might help, but in most cases you have got to live with that.

Thanks, can you please suggest the SD card would perform better?
Further, you mentioned standard Teensy audio lib modules will not perform better, is there any other alternative?
 
OK, so the phone *is* playing back my greeting, and then recording a message, but only when I physically unplug and then reconnect Pin 0 on the Teensy 4.1. The phone then doesn't immediately stop recording when I hang up the handset. I'm now noticing that after the first 2 recordings, subsequent recordings appear to be corrupted.
 
OK, so the phone *is* playing back my greeting, and then recording a message, but only when I physically unplug and then reconnect Pin 0 on the Teensy 4.1. The phone then doesn't immediately stop recording when I hang up the handset. I'm now noticing that after the first 2 recordings, subsequent recordings appear to be corrupted.

It may help to read the instructions from my github:
https://github.com/DD4WH/audio-guestbook
Also make sure you understand whether your handset switch opens or closes on lifting the handset (and adjust the software switches accordingly).
And ensure that your handset switch hardware is working properly and 100% reliably.
Corrupted recordings are most probably caused by your SD card. Use a good SD card. Search for Bill Greiman SD card test, he had a thread here on the forum where SD cards were compared.
 
Further, you mentioned standard Teensy audio lib modules will not perform better, is there any other alternative?

Yes, the microSoundRecorder sketch by WMXZ does allow to record audio without glitches on the T3.6. Search for it on github. You would have to merge the two sketches together, adapt them to the Teensy 4.0/4.1 and put a whole lot of effort and know-how into that in order to produce a working audio guest book.
 
It may help to read the instructions from my github:
https://github.com/DD4WH/audio-guestbook
Also make sure you understand whether your handset switch opens or closes on lifting the handset (and adjust the software switches accordingly).
And ensure that your handset switch hardware is working properly and 100% reliably.
Corrupted recordings are most probably caused by your SD card. Use a good SD card. Search for Bill Greiman SD card test, he had a thread here on the forum where SD cards were compared.

I got it working as of last night. I found that I had misidentified the pins (there were 4 of them because it was a ribbon cable with 4 pins) that trigger when I press/depress the hook switch, and I also didn't press the Teensy 4.1 and the Audio Shield together enough, so they weren't making a strong enough connection. After soldering wires to the correct pins on the phone's circuit board, I was getting the correct behavior out of GPIO Pin 0, and thus the recording started. This also seemed to fix the issue with the SD card, because the hook switch controls were completely divorced from the actual Teensy until I made that discovery last night.

So long story short, my problem was that I mistakenly bought a Teensy LC and didn't correctly follow the sequence in the tutorial vid where you're supposed to ID the hook switch, because I'm inexperienced with multimeter and didn't know what I was looking for.

I think it might help future users to pay special attention to the hook switch for digital phones, and triple check any soldering connections you make to a PCB, because I had to re-solder all of the connections from the wires I had going to the Teensy to my phone's board. To any newbie reading this, you will want wire strippers and you may need a soldering iron (as well as flux, solder, a solder sucker, and solder wick).
 
Congratulations!!! Very good.

Thanks a lot for your detailed feedback and recommendations, which will help builders to check their builds and make them work :).

Have fun with the Teensy! Frank DD4WH
 
So did a few upgrades to the code to be able to use it with a more modern phone (https://a.co/d/8yH8w7j) and to have it have an LED status light when recording (on pin 2 for T4). Also now have a time recording limit.

Issue that I'm still having is that the phone doesn't always seem to catch pickups or hangups. It also doesn't seem to like my externally recorded greeting.wav Here's the code for anyone wanting to update or play with it, thanks to @dd4wh for the work on it from the getgo!

Code:
/**
 * Audio Guestbook, Copyright (c) 2022 Playful Technology
 * 
 * Tested using a Teensy 4.0 with Teensy Audio Shield, although should work 
 * with minor modifications on other similar hardware
 * 
 * When handset is lifted, a pre-recorded greeting message is played, followed by a tone.
 * Then, recording starts, and continues until the handset is replaced.
 * Playback button allows all messages currently saved on SD card through earpiece 
 * 
 * follow the detailed instructions here:
 * https://github.com/DD4WH/audio-guestbook/blob/main/README.md
 * 
 * 
 *   the sketch only works with the latest Teensyduino 1.57 version, so please update your Arduino IDE AND your Teensyduino to Arduino version 1.8.19 and the latest Teensyduino version 1.57
 *   download the following library, unzip it and put it into your local Arduino folder (on my computer, the local Arduino folder is: "C:/Users/DD4WH/Documents/Arduino/libraries/"): https://github.com/KurtE/MTP_Teensy
 *   compile with option: "Serial + MTP Disk (Experimental)"" and with option "CPU speed: 150MHz" (this can save about 70% of battery power)
 *
 * Modifications by Frank DD4WH, August 2022
 * - now uses a Teensy 4.1 with built-in SD card (faster via SDIO), if you want to use a Teensy 4.0, uncomment in the USER CONFIGURATION below
 * - Files are saved on SD card as 44.1kHz, 16-bit mono WAV audio files 
 * - if you plug in the telephones´ USB cable into your computer, the telephone is mounted as a drive and you can acess the recordings 
 * - if there is no "greeting.wav" message on the SD card, the telephone automatically plays an invitation to record this message and then you can record the greeting message 
 * - if you want to record the greeting message again, just delete it from the telephone and lift the handheld again to record the greeting message  
 * --> if your handheld contact switch opens on lifting, simply uncomment in the USER CONFIGURATION below, everything else is done by the software
 * 
 * GNU GPL v3.0 license
 * 
 */

#include <Bounce.h>
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <TimeLib.h>
#include <MTP_Teensy.h>  // this library has to be downloaded separately (https://github.com/KurtE/MTP_Teensy)
// unzip the downloaded file and its content into your local Arduino folder (on my computer, the local Arduino folder is: "C:/Users/DD4WH/Documents/Arduino/libraries/")

/***************************************************************************************************************************************************/
/**USER CONFIGURATION ******************************************************************************************************************************/
/**COMMENT / UNCOMMENT ACCORDING TO YOUR HARDWARE **************************************************************************************************/
/***************************************************************************************************************************************************/

// comment this out, if your handheld OPENS the contact on lift
// use a digital voltmeter to find out
#define HANDHELD_CLOSES_ON_LIFT

// comment this out, if you want to record your greeting message with an external recorder
// leave as-is if you want to have the telephone automatically switch to recording the greeting message, in case there is no "greeting.wav" on the SD card 
#define AUTO_GREETING_MESSAGE

// comment out, if you use a Teensy 4.0 (and thus the SD card slot on the audio board)
// if you leave this as-is, you have to use the built-in SD card slot on the Teensy 4.1, NOT the SD card slot on the audio board 
////#define TEENSY_41

/***************************************************************************************************************************************************/
/**END OF USER CONFIGURATION ***********************************************************************************************************************/
/***************************************************************************************************************************************************/
/***************************************************************************************************************************************************/

// Define pins used by Teensy Audio Shield
#ifdef TEENSY_41
#define SDCARD_CS_PIN    BUILTIN_SDCARD
#else
#define SDCARD_CS_PIN    10
#endif
#define SDCARD_MOSI_PIN  7
#define SDCARD_SCK_PIN   14
// And those used for inputs
// You can choose the pins you use here:
//#define HOOK_PIN 40
//#define PLAYBACK_BUTTON_PIN 41
#define HOOK_PIN 0              // this is the default
#define PLAYBACK_BUTTON_PIN 1   // this is the default


// GLOBALS
// Audio initialisation code can be generated using the GUI interface at https://www.pjrc.com/teensy/gui/
// Inputs
AudioSynthWaveform          waveform1; // To create the "beep" sfx
AudioInputI2S               i2s2; // I2S input from microphone on audio shield
AudioPlaySdWav              playWav1; // Play 44.1kHz 16-bit PCM greeting WAV file
AudioRecordQueue            queue1; // Creating an audio buffer in memory before saving to SD
AudioMixer4                 mixer; // Allows merging several inputs to same output
AudioOutputI2S              i2s1; // I2S interface to Speaker/Line Out on Audio shield
AudioConnection patchCord1(waveform1, 0, mixer, 0); // wave to mixer 
AudioConnection patchCord3(playWav1, 0, mixer, 1); // wav file playback mixer
AudioConnection patchCord4(mixer, 0, i2s1, 0); // mixer output to speaker (L)
AudioConnection patchCord6(mixer, 0, i2s1, 1); // mixer output to speaker (R)
AudioConnection patchCord5(i2s2, 0, queue1, 0); // mic input to queue (L)
AudioControlSGTL5000      sgtl5000_1;

// Filename to save audio recording on SD card
char filename[15];
// The file object itself
File frec;

// Use long 40ms debounce time on both switches
Bounce buttonRecord = Bounce(HOOK_PIN, 100);
Bounce buttonPlay = Bounce(PLAYBACK_BUTTON_PIN, 40);

// Keep track of current state of the device
enum Mode {Initialising, Ready, Prompting, Recording, Playing, Recording_Greeting};
Mode mode = Mode::Initialising;

float beep_volume = 0.4f; // not too loud :-)

// variables for writing to WAV file
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;
// PiProjects variables 
int recordTimeStamp;
int recordingTimeLimit = 60000; // This is the recording time limit in milliseconds 
int LED_PIN = 2;

void setup() {

  Serial.begin(9600);
  while (!Serial && millis() < 5000) {
    // wait for serial port to connect.
  }
  Serial.println("Serial set up correctly");
  print_mode();
  // Configure the input pins
  pinMode(HOOK_PIN, INPUT_PULLUP);
  pinMode(PLAYBACK_BUTTON_PIN, INPUT_PULLUP);
  pinMode(LED_PIN, OUTPUT);
  
  // Audio connections require memory, and the record queue
  // uses this memory to buffer incoming audio.
  AudioMemory(60);

  // Enable the audio shield, select input, and enable output
  sgtl5000_1.enable();
  // Define which input on the audio shield to use (AUDIO_INPUT_LINEIN / AUDIO_INPUT_MIC)
  sgtl5000_1.inputSelect(AUDIO_INPUT_MIC);
  sgtl5000_1.adcHighPassFilterDisable(); //
  sgtl5000_1.volume(1.0);

  mixer.gain(0, 1.0f);
  mixer.gain(1, 1.0f);

  // Play a beep to indicate system is online
  waveform1.begin(beep_volume, 440, WAVEFORM_SINE);
  wait(500);
  waveform1.amplitude(0);
  delay(500);

  // Initialize the SD card
#ifndef TEENSY_41   // assumes that you are using the SD card slot of the AUDIO BOARD
  SPI.setMOSI(SDCARD_MOSI_PIN);
  SPI.setSCK(SDCARD_SCK_PIN);
#endif  
  if (!(SD.begin(SDCARD_CS_PIN))) 
  {
    // stop here if no SD card, but print a message
    while (1) {
      Serial.println("Unable to access the SD card");
      delay(5000);
    }
  }
    else Serial.println("SD card correctly initialized");

  // mandatory to begin the MTP session.
    MTP.begin();

  // Add SD Card
    MTP.addFilesystem(SD, "My Audio guestbook"); // choose a nice name for the SD card volume to appear in your file explorer
    Serial.println("Added SD card via MTP");
    
    // Value in dB
//  sgtl5000_1.micGain(15);
  sgtl5000_1.micGain(30); // much lower gain is required for the AOM5024 electret capsule

  // Synchronise the Time object used in the program code with the RTC time provider.
  // See https://github.com/PaulStoffregen/Time
  setSyncProvider(getTeensy3Time);
  
  // Define a callback that will assign the correct datetime for any file system operations
  // (i.e. saving a new audio recording onto the SD card)
  FsDateTime::setCallback(dateTime);

  mode = Mode::Ready; print_mode();
}

void loop() { //1
  // First, read the buttons
  buttonRecord.update();
  buttonPlay.update();

  switch(mode)
  { //2
    case Mode::Ready:
      // Falling edge occurs when the handset is lifted --> 611 telephone
#if defined(HANDHELD_CLOSES_ON_LIFT)
      if (buttonRecord.fallingEdge()) 
#else
      if (buttonRecord.risingEdge()) 
#endif
      {
        Serial.println("Handset lifted");
        mode = Mode::Prompting; print_mode();
      } //3
      else if(buttonPlay.fallingEdge()) 
      { //4
        //playAllRecordings();
        playLastRecording();
      } //4
      break;

    case Mode::Prompting:
      // Wait a second for users to put the handset to their ear
      wait(1000);

#if defined(AUTO_GREETING_MESSAGE)

    if (!SD.exists("greeting.wav")) 
    { //5
      mode = Mode::Recording_Greeting;
      break;
    } //5
#endif
     
      // Play the greeting inviting them to record their message
      playWav1.play("greeting.wav");    
      // Wait until the  message has finished playing
//      while (playWav1.isPlaying()) {
      while (!playWav1.isStopped()) 
      { //6
        // Check whether the handset is replaced
        buttonRecord.update();
        buttonPlay.update();
        // Handset is replaced
#if defined(HANDHELD_CLOSES_ON_LIFT)
      if (buttonRecord.risingEdge()) 
#else
      if (buttonRecord.fallingEdge())
#endif
        {
          playWav1.stop();
          mode = Mode::Ready; print_mode();
          return;
        } //7
        if(buttonPlay.fallingEdge()) 
        { //8
          playWav1.stop();
          //playAllRecordings();
          playLastRecording();
          return;
        } //8
        
      }  // 
      
      // Debug message
      Serial.println("Starting Recording");
      // Play the tone sound effect
      waveform1.begin(beep_volume, 440, WAVEFORM_SINE);
      wait(1250);
      waveform1.amplitude(0);
      // Start the recording function
      startRecording();
      digitalWrite(LED_PIN, HIGH);
      recordTimeStamp = millis(); // For recording time limit
      break;

    case Mode::Recording:
      // Handset is replaced
#if defined(HANDHELD_CLOSES_ON_LIFT)
      if (buttonRecord.risingEdge()) 
#else
      if (buttonRecord.fallingEdge())
#endif
      { //9  
      // Debug log
        Serial.println("Stopping Recording");
        // Stop recording
        stopRecording();
        // Play audio tone to confirm recording has ended
        end_Beep();
        digitalWrite(LED_PIN, LOW);
      } //9
      else 
      { //10
        if(recordTimeStamp + recordingTimeLimit < millis()){
          stopRecording();
           // Play audio tone to confirm recording has ended
          end_Beep();
          digitalWrite(LED_PIN, LOW);
        }
        continueRecording();
      } // 10
      break;

    case Mode::Playing: // to make compiler happy
      break;  

    case Mode::Initialising: // to make compiler happy
      break;  

    case Mode::Recording_Greeting: // to make compiler happy
      startRecordingGreeting();
      mode = Mode::Recording;
      break;  
      } // 2 end switch   
  MTP.loop();  //This is mandatory to be placed in the loop code.
} // 1 end loop

void startRecordingGreeting() {
    if (SD.exists("greeting.wav")) {
      return;
    }
    // play message "Please record Greeting message now !" 
    playWav1.play("invitation_greeting.wav");
    while (!playWav1.isStopped()) { // this works for playWav
      buttonPlay.update();
      buttonRecord.update();
      // Button is pressed again
#if defined(HANDHELD_CLOSES_ON_LIFT)
      if(buttonPlay.fallingEdge() || buttonRecord.risingEdge())  
#else
      if(buttonPlay.fallingEdge() || buttonRecord.fallingEdge())  
#endif
      { 
        playWav1.stop();
        mode = Mode::Ready; print_mode();
        return;
      }   
    }
    // play beep
    two_tone_Beep();
  frec = SD.open("greeting.wav", FILE_WRITE);
  Serial.println("Opened Greeting file !");
  if(frec) {
    Serial.print("Recording to greeting.wav");
    queue1.begin();
    mode = Mode::Recording; print_mode();
    recByteSaved = 0L;
  }
  else {
    Serial.println("Couldn't open file to record!");
  }
}

void startRecording() {
  // Find the first available file number
//  for (uint8_t i=0; i<9999; i++) { // BUGFIX uint8_t overflows if it reaches 255  
  for (uint16_t i=0; i<9999; i++) {   
    // Format the counter as a five-digit number with leading zeroes, followed by file extension
    snprintf(filename, 11, " %05d.wav", i);
    // Create if does not exist, do not open existing, write, sync after write
    if (!SD.exists(filename)) {
      break;
    }
  }
  frec = SD.open(filename, FILE_WRITE);
  Serial.println("Opened file !");
  if(frec) {
    Serial.print("Recording to ");
    Serial.println(filename);
    queue1.begin();
    mode = Mode::Recording; print_mode();
    recByteSaved = 0L;
  }
  else {
    Serial.println("Couldn't open file to record!");
  }
}

void continueRecording() {
  // Check if there is data in the queue
  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;
  }
}

void stopRecording() {
  // Stop adding any new data to the queue
  queue1.end();
  // Flush all existing remaining data from the queue
  while (queue1.available() > 0) {
    // Save to open file
    frec.write((byte*)queue1.readBuffer(), 256);
    queue1.freeBuffer();
    recByteSaved += 256;
  }
  writeOutHeader();
  // Close the file
  frec.close();
  Serial.println("Closed file");
  mode = Mode::Ready; print_mode();
}


void playAllRecordings() {
  // Recording files are saved in the root directory
  File dir = SD.open("/");
  
  while (true) {
    File entry =  dir.openNextFile();
    if (strstr(entry.name(), "greeting"))
    {
       entry =  dir.openNextFile();
    }
    if (!entry) {
      // no more files
      entry.close();
      end_Beep();
      break;
    }
    //int8_t len = strlen(entry.name()) - 4;
//    if (strstr(strlwr(entry.name() + (len - 4)), ".raw")) {
//    if (strstr(strlwr(entry.name() + (len - 4)), ".wav")) {
    // the lines above throw a warning, so I replace them with this (which is also easier to read):
    if (strstr(entry.name(), ".wav") || strstr(entry.name(), ".WAV")) {
      Serial.print("Now playing ");
      Serial.println(entry.name());
      // Play a short beep before each message
      waveform1.amplitude(beep_volume);
      wait(750);
      waveform1.amplitude(0);
      // Play the file
      playWav1.play(entry.name());
      mode = Mode::Playing; print_mode();
    }
    entry.close();

//    while (playWav1.isPlaying()) { // strangely enough, this works for playRaw, but it does not work properly for playWav
    while (!playWav1.isStopped()) { // this works for playWav
      buttonPlay.update();
      buttonRecord.update();
      // Button is pressed again
#if defined(HANDHELD_CLOSES_ON_LIFT)
      if(buttonPlay.fallingEdge() || buttonRecord.risingEdge())  
#else
      if(buttonPlay.fallingEdge() || buttonRecord.fallingEdge())  
#endif
      { 
        playWav1.stop();
        mode = Mode::Ready; print_mode();
        return;
      }   
    }
  }
  // All files have been played
  mode = Mode::Ready; print_mode();
}

void playLastRecording() { // 1
  // Find the first available file number
  uint16_t idx = 0; 
  for (uint16_t i=0; i<9999; i++) { // 2
    // Format the counter as a five-digit number with leading zeroes, followed by file extension
    snprintf(filename, 11, " %05d.wav", i);
    // check, if file with index i exists
    if (!SD.exists(filename)) { // 3
     idx = i - 1;
     break;
      } // 3
  } // 2
      // now play file with index idx == last recorded file
      snprintf(filename, 11, " %05d.wav", idx);
      Serial.println(filename);
      playWav1.play(filename);
      mode = Mode::Playing; print_mode();
      while (!playWav1.isStopped()) 
      { // 5 // this works for playWav
          buttonPlay.update();
          buttonRecord.update();
          // Button is pressed again
    #if defined(HANDHELD_CLOSES_ON_LIFT)
          if(buttonPlay.fallingEdge() || buttonRecord.risingEdge())  
    #else
          if(buttonPlay.fallingEdge() || buttonRecord.fallingEdge()) 
    #endif
          {
            playWav1.stop();
            mode = Mode::Ready; print_mode();
            return;
          }   //4
      } // 5 end while
      // file has been played
  mode = Mode::Ready; print_mode();  
  end_Beep();
} // 1 end playLastRecording


// Retrieve the current time from Teensy built-in RTC
time_t getTeensy3Time(){
  return Teensy3Clock.get();
}

// Callback to assign timestamps for file system operations
void dateTime(uint16_t* date, uint16_t* time, uint8_t* ms10) {

  // Return date using FS_DATE macro to format fields.
  *date = FS_DATE(year(), month(), day());

  // Return time using FS_TIME macro to format fields.
  *time = FS_TIME(hour(), minute(), second());

  // Return low time bits in units of 10 ms.
  *ms10 = second() & 1 ? 100 : 0;
}

// Non-blocking delay, which pauses execution of main program logic,
// but while still listening for input 
void wait(unsigned int milliseconds) {
  elapsedMillis msec=0;

  while (msec <= milliseconds) {
    buttonRecord.update();
    buttonPlay.update();
    if (buttonRecord.fallingEdge()) Serial.println("Button (pin 0) Press");
    if (buttonPlay.fallingEdge()) Serial.println("Button (pin 1) Press");
    if (buttonRecord.risingEdge()) Serial.println("Button (pin 0) Release");
    if (buttonPlay.risingEdge()) Serial.println("Button (pin 1) Release");
  }
}


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();
  Serial.println("header written"); 
  Serial.print("Subchunk2: "); 
  Serial.println(Subchunk2Size); 
}

void end_Beep(void) {
        waveform1.frequency(523.25);
        waveform1.amplitude(beep_volume);
        wait(250);
        waveform1.amplitude(0);
        wait(250);
        waveform1.amplitude(beep_volume);
        wait(250);
        waveform1.amplitude(0);
        wait(250);
        waveform1.amplitude(beep_volume);
        wait(250);
        waveform1.amplitude(0);
        wait(250);
        waveform1.amplitude(beep_volume);
        wait(250);
        waveform1.amplitude(0);
}

void two_tone_Beep(void) {
        waveform1.frequency(523.25);
        waveform1.amplitude(beep_volume);
        wait(250);
        waveform1.amplitude(0);
        waveform1.frequency(375.0);
        wait(250);
        waveform1.amplitude(beep_volume);
        wait(250);
        waveform1.amplitude(0);
        waveform1.frequency(523.25);
        wait(250);
        waveform1.amplitude(beep_volume);
        wait(250);
        waveform1.amplitude(0);
        waveform1.frequency(375.0);
        wait(250);
        waveform1.amplitude(beep_volume);
        wait(250);
        waveform1.amplitude(0);
}

void print_mode(void) { // only for debugging
  Serial.print("Mode switched to: ");
  // Initialising, Ready, Prompting, Recording, Playing
  if(mode == Mode::Ready)           Serial.println(" Ready");
  else if(mode == Mode::Prompting)  Serial.println(" Prompting");
  else if(mode == Mode::Recording)  Serial.println(" Recording");
  else if(mode == Mode::Playing)    Serial.println(" Playing");
  else if(mode == Mode::Initialising)  Serial.println(" Initialising");
  else if(mode == Mode::Recording_Greeting)  Serial.println(" Recording Greeting");
  else Serial.println(" Undefined");
}
 
I badly need help. I followed all the steps and connected everything. Copy pasted the code (removed Teensy 4.1 part as I am using 4.0), compiled successfully, then nothing. Not even a beep.

Checked the serial monitor and it says "Unable to access the SD card" repeatedly. I understand that this is a printed message to check if there is an SD card. I don't know why it is stuck in this loop.

To check my SD Card, i ran File > Examples > MTP_Teensy > Simplified Examples. My SD card got detected but 0 gb. Not sure if this is purely an SD card problem but at least I should hear a beep, correct?
 
Follow up on issue

Hi Ujjal, I have a similar problem. If I count from 1-20, I only record every other number, so the recording is not continuous. Can I ask if you were able to fix the issue and how did you fix it?
 
Last edited:
Back
Top