瑞芯微-I2S|语音文件格式wav与pcm快速入门-4

原创 一口Linux 2024-05-20 11:50

点击左上方蓝色“一口Linux”,选择“设为星标

第一时间看干货文章 

【干货】嵌入式驱动工程师学习路线
【干货】Linux嵌入式知识点-思维导图-免费获取
【就业】一个可以写到简历的基于Linux物联网综合项目
【就业】找工作简历模版



 1

一口君后面会陆续更新基于瑞芯微rk3568的I2S系列文章。

预计10篇左右。有对语音感兴趣的朋友,可以收藏该专题。

《瑞芯微 | I2S-音频基础 -1》

《瑞芯微-I2S | 音频驱动调试基本命令和工具-基于rk3568-2》

《瑞芯微-I2S | ALSA基础-3 》

调试I2S,最常用到的测试文件就是wav格式和pcm格式,本文主要讲解语音格式相关知识点。

本文还用到逻辑分析仪,使用方法如下:

《推荐最近在使用的还不错的一款逻辑分析仪》

本文用到的 音频文件+逻辑分析仪软件+i2s数据波形 后台回复:i2s

一、pcm

与pcm相关的几个参数:

1. PCM数据常用量化指标

  • 采样率(Sample rate):每秒钟采样多少次,以Hz为单位。采样率表示音频信号每秒的数字快照数。该速率决定了音频文件的频率范围。采样率越高,数字波形的形状越接近原始模拟波形。低采样率会限制可录制的频率范围,这可导致录音表现原始声音的效果不佳。

根据 奈奎斯特采样定理,为了重现给定频率,采样率必须至少是该频率的两倍。例如,CD 的采样率为每秒 44,100 个采样,因此可重现最高为 22,050 Hz 的频率,此频率刚好超过人类的听力极限 20,000 Hz。

  1. 位深度(Bit-depth):表示用多少个二进制位来描述采样数据,一般为16bit。位深度决定动态范围。采样声波时,为每个采样指定最接近原始声波振幅的振幅值。较高的位深度可提供更多可能的振幅值,产生更大的动态范围、更低的噪声基准和更高的保真度。

  2. 字节序:表示音频PCM数据存储的字节序是大端存储(big-endian)还是小端存储(little-endian),为了数据处理效率的高效,通常为小端存储。

  3. 声道数(channel number):当前PCM文件中包含的声道数,是单声道(mono)、双声道(stereo)?此外还有5.1声道等。

  4. 采样数据是否有符号(Sign):要表达的就是字面上的意思,需要注意的是,使用有符号的采样数据不能用无符号的方式播放。

以FFmpeg中常见的PCM数据格式s16le为例:

  • 它描述的是有符号16位小端PCM数据
s表示有符号,
16表示位深,
le表示小端存储。

2. PCM数据流

PCM (Pulse Code Modulation) 也被称为脉冲编码调制。PCM 音频数据是未经压缩的音频采样数据裸流,它是由模拟信号经过采样、量化、编码转换成的标准的数字音频数据。

PCM 音频数据的存储

如果是单声道的音频文件,采样数据按时间的先后顺序依次存入(有的时候也会采用 LRLRLR 方式存储,只是另一个声道的数据为 0),如果是双声道的话通常按照 LRLRLR 的方式存储,存储的时候还和机器的大小端有关。

小端模式如下图所示:

PCM 音频数据是未经压缩的数据,所以通常都比较大,常见的 MP3 格式都是经过压缩的,128Kbps 的 MP3 压缩率可以达到 1:11

PCM 音频数据的参数

一般我们描述 PCM 音频数据的参数的时候有如下描述方式:

  • 44100HZ 16bit stereo:
每秒钟有 44100 次采样, 
采样数据用 16 位(2 字节)记录, 
双声道(立体声)

44100Hz 指的是采样率,它的意思是每秒取样 44100 次。采样率越大,存储数字音频所占的空间就越大。

16bit 指的是采样精度,意思是原始模拟信号被采样后,每一个采样点在计算机中用 16 位(两个字节)来表示。采样精度越高越能精细地表示模拟信号的差异。

