Audio Delay
- Aduio delay:當信號輸入進來時,使信號的輸出波形比輸入滯後設定的時間值比如100ms。
軟件設計思路
- 把信號持續輸入看成一個和時間相關的數據流,設定一個緩衝Buffer,大小根據delay的最大值設定,比如delay最大值爲2000ms、那麼對於96Khz採樣頻率的處理來說Buffer=96∗2000; Buffer的大小可能還需要加上DSP一次運算的樣本點數比如128,這樣最終的數據緩衝值Buffer=192128;
- 設定一個結構體,內部含有緩衝區信號樣本點輸入計數器指針∗inP和樣本信號計數器輸出指針∗outP、以及延遲設置值Dly;
- ∗outP的值根據∗inP和Dly之差來確定,要注意∗inP比Dly小的情況,這種情況下 ∗outP的值應該取上一個Buffer的數據,即∗outP位於∗inP上一個Buffer中而不是同屬一個Buffer裏面。
信號處理流程圖
- ∗inP值大於延時時間Delay的情況下,∗inP和∗outP處在同一個Buffer中。
- ∗inP值小於延時時間Delay的情況下,∗outP處在∗inP所在Buffer的上一個Buffer中。
程序
#ifndef __delay_h__
#define __delay_h__
#include "..\inc\constants.h"
typedef struct
{
float *pDlyBuff;
int iPnt;
int oPnt;
unsigned int dlyPnts;
}Dly_Type;
extern int* iPnt;
extern int* oPnt;
extern void entry_InputDelayExec(float *input);
extern void entry_OutputDelayExec(float *input);
extern void Init_delay_param(void);
extern void Get_inputDelay_Newparam(void);
extern void Get_outputDelay_Newparam(void);
#endif
bool gInput_Delay_Update;
bool gOutput_Delay_Update;
unsigned int gI_Delay_Upd_chID;
unsigned int gO_Delay_Upd_chID;
Dly_Type InDlyData[MG_INPUT_CHN_MAX] = {{((float *)SDRAM_START_ADDR),0,0,0},
{((float *)(SDRAM_START_ADDR + MAX_INDELAYBUFNUM)),0,0,0}};
Dly_Type OutDlyData[MG_OUTPUT_CHN_MAX] = {{((float *)(SDRAM_START_ADDR + 2*MAX_INDELAYBUFNUM)),0,0,0},
{((float *)(SDRAM_START_ADDR + 2*MAX_INDELAYBUFNUM + MAX_OUTDELAYBUFNUM)),0,0,0}};
int* iPnt;
int* oPnt;
void entry_InputDelayExec(float *input);
void entry_OutputDelayExec(float *input);
void compare_inputDelay_param(unsigned int channelID, Dly_Type* pDly);
void compare_outputDelay_param(unsigned int channelID, Dly_Type* pDly);
void Get_inputDelay_Newparam(void);
void Get_outputDelay_Newparam(void);
void vDelayExec(float* input, Dly_Type* pDly);
void entry_InputDelayExec(float *input)
{
int j;
int buffer_start;
if (gInput_Delay_Update)
{
compare_inputDelay_param(gI_Delay_Upd_chID, &InDlyData[gI_Delay_Upd_chID]);
gInput_Delay_Update = FALSE;
}
if (gDevice_update_order == PSDATA_UPD_DELAY)
{
Get_inputDelay_Newparam();
}
for (j = 0; j < MG_INPUT_CHN_MAX; j++)
{
buffer_start = j * MG_DEF_BLK_SZ;
vDelayExec(&input[buffer_start],&InDlyData[j]);
}
}
void entry_OutputDelayExec(float *input)
{
int j;
int buffer_start;
if (gOutput_Delay_Update)
{
compare_outputDelay_param(gO_Delay_Upd_chID, &OutDlyData[gO_Delay_Upd_chID]);
gOutput_Delay_Update = FALSE;
}
if (gDevice_update_order == PSDATA_UPD_DELAY)
{
Get_outputDelay_Newparam();
}
for (j = 0; j < MG_OUTPUT_CHN_MAX; j++)
{
buffer_start = j * MG_DEF_BLK_SZ;
vDelayExec(&input[buffer_start],&OutDlyData[j]);
}
}
#if 1
void vDelayExec(float* input, Dly_Type* pDly)
{
int i;
for(i= 0; i < MG_DEF_BLK_SZ; i++)
{
pDly->pDlyBuff[pDly->iPnt] = input[i];
pDly->oPnt = pDly->iPnt - pDly->dlyPnts;
if(pDly->oPnt < 0)
{
pDly->oPnt += MAX_DELAYBUFNUM;
}
input[i] = pDly->pDlyBuff[pDly->oPnt];
(pDly->iPnt)++;
if(pDly->iPnt >= MAX_DELAYBUFNUM)
{
pDly->iPnt= 0;
}
}
}
#endif
#if 0
void vDelayExec(float* input, Dly_Type* pDly)
{
#if 0
int i;
for(i= 0; i < MG_DEF_BLK_SZ; i++)
{
pDly->pDlyBuff[pDly->iPnt] = input[i];
pDly->oPnt = pDly->iPnt - pDly->dlyPnts;
if(pDly->oPnt < 0)
{
pDly->oPnt += MAX_DELAYBUFNUM;
}
input[i] = pDly->pDlyBuff[pDly->oPnt];
(pDly->iPnt)++;
if(pDly->iPnt >= MAX_DELAYBUFNUM)
{
pDly->iPnt= 0;
}
}
#endif
iPnt = &pDly->iPnt;
oPnt = &pDly->oPnt;
DelayExec(input, pDly->pDlyBuff, &pDly->dlyPnts);
}
#endif
void compare_inputDelay_param(unsigned int channelID, Dly_Type* pDly)
{
SetMaxMinValue_UnInt(&channelID, (MG_INPUT_CHN_MAX-1));
SetMaxMinValue_Float(&(gDevice_Config.stInDelay[channelID].fDelay), 0, 2000);
pDly->dlyPnts = gDevice_Config.stInDelay[channelID].fDelay * FS_MS;
}
void compare_outputDelay_param(unsigned int channelID, Dly_Type* pDly)
{
SetMaxMinValue_UnInt(&channelID, (MG_OUTPUT_CHN_MAX-1));
SetMaxMinValue_Float(&gDevice_Config.stOutDelay[channelID].fDelay, 0, 2000);
pDly->dlyPnts = gDevice_Config.stOutDelay[channelID].fDelay * FS_MS;
}
void Get_inputDelay_Newparam(void)
{
compare_inputDelay_param(0,&InDlyData[0]);
compare_inputDelay_param(1,&InDlyData[1]);
}
void Get_outputDelay_Newparam(void)
{
compare_outputDelay_param(0,&OutDlyData[0]);
compare_outputDelay_param(1,&OutDlyData[1]);
}