From 804aa7f4f67fb0d3f5955626cdfea50107e7c8a5 Mon Sep 17 00:00:00 2001
From: DarkSlein <slava982007@gmail.com>
Date: Tue, 11 Jun 2024 19:41:52 +0300
Subject: [PATCH] Divided into strategies

---
 src/domain/AidStrategy copy.cpp.1 | 125 ++++++++++++++++++++++++++++++
 src/domain/AidStrategy.cpp        | 104 +++++++++++++++++++++++++
 src/domain/AidStrategy.h          |  37 +++++++++
 src/domain/BaseStrategy.h         |  37 +++++++++
 src/domain/Controller.cpp         |  30 +++++++
 src/domain/Controller.h           |  17 ++++
 src/domain/Recorder.cpp           |  93 ----------------------
 src/domain/Recorder.h             |  29 -------
 src/domain/RecorderStrategy.cpp   |  13 ++++
 src/domain/RecorderStrategy.h     |  16 ++++
 src/infra/Audio.cpp               |  31 ++++++--
 src/infra/Audio.h                 |  21 ++---
 src/infra/Http.cpp                |   7 ++
 src/infra/Http.h                  |   1 +
 src/infra/I2S.cpp                 |  65 ++++++++++------
 src/infra/I2S.h                   |   8 +-
 src/main.cpp                      |  22 ++----
 17 files changed, 480 insertions(+), 176 deletions(-)
 create mode 100644 src/domain/AidStrategy copy.cpp.1
 create mode 100644 src/domain/AidStrategy.cpp
 create mode 100644 src/domain/AidStrategy.h
 create mode 100644 src/domain/BaseStrategy.h
 create mode 100644 src/domain/Controller.cpp
 create mode 100644 src/domain/Controller.h
 delete mode 100644 src/domain/Recorder.cpp
 delete mode 100644 src/domain/Recorder.h
 create mode 100644 src/domain/RecorderStrategy.cpp
 create mode 100644 src/domain/RecorderStrategy.h