Stereo 指的是声道数,也即采样时用到的麦克风的数量,麦克风越多就越能还原真实的采样环境(当然麦克风的放置位置也是有规定的)。

其他格式例子:

  • 22050HZ 8bit  mono:
每秒钟有 22050 次采样, 采样数据用 8 位(1 字节)记录, 单声道
  • 48000HZ 32bit 51ch:
每秒钟有 48000 次采样, 采样数据用 32 位(4 字节浮点型)记录, 5.1 声道

二、WAV文件

WAV 是 Microsoft 和 IBM 为 PC 开发的一种声音文件格式,它符合 RIFF(Resource Interchange File Format)文件规范,用于保存 Windows 平台的音频信息资源,被 Windows 平台及其应用程序所广泛支持。

1. wav文件头

WAVE 文件通常只是一个具有单个 “WAVE” 块的 RIFF 文件,该块由两个子块(”fmt” 子数据块和 ”data” 子数据块),它的标准格式如下图所示:图片来源:

http://soundfile.sapp.org/doc/WaveFormat/

该格式的实质就是在 PCM 文件的前面加了一个文件头,各字段含义如下:

偏移与大小名称说明
0 4ChunkID包含 ASCII 形式的字母“RIFF”(0x52494646 大端形式)。
4 4ChunkSize36 + SubChunk2Size,或更准确地说:4 + (8 + SubChunk1Size) + (8 + SubChunk2Size)这是此数字之后的块的其余部分的大小。这是整个文件的大小(以字节为单位)减去未包含在此计数中的两个字段的 8 字节:ChunkID 和 ChunkSize。
8 4格式包含字母“WAVE”(0x57415645 大端形式)。
12 4Subchunk1ID包含字母“fmt”(0x666d7420 大端格式)。
16 4Subchunk1Size16 用于 PCM。这是该数字之后的其余子块的大小。
20 2AudioFormatPCM = 1(即线性量化)1 以外的值表示某种形式的压缩。
22 2NumChannelsMono = 1、Stereo = 2 等
24 4SampleRate8000、44100 等
28 4ByteRate== SampleRate * NumChannels * BitsPerSample/8
32 2BlockAlign== NumChannels * BitsPerSample/8 1 的字节数样本包括所有通道。
34 2BitsPerSample8 位 = 8,16 位 = 16,等等
2ExtraParamSize如果是 PCM,则不存在
XExtraParams用于额外参数的空间
36 4Subchunk2ID包含字母“数据”(0x64617461 大端形式)。
40 4Subchunk2Size== NumSamples * NumChannels * BitsPerSample/8 这是数据中的字节数。您还可以将其视为该数字后面的子块的读取大小。
44 *Data实际的声音数据。

2. wav文件头结构体

wav文件头信息对应结构体:

typedef struct {
    char          ChunkID[4]; //内容为"RIFF"
    unsigned long ChunkSize;  //存储文件的字节数(不包含ChunkID和ChunkSize这8个字节)
    char          Format[4];  //内容为"WAVE“
} WAVE_HEADER;

typedef struct {
   char           Subchunk1ID[4]; //内容为"fmt"
   unsigned long  Subchunk1Size;  //存储该子块的字节数(不含前面的Subchunk1ID和Subchunk1Size这8个字节)
   unsigned short AudioFormat;    //存储音频文件的编码格式,例如若为PCM则其存储值为1。
   unsigned short NumChannels;    //声道数,单声道(Mono)值为1,双声道(Stereo)值为2,等等
   unsigned long  SampleRate;     //采样率,如8k,44.1k等
   unsigned long  ByteRate;       //每秒存储的bit数,其值 = SampleRate * NumChannels * BitsPerSample / 8
   unsigned short BlockAlign;     //块对齐大小,其值 = NumChannels * BitsPerSample / 8
   unsigned short BitsPerSample;  //每个采样点的bit数,一般为8,16,32等。
} WAVE_FMT;

