文章目录

  • WAV
    • 简介
    • 组成
      • RIFF Chunk
      • Format块
      • Fact Chunk
      • Data Chunk
    • 数据
  • WM8978
    • 特点
    • 接口
    • 寄存器(9位)
    • 初始化
      • 初始化WM8978
      • 初始化I2S
      • 解析WAV文件
      • 设置DMA
      • 编写DMA传输完成中断服务函数
      • 开启DMA传输 填充数据
  • 代码

WAV

简介

WAVE文件 是最常用的数字化声音文件格式之一
扩展名为 .wav 符合RIFF文件规范
适用Windows平台
支持MS ADPCM 、CCITT A LAW等压缩运算法
支持多种音频数字 取样频率和声道
(MS ADPCM 针对16bit或更高声音波形数据的一种有损压缩算法,它将声音流中每次采样的16bit数据以4bit存储 即压缩比1:4,ADPCM针对连续的波形数据,保存波形的变化情况,已达到描述整个波形的目的
CCITT A LAW 彩铃格式 A率压缩算法

组成

WAV由若干Chunk组成
包括①RIFF WAV Chunk 、②Format Chunk、③Fact Chunk和④Data Chunk
各部分由块标识符(4ASCLL)、数据大小和数据三部分组成

RIFF Chunk

//RIFF块
typedef_packed struct
{u32 ChunkID;u32 ChunkSize;   //集合大小 文件总大小8u32 Format;           //集合大小 WAVE 即0X45564157
}ChunkRIFF;

Format块

//fmt 块
typedef _packed struct
{u32 ChunkID;                 //chunk id  固定fmt ,即0X2074D66u32 ChunkSize;             //子集合大小u16 AudioFormat;          //音频格式 表示线性PCMu16 NumOfChannels;    //通道数量 1:单声道 2:双声道u32 SampleRate;          //采样率0X1F40 表示8Khzu32 ByteRate;               //字节速率 =采样率*通道数*(ADC位数/8)u16 BlockAlign;             //块对齐(字节)u16 BitsPerSamples;    //单个采样的位数 16位PCM 设置为16u16 ByteExtraData;        //附加数据字节2个
}ChunkFMT;

Fact Chunk

非PCM格式的文件中 一般会在Format结构后加入一个FACT块

typedef _packed struct
{u32 ChunkID ;    //chunk id u32 ChunkSize;  //子集合大小 这里为4u32 DataFactSize; //数据转换为PCM格式后的大小
}ChunkFACT;

Data Chunk

typedef _packed struct
{
u32 ChunkID; //chunk id 固定为data 即0X61746164
u32 ChunkSize; //子集合大小
}ChunkDATA;

数据


每个取样为4或6个字节 低字节在前 高字节在后
得到WAV数据 经I2S传输到WM8978

WM8978

全功能音频处理 带有HIFI级数字信号处理内核
输出功率达0.9W

特点

I2S接口 支持最高192K 24bit音频播放
DAC信噪比98DB ADC信噪比90DB
支持无电容耳机驱动 扬声器输出 麦克风输入 左右声道音量独立调节 5路EQ调节

接口

通过I2S接口同MCU进行音频数据传输 通过两线(MODE=0,即IIC接口)或三线(MODE=1)接口进行配置
4个引脚组成
ADCDAT: ADC数据输出
DACDAT:DAC数据输入
LRC:数据左右对齐时钟
BCLK :位时钟 用于同步
数据传输协议:

数据在跟随LRC传输的BCLK的第二个上升沿传输MSB 其他位一直到LSB按顺序传输
LRC频率就是音频信号的采样率
对于STM32F4 提供MCLK时钟 频率必须等于256fs 也就是音频采样率的256倍

寄存器(9位)

R0寄存器

用于控制WM8978的软复位 写任意值到该寄存器地址 可实现软复位

R1寄存器:

第三位设置为1 使模拟部分的放大器工作

R2寄存器:

R3寄存器:

ROUT1EN 和 LOUT1EN设置为1 使能耳机 SLEEP=0 进入正常工作模式

R4寄存器:
WL设置字长 00表示16位音频 10表示24位音频 FMT用于设置I2S音频数据格式 10即为飞利浦模式
R6寄存器:
MCLK和BCLK都来自STM32F4

R10寄存器:

SOFTMUTE设置为0 关闭软件静音
DACOSR128设置为1 DAC得到最好的SNR

R49寄存器

音量大小:SPKBOOST
TSDEN:过热保护

R50 R51:左右声道

需要将左右声道DAC输出接入左右声道混合器里面

R52 R53寄存器

设置耳机输出的左右声道

初始化

初始化WM8978

即配置WM8978 的寄存器

初始化I2S

使能SPI_I2SCFGR 寄存器 设置I2S模式 I2S标准 使能I2S外设

解析WAV文件

获取音频信号采样率和位数并设置I2S时钟分频器

设置DMA

F4具有双缓冲机制 设置为双缓冲循环模式 外设和存储器都是16位宽 开启DMA传输完成中断

编写DMA传输完成中断服务函数


音频数据流进入DMA 每一个缓冲数据发送完后 硬件自动切换为下一个缓冲 同时进入中断服务函数
填充数据到发送完的这个缓冲

开启DMA传输 填充数据

开启DMA传输 及时填充WAV数据到DMA的两个缓冲区

代码

u8 WM8978_Init(void)
u8 res;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB|RCC_AHBlPeriph_GPIOC, ENABLE);
//使能外设GPIOB,GPIOC时钟
//PB12/13 复用功能输出
GPIO InitStructure.GPIO_Pin = GPIO Pin 12 I GPIO Pin 13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_l00MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
//PC2/PC3/PC6复用功能输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 I GPIO_Pin_3|GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_lOOMHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPdUP;//上拉
GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化
GPIO_PinAFConfig(GPIOB,GPIO_PinSourcel2,GPIO_AF_SPI2);//PB12,AF5 I2S_LRCK
GPIO_PinAFConfig(GPIOB,GPIO_PinSourcel3,GPIO_AF_SPI2):;//PB13,AF5 I2S_SCLK
GPIO_PinAFConfig(GPIOC,GPIO_PinSource3,GPIO_AF_SPI2);//PC3 ,AF5 I2S DACDATA
GPIO_PinAFConfig(GPIOC,GPIO_PinSource6,GPIO_AF_SPI2):;//PC6 ,AF5 I2S MCK
GPIO_PinAFConfig(GPIOC,GPIO_PinSource2,GPIO_AF6_SPI2); //PC2 ,AF6 I2S_ADCDATA I2S2ext_SD是AFIIC_Init();//初始化IIC接口
res=WM8978_Write_Reg(0,0);
//软复位WM8978
if(res)return 1;
//发送指令失败,WM8978异常
//以下为通用设置
WM8978_Write_Reg(1,0X1B);//R1,MICEN设置为1(MIc使能),BIASEN设置为1(模拟器工作),VMIDSEL[1:0]设置为:11(5K)
WM8978_Write_Reg(2,0X1B0); //R2,ROUT1,LOUT1输出使能(耳机可以工作),BOOSTENR,BOOSTENL使能
WM8978_Write_Reg(3,0X6C);//R3,LOUT2,ROUT2输出使能(喇叭工作),RMIX,LMIX使能
WM8978_Write_Reg(6,0);
//R6,MCLK由外部提供
WM8978_Write_Reg(43,1<<4);
//R43,INVROUT2反向,驱动喇叭
WM8978_Write_Reg(47,1<<8);
//R47设置,PGABOOSTL,左通道MIC获得20倍增益
WM8978_Write_Reg(48,1<<8);
//R48设置,PGABOOSTR,右通道MIC获得20倍增益
WM8978_Write_Reg(49,1<<1);
: //R49,TSDEN,开启过热保护
WM8978_Write_Reg(10,1<<3);
//R10,SOFTMUTE关闭,128x采样,最佳SNR
WM8978_Write_Reg(l4,l<<3);
//R14,ADC 128x采样率
return 0;
}

