2301_80478122 2025-03-02 23:23 采纳率: 0%
浏览 130

esp32 怎么储存五秒音频通过inmp441(标签-http|关键词-#include)

我在尝试用esp32和inmp441来储存一个五秒的音频,然后通过http上传到服务器,但是一直不知道是否存储了音频。


#include <Arduino.h>
#include <WiFi.h>
#include <driver/i2s.h>
#include <SPIFFS.h>
#include <HTTPClient.h>

// Wi-Fi credentials
const char* ssid = "4B";
const char* password = "88886666@feihe";
const char* serverHost = "http://192.168.xxx:3000"; // Server address with port
const char* uploadEndpoint = "/uploadAudio";

// I2S pin configuration
#define I2S_WS 4
#define I2S_SD 5
#define I2S_SCK 6
#define I2S_PORT I2S_NUM_0

// Audio parameters
#define SAMPLE_RATE 16000       // Sample rate in Hz
#define I2S_SAMPLE_BITS 16
#define I2S_BUFFER_SIZE 1024   // Size of each I2S buffer (in 16-bit samples)
#define I2S_NUM_BUFFERS 4       // Number of buffers
#define I2S_READ_LEN (I2S_BUFFER_SIZE * I2S_NUM_BUFFERS) // Total buffer size
#define RECORD_TIME 5           // Record duration in seconds

// Calculating the size of the recorded audio
const int AUDIO_DATA_SIZE = (I2S_SAMPLE_BITS / 8) * SAMPLE_RATE * RECORD_TIME;
const int FLASH_RECORD_SIZE = AUDIO_DATA_SIZE + 44; // Including WAV header

// File management
const char filename[] = "/audio_recording.wav";
const int headerSize = 44;

// Status flags
volatile bool recordingComplete = false;
volatile bool uploadComplete = false;

// Function prototypes
void i2sInit();
void recordAudio();
void writeWavHeader(File &file, uint32_t dataSize);
void updateWavHeader(const char* filepath, uint32_t dataSize);
void uploadFile(const char* filepath);

void setup() {
  Serial.begin(115200);
  delay(1000);
  Serial.println("\nESP32 Voice Control System Starting...");

  // Initialize SPIFFS
  if(!SPIFFS.begin(true)){
    Serial.println("SPIFFS initialization failed!");
    while(1); // Infinite loop if SPIFFS initialization fails
  }
  Serial.println("SPIFFS initialized successfully");

  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  Serial.print("Connecting to WiFi");
  while(WiFi.status() != WL_CONNECTED){
    delay(500);
    Serial.print(".");
  }
  
  if(WiFi.status() == WL_CONNECTED) {
    Serial.println("\nWiFi connected!");
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());
  } else {
    Serial.println("\nWiFi connection failed. Continuing without network...");
  }

  // Initialize I2S
  i2sInit();
  Serial.println("I2S initialized");

  // Start the recording process
  recordAudio();
  
  // Upload the recorded file
  if(recordingComplete && WiFi.status() == WL_CONNECTED) {
    uploadFile(filename);
  }
  
  Serial.println("Operation complete. Going to sleep...");
}

void loop() {
  // Nothing to do in the loop
  delay(1000);
}

// I2S initialization
void i2sInit() {
  i2s_config_t i2s_config = {
    .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),
    .sample_rate = SAMPLE_RATE,
    .bits_per_sample = i2s_bits_per_sample_t(I2S_SAMPLE_BITS),
    .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
    .communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_STAND_I2S),
    .intr_alloc_flags = 0,
    .dma_buf_count = 8,
    .dma_buf_len = I2S_BUFFER_SIZE,
    .use_apll = 1,
    .tx_desc_auto_clear = false,
    .fixed_mclk = 0
  };

  i2s_pin_config_t pin_config = {
    .bck_io_num = I2S_SCK,
    .ws_io_num = I2S_WS,
    .data_out_num = -1,
    .data_in_num = I2S_SD
  };

  esp_err_t err = i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL);
  if (err != ESP_OK) {
    Serial.printf("Failed to install I2S driver: %d\n", err);
    return;
  }
  
  err = i2s_set_pin(I2S_PORT, &pin_config);
  if (err != ESP_OK) {
    Serial.printf("Failed to set I2S pins: %d\n", err);
    return;
  }
  
  // Clear I2S buffer
  i2s_zero_dma_buffer(I2S_PORT);
}

