Audio Delay

Audio Delay

  • Aduio delay:當信號輸入進來時,使信號的輸出波形比輸入滯後設定的時間值比如100ms。

軟件設計思路

  • 把信號持續輸入看成一個和時間相關的數據流,設定一個緩衝Buffer,大小根據delay的最大值設定,比如delay最大值爲2000ms、那麼對於96Khz採樣頻率的處理來說Buffer=962000Buffer = 96 * 2000; Buffer的大小可能還需要加上DSP一次運算的樣本點數比如128,這樣最終的數據緩衝值Buffer=192128Buffer = 192128;
  • 設定一個結構體,內部含有緩衝區信號樣本點輸入計數器指針inP*inP和樣本信號計數器輸出指針outP*outP、以及延遲設置值DlyDly;
  • outP*outP的值根據inP*inPDlyDly之差來確定,要注意inP*inPDlyDly小的情況,這種情況下 outP*outP的值應該取上一個Buffer的數據,即outP*outP位於inP*inP上一個Buffer中而不是同屬一個Buffer裏面。

信號處理流程圖

delay

  • inP*inP值大於延時時間DelayDelay的情況下,inP*inPoutP*outP處在同一個BufferBuffer中。

在這裏插入圖片描述

  • inP*inP值小於延時時間DelayDelay的情況下,outP*outP處在inP*inP所在BufferBuffer的上一個BufferBuffer中。

程序

#ifndef __delay_h__
#define __delay_h__

#include "..\inc\constants.h"

typedef struct
{
    float *pDlyBuff;    /* delay buffer store (192000 + 128) points*/
    int iPnt;    /* in point */
    int oPnt;    /* out point */
    unsigned int dlyPnts;    /* delay points */
}Dly_Type;

extern int* iPnt;
extern int* oPnt;
/* Exported types ------------------------------------------------------------*/
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
/* Exported datas ------------------------------------------------------------*/
bool gInput_Delay_Update;
bool gOutput_Delay_Update;
unsigned int gI_Delay_Upd_chID;
unsigned int gO_Delay_Upd_chID;

/* init variate*/
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;
/* Function declaration ------------------------------------------------------*/
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);

/* Function  ------------------------------------------------------*/

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];    /* store points to the buffer*/
        pDly->oPnt = pDly->iPnt - pDly->dlyPnts;
        if(pDly->oPnt < 0)
        {
            pDly->oPnt += MAX_DELAYBUFNUM;    /* needs to get point from last buffer*/
        }
        input[i] = pDly->pDlyBuff[pDly->oPnt];    /* put buffer points to the data stream*/
        (pDly->iPnt)++;    /* next point */
        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];    /* store points to the buffer*/
        pDly->oPnt = pDly->iPnt - pDly->dlyPnts;
        if(pDly->oPnt < 0)
        {
            pDly->oPnt += MAX_DELAYBUFNUM;    /* needs to get point from last buffer*/
        }
        input[i] = pDly->pDlyBuff[pDly->oPnt];    /* put buffer points to the data stream*/
        (pDly->iPnt)++;    /* next point */
        if(pDly->iPnt >= MAX_DELAYBUFNUM)
        {
            pDly->iPnt= 0;
        }
    }
    #endif
    iPnt = &pDly->iPnt;
    oPnt = &pDly->oPnt;
    DelayExec(input, pDly->pDlyBuff, &pDly->dlyPnts);   /* asm optimized*/
}
#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]);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章