Speech Recognition and Synthesis with Arduino

#include <BVSP.h>
#include <BVSMic.h>
#include <BVSSpeaker.h>
#include <DAC.h>

// Defines the Arduino pin that will be used to capture audio 
#define BVSM_AUDIO_INPUT 7

// Defines the LED pins
#define RED_LED_PIN 6
#define YELLOW_LED_PIN 9
#define GREEN_LED_PIN 10

// Defines the constants that will be passed as parameters to 
// the BVSP.begin function
const unsigned long STATUS_REQUEST_TIMEOUT = 3000;
const unsigned long STATUS_REQUEST_INTERVAL = 4000;

// Defines the size of the mic audio buffer 
const int MIC_BUFFER_SIZE = 64;

// Defines the size of the speaker audio buffer
const int SPEAKER_BUFFER_SIZE = 128;

// Defines the size of the receive buffer
const int RECEIVE_BUFFER_SIZE = 2;

// Initializes a new global instance of the BVSP class 
BVSP bvsp = BVSP();

// Initializes a new global instance of the BVSMic class 
BVSMic bvsm = BVSMic();

// Initializes a new global instance of the BVSSpeaker class 
BVSSpeaker bvss = BVSSpeaker();

// Creates a buffer that will be used to read recorded samples 
// from the BVSMic class 
byte micBuffer[MIC_BUFFER_SIZE];

// Creates a buffer that will be used to write audio samples 
// into the BVSSpeaker class 
byte speakerBuffer[SPEAKER_BUFFER_SIZE];

// Creates a buffer that will be used to read the commands sent
// from BitVoicer Server.
// Byte 0 = pin number
// Byte 1 = pin value
byte receiveBuffer[RECEIVE_BUFFER_SIZE];

// These variables are used to control when to play
// "LED Notes". These notes will be played along with 
// the song streamed from BitVoicer Server.
bool playLEDNotes = false;
unsigned int playStartTime = 0;

void setup() 
{
  // Sets up the pin modes
  pinMode(RED_LED_PIN, OUTPUT);
  pinMode(YELLOW_LED_PIN, OUTPUT);
  pinMode(GREEN_LED_PIN, OUTPUT);

  // Sets the initial state of all LEDs
  digitalWrite(RED_LED_PIN, LOW);
  digitalWrite(YELLOW_LED_PIN, LOW);
  digitalWrite(GREEN_LED_PIN, LOW);
  
  // Starts serial communication at 115200 bps 
  Serial.begin(115200); 
  
  // Sets the Arduino serial port that will be used for 
  // communication, how long it will take before a status request 
  // times out and how often status requests should be sent to 
  // BitVoicer Server. 
  bvsp.begin(Serial, STATUS_REQUEST_TIMEOUT, STATUS_REQUEST_INTERVAL);
    
  // Defines the function that will handle the frameReceived 
  // event 
  bvsp.frameReceived = BVSP_frameReceived;

  // Sets the function that will handle the modeChanged 
  // event 
  bvsp.modeChanged = BVSP_modeChanged; 
  
  // Sets the function that will handle the streamReceived 
  // event 
  bvsp.streamReceived = BVSP_streamReceived;
  
  // Prepares the BVSMic class timer 
  bvsm.begin();

  // Sets the DAC that will be used by the BVSSpeaker class 
  bvss.begin(DAC);
}

void loop() 
{
  // Checks if the status request interval has elapsed and if it 
  // has, sends a status request to BitVoicer Server 
  bvsp.keepAlive();
  
  // Checks if there is data available at the serial port buffer 
  // and processes its content according to the specifications 
  // of the BitVoicer Server Protocol 
  bvsp.receive();

  // Checks if there is one SRE available. If there is one, 
  // starts recording.
  if (bvsp.isSREAvailable()) 
  {
    // If the BVSMic class is not recording, sets up the audio 
    // input and starts recording 
    if (!bvsm.isRecording)
    {
      bvsm.setAudioInput(BVSM_AUDIO_INPUT, DEFAULT); 
      bvsm.startRecording();
    }

    // Checks if the BVSMic class has available samples 
    if (bvsm.available)
    {
      // Makes sure the inbound mode is STREAM_MODE before 
      // transmitting the stream
      if (bvsp.inboundMode == FRAMED_MODE)
        bvsp.setInboundMode(STREAM_MODE); 
        
      // Reads the audio samples from the BVSMic class
      int bytesRead = bvsm.read(micBuffer, MIC_BUFFER_SIZE);
      
      // Sends the audio stream to BitVoicer Server
      bvsp.sendStream(micBuffer, bytesRead);
    }
  }
  else
  {
    // No SRE is available. If the BVSMic class is recording, 
    // stops it.
    if (bvsm.isRecording)
      bvsm.stopRecording();
  }

  // Plays all audio samples available in the BVSSpeaker class
  // internal buffer. These samples are written in the 
  // BVSP_streamReceived event handler. If no samples are 
  // available in the internal buffer, nothing is played.
  bvss.play();

  // If playLEDNotes has been set to true, 
  // plays the "LED notes" along with the music.
  if (playLEDNotes)
    playNextLEDNote();
}