// Record audio function
void recordAudio() {
  // Allocate buffer for recording
  int16_t* i2sBuffer = (int16_t*) malloc(I2S_READ_LEN);
  if (!i2sBuffer) {
    Serial.println("Failed to allocate I2S buffer");
    return;
  }
  
  // Clear any old file
  if (SPIFFS.exists(filename)) {
    SPIFFS.remove(filename);
  }
      
  // Open file for writing
  File audioFile = SPIFFS.open(filename, FILE_WRITE);
  if (!audioFile) {
    Serial.println("Failed to open file for writing");
    free(i2sBuffer);
    return;
  }
      
  // Write WAV header
  writeWavHeader(audioFile, AUDIO_DATA_SIZE);
      
  // Start recording
  Serial.println("Recording started...");
  size_t bytesRead = 0;
  unsigned long totalBytesWritten = 0;
  unsigned long startTime = millis();
      
  // Record for RECORD_TIME seconds
  while(millis() - startTime < RECORD_TIME * 1000) {
    esp_err_t result = i2s_read(I2S_PORT, i2sBuffer, I2S_READ_LEN, &bytesRead, 100);
        
    if (result == ESP_OK && bytesRead > 0) {
      audioFile.write((uint8_t*)i2sBuffer, bytesRead);
      totalBytesWritten += bytesRead;
    }
  }
      
  // Close file
  audioFile.close();
      
  // Update WAV header with actual data size
  updateWavHeader(filename, totalBytesWritten);
      
  Serial.printf("Recording finished. %lu bytes recorded\n", totalBytesWritten);
  
  // Free the buffer
  free(i2sBuffer);
  
  // Set the flag
  recordingComplete = true;
}

// Function to write the WAV header
void writeWavHeader(File &file, uint32_t dataSize) {
  unsigned char header[headerSize];
  
  // RIFF chunk
  header[0] = 'R'; header[1] = 'I'; header[2] = 'F'; header[3] = 'F';
  // File size (will be updated later)
  uint32_t fileSize = dataSize + headerSize - 8;
  header[4] = fileSize & 0xFF;
  header[5] = (fileSize >> 8) & 0xFF;
  header[6] = (fileSize >> 16) & 0xFF;
  header[7] = (fileSize >> 24) & 0xFF;
  // WAVE chunk
  header[8] = 'W'; header[9] = 'A'; header[10] = 'V'; header[11] = 'E';
  // fmt subchunk
  header[12] = 'f'; header[13] = 'm'; header[14] = 't'; header[15] = ' ';
  // Subchunk1 size (16 for PCM)
  header[16] = 16; header[17] = 0; header[18] = 0; header[19] = 0;
  // Audio format (1 for PCM)
  header[20] = 1; header[21] = 0;
  // Number of channels (1 for mono)
  header[22] = 1; header[23] = 0;
  // Sample rate
  header[24] = SAMPLE_RATE & 0xFF;
  header[25] = (SAMPLE_RATE >> 8) & 0xFF;
  header[26] = (SAMPLE_RATE >> 16) & 0xFF;
  header[27] = (SAMPLE_RATE >> 24) & 0xFF;
  // Byte rate (SampleRate * NumChannels * BitsPerSample/8)
  uint32_t byteRate = SAMPLE_RATE * 1 * I2S_SAMPLE_BITS/8;
  header[28] = byteRate & 0xFF;
  header[29] = (byteRate >> 8) & 0xFF;
  header[30] = (byteRate >> 16) & 0xFF;
  header[31] = (byteRate >> 24) & 0xFF;
  // Block align (NumChannels * BitsPerSample/8)
  header[32] = 1 * I2S_SAMPLE_BITS/8;
  header[33] = 0;
  // Bits per sample
  header[34] = I2S_SAMPLE_BITS;
  header[35] = 0;
  // data subchunk
  header[36] = 'd'; header[37] = 'a'; header[38] = 't'; header[39] = 'a';
  // Subchunk2 size (will be updated later)
  header[40] = dataSize & 0xFF;
  header[41] = (dataSize >> 8) & 0xFF;
  header[42] = (dataSize >> 16) & 0xFF;
  header[43] = (dataSize >> 24) & 0xFF;
  
  file.write(header, headerSize);
}

// Function to update the WAV header after recording
void updateWavHeader(const char* filepath, uint32_t dataSize) {
  File file = SPIFFS.open(filepath, "r+");
  if(!file) {
    Serial.println("Failed to open file for header update");
    return;
  }

  // Update the RIFF chunk size (file size - 8)
  uint32_t fileSize = dataSize + headerSize - 8;
  file.seek(4);
  file.write((uint8_t*)&fileSize, 4);

  // Update the data chunk size
  file.seek(40);
  file.write((uint8_t*)&dataSize, 4);
  
  file.close();
}

