2014-12-09 10 views
1

OpenGL, Libsamplerate, portaudio 및 libsndfile이있는 C의 오디오 시각화 프로그램에서 작업하고 있습니다. 내 전체 패러다임 내에서 src_process를 올바르게 사용하는 데 어려움을 겪고있다. 내 목표는 src_process를 사용하여 Visualizer 내에서 실시간으로 Vinyl Like varispeed를 달성하는 것입니다. 현재 구현은 속도를 변경하지 않고 오디오의 음높이를 변경합니다. 그것은 src_ratio로 속도를 낮추었을 때 잘게 잘린 샘플과 같이 세분화 된 사운드처럼 프레임이 누락 된 것과 같은 사운드 때문에 왜곡이 많이 발생합니다. 어떤 도움을 주시면 감사하겠습니다, 나는 내 버퍼링 덩어리로 실험을 계속하지만 10 번 중 9 번은 libsamplerate 오류가 발생하여 입력 및 출력 배열이 겹치는 오류가 발생합니다. 또한 libsamplerate와 함께 제공되는 속도 변경 예제를보고 있었는데 어디서 잘못되었는지 찾을 수 없습니다. 어떤 도움을 주시면 감사하겠습니다.Varispeed가 Libsndfile, Libsamplerate 및 Portaudio with 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이라고하면 배열 int 값으로 작동하지 않는 부동 소수점 숫자로 끝납니다. 그러므로 src 비율이 각 블록의 끝에 잠재적으로 프레임 버퍼로 나누어지기 전에 샘플이 누락됩니다. 그래서 내가 한 것은 frameperbuffer % src.ratio! = 0이라면 +2 프레임을 추가하여 글리치의 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);