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


#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;

#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); // Частота * каналы * (бит на сэмпл / 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; // PCM (без сжатия)
  uint16_t numChannels = 1; // Моно
  uint32_t sampleRate = SAMPLE_RATE;
  uint16_t bitsPerSample = 32; // Ваши 32-битные настройки I2S
  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();
  
  // Отправляем HTTP-заголовки, говорящие браузеру, что это аудиопоток
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: audio/wav");
  client.println("Connection: close");
  client.println(); // Пустая строка завершает заголовки

  // Отправляем WAV заголовок один раз в самом начале
  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()) {
    esp_err_t err = i2s_channel_read(rx_chan, i2s_buffer, sizeof(i2s_buffer), &bytes_read, 100);
    
    if (err == ESP_OK && bytes_read > 0) {
      // Отправляем бинарные аудиоданные в Wi-Fi клиент напрямую
      client.write((uint8_t*)i2s_buffer, bytes_read);
    }
  }
  
  Serial.println("Браузер отключился от стрима.");
}

void setup() {
  Serial.begin(115200);
  while (!Serial) { delay(10); }

  // 1. Инициализация I2S
  i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_AUTO, 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_4,
      .ws   = GPIO_NUM_5,
      .dout = I2S_GPIO_UNUSED,
      .din  = GPIO_NUM_3,
      .invert_flags = { .mclk_inv = false, .bclk_inv = false, .ws_inv = false }
    }
  };
  i2s_channel_init_std_mode(rx_chan, &cfg);
  i2s_channel_enable(rx_chan);

  // 2. Подключение к Wi-Fi
  WiFi.begin(ssid, password);
  Serial.print("Подключение к Wi-Fi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWi-Fi подключен!");
  Serial.print("IP адрес платы: ");
  Serial.println(WiFi.localIP());

  /* 
  // ЕСЛИ ХОТИТЕ ТОЧКУ ДОСТУПА вместо домашнего роутера:
  WiFi.softAP("ESP32-C3-Mic", "12345678");
  Serial.print("IP адрес точки: ");
  Serial.println(WiFi.softAPIP());
  */

  // 3. Настройка веб-сервера
  server.on("/", handleAudioStream); // Привязываем функцию стрима к главному адресу
  server.begin();
  Serial.println("HTTP сервер запущен.");
}

void loop() {
  server.handleClient(); // Даем серверу обрабатывать запросы
}