diff --git a/src/domain/AidStrategy copy.cpp.1 b/src/domain/AidStrategy copy.cpp.1
new file mode 100644
index 0000000..6cba229
--- /dev/null
+++ b/src/domain/AidStrategy copy.cpp.1	
@@ -0,0 +1,125 @@
+#include "domain/AidStrategy.h"
+
+#include "utils/Time.h"
+#include "config/config.h"
+
+void AidStrategy::setup() {
+  _task1_mutex = xSemaphoreCreateMutex();
+  _task2_mutex = xSemaphoreCreateMutex();
+  _http_mutex = xSemaphoreCreateMutex();
+}
+
+void AidStrategy::process() {
+  xTaskCreatePinnedToCore(processTask, "ProcessTask1", 4096, this, 1, NULL, 0);
+  //xTaskCreatePinnedToCore(processTask, "ProcessTask2", 4096, this, 1, NULL, 1);
+}
+
+void AidStrategy::processTask(void* parameters) {
+  AidStrategy* aidStrategy = static_cast<AidStrategy*>(parameters);
+  Audio* audioSource = 
+    (xTaskGetAffinity(NULL) == 0) ? aidStrategy->_audio : aidStrategy->_audio1;
+
+  aidStrategy->_writeToPrecedingBuffer(audioSource);
+
+  if (aidStrategy->_isNoiseDetected(audioSource)) {
+    aidStrategy->_recordAudio(audioSource);
+  }
+
+  vTaskDelete(NULL);
+}
+
+void AidStrategy::_writeToPrecedingBuffer(Audio* audioSource) {
+  if (!_isWritingToPrecedingBuffer && !_recordingAudio) {
+    _isWritingToPrecedingBuffer = true;
+    audioSource->writeToPrecedingBuffer();
+    _isWritingToPrecedingBuffer = false;
+  }
+}
+
+bool AidStrategy::_isNoiseDetected(Audio* audioSource) {
+  return audioSource->isNoiseDetected();
+}
+
+void AidStrategy::_recordAudio(Audio* audioSource) {
+  if (_recordingAudio)
+    return;
+
+  Serial.println("!!!");
+
+  bool isReady = false;
+  _recordingAudio = true;
+
+  if (xSemaphoreTake(_http_mutex, portMAX_DELAY)) {
+    isReady = _ready();
+    xSemaphoreGive(_http_mutex);
+  }
+
+  if (isReady) {
+    Serial.println("========================================");
+    Serial.println("| RECORDING...");
+    audioSource->record();
+    Serial.println("| Recording finished");
+  }
+
+  if (xSemaphoreTake(_http_mutex, portMAX_DELAY)) {
+    if (_http->connect(RAT_IP, RAT_PORT)) {  
+      _sendAudio(audioSource);
+      _http->stop();
+
+    } else {
+      Serial.println("| Connection failed");
+    }
+
+    xSemaphoreGive(_http_mutex);
+  }
+
+  _recordingAudio = false;
+}
+
+String AidStrategy::_ready() {
+  return _http->send("POST", "/aid/ready", RAT_IP, RAT_PORT, "", "");
+}
+
+void AidStrategy::_sendAudio(Audio* audioSource) {
+  String payloadStart = _formPayloadStart(_audio->getStartMicros());
+  String payloadEnd = _formPayloadEnd();
+
+  int audioLength = _audio->getSize();
+  int jsonLength = payloadStart.length() + audioLength + payloadEnd.length();
+
+  _http->printHeader("POST", "/aid/save", RAT_IP, "application/json");
+  _http->printContentLength(jsonLength);
+
+  this->_printContent(payloadStart, payloadEnd, _http->getClient());
+}
+
+void AidStrategy::_printContent(String payloadStart, String payloadEnd, Stream* stream) {
+  stream->print(payloadStart);
+  _audio->print(stream);
+  stream->print(payloadEnd);
+
+  _logContent(payloadStart, payloadEnd);
+}
+
+void AidStrategy::_logContent(String payloadStart, String payloadEnd) {
+  Serial.print("| ");
+  Serial.print(payloadStart);
+  Serial.print("...");
+  Serial.print(payloadEnd);
+}
+
+String AidStrategy::_formPayloadStart(unsigned long startMicros) {
+  String payloadStart = "";
+
+  payloadStart += "{\"audio\":{\"micros\":";
+  payloadStart += String(_audio->getStartMicros() - _timeModule.getInitialMicros());
+  payloadStart += ",\"initialTime\":";
+  payloadStart += String(_timeModule.getInitialTime());
+  payloadStart += ",\"content\":\"";
+
+  return payloadStart;
+}
+
+String AidStrategy::_formPayloadEnd() {
+  return "\"}}\r\n\r\n";
+}
\ No newline at end of file
diff --git a/src/domain/AidStrategy.cpp b/src/domain/AidStrategy.cpp
new file mode 100644
index 0000000..ba239bd
--- /dev/null
+++ b/src/domain/AidStrategy.cpp
@@ -0,0 +1,104 @@
+#include "domain/AidStrategy.h"
+
+#include "utils/Time.h"
+#include "config/config.h"
+
+void AidStrategy::setup() {}
+
+void AidStrategy::process() {
+  _writeToPrecedingBuffer(_audio);
+
+  if (_isNoiseDetected(_audio)) {
+    _recordAudio(_audio);
+  }
+}
+
+void AidStrategy::_writeToPrecedingBuffer(Audio* audioSource) {
+  if (!_isWritingToPrecedingBuffer && !_recordingAudio) {
+    _isWritingToPrecedingBuffer = true;
+    audioSource->writeToPrecedingBuffer();
+    _isWritingToPrecedingBuffer = false;
+  }
+}
+
+bool AidStrategy::_isNoiseDetected(Audio* audioSource) {
+  return audioSource->isNoiseDetected();
+}
+
+void AidStrategy::_recordAudio(Audio* audioSource) {
+  if (_recordingAudio)
+    return;
+
+  Serial.println("!!!");
+
+  bool isReady = false;
+  _recordingAudio = true;
+
+  isReady = _ready();
+
+  if (!isReady)
+    return;
+
+  if (_http->connect(RAT_IP, RAT_PORT)) {
+    Serial.println("========================================");
+    Serial.println("| RECORDING...");
+    audioSource->record();
+    Serial.println("| Recording finished");
+
+    _sendAudio(audioSource);
+    _http->stop();
+
+  } else {
+    Serial.println("| Connection failed");
+  }
+
+  _recordingAudio = false;
+}
+
+String AidStrategy::_ready() {
+  return _http->send("POST", "/aid/ready", RAT_IP, RAT_PORT, "", "");
+}
+
+void AidStrategy::_sendAudio(Audio* audioSource) {
+  String payloadStart = _formPayloadStart(_audio->getStartMicros());
+  String payloadEnd = _formPayloadEnd();
+
+  int audioLength = _audio->getSize();
+  int jsonLength = payloadStart.length() + audioLength + payloadEnd.length();
+
+  _http->printHeader("POST", "/aid/save", RAT_IP, "application/json");
+  _http->printContentLength(jsonLength);
+
+  this->_printContent(payloadStart, payloadEnd, _http->getClient());
+}
+
+void AidStrategy::_printContent(String payloadStart, String payloadEnd, Stream* stream) {
+  stream->print(payloadStart);
+  _audio->print(stream);
+  stream->print(payloadEnd);
+
+  _logContent(payloadStart, payloadEnd);
+}
+
+void AidStrategy::_logContent(String payloadStart, String payloadEnd) {
+  Serial.print("| ");
+  Serial.print(payloadStart);
+  Serial.print("...");
+  Serial.print(payloadEnd);
+}
+
+String AidStrategy::_formPayloadStart(unsigned long startMicros) {
+  String payloadStart = "";
+
+  payloadStart += "{\"audio\":{\"micros\":";
+  payloadStart += String(_audio->getStartMicros() - _timeModule.getInitialMicros());
+  payloadStart += ",\"initialTime\":";
+  payloadStart += String(_timeModule.getInitialTime());
+  payloadStart += ",\"content\":\"";
+
+  return payloadStart;
+}
+
+String AidStrategy::_formPayloadEnd() {
+  return "\"}}\r\n\r\n";
+}
\ No newline at end of file
diff --git a/src/domain/AidStrategy.h b/src/domain/AidStrategy.h
new file mode 100644
index 0000000..538d302
--- /dev/null
+++ b/src/domain/AidStrategy.h
@@ -0,0 +1,37 @@
+#pragma once
+
+#include "domain/BaseStrategy.h"
+
+#include "utils/Time.h"
+
+class AidStrategy : public BaseStrategy {
+private:
+  Time& _timeModule = Time::getInstance();
+  SemaphoreHandle_t _task1_mutex;
+  SemaphoreHandle_t _task2_mutex;
+  SemaphoreHandle_t _http_mutex;
+
+  bool _isWritingToPrecedingBuffer = false;
+  bool _recordingAudio = false;
+
+  void _recordAudio(Audio* audioSource);
+  void _writeToPrecedingBuffer(Audio* audioSource);
+  bool _isNoiseDetected(Audio* audioSource);
+
+  String _ready();
+  void _sendAudio(Audio* audioSource);
+  void _printContent(String payloadStart, String payloadEnd, Stream* stream);
+  void _logContent(String payloadStart, String payloadEnd);
+
+  String _formPayloadStart(unsigned long startMicros);
+  String _formPayloadEnd();
+
+  static void processTask(void* parameters);
+
+public:
+  AidStrategy(MicType micType, Http* http) : BaseStrategy(micType, http) {}
+  ~AidStrategy() {}
+
+  void setup();
+  void process();
+};
\ No newline at end of file
diff --git a/src/domain/BaseStrategy.h b/src/domain/BaseStrategy.h
new file mode 100644
index 0000000..8654399
--- /dev/null
+++ b/src/domain/BaseStrategy.h
@@ -0,0 +1,37 @@
+#pragma once
+
+#include "infra/Audio.h"
+#include "infra/Http.h"
+
+class BaseStrategy {
+protected:
+  Audio* _audio;
+  Audio* _audio1;
+  Http* _http;
+
+public:
+  BaseStrategy(MicType micType, Http* http) {
+    Serial.print("Free heap: ");
+    Serial.println(esp_get_minimum_free_heap_size());
+
+    _audio = new Audio(micType, I2S_NUM_0);
+
+    Serial.print("Free heap: ");
+    Serial.println(esp_get_minimum_free_heap_size());
+
+    _audio1 = new Audio(micType, I2S_NUM_1);
+
+    Serial.print("Free heap: ");
+    Serial.println(esp_get_minimum_free_heap_size());
+
+    _http = http;
+  }
+
+  ~BaseStrategy() {
+    delete _audio;
+    delete _audio1;
+  }
+
+  virtual void setup() = 0;
+  virtual void process() = 0;
+};
\ No newline at end of file
diff --git a/src/domain/Controller.cpp b/src/domain/Controller.cpp
new file mode 100644
index 0000000..a25073a
--- /dev/null
+++ b/src/domain/Controller.cpp
@@ -0,0 +1,30 @@
+
+#include "domain/Controller.h"
+
+Controller Controller::_instance;
+Controller::Controller() : _strategy(nullptr) {}
+
+void Controller::setStrategy(BaseStrategy* newStrategy) {
+  if (_strategy) {
+    delete _strategy;
+  }
+
+  _strategy = newStrategy;
+  if (_strategy) {
+    _strategy->setup();
+  }
+}
+
+Controller::~Controller() {
+  if (_strategy) {
+    delete _strategy;
+  }
+}
+
+Controller& Controller::getInstance() {
+  return _instance;
+}
+
+void Controller::process() {
+  _strategy->process();
+}
\ No newline at end of file
diff --git a/src/domain/Controller.h b/src/domain/Controller.h
new file mode 100644
index 0000000..c3c066c
--- /dev/null
+++ b/src/domain/Controller.h
@@ -0,0 +1,17 @@
+#include "domain/BaseStrategy.h"
+
+class Controller {
+private:
+  static Controller _instance;
+  BaseStrategy* _strategy;
+
+  Controller();
+  Controller(Controller const&) = delete;
+  void operator=(Controller const&) = delete;
+  ~Controller();
+
+public:
+  static Controller& getInstance();
+  void setStrategy(BaseStrategy* strategy);
+  void process();
+};
\ No newline at end of file
diff --git a/src/domain/Recorder.cpp b/src/domain/Recorder.cpp
deleted file mode 100644
index ed6cd71..0000000
--- a/src/domain/Recorder.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-#include "domain/Recorder.h"
-
-#include "config/config.h"
-#include "utils/Time.h"
-
-Time& timeModule = Time::getInstance();
-
-Recorder::Recorder(MicType micType, Http* http) {
-  _audio = new Audio(micType);
-  _http = http;
-}
-
-Recorder::~Recorder() {
-  delete _audio;
-}
-
-void Recorder::recordAudio() {
-  _recordingAudio = true;
-  _ready();
-
-  if (_http->connect(RAT_IP, RAT_PORT)) {
-    Serial.println("========================================");
-    Serial.println("| RECORDING...");
-    _audio->record();
-    Serial.println("| Recording finished");
-    
-    _transcribe();
-
-  } else {
-    Serial.println("| Connection failed");
-  }
-  _recordingAudio = false;
-}
-
-void Recorder::_ready() {
-  _http->send("POST", "/ready", RAT_IP, RAT_PORT, "", "");
-}
-
-void Recorder::_transcribe() {
-  String payloadStart = _formPayloadStart();
-  String payloadEnd = _formPayloadEnd();
-
-  int audioLength = _audio->getSize();
-  int jsonLength = payloadStart.length() + audioLength + payloadEnd.length();
-
-  _http->printHeader("POST", "/save_to_file", RAT_IP, "application/json");
-  _http->printContentLength(jsonLength);
-
-  this->_printContent(payloadStart, payloadEnd, _http->getClient());
-}
-
-void Recorder::_printContent(String payloadStart, String payloadEnd, Stream* stream) {
-  stream->print(payloadStart);
-  _audio->print(stream);
-  stream->print(payloadEnd);
-
-  _logContent(payloadStart, payloadEnd);
-}
-
-void Recorder::_logContent(String payloadStart, String payloadEnd) {
-  Serial.print("| ");
-  Serial.print(payloadStart);
-  Serial.print("...");
-  Serial.print(payloadEnd);
-}
-
-String Recorder::_formPayloadStart() {
-  String payloadStart = "";
-
-  payloadStart += "{\"audio\":{\"micros\":";
-  payloadStart += String(_audio->getStartMicros() - timeModule.getInitialMicros());
-  payloadStart += ",\"initialTime\":";
-  payloadStart += String(timeModule.getInitialTime());
-  payloadStart += ",\"content\":\"";
-
-  return payloadStart;
-}
-
-String Recorder::_formPayloadEnd() {
-  return "\"}}\r\n\r\n";
-}
-
-void Recorder::writeToPrecedingBuffer() {
-  if (!_isWritingToPrecedingBuffer && !_recordingAudio) {
-    _isWritingToPrecedingBuffer = true;
-    _audio->writeToPrecedingBuffer();
-    _isWritingToPrecedingBuffer = false;
-  }
-}
-
-bool Recorder::isNoiseDetected() {
-  return _audio->isNoiseDetected();
-}
\ No newline at end of file
diff --git a/src/domain/Recorder.h b/src/domain/Recorder.h
deleted file mode 100644
index 51b9cd4..0000000
--- a/src/domain/Recorder.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#pragma once
-
-#include "infra/Audio.h"
-#include "infra/Http.h"
-
-class Recorder {
-private:
-  Audio* _audio;
-  Http* _http;
-
-  bool _isWritingToPrecedingBuffer = false;
-  bool _recordingAudio = false;
-
-  void _ready();
-  void _transcribe();
-  void _printContent(String payloadStart, String payloadEnd, Stream* stream);
-  void _logContent(String payloadStart, String payloadEnd);
-  void _printAudio();
-
-  String _formPayloadStart();
-  String _formPayloadEnd();
-
-public:
-  Recorder(MicType micType, Http* http);
-  ~Recorder();
-  void recordAudio();
-  void writeToPrecedingBuffer();
-  bool isNoiseDetected();
-};
diff --git a/src/domain/RecorderStrategy.cpp b/src/domain/RecorderStrategy.cpp
new file mode 100644
index 0000000..4fef813
--- /dev/null
+++ b/src/domain/RecorderStrategy.cpp
@@ -0,0 +1,13 @@
+#include "domain/RecorderStrategy.h"
+
+#include "config/config.h"
+
+void RecorderStrategy::setup() {}
+
+void RecorderStrategy::process() {
+  
+}
+
+void RecorderStrategy::_check() {
+  _http->send("POST", "/recorder/check", RAT_IP, RAT_PORT, "", "");
+}
\ No newline at end of file
diff --git a/src/domain/RecorderStrategy.h b/src/domain/RecorderStrategy.h
new file mode 100644
index 0000000..ada65f2
--- /dev/null
+++ b/src/domain/RecorderStrategy.h
@@ -0,0 +1,16 @@
+#pragma once
+
+#include "domain/BaseStrategy.h"
+
+#include "utils/Time.h"
+
+class RecorderStrategy : public BaseStrategy {
+private:
+  Time& _timeModule = Time::getInstance();
+
+  void _check();
+
+public:
+  void setup();
+  void process();
+};
\ No newline at end of file
diff --git a/src/infra/Audio.cpp b/src/infra/Audio.cpp
index d3e1dfb..e703fe7 100644
--- a/src/infra/Audio.cpp
+++ b/src/infra/Audio.cpp
@@ -5,14 +5,14 @@
 
 #define PRECEDING_BUFFER_SIZE 4
 
