Monitoring voice while recording it

letNic

Member
Hi everyone,

I’m in the last phase of a project: a stand-alone old rotary phone that acts as a direct voice message answer machine when you lift the line. I use the Teensy 3.6 with the Audio Shield. All messages are recorded on an MicroSD card.

It work very well, but to get some improvements and realism, it would be great that the user could hear his voice while leaving his message. Without this, it looks that he’s not “live” and maybe his message wasn’t recorded. This audio feedback (not a Larsen, but a witness) is very important, based on some users comments I had with my proto.

I thought it was a special mixer configurations, or maybe just a “physical” thing to do with the electronics on the board.

What do you think?

Thanks for your help.
 
Just want to add that I will post my code! I’m just presently on my cellphone and can’t access to the files on my computer.

I also have photos of the project, but the forum interface give me errors when I try to upload them.
 
Ok, here's my code, as you can see, it's a blend of multiple codes I found, thanks to generous predecessor coders:
Code:
//===============================================================
//------------------- VoxPHONE PROTO - 018 ----------------------
//---------------------- 2018 - 02 - 07 -------------------------
//===============================================================

#include <Bounce.h>
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SD_t3.h>
#include <SerialFlash.h>
#include <Time.h>
#include <TimeLib.h>

// write wav
unsigned long ChunkSize = 0L;
unsigned long Subchunk1Size = 16;
unsigned int AudioFormat = 1;
unsigned int numChannels = 1;
unsigned long sampleRate = 44100;
unsigned int bitsPerSample = 16;
unsigned long byteRate = sampleRate * numChannels * (bitsPerSample / 8); // samplerate x channels x (bitspersample / 8)
unsigned int blockAlign = numChannels * bitsPerSample / 8;
unsigned long Subchunk2Size = 0L;
unsigned long recByteSaved = 0L;
unsigned long NumSamples = 0L;
byte byte1, byte2, byte3, byte4;

// Audio input on Teensy
const int myInput = AUDIO_INPUT_MIC;


// GUItool: begin automatically generated code
AudioPlaySdWav           playSdWav1;     //xy=235,318
AudioSynthWaveform       waveform1;      //xy=233,360
AudioInputI2S            i2s2;           //xy=188,136
AudioOutputI2S           i2s1;           //xy=658,347
AudioRecordQueue         queue1;         //xy=411,93
AudioAnalyzePeak         peak1;          //xy=413,178
AudioConnection          patchCord1(i2s2, 0, queue1, 0);
AudioConnection          patchCord2(i2s2, 0, peak1, 0);
AudioConnection          patchCord3(waveform1, 0, i2s1, 0);
AudioConnection          patchCord4(waveform1, 0, i2s1, 1);
AudioConnection          patchCord5(playSdWav1, 0, i2s1, 0);
AudioConnection          patchCord6(playSdWav1, 1, i2s1, 1);
AudioControlSGTL5000     audioShield;     //xy=103,62
// GUItool: end automatically generated code

///const int HOME_MSG = "HOME/ACCU.WAV";

// Use these with the Teensy 3.5 & 3.6 SD card
#define SDCARD_CS_PIN    BUILTIN_SDCARD
#define SDCARD_MOSI_PIN  11  // not actually used
#define SDCARD_SCK_PIN   13  // not actually used

#define    b1Pin       0
//#define    b1ON        digitalWrite(b1Pin,HIGH)
//#define    b1OFF       digitalWrite(b1Pin,LOW)
#define    b2Pin       1
//#define    b2ON        digitalWrite(b2Pin,HIGH)
//#define    b2OFF       digitalWrite(b2Pin,LOW)
#define    vPin        2
#define    vLedON      digitalWrite(vPin,HIGH)
#define    vLedOFF     digitalWrite(vPin,LOW)
#define    rPin        3
#define    rLedON      digitalWrite(rPin,HIGH)
#define    rLedOFF     digitalWrite(rPin,LOW)
#define    aPin        4
#define    aLedON      digitalWrite(aPin,HIGH)
#define    aLedOFF     digitalWrite(aPin,LOW)

