Varispeed与C中的Libsndfile,Libsamplerate和Portaudio

时间:2014-12-09 23:12:13

标签: portaudio libsndfile sample-rate

我正在使用OpenGL,Libsamplerate,portaudio和libsndfile处理C语音可视化工具。我在整个范例中正确使用src_process有困难。我的目标是使用src_process在可视化工具中实时实现Vinyl Like varispeed。现在我的实现改变了音频的音高而不改变速度。由于听起来像丢失的帧,所以它有很多失真,因为当我用src_ratio降低速度时,它几乎听起来像切碎的样本一样颗粒状。任何帮助将不胜感激,我一直在尝试我的缓冲块然而9次中有10次我得到一个libsamplerate错误说我的输入和输出数组是重叠的。我也一直在查看libsamplerate附带的速度变化示例,但我无法找到出错的地方。任何帮助将不胜感激。

以下是我认为相关的代码。谢谢,让我知道,如果我可以更具体,这个学期是我在C和编程方面的第一次经历。

#define FRAMES_PER_BUFFER       1024
#define ITEMS_PER_BUFFER        (FRAMES_PER_BUFFER * 2)
float src_inBuffer[ITEMS_PER_BUFFER];
float src_outBuffer[ITEMS_PER_BUFFER];

void initialize_SRC_DATA()
{
    data.src_ratio = 1;                             //Sets Default Playback Speed
    /*---------------*/
    data.src_data.data_in = data.src_inBuffer;      //Point to SRC inBuffer
    data.src_data.data_out = data.src_outBuffer;    //Point to SRC OutBuffer
    data.src_data.input_frames = 0;                 //Start with Zero to Force Load
    data.src_data.output_frames = ITEMS_PER_BUFFER
                         / data.sfinfo1.channels;   //Number of Frames to Write Out
    data.src_data.src_ratio = data.src_ratio;       //Sets Default Playback Speed
    }

/* Open audio stream */
err = Pa_OpenStream( &g_stream,
        NULL,
        &outputParameters,
        data.sfinfo1.samplerate, 
        FRAMES_PER_BUFFER, 
        paNoFlag, 
        paCallback, 
        &data );

/* Read FramesPerBuffer Amount of Data from inFile into buffer[] */
numberOfFrames = sf_readf_float(data->inFile, data->src_inBuffer, framesPerBuffer);

/* Looping of inFile if EOF is Reached */
if (numberOfFrames < framesPerBuffer) 
{
    sf_seek(data->inFile, 0, SEEK_SET);
    numberOfFrames = sf_readf_float(data->inFile, 
                                    data->src_inBuffer+(numberOfFrames*data->sfinfo1.channels), 
                                    framesPerBuffer-numberOfFrames);  
}

/* Inform SRC Data How Many Input Frames To Process */
data->src_data.end_of_input = 0;
data->src_data.input_frames = numberOfFrames;

/* Perform SRC Modulation, Processed Samples are in src_outBuffer[] */
if ((data->src_error = src_process (data->src_state, &data->src_data))) {   
    printf ("\nError : %s\n\n", src_strerror (data->src_error)) ;
    exit (1);
}

* Write Processed SRC Data to Audio Out and Visual Out */
for (i = 0; i < framesPerBuffer * data->sfinfo1.channels; i++)
{
    // gl_audioBuffer[i] = data->src_outBuffer[i] * data->amplitude;   
    out[i] = data->src_outBuffer[i] * data->amplitude;
}

1 个答案:

答案 0 :(得分:0)

我找到了一个对我来说运作良好的解决方案,并且我将尽可能地为其他有类似问题的人解释它。因此,要使Varispeed工作,API的工作方式是给它一定数量的帧,并且它会吐出一定数量的帧。因此,对于SRC比率为0.5,如果每个循环处理512帧,则以512 / 0.5帧= 1024帧为单位进行输入。这样,当API运行其src_process函数时,它会将这1024帧压缩为512,从而加快了样本速度。所以我不完全理解为什么它解决了我的问题,但问题是如果比率是0.7,你最终得到一个浮点数,它不适用于数组索引的int值。因此,除非src比率可能被每个块末尾的framesperbuffer分解,否则会丢失样本。所以我做的是添加+2帧,如果framesperbuffer%src.ratio!= 0并且它似乎修复了99%的毛刺。

/* This if Statement Ensures Smooth VariSpeed Output */
if (fmod((double)framesPerBuffer, data->src_data.src_ratio) == 0)
{
    numInFrames = framesPerBuffer;
}
else
    numInFrames = (framesPerBuffer/data->src_data.src_ratio) + 2;

/* Read FramesPerBuffer Amount of Data from inFile into buffer[] */
numberOfFrames = sf_readf_float(data->inFile, data->src_inBuffer, numInFrames);