// Handles the frameReceived event 
void BVSP_frameReceived(byte dataType, int payloadSize) 
{
  // Checks if the received frame contains binary data
  // 0x07 = Binary data (byte array)
  if (dataType == DATA_TYPE_BINARY)
  {
    // If 2 bytes were received, process the command.
    if (bvsp.getReceivedBytes(receiveBuffer, RECEIVE_BUFFER_SIZE) == 
      RECEIVE_BUFFER_SIZE)
    {
      analogWrite(receiveBuffer[0], receiveBuffer[1]);
    }
  }
  // Checks if the received frame contains byte data type
  // 0x01 = Byte data type
  else if (dataType == DATA_TYPE_BYTE)
  {   
    // If the received byte value is 255, sets playLEDNotes
    // and marks the current time.
    if (bvsp.getReceivedByte() == 255)
    {
      playLEDNotes = true;
      playStartTime = millis();
    }
  }
}

// Handles the modeChanged event 
void BVSP_modeChanged() 
{ 
  // If the outboundMode (Server --> Device) has turned to 
  // FRAMED_MODE, no audio stream is supposed to be received. 
  // Tells the BVSSpeaker class to finish playing when its 
  // internal buffer become empty. 
  if (bvsp.outboundMode == FRAMED_MODE)
    bvss.finishPlaying();
} 

// Handles the streamReceived event 
void BVSP_streamReceived(int size) 
{ 
  // Gets the received stream from the BVSP class 
  int bytesRead = bvsp.getReceivedStream(speakerBuffer, 
    SPEAKER_BUFFER_SIZE); 
    
  // Enqueues the received stream to play
  bvss.enqueue(speakerBuffer, bytesRead);
}

// Lights up the appropriate LED based on the time 
// the command to start playing LED notes was received.
// The timings used here are syncronized with the music.
void playNextLEDNote()
{
  // Gets the elapsed time between playStartTime and the 
  // current time.
  unsigned long elapsed = millis() - playStartTime;

  // Turns off all LEDs
  allLEDsOff();

  // The last note has been played.
  // Turns off the last LED and stops playing LED notes.
  if (elapsed >= 11500)
  {
    analogWrite(RED_LED_PIN, 0);
    playLEDNotes = false;
  }
  else if (elapsed >= 9900)
    analogWrite(RED_LED_PIN, 255); // C note
  else if (elapsed >= 9370)
    analogWrite(RED_LED_PIN, 255); // C note
  else if (elapsed >= 8900)
    analogWrite(YELLOW_LED_PIN, 255); // D note
  else if (elapsed >= 8610)
    analogWrite(RED_LED_PIN, 255); // C note
  else if (elapsed >= 8230)
    analogWrite(YELLOW_LED_PIN, 255); // D note
  else if (elapsed >= 7970)
    analogWrite(YELLOW_LED_PIN, 255); // D note
  else if (elapsed >= 7470)
    analogWrite(RED_LED_PIN, 255); // C note
  else if (elapsed >= 6760)
    analogWrite(GREEN_LED_PIN, 255); // E note
  else if (elapsed >= 6350)
    analogWrite(RED_LED_PIN, 255); // C note
  else if (elapsed >= 5880)
    analogWrite(YELLOW_LED_PIN, 255); // D note
  else if (elapsed >= 5560)
    analogWrite(RED_LED_PIN, 255); // C note
  else if (elapsed >= 5180)
    analogWrite(YELLOW_LED_PIN, 255); // D note
  else if (elapsed >= 4890)
    analogWrite(YELLOW_LED_PIN, 255); // D note
  else if (elapsed >= 4420)
    analogWrite(RED_LED_PIN, 255); // C note
  else if (elapsed >= 3810)
    analogWrite(GREEN_LED_PIN, 255); // E note
  else if (elapsed >= 3420)
    analogWrite(RED_LED_PIN, 255); // C note
  else if (elapsed >= 2930)
    analogWrite(YELLOW_LED_PIN, 255); // D note
  else if (elapsed >= 2560)
    analogWrite(RED_LED_PIN, 255); // C note
  else if (elapsed >= 2200)
    analogWrite(YELLOW_LED_PIN, 255); // D note
  else if (elapsed >= 1930)
    analogWrite(YELLOW_LED_PIN, 255); // D note
  else if (elapsed >= 1470)
    analogWrite(RED_LED_PIN, 255); // C note
  else if (elapsed >= 1000)
    analogWrite(GREEN_LED_PIN, 255); // E note
}

// Turns off all LEDs.
void allLEDsOff()
{
  analogWrite(RED_LED_PIN, 0);
  analogWrite(YELLOW_LED_PIN, 0);
  analogWrite(GREEN_LED_PIN, 0);
}


BVS_Demo2.ino