// Bounce objects to easily and reliably read the buttons
Bounce lineUpButton = Bounce(b1Pin, 12);
Bounce lineDownButton = Bounce(b2Pin, 12);

// Variables globales
int mode = 0;  // 0=Stby, 1=homeMsg, 2=beep1, 3=recording, 4=beep2, 5=stopAll
int line; // 0=Down, 1=Up

// Timers
elapsedMillis recTime;
elapsedMillis UpTime;
elapsedMillis AlertTime;

// The file where data is recorded
File frec;


//===============================================================
//===============================================================
//===============================================================

void setup() {
  Serial.begin(9600);
  AudioMemory(60);
  pinMode(b1Pin, INPUT_PULLUP);
  pinMode(b2Pin, INPUT_PULLUP);
  pinMode(vPin, OUTPUT);
  pinMode(rPin, OUTPUT);
  pinMode(aPin, OUTPUT);
  audioShield.enable();
  audioShield.inputSelect(myInput);
  audioShield.micGain(10);  //0-63
  audioShield.volume(0.6);
  waveform1.begin(WAVEFORM_SINE);
  aLedON;
  SPI.setMOSI(SDCARD_MOSI_PIN);
  SPI.setSCK(SDCARD_SCK_PIN);
  if (!(SD.begin(SDCARD_CS_PIN))) {
    while (1) {
      Serial.println("Unable to access the SD card");
      rLedON;
      vLedOFF;
      delay(500);
      rLedOFF;
      vLedON;
      delay(500);
    }
  }
  vLedON;
  Serial.println("Bienvenue dans VoxPHONE");
  delay(500);
  Serial.println("VoxPHONE en Stand by");
  delay(1000);
}

void loop() {
  lineDownButton.update();
  if (lineDownButton.fallingEdge()) {
    line = 0;
    Serial.println("La ligne est fermee");
    //Serial.println(line);
    stopAll();
  }
  lineUpButton.update();
  if (lineUpButton.fallingEdge()) {
    line = 1;
    Serial.println("La ligne est ouverte");
    //Serial.println(line);
    vLedOFF;
    rLedON;
    if (mode == 0) startHomeMsg();
  }
  if (line == 1) {
    if (mode == 1) continueHomeMsg();
    if (mode == 2) playBeepOne();
    if (mode == 3) recordUser();
    if (mode == 4) continueRecordUser();
    if (mode == 5) playBeepTwo();
    if (mode == 6) alert();
    if (mode == 8) alertLoop();
  }
  //  // read the knob position (analog input A1 ou 15) =========================== VOLUME GLOBAL
  //  int knob = analogRead(15);
  //  float vol = (float)knob / 1280.0;
  //  audioShield.volume(vol);
}





//===============================================================
//===============================================================
//===============================================================

void alert() { //================================================================ ALERT!
  lineDownButton.update();
  if (lineDownButton.fallingEdge()) {
    waveform1.amplitude(0);
    stopAll();
  } else {
    if (UpTime >= 5000) {
      Serial.println("Veuillez raccrocher");
      mode = 8;
      //      Serial.print("Mode = ");
      //      Serial.println(mode);
      waveform1.frequency(1320);
      waveform1.amplitude(0.1);
      delay(1000);
      AlertTime = 0;
    }
  }
}

void alertLoop() {
  if (AlertTime >= 15000) {
    waveform1.amplitude(0);
    rLedON;
    vLedON;
    line = 0;
    Serial.println("S.V.P. Veuillez raccrocher...");
  } else {
    waveform1.frequency(1000);
    waveform1.amplitude(0.1);
    rLedOFF;
    vLedON;
    delay(100);
    waveform1.amplitude(0);
    rLedON;
    vLedOFF;
    delay(100);
  }
}



void startHomeMsg() { //===================================================== HOME MSG
  delay(1000);
  Serial.println("Message d\'accueil");
  playSdWav1.play("HOME/ACCU.WAV");
  mode = 1;
  //  Serial.print("Mode = ");
  //  Serial.println(mode);
  delay(10); // wait for library to parse WAV info
}

