历史上的今天
今天是:2025年07月24日(星期四)
2018年07月24日 | LPC1768 WAV播放器 笔记
2018-07-24 来源:eefocus
实验使用的是LPC1768 DMA + 10bit DAC作为音频信号输出,使用USB HOST 读取U盘中存储的WAV格式的音频文件,读取和播放数据文件使用的是乒乓算法。
WAV文件格式见:http://blog.csdn.net/seeker_zeroone/article/details/17526523(备注: 网络转载)
以下是根据文件格式定义的结构图。
typedef struct RIFF_HEADER
{
uint32_t RiffFlg; //RIFF
uint32_t FileSize; //整个文件大小(不包含 RiffFlg FileSize)
uint32_t FileType; //WAVE
}WAV_HEADER;
typedef struct FORMAT
{
uint32_t FmtFlg; //FMT
uint32_t FmtSize; // 0X16 或者 0X18,0X18 表示有附加信息
uint16_t FmtTag; //编码方式 0x0001
uint16_t ChN; //声道 1-单声道 2 双声道
uint32_t Samples; //采样频率
uint32_t AvgBytes; //每秒所需字节数
uint16_t BlockAlign; //块对起
uint16_t AvrBits; //每个采样所需要的bit
uint16_t ROF; //附加信息——由SIZE决定
}WAV_FORMAT;
typedef struct FACT_BLOCK //选项
{
uint32_t FactFlg; //FACT
uint32_t FactSize;
}WAV_FCTBLOCK;
typedef struct DATA_BLOCK
{
uint32_t DataFlg; //DATA
uint32_t DataSize;
}WAV_DATA;
typedef struct Inf
{
uint32_t StartAddr; //文件头地址
uint32_t EndAddr; //文件尾地址
uint32_t DataSize;
// uint32_t IndexF; //读文件地址
uint8_t *pIndexB; //缓存读取地址
// uint16_t FmtTag; //编码方式
// uint16_t ChN; //通道
uint32_t Samples; //采样频率
// uint32_t AvgBytes; //每秒种采样字节数
// uint16_t BlockAlign; //数据块对齐单位(每个采样需要的字节数)
// uint16_t BitsPerSample; //每个采样需要的bit数
uint16_t *pBuff; //缓存
uint8_t State; //状态
uint8_t Flag; //有效标志
uint16_t PlayWords; //
uint8_t PlayPingPeng; //
}WAV_INF;
加载文件信息,识别该文件是符合规则的WAV文件,这里只允许单声道 PCM 编码 16位量化精度 的WAV文件播放。
uint8_t WAV_LoadFileMsg(void)
{
#if USB
FRESULT res;
uint32_t re;
#endif
uint16_t Temp,Index,Data,*pData;
uint32_t IDFlag;
WAV_HEADER *pHWav;
WAV_FORMAT *pFWav;
WAV_FCTBLOCK *pFctWav;
WAV_DATA *pDatWav;
WAV_File.StartAddr =(uint32_t)File1_Sec * (uint32_t)Sec_SIZE;
WAV_File.pIndexB =(uint8_t *)WAVBuff;
#if (USB)
res = f_read(&usbfile0,WAVBuff,BUFF_SIZE,&re);
if((res != FR_OK)||(re != BUFF_SIZE))
{
UART0_Printf("文件读取失败,错误代码 %d \r\n",res);
}
#endif
pHWav =(WAV_HEADER *)WAV_File.pIndexB;
IDFlag =('R') | ('I' << 8) | ('F' << 16) | ('F' << 24);
if(IDFlag !=pHWav->RiffFlg)
{
UART0_Printf("RIFF logo 未找到!\r\n");
return FALSE;
}
IDFlag =('W') | ('A' << 8) | ('V' << 16) | ('E' << 24);
if(IDFlag !=pHWav->FileType)
{
UART0_Printf("WAVE logo 未找到!\r\n");
return FALSE;
}
WAV_File.EndAddr = 8 + pHWav->FileSize + WAV_File.StartAddr;
WAV_File.pIndexB +=sizeof( WAV_HEADER );
pFWav =(WAV_FORMAT *)WAV_File.pIndexB;
IDFlag =('f') | ('m' << 8) | ('t' << 16) | (' '<< 24);
if(IDFlag!= pFWav->FmtFlg)
{
UART0_Printf("fmt logo 未找到!\r\n");
return FALSE;
}
if( pFWav->FmtTag!=WAVE_FORMAT_PCM)
{
UART0_Printf("不是PCM格式编码\r\n");
return FALSE;
}
if( pFWav->ChN != 0x01)
{
UART0_Printf("不是单声道\r\n");
return FALSE;
}
if( pFWav->AvrBits != 0x10)
{
UART0_Printf("量化分辨率不是16 Bit\r\n");
return FALSE;
}
WAV_File.BitsPerSample =pFWav->AvrBits;
WAV_File.Samples =pFWav->Samples;
UART0_Printf("采样率是 %d bps \r\n",pFWav->Samples * pFWav->AvrBits);
WAV_File.pIndexB +=0x1a; //sizeof(WAV_FORMAT);====>有点问题待处理
if(pFWav->FmtSize == 16) WAV_File.pIndexB -=2;
pFctWav =(WAV_FCTBLOCK *)WAV_File.pIndexB;
IDFlag =('f') | ('a' << 8) | ('c' << 16) | ('t' << 24);
if(IDFlag == pFctWav->FactFlg)
{
WAV_File.pIndexB +=pFctWav->FactSize + sizeof(WAV_FCTBLOCK);
}
pDatWav =(WAV_DATA *)WAV_File.pIndexB;
IDFlag =('d') | ('a' << 8) | ('t' << 16) | ('a' << 24);
if(IDFlag != pDatWav->DataFlg)
{
UART0_Printf("没有找到 data logo \r\n");
return FALSE;
}
Index =WAV_File.pIndexB - (uint8_t *)WAVBuff;
WAV_File.PlayWords =BUFF_SIZE - Index;
WAV_File.DataSize =pDatWav->DataSize -WAV_File.PlayWords;
WAV_File.PlayWords >>=1;
WAV_File.PlayPingPeng =PlayPeng;
WAV_File.pBuff =WAVBuff + BUFF_HalfSize;
WAV_File.pIndexB =(uint8_t *)WAVBuff + Index;
pData =(uint16_t *)WAV_File.pIndexB;
for(Temp=0;Temp
Data = *(pData + Temp);
if(Data & 0x8000) //负数
{
Data =(~Data) + 0x8001;
}
else //正数
{
Data +=0x8000;
}
WAV_File.pBuff[Temp] = Data & 0xffc0;
}
return TRUE;
}
加载波形文件数据
uint8_t WAV_LoadData(void)
{
#if USB
FRESULT res;
uint32_t re;
#endif
uint16_t ReadSize;
if(WAV_File.DataSize)
{
if(WAV_File.DataSize > BUFF_SIZE)
{
ReadSize =BUFF_SIZE;
}
else
{
ReadSize =WAV_File.DataSize;
}
WAV_File.DataSize -=ReadSize;
WAV_File.PlayWords =ReadSize >> 1;
if(WAV_File.PlayPingPeng == PlayPeng)
{
WAV_File.pBuff =WAVBuff;
#if USB
res = f_read(&usbfile0,(void *)WAV_File.pBuff,ReadSize ,&re);
if((res != FR_OK)||(re != ReadSize))
{
UART0_Printf("读文件失败\r\n");
}
for(re=0;re
if( WAV_File.pBuff[re] & 0x8000) //负数
{
WAV_File.pBuff[re] =(~ WAV_File.pBuff[re]) + 0x8001;
}
else //正数
{
WAV_File.pBuff[re] +=0x8000;
}
}
#endif
if(WAV_File.DataSize)
{
WAV_File.PlayPingPeng =PlayPing;
}
else
{
WAV_File.PlayPingPeng =PlayEnd;
}
}
else if(WAV_File.PlayPingPeng ==PlayPing)
{
WAV_File.pBuff =WAVBuff + BUFF_HalfSize;
#if USB
res = f_read(&usbfile0,(void *)WAV_File.pBuff,ReadSize ,&re);
if((res != FR_OK)||(re != ReadSize))
{
UART0_Printf("读文件失败\r\n");
}
for(re=0;re
if( WAV_File.pBuff[re] & 0x8000) //负数
{
WAV_File.pBuff[re] =(~ WAV_File.pBuff[re]) + 0x8001;
}
else //正数
{
WAV_File.pBuff[re] +=0x8000;
}
}
#endif
if(WAV_File.DataSize)
{
WAV_File.PlayPingPeng =PlayPeng;
}
else
{
WAV_File.PlayPingPeng =PlayEnd;
}
}
return TRUE;
}
return FALSE;
}
史海拾趣
|
达盛公司的TechvDM355开发板是款不错的达芬奇产品,给大家推荐一下: 硬件资源有: • 1路TV视频输出,用户可选的PAL/NTSC制式 • 用户可选的Nor Flash接口 • 64kb的 I2C 铁电存储 ...… 查看全部问答> |
|
新闻早班车:ST也推低于1美元的STM32 Value line 就在前两周,TI推出了其MSP430 VALUE LINE,准备进军8位市场 无独有偶,ST也推出了价格低于1美元的stm32 Value line 虽然目标市场还些许有些区别,但是共同点就一个:便宜。 ST VALUE LINE的概况: The STM32 Value line complements our STM ...… 查看全部问答> |
|
你能信任街道上行驶的交通工具能成为空气净化的一个要害么?以前这样的工作可是由道路两旁的绿化树木来完成的。下面就来介绍这样一款神奇的交通工具,该车配备了电动马达,四轮转向驱动,应用纳米钛阳极电池供给动力,车中载有过滤装置以扫除空气中 ...… 查看全部问答> |
|
现在我用BP_OpenPartition 将我的nand分成两个分区。 完了在ce上两个分区的盘符都正常 我USB 设为Mass_Storage_Class,完了接上USB在电脑上只能弹出第一个分区。后面另一个怎么也不出来 各位有没有遇到这种情况的。我的注册表 [HKEY_LOCAL_ ...… 查看全部问答> |
|
这里的“开关电源”指常规的各类低压集成式单片开关电源,在嵌入式系统及便携产品中有广泛的应用。 开关电源要降低纹波主要要在以下三个方面下功夫: 1、储能电感的正确选择。储能电感在工作频率下的Q值原则上越大越好 ...… 查看全部问答> |
|
有个项目需要在没有电源输入时,使用备用电池,如果有电源输入就使用输入电源供电,并为备用电池充电,不知道大家有没有什么好的电源切换和充电管理芯片,先谢了,电流最好是几个安培的。… 查看全部问答> |




