Wave Driver介绍-1(PCM文件格式)

本文介绍了PCM(脉冲编码调制)的基本原理,包括关键概念如采样率、采样位宽及声道数,并通过实例计算了不同参数下PCM音频文件的数据量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

   PCMPluse Code Modulation)即脉冲编码调制,它将AD转换直接形成的二进制序列,没有头和尾巴,它也是音频数字化的常用方法。

         假设声音信号如下图所示:

 

         上图中的一个个点表示采样点,显然,这里引入了两个概念即采样率,采样位宽。另外,在实际情况下,对于声音信号而言,会存在多路采样的情况,因此还会有声道数的概念。

         显然,PCM数据量(字节为单位)为(声道数×采样率×采样位宽)×时间(S为单位)/8Eg,对于CD音质(标准CD音质采样参数为双声道/44.1K/16位宽)的数据而言,每分钟的数据量就是(44.1×1000×16×2)×60/8 = 10584000字节。

### ESP32 生成或处理 Wave 音频文件教程 #### 使用 ESP32 处理音频数据的基础概念 ESP32 是一款功能强大的微控制器,支持多种外设接口和协议。对于 Wave 文件的生成和处理,主要依赖于 I2S 接口来传输 PCM 数据流[^1]。 #### 波形文件结构简介 Wave 文件是一种常见的音频存储格式,通常由 RIFF 容器封装而成。其基本结构包括文件头(RIFF 和 fmt 子块)、数据长度说明以及实际的声音样本数据部分。为了在 ESP32 上创建有效的 .wav 文件,必须遵循这一标准格式编写相应的头部信息并填充正确的采样率、位深等参数。 #### 实现方法概述 通过配置 I2S 模块可以实现对原始 PCM 数据的有效读取与写入操作;利用 SPIFFS 或者 SD 卡作为外部存储介质保存最终形成的 wave 文件;借助第三方库简化编码过程中的复杂度提升开发效率。 #### 示例代码展示如何使用 Arduino IDE 创建简单的 sine wave 并将其转换成 wav 格式: ```cpp #include "Arduino.h" #include <driver/i2s.h> #include <SD_MMC.h> #define SAMPLE_RATE (22050) #define BITS_PER_SAMPLE (16) void setup() { Serial.begin(115200); // 初始化I2S模块用于播放声音 i2s_config_t i2s_config = { .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX), .sample_rate = SAMPLE_RATE, .bits_per_sample = BITS_PER_SAMPLE, .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, .communication_format = I2S_COMM_FORMAT_I2S_MSB, .intr_alloc_flags = 0, .dma_buf_count = 8, .dma_buf_len = 64, .use_apll = false, .tx_desc_auto_clear = true, .fixed_mclk = 0 }; i2s_pin_config_t pin_config; i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL); File file = SD_MMC.open("/test.wav", FILE_WRITE); uint8_t riff[] = {'R', 'I', 'F', 'F'}; uint32_t chunkSize = sizeof(riff)+sizeof(uint32_t)*7+SAMPLE_RATE*BITS_PER_SAMPLE/8; uint8_t wave[] = {'W','A','V','E'}; uint8_t format[]={'f','m','t',' '}; uint32_t subchunk1size=16; uint16_t audioformat=1,numChannels=1,samplesPerSec=SAMPLE_RATE,bitspersample=BITS_PER_SAMPLE; uint32_t byteRate=samplesPerSec*numChannels*(bitspersample>>3),blockAlign=numChannels*(bitspersample>>3); uint8_t data[]={"d","a","t","a"}; uint32_t subChunk2Size; file.write(riff,sizeof(riff)); file.write((uint8_t*)&chunkSize,sizeof(chunkSize)); file.write(wave,sizeof(wave)); file.write(format,sizeof(format)); file.write((uint8_t*)&subchunk1size,sizeof(subchunk1size)); file.write((uint8_t*)&audioformat,sizeof(audioformat)); file.write((uint8_t*)&numChannels,sizeof(numChannels)); file.write((uint8_t*)&samplesPerSec,sizeof(samplesPerSec)); file.write((uint8_t*)&byteRate,sizeof(byteRate)); file.write((uint8_t*)&blockAlign,sizeof(blockAlign)); file.write((uint8_t*)&bitspersample,sizeof(bitspersample)); file.write(data,sizeof(data)); subChunk2Size=(SAMPLE_RATE)*(BITS_PER_SAMPLE)/8; file.write((uint8_t*)&subChunk2Size,sizeof(subChunk2Size)); float frequency = 440.0; // A note frequency int samplesCount = SAMPLE_RATE * 1 ;// one second of sound short sampleBuffer[samplesCount]; for(int n = 0;n<samplesCount;++n){ double angle = ((double)n / (double)samplesCount) * M_PI * 2.0 *frequency; sampleBuffer[n]=(short)((sin(angle))*SHRT_MAX); } file.write(reinterpret_cast<uint8_t*>(sampleBuffer),(samplesCount*sizeof(short))); } void loop(){ } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值