void continueHomeMsg() {
  if (playSdWav1.isPlaying() == 0) {
    playSdWav1.stop();
    //Serial.println("Fin du message d\'accueil");
    mode = 2;
    //    Serial.print("Mode = ");
    //    Serial.println(mode);
  }
}

void stopHomeMsg() {
  //Serial.println("Arret du message d\'accueil");
  if (mode == 1) playSdWav1.stop();
}


void playBeepOne() { //===================================================== BEEP 1
  lineDownButton.update();
  if (lineDownButton.fallingEdge()) {
    stopAll();
  } else {
    //Serial.println("Beep 1");
    waveform1.frequency(880);
    waveform1.amplitude(0.1);
    delay(1000);
    waveform1.amplitude(0);
    mode = 3;
    //    Serial.print("Mode = ");
    //    Serial.println(mode);
  }
}


void recordUser() { //===================================================== RECORD
  Serial.println("Enregistrement du message");
  if (SD.exists("RECORD.WAV")) {
    SD.remove("RECORD.WAV");
  }
  frec = SD.open("RECORD.WAV", FILE_WRITE);
  if (frec) {
    queue1.begin();
    recTime = 0;
    mode = 4;
    //    Serial.print("Mode = ");
    //    Serial.println(mode);
    recByteSaved = 0L;
  }
}

void continueRecordUser() {
  if (recTime  >= 5000) {
    stopRecording();
  } else {
    if (queue1.available() >= 2) {
      byte buffer[512];
      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() {
  Serial.println("Fin de l\'enregistrement");
  queue1.end();
  if (mode == 4) {
    while (queue1.available() > 0) {
      frec.write((byte*)queue1.readBuffer(), 256);
      queue1.freeBuffer();
      recByteSaved += 256;
    }
    writeOutHeader();
    frec.close();
  }
  mode = 5;
  //  Serial.print("Mode = ");
  //  Serial.println(mode);
}

void playBeepTwo() { //===================================================== BEEP 2
  lineDownButton.update();
  if (lineDownButton.fallingEdge()) {
    stopAll();
  } else {
    //Serial.println("Beep 2");
    waveform1.frequency(880);
    waveform1.amplitude(0.1);
    delay(1000);
    waveform1.frequency(440);
    delay(125);
    waveform1.frequency(220);
    delay(500);
    waveform1.amplitude(0);
    mode = 6;
    //    Serial.print("Mode = ");
    //    Serial.println(mode);
    UpTime = 0;
  }
}

void stopAll() { //===================================================== STOP-ALL
  if (mode == 1) playSdWav1.stop();
  if ((mode == 3) | (mode == 4)) stopRecording();
  if ((mode == 2) | (mode == 5)) waveform1.amplitude(0);
  rLedOFF;
  vLedON;
  mode = 0;
  //  Serial.print("Mode = ");
  //  Serial.println(mode);
  //  Serial.println("All reset");
  Serial.println("VoxPHONE en Stand by");
}




//===================================================== RAW TO WAV

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);
}


//=====================================================
//===================== TODOS =========================
//=====================================================
/*

  - Indexer les fichiers enregistres

  √ - Traduire en WAV les enregistrements RAW

  - Bouton On/Off ext

  - Bouton reset ext

  - Potentiometre de volume ext

*/
 
And here's some photos...
IMG_4862.JPG

IMG_4864.jpg

IMG_4866.JPG
 
So to return to my question, I'd like the user to hear his voice in the phone speaker when he leave his message. It already can record the voice from the phone mic, no problem.

I thought I could maybe inspire my code with Synth examples where if you want to record your play, you should hear it at the same time. Not sure where to find that kind of example though.

But in my case, it is audio input from the phone mic.

Any ideas?
 
I would do it in analog with a headphone amplifier chip to avoid any latency. Otherwise you should be able to pass the input to the output.

BUT you have to have a mixer to combine with any playback as you're not supposed to use more than one signal at on input in the audio design tool.

(Play from 12:45 of the audio tutorial video to hear Paul tell you this!)

It looks like you didn't use a mixer for your two existing sources in your code. Surprised that works.
 
Wow, that's a really nice looking build.

Would it be ok with you if we showed this on the website, when you've got it finished?
 
Thanks Oddson, it worked perfectly! I also added a if term to open and close the Mixer volume when line is open or close.

It give now avery realistic feeling!!
 
Oh! Sure Paul, I’d be honored.

I have photos for pretty all steps and tonight we will mount the phone to its cabin which is have a funny ‘70 design.

My code changed also, so I’ll post the latest version here too.

Thanks again!!
 
Hi Paul,

Here's the latest version of the code and other photos including when it was installed yesterday. It still not finished though, many amelioration to do, but public had started to try the proto and they loved the concept..

Thanks for your interest :)

