实验使用的是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;
}
上一篇:STM32F4 FFT 音乐频谱 不要太easy!
下一篇:LPC1768 -- RTC实时时钟
推荐阅读最新更新时间:2024-03-16 16:09