我正在尝试在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;
}
答案 0 :(得分:1)
您的代码存在一些问题导致您访问数组边界,并且无法以预期的方式读取/写入循环缓冲区。
我建议阅读http://en.wikipedia.org/wiki/Circular_buffer以更好地理解循环缓冲区。
您的代码遇到的主要问题:
播放头是从负面指数中读取的。正确的播放头计算是
#define MAX_DELAY 44100
playhead++;
playhead = playhead%MAX_DELAY;
我强烈建议花一些时间在调试器中运行代码并仔细观察播放头和circular_pointer正在做什么。
麦克
答案 1 :(得分:0)
至少有一个问题是你按值传递circular_pointer,而不是通过引用传递。当您在函数中更新它时,它会在您下次调用函数时返回相同的值。
我认为你走在正确的轨道上,但是如果你想要一些结构更好的东西,你可能也想看看这个答案:
答案 2 :(得分:-3)
样品的延迟可以放在100毫秒就足够了