Code:
//===============================================================
//------------------- VoxPHONE PROTO - 021 ----------------------
//---------------------- 2018 - 02 - 09 -------------------------
//--------------------- NICOLAS__LETARTE ------------------------
//===============================================================

#include <Bounce.h>
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SD_t3.h>
#include <SerialFlash.h>
//#include <Time.h>
//#include <TimeLib.h>

// write wav
unsigned long ChunkSize = 0L;
unsigned long Subchunk1Size = 16;
unsigned int AudioFormat = 1;
unsigned int numChannels = 1;
unsigned long sampleRate = 44100;
unsigned int bitsPerSample = 16;
unsigned long byteRate = sampleRate * numChannels * (bitsPerSample / 8); // samplerate x channels x (bitspersample / 8)
unsigned int blockAlign = numChannels * bitsPerSample / 8;
unsigned long Subchunk2Size = 0L;
unsigned long recByteSaved = 0L;
unsigned long NumSamples = 0L;
byte byte1, byte2, byte3, byte4;

// Audio input on Teensy
const int myInput = AUDIO_INPUT_MIC;


// GUItool: begin automatically generated code
AudioInputI2S            i2s2;           //xy=188,136
AudioSynthWaveform       waveform1;      //xy=233,360
AudioPlaySdWav           playSdWav1;     //xy=235,318
AudioMixer4              mixer1;         //xy=398,343
AudioRecordQueue         queue1;         //xy=411,93
AudioAnalyzePeak         peak1;          //xy=413,178
AudioOutputI2S           i2s1;           //xy=658,347
AudioConnection          patchCord1(i2s2, 0, queue1, 0);
AudioConnection          patchCord2(i2s2, 0, peak1, 0);
AudioConnection          patchCord6(i2s2, 0, mixer1, 1);
AudioConnection          patchCord3(waveform1, 0, mixer1, 2);
AudioConnection          patchCord4(waveform1, 0, mixer1, 3);
AudioConnection          patchCord5(playSdWav1, 0, mixer1, 0);
//AudioConnection          patchCord6(playSdWav1, 1, mixer1, 1);
AudioConnection          patchCord7(mixer1, 0, i2s1, 0);
AudioConnection          patchCord8(mixer1, 0, i2s1, 1);
AudioControlSGTL5000     audioShield;     //xy=103,62
// GUItool: end automatically generated code

///const int HOME_MSG = "HOME/ACCU.WAV";

// Use these with the Teensy 3.5 & 3.6 SD card
#define SDCARD_CS_PIN    BUILTIN_SDCARD
#define SDCARD_MOSI_PIN  11  // not actually used
#define SDCARD_SCK_PIN   13  // not actually used

#define    b1Pin       0
//#define    b1ON        digitalWrite(b1Pin,HIGH)
//#define    b1OFF       digitalWrite(b1Pin,LOW)
#define    b2Pin       1
//#define    b2ON        digitalWrite(b2Pin,HIGH)
//#define    b2OFF       digitalWrite(b2Pin,LOW)
#define    vPin        2
#define    vLedON      digitalWrite(vPin,HIGH)
#define    vLedOFF     digitalWrite(vPin,LOW)
#define    rPin        3
#define    rLedON      digitalWrite(rPin,HIGH)
#define    rLedOFF     digitalWrite(rPin,LOW)
#define    aPin        4
#define    aLedON      digitalWrite(aPin,HIGH)
#define    aLedOFF     digitalWrite(aPin,LOW)

