2016-09-20 16 views
0

ffmpeg/libswresample을 사용하여 C++ 응용 프로그램에서 스트리밍 오디오를 리샘플링하려고합니다. 샘플 너비를 변경하면 결과가 잘 작동하고 예상대로 소리가납니다. 그러나 샘플 속도를 변경할 때 결과는 다소 균열이 있습니다. libswresample 라이브러리의 잘못된 사용으로 인한 것인지 아니면 리샘플링 이론을 오해하고 있는지 확실하지 않습니다. 여기 libswresample : 충분한 샘플을 생성하지 않는 swr_convert()

데모를 위해서 간단하게 내 리샘플링 과정이다 : 나는 다시 샘플링 된 오디오가 잘 들리지 않는 이유는 의심

//Externally supplied data 
const uint8_t* in_samples //contains the audio data to be resampled 
int in_num_samples = 256 

//Set up resampling context 
SwrContext *swr = swr_alloc(); 
av_opt_set_channel_layout(swr, "in_channel_layout", AV_CH_LAYOUT_STEREO, 0); 
av_opt_set_channel_layout(swr, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0); 
av_opt_set_int(swr, "in_sample_rate", 44100, 0); 
av_opt_set_int(swr, "out_sample_rate", 22050, 0); 
av_opt_set_sample_fmt(swr, "in_sample_fmt", AV_SAMPLE_FMT_FLT, 0); 
av_opt_set_sample_fmt(swr, "out_sample_fmt", AV_SAMPLE_FMT_FLT, 0); 
swr_init(swr); 

//Perform the resampe 
uint8_t* out_samples; 
int out_num_samples = av_rescale_rnd(swr_get_delay(swr, in_samplerate) + in_num_samples, out_samplerate, in_samplerate, AV_ROUND_UP); 
av_samples_alloc(&out_samples, NULL, out_num_channels, out_num_samples, AV_SAMPLE_FMT_FLT, 0); 
out_num_samples = swr_convert(swr, &out_samples, out_num_samples, &in_samples, in_num_samples); 
av_freep(&out_samples); 
swr_free(&swr); 

swr_convert() 반환 내가 128를 반환 할 것으로 예상 (112), (수 있기 때문에 샘플링 레이트 44100에서 샘플 레이트 22050으로 256 샘플을 다운 샘플링하면 128 샘플을 얻을 수 있지만 swr_convert()은 112 샘플을 생성합니다. 오디오 지속 시간의 측면에서 표현할 때 이것은 또한 수수께끼입니다. 44100 = 5.8 ms에서 256 샘플, 22050에서 112 샘플 = 5.07 ms. 다운 샘플링 프로세스가 리샘플링 된 오디오의 지속 시간을 변경하지 않아야합니까?

또한 ffmpeg와 함께 제공되는 예제를 살펴 보았습니다. swf_convert()도 예상보다 작은 수를 반환합니다. 그래서 문제는 libswresample의 버그 때문이 아니라 내 자신의 이해 부족 때문인 것으로 생각됩니다.

+0

더 큰 크기의 out_samples 배열로 시도해보십시오. 계산에 문제가 있다고 의심됩니다. –

답변

2

샘플 수가 줄어든 이유는 리샘플링이 시간적으로 인접한 여러 샘플을 필터링하기 때문입니다. 32- 탭 필터를 사용하여 재 샘플링한다고 가정하고, 샘플 127은 입력 127-16에서 127 + 16 (또는 샘플 속도 조정을 위해 보정 된 유사한 위치)이 필요합니다. 128 개의 입력 샘플 만 있기 때문에이 예제에서 112까지만 출력 할 수 있습니다. 나머지는 다음 입력을 사용할 수있을 때까지 내부 대기열에 저장됩니다.

마지막 (후미) 샘플을 얻으려면 (입력이 끝나면) 입력을 NULL로 입력하면 내부 대기열이 비워집니다.

+0

그 트릭을 했어, 당신의 신속한 회신에 감사드립니다! 따라서 실시간 컨텍스트에서 사용할 때 다음에 swr_convert()가 호출 될 때 입력 샘플은 이전 호출에서 생략 된 마지막 몇 개로 시작해야합니다. 이 올바른지? – Tsherr

+0

아니요, swr_convert()는 입력 샘플을 캐시합니다. 단지 모든 샘플을 사용자가 입력하는 것과 동시에 꺼내지 않을 것을 기대하십시오. 즉, swr_convert()가 약간의 지연을 초래할 것으로 예상하십시오. –

+0

나는 지금, 이해된다 본다. 다시 한 번 감사드립니다! – Tsherr