<acronym id="s8ci2"><small id="s8ci2"></small></acronym>
<rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
<acronym id="s8ci2"></acronym>
<acronym id="s8ci2"><center id="s8ci2"></center></acronym>
0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

如何從SD卡讀取音頻文件并將其輸出到揚聲器上?

OpenFPGA ? 來源:OpenFPGA ? 2024-01-22 09:23 ? 次閱讀

開篇第一步

在上一篇教程中,創建了一個 I2S 發送器用來發送來從FPGA內部 ROM音頻數據。下一步,我們向該 I2S 發送器添加 AXI-Stream 接口,這樣我們就可以將發送器與 ZYNQ 的處理系統連接,還可以從 SD 卡讀取音頻數據。

為此,創建一個新的top設計。本設計應具有以下接口:

501d60ec-b8c4-11ee-8b88-92fbcf53809c.png

該塊設計產生以下代碼:

entityAXIS_I2Sis
Generic(RATIO:INTEGER:=8;
WIDTH:INTEGER:=16
);
Port(MCLK:inSTD_LOGIC;
nReset:inSTD_LOGIC;
LRCLK:outSTD_LOGIC;
SCLK:outSTD_LOGIC;
SD:outSTD_LOGIC;
ACLK:inSTD_LOGIC;
ARESETn:inSTD_LOGIC;
TDATA_RXD:inSTD_LOGIC_VECTOR(31downto0);
TREADY_RXD:outSTD_LOGIC;
TVALID_RXD:inSTD_LOGIC
);
endAXIS_I2S;

SCLK與MCKL的比率通過RATIO參數定義,每個通道的數據字寬度通過WIDTH參數定義。

PS:此實現僅支持每個通道 16 位數據字(即立體聲 32 位)。

?設計中必須實現以下組件:

用于為 I2S 發送器創建輸入時鐘的時鐘預分頻器

AXI-Stream 從接口

I2S發送器的控制邏輯?

為分頻器創建了一個過程,該過程在MCLK時鐘上升沿對計數器進行計數,并在半個周期后切換信號SCLK_Int。

