2016-09-20 7 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() возвращает 112, где я ожидаю, что это вернуть 128 (число выборок дискретизированного звука): Уменьшение дискретизации 256 выборок из выборки 44100 на выборку 22050 должно давать 128 выборок, но swr_convert() производит 112 выборок. Когда это выражается в терминах продолжительности звука, это также озадачивает. 256 выборок при 44100 = 5,8 мс, но 112 выборок при 22050 = 5,07 мс. Не следует ли, чтобы процесс понижающей дискретизации не изменял продолжительность повторно сэмплированного аудио?

Я также шагнул через пример с ffmpeg, в котором swr_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