Загрузка данных


#include <WiFi.h>
#include <WebServer.h>
#include <driver/i2s_std.h>

// Укажите настройки вашего Wi-Fi
const char* ssid = "ВАШ_ИМЯ_WIFI";
const char* password = "ВАШ_ПАРОЛЬ_WIFI";

WebServer server(80);
i2s_chan_handle_t rx_chan = NULL;

#define SAMPLE_RATE 16000
#define BUFFER_SIZE 1024

// Функция генерации заголовка WAV (формат PCM, 16000Hz, 32-bit, Mono)
void generateWavHeader(uint8_t* header) {
  uint32_t totalDataLen = 0xFFFFFFFF; // Бесконечный размер для стриминга
  uint32_t chunkSize = totalDataLen + 36;
  uint32_t byteRate = SAMPLE_RATE * 1 * (32 / 8);

  memcpy(header, "RIFF", 4);
  memcpy(header + 4, &chunkSize, 4);
  memcpy(header + 8, "WAVE", 4);
  memcpy(header + 12, "fmt ", 4);
  
  uint32_t subChunk1Size = 16;
  uint16_t audioFormat = 1; 
  uint16_t numChannels = 1; 
  uint32_t sampleRate = SAMPLE_RATE;
  uint16_t bitsPerSample = 32; 
  uint16_t blockAlign = numChannels * (bitsPerSample / 8);

  memcpy(header + 16, &subChunk1Size, 4);
  memcpy(header + 20, &audioFormat, 2);
  memcpy(header + 22, &numChannels, 2);
  memcpy(header + 24, &sampleRate, 4);
  memcpy(header + 28, &byteRate, 4);
  memcpy(header + 32, &blockAlign, 2);
  memcpy(header + 34, &bitsPerSample, 2);
  memcpy(header + 36, "data", 4);
  memcpy(header + 40, &totalDataLen, 4);
}

// Обработчик аудиопотока для браузера
void handleAudioStream() {
  WiFiClient client = server.client();
  
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: audio/wav");
  client.println("Connection: close");
  client.println(); 

  // Исправлено: заголовок теперь является массивом из 44 байт
  uint8_t wavHeader[44];
  generateWavHeader(wavHeader);
  client.write(wavHeader, 44);

  int32_t i2s_buffer[BUFFER_SIZE];
  size_t bytes_read = 0;

  Serial.println("Браузер подключился. Начинаем стрим...");

  while (client.connected()) {
    if (i2s_channel_read(rx_chan, i2s_buffer, sizeof(i2s_buffer), &bytes_read, 100) == ESP_OK) {
      if (bytes_read > 0) {
        client.write((uint8_t*)i2s_buffer, bytes_read);
      }
    }
  }
  Serial.println("Браузер отключился от стрима.");
}

void setup() {
  Serial.begin(115200);
  delay(1000);
  Serial.println("\n--- Старт ESP32-WROOM ---");

  // 1. ПОДКЛЮЧЕНИЕ WI-FI
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.print("Подключение к Wi-Fi...");
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  
  Serial.println("\nWi-Fi успешно подключен!");
  Serial.print("IP адрес ESP32: ");
  Serial.println(WiFi.localIP());

  // 2. ИНИЦИАЛИЗИРУЕМ МИКРОФОН НА ПИНАХ WROOM (14, 15, 32)
  i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_0, I2S_ROLE_MASTER);
  i2s_new_channel(&chan_cfg, NULL, &rx_chan);

  i2s_std_config_t cfg = {
    .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(SAMPLE_RATE),
    .slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_32BIT, I2S_SLOT_MODE_MONO),
    .gpio_cfg = {
      .mclk = I2S_GPIO_UNUSED,
      .bclk = GPIO_NUM_14,  // SCK / BCLK микрофона
      .ws   = GPIO_NUM_15,  // WS / LRCK микрофона
      .din  = GPIO_NUM_32,  // Исправлено: din теперь идет ПЕРЕД dout по правилам ESP-IDF
      .dout = I2S_GPIO_UNUSED,
      .invert_flags = { .mclk_inv = false, .bclk_inv = false, .ws_inv = false }
    }
  };
  
  i2s_channel_init_std_mode(rx_chan, &cfg);
  i2s_channel_enable(rx_chan);
  Serial.println("I2S Микрофон запущен.");

  // 3. ЗАПУСК ВЕБ-СЕРВЕРА
  server.on("/", handleAudioStream); 
  server.begin();
  Serial.println("HTTP сервер запущен. Откройте IP в браузере.");
}

void loop() {
  server.handleClient(); 
}