From c1cb78d574c0429aa5e3ff3a2b3886e4bc153212 Mon Sep 17 00:00:00 2001 From: bbergeron Date: Wed, 3 Apr 2024 17:32:01 -0400 Subject: Reset Git repo and use a pseudonym to sign commits I used to sign my commits with my real name and my personal email address, which I wanted scrubbed off the "B." pseudosphere. Re-creating a new git repository was safer than simpler than re-writing the history (although the latter could've also worked but, oh well). --- audio/resampler.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 audio/resampler.c (limited to 'audio/resampler.c') diff --git a/audio/resampler.c b/audio/resampler.c new file mode 100644 index 0000000..6906d05 --- /dev/null +++ b/audio/resampler.c @@ -0,0 +1,121 @@ +#include +#include +#include +#include +#include +#include +#include "resampler.h" + +#define MICROSECOND 1000000 + +static inline uint64_t div_uint64_ceil(uint64_t num, uint64_t den) +{ + return (num / den) + (num % den != 0); +} + +static int resampler_init (struct Resampler *resampler, const AVChannelLayout *out_chlayout, enum AVSampleFormat out_sample_fmt, int64_t out_sample_rate, uint64_t out_frame_size) +{ + /* Let me tell you something; you --don't want-- CAN'T configure a + * SwrContext manually, GOOD ****ING LUCK DOING THAT. The documentation is + * so bad on that matter, it only referes to "tHe PaRaMeTeRs" or show off a + * list of deprecated attribute which looks nothing like what's actually + * used in their API. I tried to copy what's being done in their a API but + * whatever I do would either not work or be liable to change since it's not + * documented for shit (even the documented stuff doesn't appears stable, so + * wtf am I saying anyway). A ****ing joke, I tell you that. + * + * Pardon my french. + * + * Anywho, instead of configuring the input parameter directly, we shove + * them in resampler so we can recall them before calling ffmpeg's SWR + * allocator. + */ + resampler->out_chlayout = out_chlayout; + resampler->out_sample_fmt = out_sample_fmt; + resampler->out_sample_rate = out_sample_rate; + resampler->out_frame_size = out_frame_size; + resampler->swr = NULL; + return 0; +} + +static int resampler_conf (struct Resampler *resampler, const AVChannelLayout *in_chlayout, enum AVSampleFormat in_sample_fmt, int64_t in_sample_rate) +{ + int err; + + err = swr_alloc_set_opts2( + &resampler->swr, + resampler->out_chlayout, + resampler->out_sample_fmt, + resampler->out_sample_rate, + in_chlayout, + in_sample_fmt, + in_sample_rate, + 0, 0); + if (err) return err; + + if (!swr_is_initialized(resampler->swr)) + if ((err = swr_init(resampler->swr))) + return err; + + resampler->in_sample_rate = in_sample_rate; + resampler->needed = div_uint64_ceil(resampler->out_frame_size * in_sample_rate, resampler->out_sample_rate); + + return 0; +} + +int resampler_send_frame (struct Resampler *resampler, AVFrame *in) +{ + int err; + + if ((err = swr_convert(resampler->swr, NULL, 0, (const uint8_t **)in->extended_data, in->nb_samples)) < 0) + return err; + resampler->stored += in->nb_samples; + return 0; +} + +int resampler_send_empty (struct Resampler *resampler, unsigned int microsecond) +{ + // TODO: Check for downcasting + int nb_samples; + nb_samples = div_uint64_ceil(microsecond * resampler->in_sample_rate, 1000); + return swr_inject_silence(resampler->swr, nb_samples); +} + +int resampler_convert (struct Resampler *resampler, AVFrame *out) +{ + int err; + assert(out != NULL); + assert(resampler->swr != NULL); + + if (resampler->stored < resampler->needed) { + return AVERROR(EAGAIN); + /* + err = swr_inject_silence(resampler->swr, resampler->needed - resampler->stored); + if (err < 0) return err; + */ + } + + err = swr_convert(resampler->swr, out->extended_data, out->nb_samples, NULL, 0); + if (err < 0) return err; + resampler->stored = 0; + + return 0; +} + +void resampler_free (struct Resampler *resampler) +{ + if (resampler == NULL) return; + swr_free(&resampler->swr); +} + +int resampler_init_for_encoder (struct Resampler *resampler, const struct Encoder *encoder) +{ + AVCodecContext *avctx = encoder->avctx; + return resampler_init(resampler, &avctx->ch_layout, avctx->sample_fmt, avctx->sample_rate, avctx->frame_size); +} + +int resampler_conf_for_decoder (struct Resampler *resampler, const struct Decoder *decoder) +{ + AVCodecContext *avctx = decoder->avctx; + return resampler_conf(resampler, &avctx->ch_layout, avctx->sample_fmt, avctx->sample_rate); +} -- cgit v1.2.3