2014-12-09 4 views
1

Я работаю над аудио визуализатором на C с OpenGL, Libsamplerate, portaudio и libsndfile. У меня с трудом используется src_process правильно в рамках всей моей парадигмы. Моя цель - использовать src_process для достижения Vinyl Like varispeed в реальном времени в визуализаторе. Сейчас моя реализация меняет высоту звука без изменения скорости. Он делает это с большим количеством искажений из-за того, что звучит как отсутствующие кадры, когда я понижаю скорость с помощью src_ratio, он почти звучит гранулированно, как обрезанные образцы. Любая помощь будет оценена, я продолжаю экспериментировать с моими буферизующими кусками, но 9 раз из 10. Я получаю ошибку libsamplerate, заявляя, что мои входные и выходные массивы перекрываются. Я также рассматривал пример изменения скорости, который пришел с libsamplerate, и я не могу найти, где я ошибся. Любая помощь будет оценена по достоинству.Varispeed с Libsndfile, Libsamplerate и Portaudio в C

Вот код, который мне кажется уместным. Спасибо и дайте мне знать, если я могу быть более конкретным, этот семестр был моим первым опытом работы на 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

Я выяснил решение, которое работает достаточно хорошо для меня, и я просто объясню, что я могу для всех, кто имеет аналогичную проблему. Поэтому, чтобы заставить Varispeed работать, как работает API, вы даете ему определенное количество кадров и выплескиваете определенное количество кадров. Таким образом, для отношения SRC 0,5, если вы обрабатываете 512 кадров за цикл, вы загружаете 512/0,5 кадра = 1024 кадра. Таким образом, когда API запускает свою функцию src_process, он сжимает эти 1024 кадра в 512, ускоряя выборки. Поэтому я не полностью понимаю, почему он решил мою проблему, но проблема заключалась в том, что коэффициент равен 0.7, вы получаете число с плавающей точкой, которое не работает с индексированными значениями массивов массивов. Поэтому отсутствуют образцы, если отношение src не eqaully не делится на фреймперуффер, возможно, в конце каждого блока. Так что я сделал, добавив +2 кадра, которые нужно прочитать, если frameperbuffer% 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); 

 Смежные вопросы

  • Нет связанных вопросов^_^