typedef struct {
   char          Subchunk2ID[4]; //内容为“data”
   unsigned long Subchunk2Size;  //接下来的正式的数据部分的字节数,其值 = NumSamples * NumChannels * BitsPerSample / 8
} WAVE_DATA;

3. WAV 文件头解析实例

下面通过提供给大家的音频文件《xiaoniao.wav》来详细讲解wav文件格式,该音频文件格式为:S16_LE

peng@ubuntu:~/test$ ls -l xiaoniao.wav 
-rwxrw-rw- 1 peng peng 1764448 May 10 20:41 xiaoniao.wav

用ue打开该文件,自动显示为十六进制数字,

文件头信息解析如下图:

数据是小端,比如采样率4个字段是 44 AC 00 00实际数据是0x0000ac44,转换成10进制是44100

读者对照结构体,可以解析出改文件的所有信息。

三、i2s音频波形分析

wav文件格式我们搞清楚了,那么它和i2s是什么关系呢?

1. 嵌入式设备音频架构

一个典型的嵌入式设备的音频架构大致如下【以rk3568为例】,

当我们使用aplay工具播放wav文件时:

  1. 解析wav文件头,读取相应信息
  2. 然后通过i2s控制器驱动,将pcm音频流通过i2s接口发送给codec rk809,
  3. codec rk809会将pcm音频流进行DAC转换成对应的模拟信号,并通过耳机/喇叭播放出去。

2. 播放命令

播放命令:

root@ATK-DLRK356X:/sdcard# aplay -v xiaoniao.wav
Playing WAVE 'xiaoniao.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo
ALSA <-> PulseAudio PCM I/O Plugin
Its setup is:
  stream       : PLAYBACK
  access       : RW_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 2
  rate         : 44100
  exact rate   : 44100 (44100/1)
  msbits       : 16
  buffer_size  : 22050
  period_size  : 5512
  period_time  : 125000
  tstamp_mode  : NONE
  tstamp_type  : GETTIMEOFDAY
  period_step  : 1
  avail_min    : 5512
  period_event : 0
  start_threshold  : 22050
  stop_threshold   : 22050
  silence_threshold: 0
  silence_size : 0
  boundary     : 6206523236469964800

3.波形分析

现在我在图中i2s控制器与codec之间位置用逻辑分析仪抓取了i2s数据波形,

【该操作需要飞线,建议找硬件工程师帮忙】

波形文件aplay_xiaoniao.kvdat

一口君实际测试的i2s控制器为24位小端格式。由上图可知:

  1. xiaomiao.wav文件为s16_le格式,所以i2s控制器依次每次读取data后面2个字节的数据
  2. 根据帧时钟,依次在左右声道时隙,将pcm数据放到数据线中。
  3. 因为控制器是24位,所以各channel会有24个bit的时钟周期;
  4. 根据i2s协议,默认有效数据靠左,并且空1个bit的位置;多出来的8个bit位置默认补充填0。

5. codec就会通过该波形提取对应的pcm数据,做出相应处理之后就可以播放出去了。

四、如何在各种音频格式之间进行转换

处于测试需要,我们还需要经常转换文件格式,可以通过FFmpeg工具

1. FFmpeg

对于其他格式的音频文件,一般用FFmpeg软件进行转换,先在当前的设备安装好FFmpeg软件,然后用命令行就可以进行转换了,常用的示范如下:

  • 将mp4视频提取wav格式:
ffmpeg -i D:\input.mp4 -vn -acodec pcm_s16le -ar 44100 -ac 2 D:\output.wav
  • 将wav格式转变为pcm格式:
ffmpeg -i D:\output.wav -f s16le -acodec pcm_s16le D:\output.pcm
  • 将pcm格式转变为wav格式:
ffmpeg -f s16le -ar 44100 -ac 2 -i D:\output.pcm c:\output.wav

注意上面的命令中指定的采样率为44.1k ,双声道,存储格式是s16le

2. 编写代码实现PCM → WAV 代码

下面是一个实现将pcm文件转换成wav文件的代码实例:

int simplest_pcm16le_to_waveconst char *pcmpath, int channels, int sample_rate, const char *wavepath )
// 省去错误判断
    short pcmData;
    FILE* fp = fopen( pcmpath, "rb" );
    FILE* fpout = fopen( wavepath, "wb+" );
    
    // 填充 WAVE_HEADER
    WAVE_HEADER pcmHEADER;
    memcpy( pcmHEADER.ChunkID, "RIFF"strlen"RIFF" ) );
    memcpy( pcmHEADER.Format, "WAVE"strlen"WAVE" ) );
    fseek( fpout, sizeof( WAVE_HEADER ), 1 );
    
    //填充 WAVE_FMT 
    WAVE_FMT pcmFMT;
    pcmFMT.SampleRate = sample_rate;
    pcmFMT.ByteRate = sample_rate * sizeof( pcmData );
    pcmFMT.BitsPerSample = 8 * sizeof( pcmData );
    memcpy( pcmFMT.Subchunk1ID, "fmt "strlen"fmt " ) );
    pcmFMT.Subchunk1Size = 16;
    pcmFMT.BlockAlign = channels * sizeof( pcmData );
    pcmFMT.NumChannels = channels;
    pcmFMT.AudioFormat = 1;
    fwrite( &pcmFMT, sizeof( WAVE_FMT ), 1, fpout );

    //填充 WAVE_DATA;
    WAVE_DATA pcmDATA;
    memcpy( pcmDATA.Subchunk2ID, "data"strlen"data" ) );
    pcmDATA.Subchunk2Size = 0;
    fseek( fpout, sizeof( WAVE_DATA ), SEEK_CUR );
    fread( &m_pcmData, sizeof( short ), 1, fp );
    while ( !feof( fp ) ) {
         pcmDATA.dwSize += 2;
         fwrite( &m_pcmData, sizeof( short ), 1, fpout );
         fread( &m_pcmData, sizeof( short ), 1, fp );
    }
    
    int headerSize = sizeof( pcmHEADER.Format ) + sizeof( WAVE_FMT ) + sizeof( WAVE_DATA ); // 36
    pcmHEADER.ChunkSize = headerSize + pcmDATA.Subchunk2Size;

    rewind( fpout );
    fwrite( &pcmHEADER, sizeof( WAVE_HEADER ), 1, fpout );
    fseek( fpout, sizeof( WAVE_FMT ), SEEK_CUR );
    fwrite( &pcmDATA, sizeof( WAVE_DATA ), 1, fpout );
    fclose( fp );
    fclose( fpout );
    return 0;
}

大家可以用我提供的sound.pcmxiaoniao.wav语音文件,测试一下。

end



一口Linux 


关注,回复【1024】海量Linux资料赠送


精彩文章合集

文章推荐

【专辑】ARM
【专辑】粉丝问答
【专辑】所有原创
专辑linux入门
专辑计算机网络
专辑Linux驱动
【干货】嵌入式驱动工程师学习路线
【干货】Linux嵌入式所有知识点-思维导图


