1

我正在使用 OpenGL、Libsamplerate、portaudio 和 libsndfile 开发 C 语言的音频可视化器。我在整个范例中正确使用 src_process 时遇到了困难。我的目标是使用 src_process 在可视化器中实时实现 Vinyl Like 变速。现在我的实现改变了音频的音高而不改变速度。由于听起来像丢失帧,因此它会产生很多失真,因为当我使用 src_ratio 降低速度时,它听起来几乎像切碎的样本一样颗粒状。任何帮助将不胜感激,我一直在尝试我的缓冲块,但是 10 次中有 9 次我得到一个 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;
}
4

1 回答 1

0

我想出了一个对我来说效果很好的解决方案,我会尽我所能为有类似问题的其他人解释它。所以为了让 Varispeed 工作,API 的工作方式是你给它一定数量的帧,它会吐出一定数量的帧。因此,对于 0.5 的 SRC 比率,如果您每个循环处理 512 帧,那么您将输入 512/0.5 帧 = 1024 帧。这样,当 API 运行其 src_process 函数时,它会将这 1024 帧压缩为 512 帧,从而加快采样速度。所以我不完全理解为什么它解决了我的问题,但问题是如果比率是 0.7,你最终会得到一个浮点数,它不适用于索引 int 值的数组。因此,除非 src 比率在每个块的末尾可能被帧/缓冲区整除,否则会丢失样本。

/* 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);
于 2014-12-13T00:48:45.137 回答