總結
自己定義算法要添加在hifi工程里
hifi工程在wiki上可以下載,名字叫做project
在main.c里添加了自己的算法,算法的執行涉及到通道與effect_id
編譯hifi項目需要安裝 XtensaTool 與hifi4 configuration file
編譯成功后移植bin文件
通過hifi4_effect_audio_process調用hifi里的算法.
hifi工程總結
hifi與riscv的數據通信是通過共享內存與軟中斷tx.
RISCV 將準備好的數據-> HFMEM->軟中斷->HIFI4 讀取 RISCV 放的數據進行處理->軟中斷-> RISCV 程序拿回處理之后的數據。
895x 中編解碼,混響降噪等音效函數都是通過hifi算法處理
hifi4_effect_audio_process是app用來向hifi傳輸數據的,參數cpu1t0_idx 代表通道數x,
例如cpu1t0_idx =0 , 通道0處理 ,即cpu1_sw0_process中處理
下載hifi工程原包project
原包在BT895X 領夾麥/無線話筒SDK
hifi4編譯環境搭建
參考BT895X HIFI4開發指南
主要是下面三步
安裝 xtensa
需要去找藍訊申請激活碼
Configuration Package 安裝
在參考鏈接BT895X HIFI4開發指南下載HIFI4_win32_redist-ID636799.tgz
設置Code Blocks的 HIFI4 Compiler 配置
hifi4編譯環境配置好之后,就可以打開hifi工程,修改代碼編譯
添加自定義算法在hifi工程里
添加增益算法的效果是對音頻效果添加gain
- 在project原包的main.c中添加增益算法xt_music_effects_process,
xt_music_effects_process設置增益值,判斷樣點是否是24位,如果是16位調用pcm_soft_vol_process對音頻流增益.
//參數: ptr:指向16位有符號整數音頻數據的指針 gain:Q15格式的增益值 samples:需要處理的采樣點數
void pcm_soft_vol_process(s16 *ptr, int gain, int samples)//16位音頻音量調節
{my_printf("soft_vol_16bits\n");int i, val;ae_int32x2 d0, d2, d3;//32位×2的SIMD寄存器ae_int16x4 d1; //16位×4的SIMD寄存器(核心優化單元)ae_int64 fa0, fa1, fa2, fa3;//64位擴展精度寄存器ae_int16x4 * restrict p_x = (ae_int16x4 *)ptr;//將輸入指針轉換為AE SIMD訪問指針ae_int16x4 * restrict p_y = (ae_int16x4 *)ptr;//restrict關鍵字:向編譯器保證指針不重疊,每次處理4個16位采樣點(SIMD寬度)int shift = 32 - 15;//32位中間精度 - 15位增益精度 = 17位右移量d0 = AE_MOVDA32(gain);//將標量增益值加載到SIMD寄存器,增益值被廣播到所有通道for (i = 0; i < samples / 4; i++) {AE_L16X4_IP(d1, p_x, sizeof(ae_int16x4));//從內存加載4個16位值到d1fa0 = AE_MUL32X16_L0(d0, d1);//d0低32位 × d1第0通道(16位)fa1 = AE_MUL32X16_L1(d0, d1);//d0低32位 × d1第1通道fa2 = AE_MUL32X16_H2(d0, d1);//d0高32位 × d1第2通道fa3 = AE_MUL32X16_H3(d0, d1);//d0高32位 × d1第3通道,//結果存儲在64位寄存器(防止溢出)d2 = AE_TRUNCA32X2F64S(fa1, fa0, shift);//將兩個64位結果截斷為32位d3 = AE_TRUNCA32X2F64S(fa3, fa2, shift);//應用17位右移(32-15=17),組合為ae_int32x2寄存器(d2和d3)d1 = AE_SAT16X4(d3, d2);//將兩個32位×2寄存器飽和到16位范圍,確保結果在-32768到32767之間,組合為ae_int16x4寄存器(d1)AE_S16X4_IP(d1, p_y, sizeof(ae_int16x4));//將處理結果存儲回內存,}
}void xt_music_effects_process(xt_ipc_cb_t *pcm)
{u32 in_nch = pcm->nchannel;//音頻通道數u32 samples = pcm->samples;//每個通道采樣點數u32 is_24bit = pcm->in_24bits;//24位標志int gain = 0x7800;//Q15格式增益值(0x7800 約等于 0.9375)if (is_24bit) {my_printf("soft_vol_24bits\n");} else {pcm_soft_vol_process((s16 *)pcm->buf, gain, samples * in_nch);}// alg_user_process((u8*)pcm->buf, pcm->samples, pcm->nchannel, pcm->in_24bits); //鐢ㄦ埛綆楁硶process//調用用戶定義的音頻處理函數,傳遞 PCM 緩沖區、采樣信息等參數,在音量調整后應用用戶算法 (如均衡器、混響等)
}
- 設置算法調用條件
app層想調用hifi算法,需要通過通道數與effect_id,類似于通過通道數與effect_id給hifi編號,然后app層根據編號調用
例如設置通道1且effect_id=21時調用xt_music_effects_process
//通道1處理
AT(.text.isr) OPTIMIZE_SIZE
void cpu1_sw1_process(void)
{...} else if (ipc_pcm->effect_id == 21) {xt_music_effects_process(ipc_pcm);} else {
...
}
寫好代碼后,編譯項目,把編譯結果移到app層
編譯成功后移植bin文件
工程文件會在編譯后自動運行 postbuild.bat,生成iram.bin、dram.bin、sram.bin三個文件。HIFI4 編譯完成之后,復制 3 個 HIFI4 的 bin 文件到app\projects\earphone\Output\bin\res\hifi4 目錄下.app層就能調用hifi4中的算法了.
app層調用hifi4算法
app層通過hifi4_effect_audio_process函數調用hifi算法,hifi4_effect_audio_process的參數cpu1t0_idx為通道數,參數effect_id為ipc_pcm->effect_id
#define hifi_xt_music_process(ibuf, samples, pcm_info, obuf) hifi4_effect_audio_process(CPU0T1_DEC_IDX, 21, ibuf, samples, pcm_info, obuf);
hifi_xt_music_process與hifi的通道1 effect_id=21的hifi算法綁定.
定義在音頻流中運行的函數,在該函數內調用hifi4_effect_audio_process
hifi_echo_mic_cfg_t hifi_echo_mic_cfg AT(.buf.hifi_echo);
void hifi_echo_mic_audio_input1(u8 *ptr, u32 samples, int ch_mode, void *params)
{u32 pcm_info = (0<<28) | ((0&0x0f)<<24) | (0<<16) | ch_mode;hifi_xt_music_process((u8*)ptr, samples, pcm_info,(u8*)ptr);//輸出到下一級if (hifi_echo_mic_cfg.callback) {hifi_echo_mic_cfg.callback((void *)ptr, samples, ch_mode, params);}
}AT(.text.hifi_echo_set)WEAK
void hifi_echo_mic_output_callback_set1(audio_callback_t callback)
{hifi_echo_mic_cfg.callback = callback;
}AT(.text.hifi_echo_init)WEAK
void hifi_echo_mic_init1(u8 sample_rate, u16 samples, u8 channel)
{// memset(&echo_cfg,0,sizeof(echo_cfg));
}
在音頻流中添加hifi_echo_mic_audio_input1
static ws_link_list_t adapter_mic_rx_cfg_tbl[] = {
/* 模塊類型, 使能, 初始化, 輸入接口, 設置輸出*/{DECODER_PRIO_TRANS_TYPE, 1, decoder_prio_trans_init, NULL, decoder_prio_trans_audio_output_callback_set},{HIFI_ECHO_TYPE, 1, hifi_echo_mic_init1, hifi_echo_mic_audio_input1, hifi_echo_mic_output_callback_set1}, //ECHO#if ADAPTER_DAC_OUTPUT_EN{DAC0_OUT_TYPE, 1, dac0_out_init, dac0_out_audio_input, dac0_out_audio_output_callback_set}, //DAC輸出
#endif};