我正在使用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;
}
答案 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);