Загрузка данных
#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(); // Даем серверу обрабатывать запросы
}