一口Linux 写点代码,写点人生!
评论
  • 日前,商务部等部门办公厅印发《手机、平板、智能手表(手环)购新补贴实施方案》明确,个人消费者购买手机、平板、智能手表(手环)3类数码产品(单件销售价格不超过6000元),可享受购新补贴。每人每类可补贴1件,每件补贴比例为减去生产、流通环节及移动运营商所有优惠后最终销售价格的15%,每件最高不超过500元。目前,京东已经做好了承接手机、平板等数码产品国补优惠的落地准备工作,未来随着各省市关于手机、平板等品类的国补开启,京东将第一时间率先上线,满足消费者的换新升级需求。为保障国补的真实有效发放,基于
    华尔街科技眼 2025-01-17 10:44 221浏览
  • 现在为止,我们已经完成了Purple Pi OH主板的串口调试和部分配件的连接,接下来,让我们趁热打铁,完成剩余配件的连接!注:配件连接前请断开主板所有供电,避免敏感电路损坏!1.1 耳机接口主板有一路OTMP 标准四节耳机座J6,具备进行音频输出及录音功能,接入耳机后声音将优先从耳机输出,如下图所示:1.21.2 相机接口MIPI CSI 接口如上图所示,支持OV5648 和OV8858 摄像头模组。接入摄像头模组后,使用系统相机软件打开相机拍照和录像,如下图所示:1.3 以太网接口主板有一路
    Industio_触觉智能 2025-01-20 11:04 150浏览
  •     IPC-2581是基于ODB++标准、结合PCB行业特点而指定的PCB加工文件规范。    IPC-2581旨在替代CAM350格式,成为PCB加工行业的新的工业规范。    有一些免费软件,可以查看(不可修改)IPC-2581数据文件。这些软件典型用途是工艺校核。    1. Vu2581        出品:Downstream     
    电子知识打边炉 2025-01-22 11:12 55浏览
  • 临近春节,各方社交及应酬也变得多起来了,甚至一月份就排满了各式约见。有的是关系好的专业朋友的周末“恳谈会”,基本是关于2025年经济预判的话题,以及如何稳定工作等话题;但更多的预约是来自几个客户老板及副总裁们的见面,他们为今年的经济预判与企业发展焦虑而来。在聊天过程中,我发现今年的聊天有个很有意思的“点”,挺多人尤其关心我到底是怎么成长成现在的多领域风格的,还能掌握一些经济趋势的分析能力,到底学过哪些专业、在企业管过哪些具体事情?单单就这个一个月内,我就重复了数次“为什么”,再辅以我上次写的:《
    牛言喵语 2025-01-22 17:10 43浏览
  • 本文介绍瑞芯微开发板/主板Android配置APK默认开启性能模式方法,开启性能模式后,APK的CPU使用优先级会有所提高。触觉智能RK3562开发板演示,搭载4核A53处理器,主频高达2.0GHz;内置独立1Tops算力NPU,可应用于物联网网关、平板电脑、智能家居、教育电子、工业显示与控制等行业。源码修改修改源码根目录下文件device/rockchip/rk3562/package_performance.xml并添加以下内容,注意"+"号为添加内容,"com.tencent.mm"为AP
    Industio_触觉智能 2025-01-17 14:09 164浏览
  •  万万没想到!科幻电影中的人形机器人,正在一步步走进我们人类的日常生活中来了。1月17日,乐聚将第100台全尺寸人形机器人交付北汽越野车,再次吹响了人形机器人疯狂进厂打工的号角。无独有尔,银河通用机器人作为一家成立不到两年时间的创业公司,在短短一年多时间内推出革命性的第一代产品Galbot G1,这是一款轮式、双臂、身体可折叠的人形机器人,得到了美团战投、经纬创投、IDG资本等众多投资方的认可。作为一家成立仅仅只有两年多时间的企业,智元机器人也把机器人从梦想带进了现实。2024年8月1
    刘旷 2025-01-21 11:15 399浏览
  • 2024年是很平淡的一年,能保住饭碗就是万幸了,公司业绩不好,跳槽又不敢跳,还有一个原因就是老板对我们这些员工还是很好的,碍于人情也不能在公司困难时去雪上加霜。在工作其间遇到的大问题没有,小问题还是有不少,这里就举一两个来说一下。第一个就是,先看下下面的这个封装,你能猜出它的引脚间距是多少吗?这种排线座比较常规的是0.6mm间距(即排线是0.3mm间距)的,而这个规格也是我们用得最多的,所以我们按惯性思维来看的话,就会认为这个座子就是0.6mm间距的,这样往往就不会去细看规格书了,所以这次的运气
    wuliangu 2025-01-21 00:15 186浏览
  • 数字隔离芯片是一种实现电气隔离功能的集成电路,在工业自动化、汽车电子、光伏储能与电力通信等领域的电气系统中发挥着至关重要的作用。其不仅可令高、低压系统之间相互独立,提高低压系统的抗干扰能力,同时还可确保高、低压系统之间的安全交互,使系统稳定工作,并避免操作者遭受来自高压系统的电击伤害。典型数字隔离芯片的简化原理图值得一提的是,数字隔离芯片历经多年发展,其应用范围已十分广泛,凡涉及到在高、低压系统之间进行信号传输的场景中基本都需要应用到此种芯片。那么,电气工程师在进行电路设计时到底该如何评估选择一
    华普微HOPERF 2025-01-20 16:50 73浏览
  • 随着消费者对汽车驾乘体验的要求不断攀升,汽车照明系统作为确保道路安全、提升驾驶体验以及实现车辆与环境交互的重要组成,日益受到业界的高度重视。近日,2024 DVN(上海)国际汽车照明研讨会圆满落幕。作为照明与传感创新的全球领导者,艾迈斯欧司朗受邀参与主题演讲,并现场展示了其多项前沿技术。本届研讨会汇聚来自全球各地400余名汽车、照明、光源及Tier 2供应商的专业人士及专家共聚一堂。在研讨会第一环节中,艾迈斯欧司朗系统解决方案工程副总裁 Joachim Reill以深厚的专业素养,主持该环节多位
    艾迈斯欧司朗 2025-01-16 20:51 198浏览
  • 嘿,咱来聊聊RISC-V MCU技术哈。 这RISC-V MCU技术呢,简单来说就是基于一个叫RISC-V的指令集架构做出的微控制器技术。RISC-V这个啊,2010年的时候,是加州大学伯克利分校的研究团队弄出来的,目的就是想搞个新的、开放的指令集架构,能跟上现代计算的需要。到了2015年,专门成立了个RISC-V基金会,让这个架构更标准,也更好地推广开了。这几年啊,这个RISC-V的生态系统发展得可快了,好多公司和机构都加入了RISC-V International,还推出了不少RISC-V
    丙丁先生 2025-01-21 12:10 112浏览
  • Ubuntu20.04默认情况下为root账号自动登录,本文介绍如何取消root账号自动登录,改为通过输入账号密码登录,使用触觉智能EVB3568鸿蒙开发板演示,搭载瑞芯微RK3568,四核A55处理器,主频2.0Ghz,1T算力NPU;支持OpenHarmony5.0及Linux、Android等操作系统,接口丰富,开发评估快人一步!添加新账号1、使用adduser命令来添加新用户,用户名以industio为例,系统会提示设置密码以及其他信息,您可以根据需要填写或跳过,命令如下:root@id
    Industio_触觉智能 2025-01-17 14:14 122浏览
  •  光伏及击穿,都可视之为 复合的逆过程,但是,复合、光伏与击穿,不单是进程的方向相反,偏置状态也不一样,复合的工况,是正偏,光伏是零偏,击穿与漂移则是反偏,光伏的能源是外来的,而击穿消耗的是结区自身和电源的能量,漂移的载流子是 客席载流子,须借外延层才能引入,客席载流子 不受反偏PN结的空乏区阻碍,能漂不能漂,只取决于反偏PN结是否处于外延层的「射程」范围,而穿通的成因,则是因耗尽层的过度扩张,致使跟 端子、外延层或其他空乏区 碰触,当耗尽层融通,耐压 (反向阻断能力) 即告彻底丧失,
    MrCU204 2025-01-17 11:30 182浏览
  • 高速先生成员--黄刚这不马上就要过年了嘛,高速先生就不打算给大家上难度了,整一篇简单但很实用的文章给大伙瞧瞧好了。相信这个标题一出来,尤其对于PCB设计工程师来说,心就立马凉了半截。他们辛辛苦苦进行PCB的过孔设计,高速先生居然说设计多大的过孔他们不关心!另外估计这时候就跳出很多“挑刺”的粉丝了哈,因为翻看很多以往的文章,高速先生都表达了过孔孔径对高速性能的影响是很大的哦!咋滴,今天居然说孔径不关心了?别,别急哈,听高速先生在这篇文章中娓娓道来。首先还是要对各位设计工程师的设计表示肯定,毕竟像我
    一博科技 2025-01-21 16:17 101浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