WAV和WM8978相关推荐

  1. GitHub - ErnestChen1/SmartSpeaker: 一个基于云端语音识别的智能控制设备,类似于天猫精灵,小爱同学。采用的芯片为stm32f407,wm8978,esp8266。...

    SmartSpeaker 这是一个基于云端语音识别的智能音箱,你可以理解为类似于亚马逊Echo或者小爱同学.天猫精灵的设备,与之不同的是它并非基于嵌入式Linux,而是仅仅基于单片机和FreeRTOS ...

  2. android打开wav格式,FileNotFoundException从Android资产中打开wav文件

    在我们的android应用程序中,我们打开位于assets/config/notification.wav中的wav文件.要打开和播放声音,我们使用下面的代码:FileNotFoundExceptio ...

  3. python计算wav的语谱图_Python实现电脑录音(含音频基础知识讲解)

    前言 今天开始进入近期系列文章的第一篇,如何用 Python 来实现录音功能. 在开始"造轮子"之前,个人一直强调一个观点,如果有些东西已经有了,不妨直接去 github 上搜,用 ...

  4. iPhone开发技巧之工具篇(4)--- 使用afconvert转换WAV文件

    转载自:http://www.yifeiyang.net/iphone-development-skills-of-tool-papers-4-wav-file-conversion-using-af ...

  5. arduino下载库出错_【arduino】DIY音乐播放器,arduino播放wav音乐,TRMpcm库测试及使用...

    微信关注 "DLGG创客DIY"设为"星标",重磅干货,第一时间送达. arduino特点库超多,想必大家都领教了,今天来分享一下之前玩过的TRMpcm库. 这 ...

  6. C#文字转语音,实时播放以及mp3,wav文件保存

    源码下载地址:https://download.csdn.net/download/horseroll/10500847 无积分付费下载地址:https://download.csdn.net/dow ...

  7. python 播放 wav 文件

    python 播放 wav 文件 import pyaudio import wave def play_wav(wav_path):CHUNK = 1024# print("wav_pat ...

  8. 【windwos bat】批量把windows下的wav文件转为raw文件

    借助工具sox,可以批量将wav文件转为raw文件. @echo off set work_path=recordings set raw_path=raw SET mypath=%~dp0mkdir ...

  9. 根据时间点截取wav文件

    有一个训练数据需要整理,主要是从阿里云实时ASR获取的结果,结果中有文本与时间点信息. 比如 #test begin end yes i have found a better 20400 23530 ...

  10. java 修改wav文件头_使用Java聲音API從WAV文件中修剪開頭和結尾

    我有製作的基礎知識.但是,輸出文件一遍又一遍地重複WAV標頭字節.生成的文件大小合適,但是它與垃圾一起提交.使用Java聲音API從WAV文件中修剪開頭和結尾 我想使用一個擴展AudioInputSt ...

