mirror of
https://github.com/espressif/esp-idf.git
synced 2024-09-20 00:36:01 -04:00
example: extract wav-format related struct
This commit is contained in:
parent
7c2b137ffe
commit
be3792ea45
73
examples/peripherals/i2s/common/format_wav.h
Normal file
73
examples/peripherals/i2s/common/format_wav.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Header structure for WAV file with only one data chunk
|
||||
*
|
||||
* @note See this for reference: http://soundfile.sapp.org/doc/WaveFormat/
|
||||
*
|
||||
* @note Assignment to variables in this struct directely is only possible for little endian architectures
|
||||
* (including Xtensa & RISC-V)
|
||||
*/
|
||||
typedef struct {
|
||||
struct {
|
||||
char chunk_id[4]; /*!< Contains the letters "RIFF" in ASCII form */
|
||||
uint32_t chunk_size; /*!< This is the size of the rest of the chunk following this number */
|
||||
char chunk_format[4]; /*!< Contains the letters "WAVE" */
|
||||
} descriptor_chunk; /*!< Canonical WAVE format starts with the RIFF header */
|
||||
struct {
|
||||
char subchunk_id[4]; /*!< Contains the letters "fmt " */
|
||||
uint32_t subchunk_size; /*!< This is the size of the rest of the Subchunk which follows this number */
|
||||
uint16_t audio_format; /*!< PCM = 1, values other than 1 indicate some form of compression */
|
||||
uint16_t num_of_channels; /*!< Mono = 1, Stereo = 2, etc. */
|
||||
uint32_t sample_rate; /*!< 8000, 44100, etc. */
|
||||
uint32_t byte_rate; /*!< ==SampleRate * NumChannels * BitsPerSample s/ 8 */
|
||||
uint16_t block_align; /*!< ==NumChannels * BitsPerSample / 8 */
|
||||
uint16_t bits_per_sample; /*!< 8 bits = 8, 16 bits = 16, etc. */
|
||||
} fmt_chunk; /*!< The "fmt " subchunk describes the sound data's format */
|
||||
struct {
|
||||
char subchunk_id[4]; /*!< Contains the letters "data" */
|
||||
uint32_t subchunk_size; /*!< ==NumSamples * NumChannels * BitsPerSample / 8 */
|
||||
int16_t data[0]; /*!< Holds raw audio data */
|
||||
} data_chunk; /*!< The "data" subchunk contains the size of the data and the actual sound */
|
||||
} wav_header_t;
|
||||
|
||||
/**
|
||||
* @brief Default header for PCM format WAV files
|
||||
*
|
||||
*/
|
||||
#define WAV_HEADER_PCM_DEFAULT(wav_sample_size, wav_sample_bits, wav_sample_rate, wav_channel_num) { \
|
||||
.descriptor_chunk = { \
|
||||
.chunk_id = {'R', 'I', 'F', 'F'}, \
|
||||
.chunk_size = (wav_sample_size) + sizeof(wav_header_t) - 8, \
|
||||
.chunk_format = {'W', 'A', 'V', 'E'} \
|
||||
}, \
|
||||
.fmt_chunk = { \
|
||||
.subchunk_id = {'f', 'm', 't', ' '}, \
|
||||
.subchunk_size = 16, /* 16 for PCM */ \
|
||||
.audio_format = 1, /* 1 for PCM */ \
|
||||
.num_of_channels = (wav_channel_num), \
|
||||
.sample_rate = (wav_sample_rate), \
|
||||
.byte_rate = (wav_sample_bits) * (wav_sample_rate) * (wav_channel_num) / 8, \
|
||||
.block_align = (wav_sample_bits) * (wav_channel_num) / 8, \
|
||||
.bits_per_sample = (wav_sample_bits)\
|
||||
}, \
|
||||
.data_chunk = { \
|
||||
.subchunk_id = {'d', 'a', 't', 'a'}, \
|
||||
.subchunk_size = (wav_sample_size) \
|
||||
} \
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,2 +1,2 @@
|
||||
idf_component_register(SRCS "i2s_recorder_main.c"
|
||||
INCLUDE_DIRS ".")
|
||||
INCLUDE_DIRS "../../common")
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <math.h>
|
||||
#include <sys/unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_system.h"
|
||||
@ -20,7 +21,7 @@
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/spi_common.h"
|
||||
#include "sdmmc_cmd.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "format_wav.h"
|
||||
|
||||
static const char *TAG = "pdm_rec_example";
|
||||
|
||||
@ -90,40 +91,15 @@ void mount_sdcard(void)
|
||||
sdmmc_card_print_info(stdout, card);
|
||||
}
|
||||
|
||||
void generate_wav_header(char *wav_header, uint32_t wav_size, uint32_t sample_rate)
|
||||
{
|
||||
// See this for reference: http://soundfile.sapp.org/doc/WaveFormat/
|
||||
uint32_t file_size = wav_size + WAVE_HEADER_SIZE - 8;
|
||||
uint32_t byte_rate = BYTE_RATE;
|
||||
|
||||
const char set_wav_header[] = {
|
||||
'R', 'I', 'F', 'F', // ChunkID
|
||||
file_size, file_size >> 8, file_size >> 16, file_size >> 24, // ChunkSize
|
||||
'W', 'A', 'V', 'E', // Format
|
||||
'f', 'm', 't', ' ', // Subchunk1ID
|
||||
0x10, 0x00, 0x00, 0x00, // Subchunk1Size (16 for PCM)
|
||||
0x01, 0x00, // AudioFormat (1 for PCM)
|
||||
0x01, 0x00, // NumChannels (1 channel)
|
||||
sample_rate, sample_rate >> 8, sample_rate >> 16, sample_rate >> 24, // SampleRate
|
||||
byte_rate, byte_rate >> 8, byte_rate >> 16, byte_rate >> 24, // ByteRate
|
||||
0x02, 0x00, // BlockAlign
|
||||
0x10, 0x00, // BitsPerSample (16 bits)
|
||||
'd', 'a', 't', 'a', // Subchunk2ID
|
||||
wav_size, wav_size >> 8, wav_size >> 16, wav_size >> 24, // Subchunk2Size
|
||||
};
|
||||
|
||||
memcpy(wav_header, set_wav_header, sizeof(set_wav_header));
|
||||
}
|
||||
|
||||
void record_wav(uint32_t rec_time)
|
||||
{
|
||||
// Use POSIX and C standard library functions to work with files.
|
||||
int flash_wr_size = 0;
|
||||
ESP_LOGI(TAG, "Opening file");
|
||||
|
||||
char wav_header_fmt[WAVE_HEADER_SIZE];
|
||||
uint32_t flash_rec_time = BYTE_RATE * rec_time;
|
||||
generate_wav_header(wav_header_fmt, flash_rec_time, CONFIG_EXAMPLE_SAMPLE_RATE);
|
||||
const wav_header_t wav_header =
|
||||
WAV_HEADER_PCM_DEFAULT(flash_rec_time, 16, CONFIG_EXAMPLE_SAMPLE_RATE, 1);
|
||||
|
||||
// First check if file exists before creating a new file.
|
||||
struct stat st;
|
||||
@ -140,7 +116,7 @@ void record_wav(uint32_t rec_time)
|
||||
}
|
||||
|
||||
// Write the header to the WAV file
|
||||
fwrite(wav_header_fmt, 1, WAVE_HEADER_SIZE, f);
|
||||
fwrite(&wav_header, sizeof(wav_header), 1, f);
|
||||
|
||||
// Start recording
|
||||
while (flash_wr_size < flash_rec_time) {
|
||||
@ -148,7 +124,7 @@ void record_wav(uint32_t rec_time)
|
||||
if (i2s_channel_read(rx_handle, (char *)i2s_readraw_buff, SAMPLE_SIZE, &bytes_read, 1000) == ESP_OK) {
|
||||
printf("[0] %d [1] %d [2] %d [3]%d ...\n", i2s_readraw_buff[0], i2s_readraw_buff[1], i2s_readraw_buff[2], i2s_readraw_buff[3]);
|
||||
// Write the samples to the WAV file
|
||||
fwrite(i2s_readraw_buff, 1, bytes_read, f);
|
||||
fwrite(i2s_readraw_buff, bytes_read, 1, f);
|
||||
flash_wr_size += bytes_read;
|
||||
} else {
|
||||
printf("Read Failed!\n");
|
||||
|
Loading…
Reference in New Issue
Block a user