// Function to upload file to the server
void uploadFile(const char* filepath) {
  if (WiFi.status() != WL_CONNECTED) {
    Serial.println("WiFi not connected, cannot upload");
    return;
  }
  
  File file = SPIFFS.open(filepath, "r");
  if(!file) {
    Serial.println("Failed to open audio file for upload");
    return;
  }

  uint32_t fileSize = file.size();
  Serial.printf("Uploading file, size: %lu bytes\n", fileSize);

  HTTPClient client;
  client.setTimeout(10000);
  String url = String(serverHost) + uploadEndpoint;
  client.begin(url);
  client.addHeader("Content-Type", "audio/wav");
  client.addHeader("Content-Length", String(fileSize));
  
  Serial.print("Uploading to: ");
  Serial.println(url);
  
  int httpCode = client.sendRequest("POST", &file, fileSize);
  file.close();
  
  if(httpCode == HTTP_CODE_OK) {
    String response = client.getString();
    Serial.println("Server response: " + response);
    uploadComplete = true;
  } else {
    Serial.printf("Upload failed, error code: %d\n", httpCode);
  }

  client.end();
}

  • 写回答

3条回答 默认 最新

  • 码农阿豪@新空间 新星创作者: 前端开发技术领域 2025-03-02 23:31
    关注
    让阿豪来帮你解答,本回答参考chatgpt3.5编写提供,如果还有疑问可以评论或留言
    ; (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX), .sample_rate = SAMPLE_RATE, .bits_per_sample = I2S_SAMPLE_BITS, .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT, .communication_format = I2S_COMM_FORMAT_I2S_MSB, .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, .dma_buf_count = I2S_NUM_BUFFERS, .dma_buf_len = I2S_BUFFER_SIZE, .use_apll = true, .tx_desc_auto_clear = true, .fixed_mclk = 0, }; i2s_pin_config_t pin_config = { .bck_io_num = I2S_SCK, .ws_io_num = I2S_WS, .data_out_num = -1, .data_in_num = I2S_SD }; i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL); i2s_set_pin(I2S_PORT, &pin_config);} // Start recording audio void recordAudio() { File file = SPIFFS.open(filename, FILE_WRITE); // Open file for writing if (!file) { Serial.println("Failed to open file for recording"); return; }

    // Write WAV header writeWavHeader(file, AUDIO_DATA_SIZE);

    // Read I2S data size_t bytesWritten = 0; uint8_t audioData[I2S_READ_LEN]; while (bytesWritten < AUDIO_DATA_SIZE) { size_t bytesRead = i2s_read_bytes(I2S_PORT, audioData, I2S_BUFFER_SIZE, portMAX_DELAY); file.write(audioData, bytesRead); bytesWritten += bytesRead; }

    // Close the file and update the WAV header file.close(); updateWavHeader(filename, AUDIO_DATA_SIZE); Serial.println("Recording complete"); recordingComplete = true; } // Write the WAV header to the file void writeWavHeader(File &file, uint32_t dataSize) { file.seek(0);

    // Create the WAV header uint8_t header[headerSize]; memcpy(header, "RIFF", 4); uint32_t fileSize = headerSize + dataSize - 8; memcpy(header + 4, &fileSize, sizeof(uint32_t)); memcpy(header + 8, "WAVE", 4); memcpy(header + 12, "fmt ", 4); // Add the rest of the WAV header data (omitted for brevity)

    // Write the WAV header to the file file.write(header, headerSize); } // Update the WAV header with the actual data size void updateWavHeader(const char* filepath, uint32_t dataSize) { File file = SPIFFS.open(filepath, FILE_WRITE); if (!file) { Serial.println("Failed to open file for updating WAV header"); return; }

    // Calculate the actual data size dataSize -= headerSize;

    // Update the WAV header with the actual data size file.seek(40); file.write((const uint8_t*)&dataSize, sizeof(uint32_t));

    file.close(); } // Upload the recorded file to the server void uploadFile(const char* filepath) { HTTPClient http; String serverPath = String(serverHost) + uploadEndpoint;

    http.begin(serverPath); http.addHeader("Content-Type", "audio/wav");

    // Open the file for reading File file = SPIFFS.open(filepath, FILE_READ); if (!file) { Serial.println("Failed to open file for uploading"); return; }

    // Upload file to server int httpResponseCode = http.POST((Stream*)&file); if (httpResponseCode > 0) { Serial.print("HTTP response code: "); Serial.println(httpResponseCode); } else { Serial.print("HTTP request failed with error code: "); Serial.println(httpResponseCode); }

    // Close the file and end the HTTP connection file.close(); http.end(); uploadComplete = true; }

    在上面的代码中,首先通过`recordAudio()`函数从I2S接收音频数据并存储到SPIFFS文件系统中。在`writeWavHeader()`函数中,将音频数据以WAV文件格式添加头部信息,并在`updateWavHeader()`函数中更新WAV头文件的数据大小。最后,在`uploadFile()`函数中,将录制的文件上传到服务器。
    你可以通过调用`recordAudio()`函数来录制音频,然后调用`uploadFile()`函数上传到服务器。同时,建议在`loop()`函数中添加逻辑以检查`recordingComplete`和`uploadComplete`标志位,以确保录制和上传操作完成。
    希望以上解答对你有帮助!如果有任何疑问,请随时提问。
    评论

报告相同问题?

问题事件

  • 修改了问题 3月2日
  • 创建了问题 3月2日