最新文章

  1. 太恐怖了,Linux服务器感染了kerberods病毒...
  2. C语言:为什么用fprintf(stderr,Error);比printf(Error);更好?
  3. Java 静态变量和静态方法
  4. javascript入门_JavaScript入门手册(2020版)
  5. UCOS II怎么查找当前就绪表中,优先级最高的任务
  6. Windows驱动签名,还需要使用EV代码签名证书吗?
  7. c语言方框透视原理,FPS游戏的方框透视+自瞄原理
  8. 为WIN7原生2019版ISO更改为中文
  9. CSR8311/CSR8811 HCI vendor command说明
  10. 关于怎么查看自己电脑正版windows的产品密钥
  11. android 面包屑控件,android面包屑導航欄的實現
  12. 喉炎在临床上的症状表现
  13. OpenCV切割图片
  14. Elasticsearch实战(十三)---聚合搜索Aggs聚合及Count,Avg操作
  15. 根据卫星的方位角和仰角画卫星星空图(QT实现)
  16. R740 U盘启动设置和安装centos7报错处理
  17. 华为OD机试 - 高矮个子排队
  18. numpy均匀分布_Numpy的基本操作
  19. 血栓清道夫机器人_这几种食物是血管“清道夫”,每天吃一点,清除血管垃圾,防血栓...
  20. Shopee代贴单对商家有什么好处?星卓越货代系统告诉你

热门文章

  1. 海康威视实习第一周总结
  2. JavaScript高级—正则表达式(正则表达式在 JavaScript 中的使用、正则表达式中的特殊字符、正则表达式中的替换)
  3. slot的使用方法详解
  4. C# 文件大小字节byte换算为 Kb Mb Gb Tb
  5. 2018年迎春杯复赛入围名单(五年级)
  6. 二元函数可微与切平面存在的关系
  7. C语言中的while循环语句的使用
  8. 批处理bat优化Win10 LTSC 2019系统设置
  9. STM32F407移植FreeModbus中遇到接收最后一个字节是0xff或0xfe的解决方法
  10. 综述 | 一文看尽三种针对人工智能系统的攻击技术及防御策略