2013-05-10 84 views
2

我想實現一個簡單的音頻延遲C. 我以前做了一個測試延遲程序,在印刷的正弦波上運行,並有效地工作。 我嘗試在SFProcess中加入我的延遲 - libsndfile - 用我的音頻數據輸入替換正弦波輸入。音頻延遲使其工作

我幾乎擁有它,但不是一個乾淨的採樣延遲,我得到各種各樣的毛刺和失真。

有關如何解決此問題的任何想法?在樣品

#include <stdio.h> 
#include </usr/local/include/sndfile.h>//libsamplerate libsamplerate 
//#include </usr/local/include/samplerate.h> 

#define BUFFER_LEN 1024 //defines buffer length 
#define MAX_CHANNELS 2 //defines max channels 

static void process_data (double *data, double*circular,int count, int numchannels, int circular_pointer); 

enum {DT_PROGNAME,ARG_INFILE,ARG_OUTFILE,ARG_NARGS, DT_VOL}; 

int main (int argc, const char * argv[])//Main 
{ 
    static double data [BUFFER_LEN]; // the buffer that carries the samples 

    double circular [44100] = {0}; // the circular buffer for the delay 
    for (int i = 0; i < 44100; i++) { circular[i] = 0; } // zero the circular buffer 

    int circular_pointer = 0;   // where we currently are in the circular buffer 

    //float myvolume; // the volume entered by the user as optional 3rd argument 

    SNDFILE *infile, *outfile; 
    SF_INFO sfinfo; 

    int readcount; 
    const char *infilename = NULL; 
    const char *outfilename = NULL; 

    if(argc < ARG_NARGS) { 
     printf("usage: %s infile outfile\n",argv[DT_PROGNAME]); 
     return 1; 
    } 

    //if(argc > ARG_NARGS) { 
    // 
    // myvolume = argv[DT_VOL]; 
    //}; 
    infilename = argv[ARG_INFILE]; 
    outfilename = argv[ARG_OUTFILE]; 

    if (! (infile = sf_open (infilename, SFM_READ, &sfinfo))) 

    {printf ("Not able to open input file %s.\n", infilename) ; 
     puts (sf_strerror (NULL)) ; 
     return 1 ; 
    }; 

    if (! (outfile = sf_open (outfilename, SFM_WRITE, &sfinfo))) 
    { printf ("Not able to open output file %s.\n", outfilename) ; 
     puts (sf_strerror (NULL)) ; 
     return 1 ; 
    } ; 

    while ((readcount = sf_read_double (infile, data, BUFFER_LEN))) 
    { process_data (data, circular, readcount, sfinfo.channels, circular_pointer) ; 
     sf_write_double (outfile, data, readcount) ; 
    }; 

    sf_close (infile) ; 
    sf_close (outfile) ; 

    printf("the sample rate is %d\n", sfinfo.samplerate); 

    return 0; 
} 


static void process_data (double *data, double *circular, int count, int numchannels, int circular_pointer) { 

    //int j,k; 
    //float vol = 1; 
    int playhead; 
    int wraparound = 10000; 

    float delay = 1000; // delay time in samples 

    for (int ind = 0; ind < BUFFER_LEN; ind++){ 

     circular_pointer = fmod(ind,wraparound);  // wrap around pointer 
     circular[circular_pointer] = data[ind]; 


     playhead = fmod(ind-delay, wraparound);  // read the delayed signal 

     data[ind] = circular[playhead];   // output delayed signal 

     circular[ind] = data[ind]; // write the incoming signal 
    }; 


    //volume 
    /*for (j=0; j<numchannels; j++) { 
     for (k=0; k<count; k++){ 
      data[k] = data[k]*-vol;*/ 

     //}printf ("the volume is %f", vol); 

    return; 
} 
+1

考慮一下'playhead'會時,例如,'ind'爲0 – Michael 2013-05-10 12:48:01

回答

-3

延遲可以被置爲100毫秒將是足夠的

+0

我看不出有什麼具有與OP被詢問的扭曲去做。此外,他的代碼意味着延遲大約22毫秒(在44100赫茲的1000個採樣)。 – Michael 2013-05-10 12:52:41

+0

這個問題未能解決OP的問題 - 顯然也是錯誤的。 – marko 2013-05-10 15:27:53

+0

感謝您的意見.... – avni 2013-05-11 04:20:54

0

至少一個問題是,按值傳遞circular_pointer,而不是由參考。當你在函數中更新它時,下次調用該函數時它會回到相同的值。

我認爲你是在正確的軌道上,在這裏,但如果你想東西是結構好一點,你可能也想籤這樣的回答:

how to add echo effect on audio file using objective-c

0

有有幾個問題您的代碼會導致您訪問數組邊界,並且不會按照預期方式讀取\寫入您的循環緩衝區。

我建議閱讀http://en.wikipedia.org/wiki/Circular_buffer以更好地理解循環緩衝區。

的主要問題你的代碼是痛苦:(!基本上是寫磁頭從0開始,所以從來沒有任何延遲)

  1. circular_pointer應該被初始化爲延遲量
  2. 播放頭和circular_buffer是在對process_data的調用之間沒有更新(circular_buffer是按值傳遞的...)
  3. 播放頭正在讀取負向索引。正確的播放頭計算是

    #define MAX_DELAY  44100 
    playhead++; 
    playhead = playhead%MAX_DELAY; 
    
  4. 在process_data結尾的第二次寫入circular_buffer是不必要的也是不正確的。

我強烈建議花一些時間在調試器中運行您的代碼,並密切關注您的播放頭和circular_pointer在做什麼。

邁克