process
variableCounter:INTEGER:=0;
begin
waituntilrising_edge(MCLK);
if(Counter

下一步是實現 AXI-Stream 接口。為此使用狀態機:

process
begin
waituntilrising_edge(ACLK);
caseCurrentStateis
whenState_Reset=>
Tx_AXI<=?(others?=>'0');
CurrentState<=?State_WaitForTransmitterReady;

????????when?State_WaitForTransmitterReady?=>
if(Ready_AXI='1')then
TREADY_RXD<=?'1';
????????????????CurrentState?<=?State_WaitForValid;
????????????else
????????????????TREADY_RXD?<=?'0';
????????????????CurrentState?<=?State_WaitForTransmitterReady;
????????????end?if;
????????when?State_WaitForValid?=>
if(TVALID_RXD='1')then
TREADY_RXD<=?'0';
????????????????Tx_AXI?<=?TDATA_RXD;
????????????????CurrentState?<=?State_WaitForTransmitterBusy;
????????????else
????????????????TREADY_RXD?<=?'1';
????????????????CurrentState?<=?State_WaitForValid;
????????????end?if;
????????when?State_WaitForTransmitterBusy?=>
if(Ready_AXI='0')then
CurrentState<=?State_WaitForTransmitterReady;
????????????else
????????????????CurrentState?<=?State_WaitForTransmitterBusy;
????????????end?if;
????end?case;
????if(ARESETn?=?'0')?then
????????????CurrentState?<=?State_Reset;
????end?if;
end?process;

復位后,機器從State_Reset狀態變為State_WaitForTransmitter等待I2S 發送器發出就緒Ready信號的狀態。一旦發送器準備好,TREADY_RXD就會設置 AXI-Stream 接口的信號,通知主機從機已準備好接收數據。然后從機改變為State_WaitForValid狀態。

?在此狀態下,從機等待主機置位信號TVALID_RXD標記有效數據。一旦置位了信號,數據就會寫入內部 FIFO。然后機器改變到State_WaitForTransmitterBusy狀態。

?現在狀態機等待I2S發送器開始發送數據并“刪除”就緒信號。一旦完成,狀態機就會切換回State_WaitForTransmitterReady狀態并再次等待,直到 I2S 發送器準備就緒。

?這樣,理論上 AXI-Stream 接口就完成了。不幸的是,最后變得有點棘手,因為當前的電路設計使用兩個不同的時鐘域:

ACLK的時鐘域

MCLK的時鐘域

一般來說,這兩個時鐘信號不能從時鐘源生成(例如通過時鐘分頻器),因為 AXI 接口通常以 100 MHz 運行,而音頻接口需要可以整齊地分頻至采樣頻率的時鐘速率,例如 12.288 MHz。因此,由于最差負裕量 (WNS) 和總負裕量 (TNS) 過多,在實現過程中會出現時序錯誤:

502e470e-b8c4-11ee-8b88-92fbcf53809c.png

此外,由于觸發器在不同時鐘域中發生亞穩態而導致數據不正確的風險非常高。

因此,各個時鐘域所使用的信號必須在每種情況下經由相應的電路傳送到另一時鐘域。Xilinx 在文檔UG953(https://www.xilinx.com/support/documentation/sw_manuals/xilinx2018_3/ug953-vivado-7series-libraries.pdf)中描述了可用于此目的的相應宏。

xpm_cdc_gray - 該功能塊使用格雷碼將數據總線從一個時鐘域 (src) 傳輸到另一個時鐘域 (dest)。

xpm_cdc_single - 將單個信號從一個時鐘域 (src) 轉換到另一個時鐘域 (dest)。

宏的示例可以直接用于 VHDL 代碼:

xpm_cdc_Data:xpm_cdc_handshakegenericmap(DEST_EXT_HSK=>0,
DEST_SYNC_FF=>4,
INIT_SYNC_FF=>0,
SIM_ASSERT_CHK=>0,
SRC_SYNC_FF=>4,
WIDTH=>(2*WIDTH)
)
portmap(src_clk=>ACLK,
src_in=>Data_Fast,
dest_clk=>MCLK,
dest_out=>Data_Slow,
dest_ack=>'0',
src_send=>src_send,
src_rcv=>src_rcv,
dest_req=>dest_req
);

xpm_cdc_Ready:xpm_cdc_singlegenericmap(DEST_SYNC_FF=>4,
SRC_INPUT_REG=>1
)
portmap(src_clk=>MCLK,
src_in=>Ready_Transmitter,
dest_clk=>ACLK,
dest_out=>Ready_AXI
);

最后,必須插入 I2S 發送器并傳遞生成的信號。

Transmitter:I2S_Transmittergenericmap(WIDTH=>WIDTH
)
portmap(Clock=>SCLK_Int,
nReset=>nReset,
Ready=>Ready_Transmitter,
Tx=>Tx_Transmitter,
LRCLK=>LRCLK,
SCLK=>SCLK,
SD=>SD
);

I2S 發送器的 AXI-Stream 接口現已準備就緒并可供使用。完整的代碼如下所示:

libraryIEEE;
useIEEE.STD_LOGIC_1164.ALL;
libraryxpm;
usexpm.vcomponents.all;

entityAXIS_I2Sis
Generic(RATIO:INTEGER:=8;
WIDTH:INTEGER:=16
);
Port(MCLK:inSTD_LOGIC;
nReset:inSTD_LOGIC;
LRCLK:outSTD_LOGIC;
SCLK:outSTD_LOGIC;
SD:outSTD_LOGIC;
ACLK:inSTD_LOGIC;
ARESETn:inSTD_LOGIC;
TDATA_RXD:inSTD_LOGIC_VECTOR(31downto0);
TREADY_RXD:outSTD_LOGIC;
TVALID_RXD:inSTD_LOGIC
);
endAXIS_I2S;

architectureAXIS_I2S_ArchofAXIS_I2Sis
typeAXIS_State_tis(State_Reset,State_WaitForTransmitterReady,State_WaitForValid,State_WaitForTransmitterBusy);
signalCurrentState:AXIS_State_t:=State_Reset;
signalTx_AXI:STD_LOGIC_VECTOR(((2*WIDTH)-1)downto0):=(others=>'0');
signalReady_AXI:STD_LOGIC;
signalTx_Transmitter:STD_LOGIC_VECTOR(((2*WIDTH)-1)downto0):=(others=>'0');
signalReady_Transmitter:STD_LOGIC;
signalSCLK_Int:STD_LOGIC:='0';
componentI2S_Transmitteris
Generic(WIDTH:INTEGER:=16
);
Port(Clock:inSTD_LOGIC;
nReset:inSTD_LOGIC;
Ready:outSTD_LOGIC;
Tx:inSTD_LOGIC_VECTOR(((2*WIDTH)-1)downto0);
LRCLK:outSTD_LOGIC;
SCLK:outSTD_LOGIC;
SD:outSTD_LOGIC
);
endcomponent;

begin

Transmitter:I2S_Transmittergenericmap(WIDTH=>WIDTH
)
portmap(Clock=>SCLK_Int,
nReset=>nReset,
Ready=>Ready_Transmitter,
Tx=>Tx_Transmitter,
LRCLK=>LRCLK,
SCLK=>SCLK,
SD=>SD
);
xpm_cdc_Data:xpm_cdc_graygenericmap(DEST_SYNC_FF=>4,
SIM_ASSERT_CHK=>0,
SIM_LOSSLESS_GRAY_CHK=>0,
WIDTH=>(2*WIDTH)
)
portmap(src_clk=>ACLK,
src_in_bin=>Tx_AXI,
dest_clk=>MCLK,
dest_out_bin=>Tx_Transmitter
);
xpm_cdc_Ready:xpm_cdc_singlegenericmap(DEST_SYNC_FF=>4,
SRC_INPUT_REG=>1
)
portmap(src_clk=>MCLK,
src_in=>Ready_Transmitter,
dest_clk=>ACLK,
dest_out=>Ready_AXI
);
process
variableCounter:INTEGER:=0;
begin
waituntilrising_edge(MCLK);
if(Counter
Tx_AXI<=?(others?=>'0');
CurrentState<=?State_WaitForTransmitterReady;
????????????when?State_WaitForTransmitterReady?=>
if(Ready_AXI='1')then
TREADY_RXD<=?'1';
????????????????????CurrentState?<=?State_WaitForValid;
????????????????else
????????????????????TREADY_RXD?<=?'0';
????????????????????CurrentState?<=?State_WaitForTransmitterReady;
????????????????end?if;
????????????when?State_WaitForValid?=>
if(TVALID_RXD='1')then
TREADY_RXD<=?'0';
????????????????????Tx_AXI?<=?TDATA_RXD;
????????????????????CurrentState?<=?State_WaitForTransmitterBusy;
????????????????else
????????????????????TREADY_RXD?<=?'1';
????????????????????CurrentState?<=?State_WaitForValid;
????????????????end?if;
????????????when?State_WaitForTransmitterBusy?=>
if(Ready_AXI='0')then
CurrentState<=?State_WaitForTransmitterReady;
????????????????else
????????????????????CurrentState?<=?State_WaitForTransmitterBusy;
????????????????end?if;
????????end?case;
????????if(ARESETn?=?'0')?then
????????????CurrentState?<=?State_Reset;
????????end?if;
????end?process;
end?AXIS_I2S_Arch;

接下來,我們希望使用該接口從 SD 卡讀取波形文件,并使用 CS4344 D/A 轉換器通過連接的揚聲器輸出音樂。

該項目需要以下IP核:

具有 AXI-Stream 接口的 I2S 發送器

處理系統從 SD 卡讀取數據并將其寫入 FIFO

AXI-Stream FIFO

用于生成音頻時鐘的PLL

5038a082-b8c4-11ee-8b88-92fbcf53809c.png

時鐘向導生成時鐘,然后將其用作 CS4344 的主時鐘。輸出時鐘可以通過 AXI-Lite 接口適應音頻文件的采樣率。

5049e2b6-b8c4-11ee-8b88-92fbcf53809c.png

AXI-Stream FIFO 充當處理系統和 I2S 發送器之間的鏈接。處理系統通過 AXI-Lite(或 AXI)接口將數據寫入 FIFO,然后將數據傳輸至 I2S 發送器。

505b26d4-b8c4-11ee-8b88-92fbcf53809c.png

根據設計創建比特流,然后可以開發軟件。

讀取 SD 卡需要 Xilinx 的 xilffs FAT 庫,該庫必須集成到 Vitis 項目的板級支持包中(不要忘記啟用LFN支持大文件名的選項):

506eb532-b8c4-11ee-8b88-92fbcf53809c.png

第一步,軟件使用該AudioPlayer_Init函數初始化音頻播放器,從而初始化 FIFO、GIC 和中斷處理程序,以及時鐘向導和 SD 卡。

u32AudioPlayer_Init(void)
{
xil_printf("[INFO]LookingforFIFOconfiguration...
");
_Fifo_ConfigPtr=XLlFfio_LookupConfig(XPAR_FIFO_DEVICE_ID);
if(_Fifo_ConfigPtr==NULL)
{
xil_printf("[ERROR]InvalidFIFOconfiguration!
");
returnXST_FAILURE;
}

xil_printf("[INFO]InitializeFIFO...
");
if(XLlFifo_CfgInitialize(&_Fifo,_Fifo_ConfigPtr,_Fifo_ConfigPtr->BaseAddress)!=XST_SUCCESS)
{
xil_printf("[ERROR]FIFOinitializationfailed!

");
returnXST_FAILURE;
}

xil_printf("[INFO]LookingforGICconfiguration...
");
_GIC_ConfigPtr=XScuGic_LookupConfig(XPAR_PS7_SCUGIC_0_DEVICE_ID);
if(_GIC_ConfigPtr==NULL)
{
xil_printf("[ERROR]InvalidGICconfiguration!

");
returnXST_FAILURE;
}

xil_printf("[INFO]InitializeGIC...
");
if(XScuGic_CfgInitialize(&_GIC,_GIC_ConfigPtr,_GIC_ConfigPtr->CpuBaseAddress)!=XST_SUCCESS)
{
xil_printf("[ERROR]GICinitializationfailed!

");
returnXST_FAILURE;
}

xil_printf("[INFO]Setupinterrupthandler...
");
XScuGic_SetPriorityTriggerType(&_GIC,XPAR_FABRIC_FIFO_INTERRUPT_INTR,0xA0,0x03);
if(XScuGic_Connect(&_GIC,XPAR_FABRIC_FIFO_INTERRUPT_INTR,(Xil_ExceptionHandler)AudioPlayer_FifoHandler,&_Fifo)!=XST_SUCCESS)
{
xil_printf("[ERROR]Cannotconnectinterrupthandler!

");
returnXST_FAILURE;
}
XScuGic_Enable(&_GIC,XPAR_FABRIC_FIFO_INTERRUPT_INTR);

xil_printf("[INFO]Enableexceptions...
");
Xil_ExceptionInit();
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,&_GIC);
Xil_ExceptionEnable();

xil_printf("[INFO]EnableFIFOinterrupts...
");
XLlFifo_IntClear(&_Fifo,XLLF_INT_ALL_MASK);

xil_printf("[INFO]InitializeClockingWizard...
");
if((ClockingWizard_Init(&_ClkWiz,XPAR_CLOCKINGWIZARD_BASEADDR)||ClockingWizard_GetOutput(&_ClkWiz,&_AudioClock))!=XST_SUCCESS)
{
xil_printf("[ERROR]ClockingWizardinitializationfailed!

");
returnXST_FAILURE;
}
xil_printf("[INFO]MountSDcard...
");
if(SD_Init())
{
xil_printf("[ERROR]CannotinitializeSDcard!

");
returnXST_FAILURE;
}

returnXST_SUCCESS;
}

一旦初始化完成,就會調用AudioPlayer_LoadFile函數從 SD 卡加載Audio.wav文件 。

if(AudioPlayer_LoadFile("Audio.wav"))
{
xil_printf("[ERROR]CannotopenAudiofile!

");
returnXST_FAILURE;
}

u32AudioPlayer_LoadFile(char*File)
{
if(SD_LoadFileFromCard(File,&_File))
{
xil_printf("[ERROR]CannotopenAudiofile!

");
returnXST_FAILURE;
}

xil_printf("Filesize:%lubytes

",_File.Header.ChunkSize+8);
xil_printf("Fileformat:%lu

",_File.Format.AudioFormat);
xil_printf("Channels:%lu

",_File.Format.NumChannels);
xil_printf("Samplerate:%luHz

",_File.Format.SampleRate);
xil_printf("Bitspersample:%lubits

",_File.Format.BitsPerSample);
xil_printf("Blockalign:%lubytes

",_File.Format.BlockAlign);
xil_printf("Databytes:%lubytes

",_File.Header.ChunkSize/_File.Format.NumChannels);
xil_printf("Samples:%lu

",8*_File.Header.ChunkSize/_File.Format.NumChannels/_File.Format.BitsPerSample);

if((_File.Format.BitsPerSample!=16)||(_File.Format.NumChannels>2))
{
xil_printf("[ERROR]Invalidfileformat!

");
returnXST_FAILURE;
}
AudioPlayer_ChangeFreq(_File.Format.SampleRate);

XLlFifo_TxReset(&_Fifo);
XLlFifo_IntEnable(&_Fifo,XLLF_INT_ALL_MASK);
SD_CopyDataIntoBuffer(_FifoBuffer,256);
AudioPlayer_CopyBuffer();

returnXST_SUCCESS;
}
該函數AudioPlayer_LoadFile調用函數SD_LoadFileFromCard從SD卡加載波形文件。

u32SD_LoadFileFromCard(constchar*FileName,Wave_t*File)
{
xil_printf("[INFO]Openingfile:%s...

",FileName);

if(f_open(&_FileHandle,FileName,FA_READ))
{
xil_printf("[ERROR]Cannotopenaudiofile!

");
returnXST_FAILURE;
}

if(f_read(&_FileHandle,&File->RIFF,sizeof(Wave_RIFF_t),&_BytesRead)||f_read(&_FileHandle,&File->Format,sizeof(Wave_Format_t),&_BytesRead))
{
xil_printf("[ERROR]CannotreadSDcard!

");
returnXST_FAILURE;
}

Wave_Header_tHeader;
uint32_tOffset=sizeof(Wave_RIFF_t)+sizeof(Wave_Format_t);
if(f_read(&_FileHandle,Header.ChunkID,sizeof(Wave_Header_t),&_BytesRead)||f_lseek(&_FileHandle,Offset))
{
xil_printf("[ERROR]CannotreadSDcard!

");
returnXST_FAILURE;
}

if(strncmp("LIST",Header.ChunkID,4)==0)
{
Offset+=Header.ChunkSize+sizeof(Wave_Header_t);
if(f_read(&_FileHandle,&File->ListHeader,sizeof(Wave_Header_t),&_BytesRead)||f_lseek(&_FileHandle,Offset))
{
xil_printf("[ERROR]CannotplaceSDcardpointer!

");
returnXST_FAILURE;
}
}

if(f_read(&_FileHandle,&File->DataHeader,sizeof(Wave_Header_t),&_BytesRead))
{
xil_printf("[ERROR]CannotreadSDcard!

");
returnXST_FAILURE;
}

if(File->Format.AudioFormat!=WAVE_FORMAT_PCM)
{
xil_printf("[ERROR]Audioformatnotsupported!KeepsurethatthefileusethePCMformat!

");
returnXST_FAILURE;
}

_RemainingBytes=File->DataHeader.ChunkSize;

_IsBusy=true;

returnXST_SUCCESS;
}
在下一步中,根據使用的采樣頻率從波形文件中設置時鐘向導的輸出頻率:

staticvoidAudioPlayer_ChangeFreq(constu32SampleRate)
{
if(SampleRate==44100)
{
xil_printf("Useclocksetting1...

");
_ClkWiz.DIVCLK_DIVIDE=5;
_ClkWiz.CLKFBOUT_MULT=42;
_ClkWiz.CLKFBOUT_Frac_Multiply=0;
_AudioClock.DIVIDE=93;
_AudioClock.FRAC_Divide=0;
}
elseif(SampleRate==48000)
{
xil_printf("Useclocksetting2...

");
_ClkWiz.DIVCLK_DIVIDE=3;
_ClkWiz.CLKFBOUT_MULT=23;
_ClkWiz.CLKFBOUT_Frac_Multiply=0;
_AudioClock.DIVIDE=78;
_AudioClock.FRAC_Divide=0;
}
elseif(SampleRate==96000)
{
xil_printf("Useclocksetting3...

");
_ClkWiz.DIVCLK_DIVIDE=3;
_ClkWiz.CLKFBOUT_MULT=23;
_ClkWiz.CLKFBOUT_Frac_Multiply=0;
_AudioClock.DIVIDE=39;
_AudioClock.FRAC_Divide=0;
}

ClockingWizard_SetClockBuffer(&_ClkWiz);
ClockingWizard_SetOutput(&_ClkWiz,&_AudioClock);
}

加載音頻文件并且調整時鐘向導的輸出頻率后,將從波形文件中讀取第一個數據塊并將其復制到 FIFO:

u32SD_CopyDataIntoBuffer(u8*Buffer,constu32Length)
{
if(_RemainingBytes>=Length)
{
if(f_read(&_FileHandle,Buffer,Length,&_BytesRead))
{
returnXST_FAILURE;
}

_RemainingBytes-=_BytesRead;
}
else
{
if(f_read(&_FileHandle,Buffer,_RemainingBytes,&_BytesRead))
{
returnXST_FAILURE;
}

if(f_close(&_FileHandle))
{
xil_printf("[ERROR]Cannotcloseaudiofile!

");
returnXST_FAILURE;
}

_IsBusy=false;
}

returnXST_SUCCESS;
}

程序流程的其余部分在 FIFO 的回調中進行:

staticvoidAudioPlayer_FifoHandler(void*CallbackRef)
{
XLlFifo*InstancePtr=(XLlFifo*)CallbackRef;

u32Pending=XLlFifo_IntPending(InstancePtr);
while(Pending)
{
if(Pending&XLLF_INT_TC_MASK)
{
SD_CopyDataIntoBuffer(_FifoBuffer,AUDIOPLAYER_FIFO_BUFFER_SIZE);

XLlFifo_IntClear(InstancePtr,XLLF_INT_TC_MASK);
}
elseif(Pending&XLLF_INT_TFPE_MASK)
{
AudioPlayer_CopyBuffer();
if(!SD_IsBusy())
{
XLlFifo_IntDisable(&_Fifo,XLLF_INT_ALL_MASK);
}

XLlFifo_IntClear(InstancePtr,XLLF_INT_TFPE_MASK);
}
elseif(Pending&XLLF_INT_ERROR_MASK)
{
xil_printf("Error:%lu!

",Pending);
XLlFifo_IntClear(InstancePtr,XLLF_INT_ERROR_MASK);
}
else
{
XLlFifo_IntClear(InstancePtr,Pending);
}

Pending=XLlFifo_IntPending(InstancePtr);
}
}

一旦 FIFO 觸發TFPE中斷(發送 FIFO 可編程空),FIFO 就會被來自內部緩沖區的新數據填充。當從處理系統到 FIFO 的傳輸完成時,會觸發TC中斷(傳輸完成),并從 SD 卡讀取下一個數據塊。之后重復進行上面步驟,直到文件完全播放。

staticvoidAudioPlayer_CopyBuffer(void)
{
u32Bytes=0x00;
for(u32i=0x00;i

現在需要一個波形文件。簡單的測試信號可以wavtones.com上生成(https://www.wavtones.com/functiongenerator.php)。

然后,只需將相應的文件以Audio.wav名稱復制到 SD 卡上,即可開始使用。

-----------I2SAudioplayer-----------

[INFO]LookingforFIFOconfiguration...
[INFO]InitializeFIFO...
[INFO]LookingforGICconfiguration...
[INFO]InitializeGIC...
[INFO]Setupinterrupthandler...
[INFO]Enableexceptions...
[INFO]EnableFIFOinterrupts...
[INFO]InitializeClockingWizard...
[INFO]MountSDcard...
[INFO]Openingfile:Single.wav...
Filesize:264610bytes
Fileformat:1
Channels:1
Samplerate:48000Hz
Bitspersample:16bits
Databytes:264602bytes
Samples:132301
Useclocksetting2...
[INFO]Finished!

或者使用立體聲音頻:

508ecf98-b8c4-11ee-8b88-92fbcf53809c.png

-----------I2SAudioplayer-----------

[INFO]LookingforFIFOconfiguration...
[INFO]InitializeFIFO...
[INFO]LookingforGICconfiguration...
[INFO]InitializeGIC...
[INFO]Setupinterrupthandler...
[INFO]Enableexceptions...
[INFO]EnableFIFOinterrupts...
[INFO]InitializeClockingWizard...
[INFO]MountSDcard...
[INFO]Openingfile:Dual.wav...
Filesize:529208bytes
Fileformat:1
Channels:2
Samplerate:44100Hz
Bitspersample:16bits
Blockalign:4bytes
Databytes:264600bytes
Samples:132300
Useclocksetting1...
[INFO]Finished!
50abb266-b8c4-11ee-8b88-92fbcf53809c.png






審核編輯:劉清

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 音頻
    +關注

    關注

    28

    文章

    2618

    瀏覽量

    80184
  • 揚聲器
    +關注

    關注

    29

    文章

    1227

    瀏覽量

    60311
  • SD卡
    +關注

    關注

    2

    文章

    541

    瀏覽量

    63107
  • 分頻器
    +關注

    關注

    43

    文章

    437

    瀏覽量

    49366
  • fifo
    +關注

    關注

    3

    文章

    370

    瀏覽量

    43136
  • 發送器
    +關注

    關注

    1

    文章

    238

    瀏覽量

    26626
  • 時鐘信號
    +關注

    關注

    4

    文章

    386

    瀏覽量

    28169

原文標題:使用 FPGA 播放 SD 卡中的音頻文件

文章出處:【微信號:Open_FPGA,微信公眾號:OpenFPGA】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    用stm32f103vet6讀取SD中的音頻文件遇到的疑問求解

    各位大佬,請求援助啊。。 最近在做一個MP3播放,大概做法就是stm32f103vet6讀取SD中的音頻文件,然后在傳入VS1053b
    發表于 04-23 06:48

    5509A播放音頻文件感覺全是雜音

    我將音頻文件放到SD中,用DSP5509A將其讀取出來,并發送給AIC23,但是播放出來的音樂感覺全是雜音,請問是對AIC23的配置不對嗎
    發表于 02-12 11:41

    怎么在Virtex2p播放麥克風的音頻

    嗨,我目前正在開發一個項目,我需要調制麥克風傳入的音頻并將其輸出到揚聲器,我已經在matlab中編寫了我需要的所有內容,并且我使用HDL編
    發表于 03-01 12:58

    labview讀取wav音頻文件

    labview讀取聲音文件,為什么11S的聲音文件,波形一下子就顯示出來了,怎么實時顯示音頻文件的實時波形
    發表于 06-14 17:23

    Spat Revolution沉浸式音頻引擎中的自定義揚聲器配置

    創建新配置。圖1:揚聲器配置窗口顯示預定義的13.1 Auro 3D揚聲器布置管理揚聲器配置包括刪除配置,重命名配置,將配置導出到文件
    發表于 09-21 13:09

    【項目分享】教你用Arduino、Micro SD制作一個簡單的音樂播放

    如何與Arduino結合我們剛才提到過,這個Arduino音樂播放的重要組成成分是SD模塊。音頻文件會存儲在SD
    發表于 09-27 17:20

    怎么設置wavedac參考SD讀取?

    大家好。我想從SD讀取波形聲音放了wavevdac8連接揚聲器。我的第一個問題是可能的嗎?2-secound問題我不知道怎么設置wavedac參考
    發表于 11-04 09:27

    消除揚聲器音頻雜音的技巧有哪些?

    消除揚聲器音頻雜音的技巧有哪些?
    發表于 06-08 06:28

    基于MM32F5270開發板SD讀取音頻文件和界面的設計實現

    1、基于MM32F5270開發板SD讀取音頻文件和界面的設計目前實現功能如下:實現從SD
    發表于 08-29 14:40

    如何利用更高阻抗的揚聲器提高汽車音頻質量

    需要設計汽車外部放大器,可以通過增加輸出功率、利用更高阻抗的揚聲器以及在系統中實施H類控制來升級音頻系統架構,從而增強用戶體驗。本文將詳細介紹每種方法,包括這些方法對音頻系統重量和性能
    發表于 11-03 08:27

    如何在LPC 55S16 MICROCONTROLLER中通過i2s將音頻傳輸到揚聲器?

    - lpcxpresso55s16_i2s_interrupt_transfer(SDK 示例代碼)。 通過 i2s(中斷傳輸)將音頻文件傳輸到揚聲器,但音頻輸出完全不同。 所以請幫
    發表于 05-06 08:34

    如何本地WLANSD男取出的主機數據?

    中它的插槽。它僅在讀寫期間為 SD 模塊供電。我希望使用 Arduino SD 模塊
    發表于 06-02 08:17

    制作便攜式揚聲器的方法,DIY制作便攜式揚聲器的教程

    將兩根電線連接到放大器 ic   的 vcc 5V 和接地引腳,將一個揚聲器連接到一個通道輸出名稱 +L -L,另一個連接到 +R -R,這些是輸出到我們的揚聲器   將輸入連接到放大
    發表于 07-31 16:18

    使用M487和NAU88L25在微小SD中解碼并播放AMR音頻文件

    應用程序:此示例代碼使用 M487 微控制和外部音頻編碼NAU88L25在微小SD中解碼并播放AMR
    發表于 08-29 07:28

    消除揚聲器音頻雜音的技巧

    消除揚聲器音頻雜音的技巧音頻雜音(click and pop)是揚聲器或耳機產生的不良噪聲。它是由注入揚聲器線圈的瞬態電流脈沖引起的,該電流
    發表于 05-11 16:04 ?106次下載
    亚洲欧美日韩精品久久_久久精品AⅤ无码中文_日本中文字幕有码在线播放_亚洲视频高清不卡在线观看
    <acronym id="s8ci2"><small id="s8ci2"></small></acronym>
    <rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
    <acronym id="s8ci2"></acronym>
    <acronym id="s8ci2"><center id="s8ci2"></center></acronym>