29 #define RDFT_BITS_MIN 4
30 #define RDFT_BITS_MAX 16
54 #define NB_GAIN_ENTRY_MAX 4096
113 #define OFFSET(x) offsetof(FIREqualizerContext, x)
114 #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
214 if (nsamples <= s->nsamples_max) {
215 float *
buf = conv_buf + idx->buf_idx * s->rdft_len;
216 float *obuf = conv_buf + !idx->buf_idx * s->rdft_len + idx->overlap_idx;
217 int center = s->fir_len/2;
220 memset(buf, 0, center *
sizeof(*data));
221 memcpy(buf + center, data, nsamples *
sizeof(*data));
222 memset(buf + center + nsamples, 0, (s->rdft_len - nsamples - center) *
sizeof(*data));
225 buf[0] *= kernel_buf[0];
226 buf[1] *= kernel_buf[s->rdft_len/2];
227 for (k = 1; k < s->rdft_len/2; k++) {
228 buf[2*k] *= kernel_buf[k];
229 buf[2*k+1] *= kernel_buf[k];
233 for (k = 0; k < s->rdft_len - idx->overlap_idx; k++)
235 memcpy(data, buf, nsamples *
sizeof(*data));
236 idx->buf_idx = !idx->buf_idx;
237 idx->overlap_idx = nsamples;
239 while (nsamples > s->nsamples_max * 2) {
240 fast_convolute(s, kernel_buf, conv_buf, idx, data, s->nsamples_max);
241 data += s->nsamples_max;
242 nsamples -= s->nsamples_max;
245 fast_convolute(s, kernel_buf, conv_buf, idx, data + nsamples/2, nsamples - nsamples/2);
250 float *av_restrict conv_buf,
OverlapIndex *av_restrict idx,
251 float *av_restrict
data,
int nsamples)
253 if (nsamples <= s->nsamples_max) {
254 float *
buf = conv_buf + idx->buf_idx * s->rdft_len;
255 float *obuf = conv_buf + !idx->buf_idx * s->rdft_len + idx->overlap_idx;
258 memcpy(buf, data, nsamples *
sizeof(*data));
259 memset(buf + nsamples, 0, (s->rdft_len - nsamples) *
sizeof(*data));
262 buf[0] *= kernel_buf[0];
263 buf[1] *= kernel_buf[1];
264 for (k = 2; k < s->rdft_len; k += 2) {
266 re = buf[k] * kernel_buf[k] - buf[k+1] * kernel_buf[k+1];
267 im = buf[k] * kernel_buf[k+1] + buf[k+1] * kernel_buf[k];
273 for (k = 0; k < s->rdft_len - idx->overlap_idx; k++)
275 memcpy(data, buf, nsamples *
sizeof(*data));
276 idx->buf_idx = !idx->buf_idx;
277 idx->overlap_idx = nsamples;
279 while (nsamples > s->nsamples_max * 2) {
281 data += s->nsamples_max;
282 nsamples -= s->nsamples_max;
290 OverlapIndex *av_restrict idx,
float *av_restrict data0,
float *av_restrict data1,
int nsamples)
292 if (nsamples <= s->nsamples_max) {
294 FFTComplex *obuf = conv_buf + !idx->buf_idx * s->rdft_len + idx->overlap_idx;
295 int center = s->fir_len/2;
299 memset(buf, 0, center *
sizeof(*buf));
300 for (k = 0; k < nsamples; k++) {
301 buf[center+k].
re = data0[k];
302 buf[center+k].
im = data1[k];
304 memset(buf + center + nsamples, 0, (s->rdft_len - nsamples - center) *
sizeof(*buf));
311 buf[0].
re = 0.5f * kernel_buf[0] * buf[0].
im;
312 buf[0].
im = 0.5f * kernel_buf[0] *
tmp;
313 for (k = 1; k < s->rdft_len/2; k++) {
314 int m = s->rdft_len - k;
316 buf[k].
re = 0.5f * kernel_buf[k] * buf[k].
im;
317 buf[k].
im = 0.5f * kernel_buf[k] *
tmp;
319 buf[m].
re = 0.5f * kernel_buf[k] * buf[m].
im;
320 buf[m].
im = 0.5f * kernel_buf[k] *
tmp;
323 buf[k].
re = 0.5f * kernel_buf[k] * buf[k].
im;
324 buf[k].
im = 0.5f * kernel_buf[k] *
tmp;
329 for (k = 0; k < s->rdft_len - idx->overlap_idx; k++) {
330 buf[k].
re += obuf[k].
re;
331 buf[k].
im += obuf[k].
im;
335 for (k = 0; k < nsamples; k++) {
336 data0[k] = buf[k].
im;
337 data1[k] = buf[k].
re;
339 idx->buf_idx = !idx->buf_idx;
340 idx->overlap_idx = nsamples;
342 while (nsamples > s->nsamples_max * 2) {
343 fast_convolute2(s, kernel_buf, conv_buf, idx, data0, data1, s->nsamples_max);
344 data0 += s->nsamples_max;
345 data1 += s->nsamples_max;
346 nsamples -= s->nsamples_max;
348 fast_convolute2(s, kernel_buf, conv_buf, idx, data0, data1, nsamples/2);
349 fast_convolute2(s, kernel_buf, conv_buf, idx, data0 + nsamples/2, data1 + nsamples/2, nsamples - nsamples/2);
361 double delay = s->
zero_phase ? 0.0 : (double) center / rate;
366 for (x = 1; x <= center; x++) {
371 for (x = 0; x < s->
fir_len; x++)
378 fprintf(fp,
"# time[%d] (time amplitude)\n", ch);
381 for (x = center; x > 0; x--)
384 for (x = 0; x <= center; x++)
385 fprintf(fp,
"%15.10f %15.10f\n", delay + (
double)x / rate , (
double) s->
analysis_buf[x]);
387 for (x = 0; x < s->
fir_len; x++)
388 fprintf(fp,
"%15.10f %15.10f\n", (
double)x / rate, (
double) s->
analysis_buf[x]);
393 fprintf(fp,
"\n\n# freq[%d] (frequency desired_gain actual_gain)\n", ch);
405 ya = 20.0 * log10(fabs(ya));
406 yb = 20.0 * log10(fabs(yb));
408 fprintf(fp,
"%17.10f %17.10f %17.10f\n", vx, ya, yb);
443 const double *freq =
key;
446 if (*freq < entry[0].freq)
448 if (*freq > entry[1].freq)
466 if (freq <= s->gain_entry_tbl[0].freq)
476 d0 = freq - res[0].
freq;
477 d1 = res[1].
freq - freq;
480 return (d0 * res[1].gain + d1 * res[0].gain) / d;
495 double m0, m1, m2, msum, unit;
500 if (freq <= s->gain_entry_tbl[0].freq)
511 unit * (res[0].
gain - res[-1].
gain) / (res[0].freq - res[-1].freq) : 0;
514 unit * (res[2].
gain - res[1].
gain) / (res[2].freq - res[1].freq) : 0;
516 msum = fabs(m0) + fabs(m1);
517 m0 = msum > 0 ? (fabs(m0) * m1 + fabs(m1) * m0) / msum : 0;
518 msum = fabs(m1) + fabs(m2);
519 m1 = msum > 0 ? (fabs(m1) * m2 + fabs(m2) * m1) / msum : 0;
523 b = 3 * res[1].
gain - m1 - 2 * c - 3 * d;
524 a = res[1].
gain - b - c - d;
526 x = (freq - res[0].
freq) / unit;
530 return a * x3 + b * x2 + c * x + d;
556 double norm = 2.0 / cepstrum_len;
557 double minval = 1e-7 / rdft_len;
560 memcpy(s->
cepstrum_buf, rdft_buf, rdft_len/2 *
sizeof(*rdft_buf));
561 memcpy(s->
cepstrum_buf + cepstrum_len - rdft_len/2, rdft_buf + rdft_len/2, rdft_len/2 *
sizeof(*rdft_buf));
568 for (k = 2; k < cepstrum_len; k += 2) {
576 for (k = 1; k < cepstrum_len/2; k++)
583 for (k = 2; k < cepstrum_len; k += 2) {
591 memset(rdft_buf, 0, s->
rdft_len *
sizeof(*rdft_buf));
605 const char *gain_entry_func_names[] = {
"entry",
NULL };
606 const char *gain_func_names[] = {
"gain_interpolate",
"cubic_interpolate",
NULL };
607 double (*gain_entry_funcs[])(
void *, double, double) = {
entry_func,
NULL };
611 int ret, k, center,
ch;
614 FILE *dump_fp =
NULL;
621 gain_entry_func_names, gain_entry_funcs, ctx, 0, ctx);
631 gain_func_names, gain_funcs,
NULL,
NULL, 0, ctx);
641 for (ch = 0; ch < inlink->
channels; ch++) {
650 s->
analysis_buf[0] = ylog ? pow(10.0, 0.05 * result) : result;
656 s->
analysis_buf[1] = ylog ? pow(10.0, 0.05 * result) : result;
673 for (k = 0; k <= center; k++) {
674 double u = k * (
M_PI/center);
681 win = 0.5 + 0.5 * cos(u);
684 win = 0.53836 + 0.46164 * cos(u);
687 win = 0.42 + 0.5 * cos(u) + 0.08 * cos(2*u);
690 win = 0.40897 + 0.5 * cos(u) + 0.09103 * cos(2*u);
693 win = 0.4243801 + 0.4973406 * cos(u) + 0.0782793 * cos(2*u);
696 win = 0.355768 + 0.487396 * cos(u) + 0.144232 * cos(2*u) + 0.012604 * cos(3*u);
699 win = 0.3635819 + 0.4891775 * cos(u) + 0.1365995 * cos(2*u) + 0.0106411 * cos(3*u);
702 win = 0.35875 + 0.48829 * cos(u) + 0.14128 * cos(2*u) + 0.01168 * cos(3*u);
705 win = (u <= 0.5 *
M_PI) ? 1.0 : (0.5 + 0.5 * cos(2*u -
M_PI));
723 if (
isnan(rdft_buf[k]) ||
isinf(rdft_buf[k])) {
733 rdft_buf[s->
rdft_len-1] = rdft_buf[1];
735 rdft_buf[k] = rdft_buf[2*k];
753 #define SELECT_GAIN(s) (s->gain_cmd ? s->gain_cmd : s->gain)
754 #define SELECT_GAIN_ENTRY(s) (s->gain_entry_cmd ? s->gain_entry_cmd : s->gain_entry)
789 int cepstrum_bits = rdft_bits + 2;
834 av_log(ctx,
AV_LOG_DEBUG,
"sample_rate = %d, channels = %d, analysis_rdft_len = %d, rdft_len = %d, fir_len = %d, nsamples_max = %d.\n",
856 for ( ; ch < inlink->
channels; ch++) {
862 for (ch = 0; ch < inlink->
channels; ch++) {
902 char *res,
int res_len,
int flags)
907 if (!strcmp(cmd,
"gain")) {
926 }
else if (!strcmp(cmd,
"gain_entry")) {
927 char *gain_entry_cmd;
971 .
name =
"firequalizer",
977 .
inputs = firequalizer_inputs,
978 .
outputs = firequalizer_outputs,
979 .priv_class = &firequalizer_class,
This structure describes decoded (raw) audio or video data.
ptrdiff_t const GLvoid * data
av_cold void av_fft_end(FFTContext *s)
#define fixed(width, name, value)
#define AV_LOG_WARNING
Something somehow does not look correct.
static void common_uninit(FIREqualizerContext *s)
Main libavfilter public API header.
static float win(SuperEqualizerContext *s, float n, int N)
int max_samples
Maximum number of samples to filter at once.
static void generate_min_phase_kernel(FIREqualizerContext *s, float *rdft_buf)
static double gain_interpolate_func(void *p, double freq)
static int request_frame(AVFilterLink *outlink)
void av_fft_permute(FFTContext *s, FFTComplex *z)
Do the permutation needed BEFORE calling ff_fft_calc().
static int config_input(AVFilterLink *inlink)
int av_expr_parse(AVExpr **expr, const char *s, const char *const *const_names, const char *const *func1_names, double(*const *funcs1)(void *, double), const char *const *func2_names, double(*const *funcs2)(void *, double, double), int log_offset, void *log_ctx)
Parse an expression.
#define SELECT_GAIN_ENTRY(s)
void * av_calloc(size_t nmemb, size_t size)
Non-inlined equivalent of av_mallocz_array().
#define NB_GAIN_ENTRY_MAX
static const AVFilterPad firequalizer_outputs[]
const char * name
Pad name.
AVFilterLink ** inputs
array of pointers to input links
#define av_assert0(cond)
assert() equivalent, that is always enabled.
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
static double cubic_interpolate_func(void *p, double freq)
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
#define u(width, name, range_min, range_max)
static const char *const var_names[]
#define AVERROR_EOF
End of file.
A filter pad used for either input or output.
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
A link between two filters.
int av_expr_parse_and_eval(double *d, const char *s, const char *const *const_names, const double *const_values, const char *const *func1_names, double(*const *funcs1)(void *, double), const char *const *func2_names, double(*const *funcs2)(void *, double, double), void *opaque, int log_offset, void *log_ctx)
Parse and evaluate an expression.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
int av_samples_set_silence(uint8_t **audio_data, int offset, int nb_samples, int nb_channels, enum AVSampleFormat sample_fmt)
Fill an audio buffer with silence.
int min_samples
Minimum number of samples to filter at once.
int sample_rate
samples per second
AVFrame * ff_get_audio_buffer(AVFilterLink *link, int nb_samples)
Request an audio samples buffer with a specific set of permissions.
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
AVFILTER_DEFINE_CLASS(firequalizer)
RDFTContext * cepstrum_rdft
void * priv
private data for use by the filter
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
AVRational time_base
Define the time base used by the PTS of the frames/samples which will pass through this link...
simple assert() macros that are a bit more flexible than ISO C assert().
FFTContext * av_fft_init(int nbits, int inverse)
Set up a complex FFT.
RDFTContext * cepstrum_irdft
RDFTContext * analysis_irdft
static av_cold void uninit(AVFilterContext *ctx)
static const AVOption firequalizer_options[]
void av_rdft_calc(RDFTContext *s, FFTSample *data)
static const AVFilterPad firequalizer_inputs[]
static void fast_convolute2(FIREqualizerContext *av_restrict s, const float *av_restrict kernel_buf, FFTComplex *av_restrict conv_buf, OverlapIndex *av_restrict idx, float *av_restrict data0, float *av_restrict data1, int nsamples)
static void fast_convolute_nonlinear(FIREqualizerContext *av_restrict s, const float *av_restrict kernel_buf, float *av_restrict conv_buf, OverlapIndex *av_restrict idx, float *av_restrict data, int nsamples)
void av_rdft_end(RDFTContext *s)
AVFilterContext * src
source filter
RDFTContext * av_rdft_init(int nbits, enum RDFTransformType trans)
Set up a real FFT.
int partial_buf_size
Size of the partial buffer to allocate.
static const AVFilterPad inputs[]
static const AVFilterPad outputs[]
A list of supported channel layouts.
static double entry_func(void *p, double freq, double gain)
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames...
static const uint8_t vars[2][12]
char * av_strdup(const char *s)
Duplicate a string.
AVSampleFormat
Audio sample formats.
void av_expr_free(AVExpr *e)
Free a parsed expression previously created with av_expr_parse().
AVFilter ff_af_firequalizer
static AVRational av_make_q(int num, int den)
Create an AVRational.
static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, char *res, int res_len, int flags)
static void fast_convolute(FIREqualizerContext *av_restrict s, const float *av_restrict kernel_buf, float *av_restrict conv_buf, OverlapIndex *av_restrict idx, float *av_restrict data, int nsamples)
Describe the class of an AVClass context structure.
GainEntry gain_entry_tbl[NB_GAIN_ENTRY_MAX]
const char * name
Filter name.
AVFilterLink ** outputs
array of pointers to output links
enum MovChannelLayoutTag * layouts
static void dump_fir(AVFilterContext *ctx, FILE *fp, int ch)
#define flags(name, subs,...)
RDFTContext * analysis_rdft
uint64_t av_channel_layout_extract_channel(uint64_t channel_layout, int index)
Get the channel with the given index in channel_layout.
static int query_formats(AVFilterContext *ctx)
static int generate_kernel(AVFilterContext *ctx, const char *gain, const char *gain_entry)
uint64_t channel_layout
channel layout of current buffer (see libavutil/channel_layout.h)
int channels
Number of channels.
double av_expr_eval(AVExpr *e, const double *const_values, void *opaque)
Evaluate a previously parsed expression.
AVFilterContext * dst
dest filter
static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
static enum AVSampleFormat sample_fmts[]
#define av_malloc_array(a, b)
static int gain_entry_compare(const void *key, const void *memb)
int ff_request_frame(AVFilterLink *link)
Request an input frame from the filter at the other end of the link.
uint8_t ** extended_data
pointers to the data planes/channels.
void av_fft_calc(FFTContext *s, FFTComplex *z)
Do a complex FFT with the parameters defined in av_fft_init().
int nb_samples
number of audio samples (per channel) described by this frame
#define AV_NOPTS_VALUE
Undefined timestamp value.
uint8_t pi<< 24) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_U8,(uint64_t)((*(constuint8_t *) pi-0x80U))<< 56) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8,(*(constuint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8,(*(constuint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16,(*(constint16_t *) pi >>8)+0x80) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_S16,(uint64_t)(*(constint16_t *) pi)<< 48) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16,*(constint16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16,*(constint16_t *) pi *(1.0/(1<< 15))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32,(*(constint32_t *) pi >>24)+0x80) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_S32,(uint64_t)(*(constint32_t *) pi)<< 32) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32,*(constint32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32,*(constint32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S64,(*(constint64_t *) pi >>56)+0x80) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S64,*(constint64_t *) pi *(1.0f/(INT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S64,*(constint64_t *) pi *(1.0/(INT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, av_clip_uint8(lrintf(*(constfloat *) pi *(1<< 7))+0x80)) CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, av_clip_int16(lrintf(*(constfloat *) pi *(1<< 15)))) CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, av_clipl_int32(llrintf(*(constfloat *) pi *(1U<< 31)))) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_FLT, llrintf(*(constfloat *) pi *(INT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, av_clip_uint8(lrint(*(constdouble *) pi *(1<< 7))+0x80)) CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, av_clip_int16(lrint(*(constdouble *) pi *(1<< 15)))) CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, av_clipl_int32(llrint(*(constdouble *) pi *(1U<< 31)))) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_DBL, llrint(*(constdouble *) pi *(INT64_C(1)<< 63)))#defineFMT_PAIR_FUNC(out, in) staticconv_func_type *constfmt_pair_to_conv_functions[AV_SAMPLE_FMT_NB *AV_SAMPLE_FMT_NB]={FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S64),};staticvoidcpy1(uint8_t **dst, constuint8_t **src, intlen){memcpy(*dst,*src, len);}staticvoidcpy2(uint8_t **dst, constuint8_t **src, intlen){memcpy(*dst,*src, 2 *len);}staticvoidcpy4(uint8_t **dst, constuint8_t **src, intlen){memcpy(*dst,*src, 4 *len);}staticvoidcpy8(uint8_t **dst, constuint8_t **src, intlen){memcpy(*dst,*src, 8 *len);}AudioConvert *swri_audio_convert_alloc(enumAVSampleFormatout_fmt, enumAVSampleFormatin_fmt, intchannels, constint *ch_map, intflags){AudioConvert *ctx;conv_func_type *f=fmt_pair_to_conv_functions[av_get_packed_sample_fmt(out_fmt)+AV_SAMPLE_FMT_NB *av_get_packed_sample_fmt(in_fmt)];if(!f) returnNULL;ctx=av_mallocz(sizeof(*ctx));if(!ctx) returnNULL;if(channels==1){in_fmt=av_get_planar_sample_fmt(in_fmt);out_fmt=av_get_planar_sample_fmt(out_fmt);}ctx->channels=channels;ctx->conv_f=f;ctx->ch_map=ch_map;if(in_fmt==AV_SAMPLE_FMT_U8||in_fmt==AV_SAMPLE_FMT_U8P) memset(ctx->silence, 0x80, sizeof(ctx->silence));if(out_fmt==in_fmt &&!ch_map){switch(av_get_bytes_per_sample(in_fmt)){case1:ctx->simd_f=cpy1;break;case2:ctx->simd_f=cpy2;break;case4:ctx->simd_f=cpy4;break;case8:ctx->simd_f=cpy8;break;}}if(HAVE_X86ASM &&1) swri_audio_convert_init_x86(ctx, out_fmt, in_fmt, channels);if(ARCH_ARM) swri_audio_convert_init_arm(ctx, out_fmt, in_fmt, channels);if(ARCH_AARCH64) swri_audio_convert_init_aarch64(ctx, out_fmt, in_fmt, channels);returnctx;}voidswri_audio_convert_free(AudioConvert **ctx){av_freep(ctx);}intswri_audio_convert(AudioConvert *ctx, AudioData *out, AudioData *in, intlen){intch;intoff=0;constintos=(out->planar?1:out->ch_count)*out->bps;unsignedmisaligned=0;av_assert0(ctx->channels==out->ch_count);if(ctx->in_simd_align_mask){intplanes=in->planar?in->ch_count:1;unsignedm=0;for(ch=0;ch< planes;ch++) m|=(intptr_t) in->ch[ch];misaligned|=m &ctx->in_simd_align_mask;}if(ctx->out_simd_align_mask){intplanes=out->planar?out->ch_count:1;unsignedm=0;for(ch=0;ch< planes;ch++) m|=(intptr_t) out->ch[ch];misaligned|=m &ctx->out_simd_align_mask;}if(ctx->simd_f &&!ctx->ch_map &&!misaligned){off=len &~15;av_assert1(off >=0);av_assert1(off<=len);av_assert2(ctx->channels==SWR_CH_MAX||!in->ch[ctx->channels]);if(off >0){if(out->planar==in->planar){intplanes=out->planar?out->ch_count:1;for(ch=0;ch< planes;ch++){ctx->simd_f(out-> ch ch
simple arithmetic expression evaluator