// Bounce objects to easily and reliably read the buttons
Bounce lineUpButton = Bounce(b1Pin, 12);
Bounce lineDownButton = Bounce(b2Pin, 12);

// Variables globales
int mode = 0;  // 0=Stby, 1=homeMsg, 2=beep1, 3=recording, 4=beep2, 5=stopAll
int line; // 0=Down, 1=Up

// Timers
elapsedMillis recTime;
elapsedMillis UpTime;
elapsedMillis AlertTime;

// The file where data is recorded
File frec;


//===============================================================
//===============================================================
//===============================================================

void setup() {
  Serial.begin(9600);
  AudioMemory(60);
  pinMode(b1Pin, INPUT_PULLUP);
  pinMode(b2Pin, INPUT_PULLUP);
  pinMode(vPin, OUTPUT);
  pinMode(rPin, OUTPUT);
  pinMode(aPin, OUTPUT);
  audioShield.enable();
  audioShield.inputSelect(myInput);
  audioShield.micGain(10);  //0-63
  audioShield.volume(0.6);
  mixer1.gain(0, 0.9); // Accueil
  mixer1.gain(1, 0.4); // Micro
  mixer1.gain(2, 0.4); // Synth L
  //  mixer1.gain(3, 0.4); // Synth R
  waveform1.begin(WAVEFORM_SINE);
  aLedON;
  SPI.setMOSI(SDCARD_MOSI_PIN);
  SPI.setSCK(SDCARD_SCK_PIN);
  if (!(SD.begin(SDCARD_CS_PIN))) {
    while (1) {
      Serial.println("Impossible d\'acceder à la carte SD");
      rLedON;
      vLedOFF;
      delay(500);
      rLedOFF;
      vLedON;
      delay(500);
    }
  }
  vLedON;
  Serial.println("Bienvenue dans VoxPHONE");
  delay(500);
  Serial.println("VoxPHONE en Stand by");
  delay(1000);
}

void loop() {
  lineDownButton.update();
  if (lineDownButton.fallingEdge()) {
    line = 0;
    audioShield.volume(0);
    Serial.println("La ligne est fermee");
    if (mode > 0) stopAll();
  }
  lineUpButton.update();
  if (lineUpButton.fallingEdge()) {
    line = 1;
    audioShield.volume(0.6);
    Serial.println("La ligne est ouverte");
    vLedOFF;
    rLedON;
    if (mode == 0) startHomeMsg();
  }
  if (line == 1) {
    if (mode == 1) continueHomeMsg();
    if (mode == 2) playBeepOne();
    if (mode == 3) recordUser();
    if (mode == 4) continueRecordUser();
    if (mode == 5) playBeepTwo();
    if (mode == 6) alert();
    if (mode == 8) alertLoop();
  }
  //  // read the knob position (analog input A1 ou 15) =========================== VOLUME GLOBAL
  //  int knob = analogRead(15);
  //  float vol = (float)knob / 1280.0;
  //  audioShield.volume(vol);
}





//=======================================================================================
//=======================================================================================
//=======================================================================================

void alert() { //================================================================ ALERT!
  lineDownButton.update();
  if (lineDownButton.fallingEdge()) {
    waveform1.amplitude(0);
    stopAll();
  } else {
    if (UpTime >= 10000) {
      Serial.println("Veuillez raccrocher");
      mode = 8;
      waveform1.frequency(1320);
      waveform1.amplitude(0.1);
      delay(1000);
      AlertTime = 0;
    }
  }
}

void alertLoop() {
  if (AlertTime >= 15000) {
    waveform1.amplitude(0);
    rLedON;
    vLedON;
    line = 0;
    Serial.println("S.V.P. Veuillez raccrocher...");
  } else {
    waveform1.frequency(1000);
    waveform1.amplitude(0.1);
    rLedOFF;
    vLedON;
    delay(100);
    waveform1.amplitude(0);
    rLedON;
    vLedOFF;
    delay(100);
  }
}


void startHomeMsg() { //===================================================== HOME MSG
  delay(1000);
  Serial.println("Message d\'accueil");
  playSdWav1.play("HOME/ACCU.WAV");
  mode = 1;
  delay(10); // wait for library to parse WAV info
}

