音频延迟使它工作

时间:2013-05-10 12:25:45

标签: c audio delay libsndfile

我正在尝试在C中实现简单的音频延迟。 我以前制作了一个测试延迟程序,它在印刷的正弦波上运行并且有效地工作。 我尝试将延迟作为SFProcess中的进程 - libsndfile - 将sinewave输入替换为我的音频'数据'输入。

我几乎拥有它,但不是一个干净的样本延迟,我得到各种各样的故障和失真。

有关如何纠正此问题的任何想法?

#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;
}

3 个答案:

答案 0 :(得分:1)

您的代码存在一些问题导致您访问数组边界,并且无法以预期的方式读取/写入循环缓冲区。

我建议阅读http://en.wikipedia.org/wiki/Circular_buffer以更好地理解循环缓冲区。

您的代码遇到的主要问题:

  1. circular_pointer应初始化为延迟量(基本上写头从0开始,所以永远不会有任何延迟!)
  2. playhead和circular_buffer在调用process_data之间没有更新(circular_buffer按值传递...)
  3. 播放头是从负面指数中读取的。正确的播放头计算是

    #define MAX_DELAY     44100
    playhead++;
    playhead = playhead%MAX_DELAY;
    
  4. 在process_data结尾处对circular_buffer的第二次写入是不必要且不正确的。
  5. 我强烈建议花一些时间在调试器中运行代码并仔细观察播放头和circular_pointer正在做什么。

    麦克

答案 1 :(得分:0)

至少有一个问题是你按值传递circular_pointer,而不是通过引用传递。当您在函数中更新它时,它会在您下次调用函数时返回相同的值。

我认为你走在正确的轨道上,但是如果你想要一些结构更好的东西,你可能也想看看这个答案:

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

答案 2 :(得分:-3)

样品的延迟可以放在100毫秒就足够了