-Audio::Audio(MicType micType) {
+Audio::Audio(MicType micType, i2s_port_t i2sNum) {
   _wavData = new char*[_wavDataSize/_dividedWavDataSize];
   for (int i = 0; i < _wavDataSize/_dividedWavDataSize; ++i) 
     _wavData[i] = new char[_dividedWavDataSize];
 
   _precedingWavBuffer = new CircularBuffer<char*>(_precedingWavPartsAmount);
 
-  i2s = new I2S(micType);
+  i2s = new I2S(micType, i2sNum);
 }
 
 Audio::~Audio() {
@@ -47,7 +47,7 @@ void Audio::_createWavHeader(byte* header, int waveDataSize){
   header[19] = 0x00;
   header[20] = 0x01;  // linear PCM
   header[21] = 0x00;
-  header[22] = 0x01;  // monoral
+  header[22] = 0x02;  // stereo
   header[23] = 0x00;
   header[24] = 0x80;  // sampling rate 16000
   header[25] = 0x3E;
@@ -141,9 +141,8 @@ void Audio::writeToPrecedingBuffer() {
 }
 
 void Audio::_convertBufferToWav(char* partialWavBuffer) {
-  for (int i = 0; i < _i2sBufferSize/8; ++i) {
-    partialWavBuffer[2*i] = _i2sBuffer[4*i + 2];
-    partialWavBuffer[2*i + 1] = _i2sBuffer[4*i + 3];
+  for (int i = 0; i < _i2sBufferSize/2; ++i) {
+    partialWavBuffer[i] = _i2sBuffer[i];
   }
 }
 
@@ -152,12 +151,30 @@ int Audio::getSize() {
 }
 
 String Audio::print(Stream* stream) {
+  return printHeader(stream) + printContent(stream);
+}
+
+String Audio::printHeader(Stream* stream) {
   String enc = base64::encode(_paddedHeader, sizeof(_paddedHeader));
   enc.replace("\n", "");
   stream->print(enc);
 
+  return enc;
+}
+
+String Audio::printContent(Stream* stream) {
+  String enc;
+
+  Serial.print("Free heap: ");
+  Serial.println(esp_get_minimum_free_heap_size());
+
   for (int j = 0; j < _wavDataSize / _dividedWavDataSize; ++j) {
-    enc = base64::encode((byte*)_wavData[j], _dividedWavDataSize);
+    enc = base64::encode((byte*)_wavData[j], _dividedWavDataSize/2);
+    enc.replace("\n", "");
+    stream->print(enc);
+
+    enc = base64::encode((byte*)_wavData[j] + _dividedWavDataSize/2, 
+      _dividedWavDataSize/2);
     enc.replace("\n", "");
     stream->print(enc);
   }
diff --git a/src/infra/Audio.h b/src/infra/Audio.h
index a2119f7..d3026ce 100644
--- a/src/infra/Audio.h
+++ b/src/infra/Audio.h
@@ -10,17 +10,18 @@
 class Audio {
 private:
   I2S* i2s;
-  static const int _headerSize = 44;
-  static const int _i2sBufferSize = 6000;
-  char _i2sBuffer[_i2sBufferSize];
-  char _i2sBuffer2[_i2sBufferSize];
 
-  static const int _wavDataSize = 90000;                   // It must be multiple of _dividedWavDataSize. Recording time is about 1.9 second.
-  static const int _dividedWavDataSize = _i2sBufferSize/4;
+  static const int _headerSize = 44;
+  static const int _i2sBufferSize = 6048/2;
+  char _i2sBuffer[_i2sBufferSize/2];
+
+  static const int _wavDataSize = 90720/2;                   // It must be multiple of _dividedWavDataSize. Recording time is about 1.9 second.
+  static const int _dividedWavDataSize = _i2sBufferSize/2;
   char** _wavData;                                         // It's divided. Because large continuous memory area can't be allocated in esp32.
 
-  static const int _precedingWavPartsAmount = 12;
-  static const int _precedingWavDataSize = _precedingWavPartsAmount*_dividedWavDataSize;
+  static const int _precedingWavPartsAmount = (_wavDataSize/_dividedWavDataSize)/5;
+  static const int _precedingWavDataSize = 
+    _precedingWavPartsAmount*_dividedWavDataSize;
   char** _precedingWavData;
   CircularBuffer<char*>* _precedingWavBuffer;
   bool _precedingBufferFull = false;
@@ -37,11 +38,13 @@ private:
   bool _isNoiseDetectedInPrecedingBuffer();
 
 public:
-  Audio(MicType micType);
+  Audio(MicType micType, i2s_port_t i2sNum=I2S_NUM_0);
   ~Audio();
   char** record();
   int getSize();
   String print(Stream* stream);
+  String printHeader(Stream* stream);
+  String printContent(Stream* stream);
   unsigned long getStartMicros();
   void emptyPrecedingBuffer();
   void writeToPrecedingBuffer();
diff --git a/src/infra/Http.cpp b/src/infra/Http.cpp
index 8d22088..c76df65 100644
--- a/src/infra/Http.cpp
+++ b/src/infra/Http.cpp
@@ -62,6 +62,8 @@ void Http::printContentLength(int contentLength) {
   _client->print("Content-Length: ");
   _client->println(contentLength);
   _client->println();
+
+  _logContentLength(contentLength);
 }
 
 String Http::readResponse() {
@@ -132,4 +134,9 @@ void Http::_logPayload(String payload) {
     Serial.println("| ");
     Serial.println(payload);
   }
+}
+
+void Http::_logContentLength(int contentLength) {
+  Serial.print("| Content-Length: ");
+  Serial.println(contentLength);
 }
\ No newline at end of file
diff --git a/src/infra/Http.h b/src/infra/Http.h
index a0d4994..54c048b 100644
--- a/src/infra/Http.h
+++ b/src/infra/Http.h
@@ -11,6 +11,7 @@ private:
   void _logHeader(String method, String endpoint, String host, String contentType);
   void _logPayload(String payload);
   void _logConnected(String host, int port);
+  void _logContentLength(int contentLength);
 
 public:
   Http(Eth* eth);
diff --git a/src/infra/I2S.cpp b/src/infra/I2S.cpp
index dbc2f35..320b6b3 100644
--- a/src/infra/I2S.cpp
+++ b/src/infra/I2S.cpp
@@ -2,11 +2,20 @@
 #include "config/config.h"
 
 #define SAMPLE_RATE (16000)
-#define PIN_I2S_BCLK (GPIO_NUM_26)
-#define PIN_I2S_LRC (GPIO_NUM_25)
-#define PIN_I2S_DIN (GPIO_NUM_3)
-#define PIN_I2S_DOUT (GPIO_NUM_22)
-#define PIN_I2S_MCK (GPIO_NUM_0)
+
+// Define pins for I2S_NUM_0
+#define PIN_I2S_0_BCLK (GPIO_NUM_26)
+#define PIN_I2S_0_LRC (GPIO_NUM_25)
+#define PIN_I2S_0_DIN (GPIO_NUM_3)
+#define PIN_I2S_0_DOUT (GPIO_NUM_22)
+#define PIN_I2S_0_MCK (GPIO_NUM_0)
+
+// Define pins for I2S_NUM_1
+#define PIN_I2S_1_BCLK (GPIO_NUM_32)
+#define PIN_I2S_1_LRC (GPIO_NUM_33)
+#define PIN_I2S_1_DIN (GPIO_NUM_35)
+#define PIN_I2S_1_DOUT (GPIO_NUM_0)
+#define PIN_I2S_1_MCK (GPIO_NUM_0)
 
 SemaphoreHandle_t dmaInterruptSemaphore;
 static intr_handle_t dmaInterruptRetHandle;
@@ -18,7 +27,7 @@ static intr_handle_t dmaInterruptRetHandle;
 //  -   Data bits are MSB first.
 //  -   DATA bits are left-aligned with respect to LRC edge.
 //  -   DATA bits are right-shifted by one with respect to LRC edges.
-I2S::I2S(MicType micType) {
+I2S::I2S(MicType micType, i2s_port_t i2sNum) : _i2sNum(i2sNum) {
   if (micType == M5GO || micType == M5STACKFIRE ) {
     BITS_PER_SAMPLE = I2S_BITS_PER_SAMPLE_16BIT;
     i2s_config_t i2s_config = {
@@ -31,10 +40,10 @@ I2S::I2S(MicType micType) {
       .dma_buf_count = 2,
       .dma_buf_len = 1024
     };
-    i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
+    i2s_driver_install(_i2sNum, &i2s_config, 0, NULL);
     i2s_set_adc_mode(ADC_UNIT_1, ADC1_CHANNEL_6);
-    i2s_set_clk(I2S_NUM_0, SAMPLE_RATE, BITS_PER_SAMPLE, I2S_CHANNEL_STEREO);
-    i2s_adc_enable(I2S_NUM_0);
+    i2s_set_clk(_i2sNum, SAMPLE_RATE, BITS_PER_SAMPLE, I2S_CHANNEL_STEREO);
+    i2s_adc_enable(_i2sNum);
   }
   else if (micType == ADMP441 || micType == ICS43434 ) {
     BITS_PER_SAMPLE = I2S_BITS_PER_SAMPLE_16BIT;// I2S_BITS_PER_SAMPLE_32BIT;
@@ -49,27 +58,39 @@ I2S::I2S(MicType micType) {
       .dma_buf_len = 60,
     };
 
-    i2s_pin_config_t pin_config;
-
-    pin_config.bck_io_num = PIN_I2S_BCLK;
-    pin_config.ws_io_num = PIN_I2S_LRC;
-    pin_config.data_out_num = I2S_PIN_NO_CHANGE;
-    pin_config.data_in_num = PIN_I2S_DIN;
-    pin_config.mck_io_num = PIN_I2S_MCK;
-
-    i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
-    i2s_set_pin(I2S_NUM_0, &pin_config);
-    i2s_set_clk(I2S_NUM_0, SAMPLE_RATE, BITS_PER_SAMPLE, I2S_CHANNEL_STEREO);
-    i2s_zero_dma_buffer(I2S_NUM_0);
+    i2s_driver_install(_i2sNum, &i2s_config, 0, NULL);
+    _setPins();
+    i2s_set_clk(_i2sNum, SAMPLE_RATE, BITS_PER_SAMPLE, I2S_CHANNEL_STEREO);
+    i2s_zero_dma_buffer(_i2sNum);
   }
 
   dmaInterruptSemaphore = xSemaphoreCreateBinary();
 }
 
+void I2S::_setPins() {
+  i2s_pin_config_t pin_config;
+  
+  if (_i2sNum == I2S_NUM_0) {
+    pin_config.bck_io_num = PIN_I2S_0_BCLK;
+    pin_config.ws_io_num = PIN_I2S_0_LRC;
+    pin_config.data_out_num = I2S_PIN_NO_CHANGE;
+    pin_config.data_in_num = PIN_I2S_0_DIN;
+    pin_config.mck_io_num = PIN_I2S_0_MCK;
+  } else if (_i2sNum == I2S_NUM_1) {
+    pin_config.bck_io_num = PIN_I2S_1_BCLK;
+    pin_config.ws_io_num = PIN_I2S_1_LRC;
+    pin_config.data_out_num = I2S_PIN_NO_CHANGE;
+    pin_config.data_in_num = PIN_I2S_1_DIN;
+    pin_config.mck_io_num = PIN_I2S_1_MCK;
+  }
+  
+  i2s_set_pin(_i2sNum, &pin_config);
+}
+
 int I2S::Read(char* data, int numData) {
   size_t bytes_read;
 
-  if (i2s_read(I2S_NUM_0, (char *)data, numData, &bytes_read, portMAX_DELAY)) {
+  if (i2s_read(_i2sNum, (char *)data, numData, &bytes_read, portMAX_DELAY)) {
     return (int)bytes_read;
   }
 
diff --git a/src/infra/I2S.h b/src/infra/I2S.h
index cf63365..3d125dd 100644
--- a/src/infra/I2S.h
+++ b/src/infra/I2S.h
@@ -14,11 +14,15 @@ enum MicType {
 };
 
 class I2S {
-  i2s_bits_per_sample_t BITS_PER_SAMPLE;
 public:
-  I2S(MicType micType);
+  I2S(MicType micType, i2s_port_t i2sNum=I2S_NUM_0);
   int Read(char* data, int numData);
   int GetBitPerSample();
+
+private:
+  i2s_port_t _i2sNum;
+  i2s_bits_per_sample_t BITS_PER_SAMPLE;
+  void _setPins();
 };
 
 #endif // _I2S_H
diff --git a/src/main.cpp b/src/main.cpp
index fef057f..2d4632b 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -10,7 +10,8 @@
 #include "infra/Http.h"
 #include "infra/Eth.h"
 
-#include "domain/Recorder.h"
+#include "domain/Controller.h"
+#include "domain/AidStrategy.h"
 
 volatile bool loudnessFlag = false;
 
@@ -20,7 +21,7 @@ Eth eth;
 EthernetClient* client = eth.getEthClient();
 Http http(&eth);
 
-Recorder* recorder;
+Controller& controller = Controller::getInstance();
 
 Time timeService = Time::getInstance();
 
@@ -39,11 +40,6 @@ void setInitialTime() {
 
 void writeToPrecedingBufferTask(void* parameter) {
   while (true) {
-    recorder->writeToPrecedingBuffer();
-
-    if (recorder->isNoiseDetected()) {
-      recorder->recordAudio();
-    }
 
     vTaskDelay(500 / portTICK_PERIOD_MS);
   }
@@ -52,7 +48,8 @@ void writeToPrecedingBufferTask(void* parameter) {
 void createWriteToPrecedingBufferTask() {
   TaskHandle_t xHandle = NULL;
 
-  xTaskCreatePinnedToCore(writeToPrecedingBufferTask, "writeToPrecedingBufferTask", 4096, NULL, 1, &xHandle, 0);
+  xTaskCreatePinnedToCore(writeToPrecedingBufferTask, 
+    "writeToPrecedingBufferTask", 4096, NULL, 1, &xHandle, 0);
 
   if (xHandle == NULL) {
     ESP_LOGE("TASK1", "Failed to task create");
@@ -66,7 +63,8 @@ void setup() {
   eth.initEthernet();
 
   setInitialTime();
-  recorder = new Recorder(ADMP441, &http);
+  Serial.println(1);
+  controller.setStrategy(new AidStrategy(ADMP441, &http));
 
   //createWriteToPrecedingBufferTask();
 
@@ -76,9 +74,5 @@ void setup() {
 void loop() {
   eth.readAndPrintData(true); // set to false for better speed measurement
 
-  recorder->writeToPrecedingBuffer();
-
-  if (recorder->isNoiseDetected()) {
-    recorder->recordAudio();
-  }
+  controller.process();
 }