void continueHomeMsg() {
  if (playSdWav1.isPlaying() == 0) {
    playSdWav1.stop();
    mode = 2;
  }
}

void stopHomeMsg() {
  if (mode == 1) playSdWav1.stop();
}


void playBeepOne() { //===================================================== BEEP 1
  lineDownButton.update();
  if (lineDownButton.fallingEdge()) {
    stopAll();
  } else {
    waveform1.frequency(880);
    waveform1.amplitude(0.1);
    delay(1000);
    waveform1.amplitude(0);
    mode = 3;
  }
}


void recordUser() { //===================================================== RECORD
  Serial.println("Enregistrement du message");
  String fileName = String();
  unsigned int filenumber = 1;
  while (!filenumber == 0) {
    fileName = "VP_";
    fileName += filenumber;
    fileName += ".WAV";
    char charFileName[fileName.length() + 1];
    fileName.toCharArray(charFileName, sizeof(charFileName));
    if (SD.exists(charFileName)) {
      filenumber++;
    }
    else {
      //File dataFile = SD.open(charFileName, FILE_WRITE);
      frec = SD.open(charFileName, FILE_WRITE);
      filenumber = 0;
    }
    //Serial.println("Nouveau fichier audio créé");
  }
  if (frec) {
    queue1.begin();
    recTime = 0;
    mode = 4;
    recByteSaved = 0L;
  }
}

void continueRecordUser() {
  if (recTime  >= 90000) { // 90000 ou 1:30
    stopRecording();
  } else {
    if (queue1.available() >= 2) {
      byte buffer[512];
      memcpy(buffer, queue1.readBuffer(), 256);
      queue1.freeBuffer();
      memcpy(buffer + 256, queue1.readBuffer(), 256);
      queue1.freeBuffer();
      //elapsedMicros usec = 0;
      // write all 512 bytes to the SD card
      frec.write(buffer, 512);
      //Serial.print("SD write, us=");
      //Serial.println(usec);
      recByteSaved += 512;
    }
  }
}

void stopRecording() {
  Serial.println("Fin de l\'enregistrement");
  queue1.end();
  if (mode == 4) {
    while (queue1.available() > 0) {
      frec.write((byte*)queue1.readBuffer(), 256);
      queue1.freeBuffer();
      recByteSaved += 256;
    }
    writeOutHeader();
    frec.close();
  }
  mode = 5;
}


void playBeepTwo() { //===================================================== BEEP 2
  lineDownButton.update();
  if (lineDownButton.fallingEdge()) {
    stopAll();
  } else {
    waveform1.frequency(880);
    waveform1.amplitude(0.1);
    delay(1000);
    waveform1.frequency(440);
    delay(125);
    waveform1.frequency(220);
    delay(500);
    waveform1.amplitude(0);
    mode = 6;
    UpTime = 0;
  }
}


void stopAll() { //====================================================================================== STOP-ALL
  if (mode == 1) playSdWav1.stop();
  if ((mode == 3) | (mode == 4)) stopRecording();
  if ((mode == 2) | (mode == 5)) waveform1.amplitude(0);
  rLedOFF;
  vLedON;
  mode = 0;
  Serial.println("VoxPHONE en Stand by");
}


void writeOutHeader() { //============================================== RAW TO WAV
  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);
}


//=====================================================
//===================== TODOS =========================
//=====================================================
/*

  √- Indexer les fichiers enregistres

  √ - Traduire en WAV les enregistrements RAW

  √- Connecteurs électriques slims + rallonger le fil

  - Bouton On/Off ext

  √- Bouton reset ext

  - Potentiometre de volume ext

  - LED différent lorsqu'un utilisateur enregistre son message

  - Pouvoir enregistrer le message d'accueil à même le VoxPhone

  - Pouvoir toujours détecter la présence de la carte SD !!!!!

  - Port Micro USB F 

*/

IMG_4859.JPG

IMG_4860.JPG

IMG_4920.JPG

IMG_4950.JPG

IMG_4951.jpg
 
Back
Top