Teensy 4.0 - based Audio Guestbook

i tried your code but it doesn't compile. i get errors for the playwav1 file.

Arduino: 1.8.19 (Windows 10), TD: 1.57, Board: "Teensy 4.0, Serial + MTP Disk (Experimental), 150 MHz, Faster, US English, Bigger blocks (256 samples)"





















C:\Users\Tripz\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:49:1: error: 'AudioPlaySdWavX' does not name a type

AudioPlaySdWavX playWav1; // Play 44.1kHz 16-bit PCM greeting WAV file

^

C:\Users\Tripz\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:54:28: error: 'playWav1' was not declared in this scope

AudioConnection patchCord3(playWav1, 0, mixer, 1); // wav file playback mixer

^

C:\Users\Tripz\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino: In function 'void loop()':

C:\Users\Tripz\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:185:7: error: 'playWav1' was not declared in this scope

playWav1.play("greeting.wav");

^

C:\Users\Tripz\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino: In function 'void playAllRecordings()':

C:\Users\Tripz\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:374:7: error: 'playWav1' was not declared in this scope

playWav1.play(entry.name());

^

C:\Users\Tripz\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:380:13: error: 'playWav1' was not declared in this scope

while (!playWav1.isStopped()) { // this works for playWav

^

C:\Users\Tripz\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino: In function 'void playLastRecording()':

C:\Users\Tripz\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:411:7: error: 'playWav1' was not declared in this scope

playWav1.play(filename);

^

Error compiling for board Teensy 4.0.



This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

have you got a wav file on the sd card ???? i'm using a t4 with the Rev D audio shield make sure you are using a data type cable as i had same error compiling board for teensy and it was the cable first cable was only 2 wires not 5
 
Hi Guys, no one else has a similar clicking noise problem? I can't figure it out and I'm running out of time, I want to give the phone as a gift. Any ideas would be much appreciated! Thx
View attachment 30333

Hi All! I still have a clicking sound, I've tried everything. Anyone have any tips on how to fix it?
T4.0, A1 SDHC 32gb micros, original repo with "256-sample audio blocks tweak"
Thank you very much!
View attachment 30333
 
to increase the mic volume i changed this code values
Code:
    // Value in dB
//  sgtl5000_1.micGain([COLOR="#FF0000"]100[/COLOR]);
  sgtl5000_1.micGain([COLOR="#FF0000"]35[/COLOR]); // much lower gain is required for the AOM5024 electret capsule

my value made the mic much louder but did not get any clicking

the original value was
Code:
    // Value in dB
//  sgtl5000_1.micGain([COLOR="#FF0000"]15[/COLOR]);
  sgtl5000_1.micGain([COLOR="#FF0000"]5[/COLOR]); // much lower gain is required for the AOM5024 electret capsule
 
no, i don't have the wav file on my sd card. the code i was using allowed me to record a greeting from the first pick up. i'll try a different USB cable as well and see if that gets me anywhere
 
anyone with any update on this? or anyone who successfully was able to accomplish this will to sell me a pre-programmed teensy? i can trade back a brand new teensy 4 since i ordered 2.
 
i tried your code but it doesn't compile. i get errors for the playwav1 file.

Arduino: 1.8.19 (Windows 10), TD: 1.57, Board: "Teensy 4.0, Serial + MTP Disk (Experimental), 150 MHz, Faster, US English, Bigger blocks (256 samples)"





















C:\Users\Tripz\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:49:1: error: 'AudioPlaySdWavX' does not name a type

AudioPlaySdWavX playWav1; // Play 44.1kHz 16-bit PCM greeting WAV file

^

C:\Users\Tripz\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:54:28: error: 'playWav1' was not declared in this scope

AudioConnection patchCord3(playWav1, 0, mixer, 1); // wav file playback mixer

^

C:\Users\Tripz\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino: In function 'void loop()':

C:\Users\Tripz\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:185:7: error: 'playWav1' was not declared in this scope

playWav1.play("greeting.wav");

^

C:\Users\Tripz\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino: In function 'void playAllRecordings()':

C:\Users\Tripz\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:374:7: error: 'playWav1' was not declared in this scope

playWav1.play(entry.name());

^

C:\Users\Tripz\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:380:13: error: 'playWav1' was not declared in this scope

while (!playWav1.isStopped()) { // this works for playWav

^

C:\Users\Tripz\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino: In function 'void playLastRecording()':

C:\Users\Tripz\Downloads\audio-guestbook-main\audio-guestbook-main\audio-guestbook\audio-guestbook.ino:411:7: error: 'playWav1' was not declared in this scope

playWav1.play(filename);

^

Error compiling for board Teensy 4.0.



This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

Did you get any help ? I'm stuck at the same place than you !
 
My serial monitor displays this :

Serial set up correctly
Mode switched to: Initialising
Button (pin 0) Release
Button (pin 1) Release
SD card correctly initialized
Add **SDClass** file system
Added SD card via MTP
Mode switched to: Ready
&&&&& Dump MTPStorage Loop Data &&&&&
Callback Data: 0 0x0 0
1 0xd059 1
2 0x0 0
3 0x0 0
4 0x0 0
File Systems:
0 0x200039c8 1

Hello there, I get similar lines on my serial monitor and I'm stuck here.

well, I finally made it !!!
Changed a couple of things in the code that I completely missed and now I see action the serial monitor and see the wav files in the card.
I can't hear anything so far, neither the greeting or the recorded message, but I guess that should be an easy fix compared to the code errors, at least in your first phone.

May I ask how did you managed to fix it and get it working? Thanks!
 
i actually was able to get it to work!!! record my greeting message AND record messages after that. using the original code i posted. i realized some pins were set for a teensy 4.1. i have a 4.0.... i kind of was just staring at the code, contemplating hanging myself with the phone cord when i noticed: hook pin 40 and button pin 41. and i was like wait... WHAT?! on the 4.0 its supposed to be 0 and 1... after i made those changes..... IT WORKED!!!! not 100% but i'm at like 95%.... something is still wrong because its seeing my hook switch like a button where when i pick up. i can record. but then when i hang up, i thinks i'm pressing it again because i can hear the greeting being played again through the earpiece lol. so i have to go through the coding to look for something that fixes that. from the original coding this was rising edge and falling edge.... i'm assuming somewhere it says something like button push, instead. im so close!!! LOL hope this helps someone else!!!

for reference, the code i'm using it from https://github.com/DD4WH/audio-guestbook
 
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:
 * [url]https://github.com/DD4WH/audio-guestbook/blob/main/README.md[/url]
 * 
 * 
 *   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/"): [url]https://github.com/KurtE/MTP_Teensy[/url]
 *   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 ([url]https://github.com/KurtE/MTP_Teensy[/url])
// 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 0
#define PLAYBACK_BUTTON_PIN 1
//#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 [url]https://www.pjrc.com/teensy/gui/[/url]
// 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, 0);
Bounce buttonPlay = Bounce(PLAYBACK_BUTTON_PIN, 1);

// 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, "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(10); // 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 [url]https://github.com/PaulStoffregen/Time[/url]
  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");
}


seems to be working for me now... i have 1 problem i think, and its if i hang up before the leave a message beep. serial output recognized button push but not "hang up" so it doesn't stop the recording. so it would hang up the phone, the greeting would finish, then beep, then it would just record until the handset is lifted and hung up again.
 
Last edited:
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-guest...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 0
#define PLAYBACK_BUTTON_PIN 1
//#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, 0);
Bounce buttonPlay = Bounce(PLAYBACK_BUTTON_PIN, 1);

// 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, "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(10); // 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");
}
seems to be working for me now... i have 1 problem i think, and its if i hang up before the leave a message beep. serial output recognized button push but not "hang up" so it doesn't stop the recording. so it would hang up the phone, the greeting would finish, then beep, then it would just record until the handset is lifted and hung up again.
When you post code again can you post it between CODE tags (as I have done above) using the # button above.
 
I have been able to get everything working in theory but the audio through the speaker is so low that it can barely be heard in a quiet environment. What am I missing here?
 
Not sure... mine is actually so loud that u can hear it while the handset it down. Haven't tested in a loud environment but it's loud when it's up against your ear for me. I'm also using a new "retro style" phone from amazon.
 
Not sure... mine is actually so loud that u can hear it while the handset it down. Haven't tested in a loud environment but it's loud when it's up against your ear for me. I'm also using a new "retro style" phone from amazon.

Interesting. I am also using a retro phone from amazon. Did you adjust any of the audio settings in the code?
 
No, nothing. I just increased the mic volume but 2 so the recordings are a little louder. It's in the code I pasted.

I'll try your code just to see. Do you mind sharing the link of the phone you are using? This actually may be my issue as the quality seems to be lacking. I am going to try a different phone to check on this.
 
i actually was able to get it to work!!! record my greeting message AND record messages after that. using the original code i posted. i realized some pins were set for a teensy 4.1. i have a 4.0.... i kind of was just staring at the code, contemplating hanging myself with the phone cord when i noticed: hook pin 40 and button pin 41. and i was like wait... WHAT?! on the 4.0 its supposed to be 0 and 1... after i made those changes..... IT WORKED!!!! not 100% but i'm at like 95%.... something is still wrong because its seeing my hook switch like a button where when i pick up. i can record. but then when i hang up, i thinks i'm pressing it again because i can hear the greeting being played again through the earpiece lol. so i have to go through the coding to look for something that fixes that. from the original coding this was rising edge and falling edge.... i'm assuming somewhere it says something like button push, instead. im so close!!! LOL hope this helps someone else!!!

for reference, the code i'm using it from https://github.com/DD4WH/audio-guestbook

Your problem is most likely that you have changed the hook switch button from 40 to 0 and 1. I almost made this mistake as well thinking I had to change this since I was using a 4.0 not a 4.1.

You have this:

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

But should have this:

Code:
// Use long 40ms debounce time on both switches
Bounce buttonRecord = Bounce(HOOK_PIN, 40);
Bounce buttonPlay = Bounce(PLAYBACK_BUTTON_PIN, 40);
 
No. My code is correct now. I am in fact using pins 0 and 1. 0 for the hook switch, 1 for the playback button switch. Everything is properly working after I made the change.
 
Same thing here, nothing was working, and no wonder why, pins were incorrect.
Now I can hear the greeting I uploaded, I get the recorded wav files in the SD, I can play them them in the computer but I don't hear any audio , so I'm guessing my mic is not working or it's wired incorrectly. Ordered a couple of new mics to see if I can switch them.

i actually was able to get it to work!!! record my greeting message AND record messages after that. using the original code i posted. i realized some pins were set for a teensy 4.1. i have a 4.0.... i kind of was just staring at the code, contemplating hanging myself with the phone cord when i noticed: hook pin 40 and button pin 41. and i was like wait... WHAT?! on the 4.0 its supposed to be 0 and 1... after i made those changes..... IT WORKED!!!! not 100% but i'm at like 95%.... something is still wrong because its seeing my hook switch like a button where when i pick up. i can record. but then when i hang up, i thinks i'm pressing it again because i can hear the greeting being played again through the earpiece lol. so i have to go through the coding to look for something that fixes that. from the original coding this was rising edge and falling edge.... i'm assuming somewhere it says something like button push, instead. im so close!!! LOL hope this helps someone else!!!

for reference, the code i'm using it from https://github.com/DD4WH/audio-guestbook
 
Ok so I think I have a weird problem now. When plugged into the computer, with the serial monitor open, everything is working perfectly. Meaning, pick up the phone, hear the greeting, leave a message. Hang up. It records. Pick up, hit the playback button while the greeting is on, it plays all the messages, I can hang up any time and it goes back to ready and I can pick up again and leave another message. Here's the problem. When I use an external power source, battery pack or wall wart, I can NOT use the playback button. It messes everything up. Everything works perfect until I hit the playback button. When I hang up it doesn't register that it's hung up so if I pick back up it doesn't record till I hang back up again and then it's recording while "hung up." Whay the hell?! Anyone have any ideas???
 
Back
Top