37#define FREQUENCY_DOMAIN 1
104 char *
arg, *tokenizer, *p;
105 uint64_t used_channels = 0;
116 if (used_channels & (1ULL << out_channel)) {
120 used_channels |= (1ULL << out_channel);
121 s->mapping[
s->nb_irs] = out_channel;
127 s->nb_hrir_inputs = 1;
129 s->nb_hrir_inputs =
s->nb_irs;
150 int *write = &td->
write[jobnr];
151 const float *
const ir = td->
ir[jobnr];
154 float *temp_src = td->
temp_src[jobnr];
155 const int ir_len =
s->ir_len;
156 const int air_len =
s->air_len;
157 const float *
src = (
const float *)in->
data[0];
158 float *
dst = (
float *)
out->data[0];
160 const int buffer_length =
s->buffer_length;
161 const uint32_t modulo = (uint32_t)buffer_length - 1;
168 for (l = 0; l < in_channels; l++) {
169 buffer[l] = ringbuffer + l * buffer_length;
173 const float *cur_ir = ir;
176 for (l = 0; l < in_channels; l++) {
180 for (l = 0; l < in_channels; cur_ir += air_len, l++) {
181 const float *
const bptr =
buffer[l];
183 if (l ==
s->lfe_channel) {
184 *
dst += *(
buffer[
s->lfe_channel] + wr) *
s->gain_lfe;
188 read = (wr - (ir_len - 1)) & modulo;
190 if (
read + ir_len < buffer_length) {
191 memcpy(temp_src, bptr +
read, ir_len *
sizeof(*temp_src));
195 memcpy(temp_src, bptr +
read,
len *
sizeof(*temp_src));
196 memcpy(temp_src +
len, bptr, (air_len -
len) *
sizeof(*temp_src));
199 dst[0] +=
s->scalarproduct_float(cur_ir, temp_src,
FFALIGN(ir_len, 32));
207 wr = (wr + 1) & modulo;
221 int *write = &td->
write[jobnr];
225 const int ir_len =
s->ir_len;
226 const float *
src = (
const float *)in->
data[0];
227 float *
dst = (
float *)
out->data[0];
229 const int buffer_length =
s->buffer_length;
230 const uint32_t modulo = (uint32_t)buffer_length - 1;
238 const int n_fft =
s->n_fft;
239 const float fft_scale = 1.0f /
s->n_fft;
248 for (j = 0; j < n_read; j++) {
249 dst[2 * j] = ringbuffer[wr];
250 ringbuffer[wr] = 0.0;
251 wr = (wr + 1) & modulo;
260 for (
i = 0;
i < in_channels;
i++) {
261 if (
i ==
s->lfe_channel) {
263 dst[2 * j] +=
src[
i + j * in_channels] *
s->gain_lfe;
269 hrtf_offset = hrtf +
s->hrir_map[
i] * n_fft;
274 fft_in[j].
re =
src[j * in_channels +
i];
277 tx_fn(fft, fft_out, fft_in,
sizeof(*fft_in));
279 for (j = 0; j < n_fft; j++) {
281 const float re = fft_out[j].
re;
282 const float im = fft_out[j].
im;
284 fft_acc[j].
re += re * hcomplex->
re - im * hcomplex->
im;
285 fft_acc[j].
im += re * hcomplex->
im + im * hcomplex->
re;
289 itx_fn(ifft, fft_out, fft_acc,
sizeof(*fft_acc));
292 dst[2 * j] += fft_out[j].
re * fft_scale;
297 for (j = 0; j < ir_len - 1; j++) {
298 int write_pos = (wr + j) & modulo;
300 *(ringbuffer + write_pos) += fft_out[in->
nb_samples + j].
re * fft_scale;
312 int ir_len, max_ir_len;
316 if (ir_len > max_ir_len) {
320 s->hrir_in[input_number].ir_len = ir_len;
321 s->ir_len =
FFMAX(ir_len,
s->ir_len);
324 s->hrir_in[input_number].eof = 1;
328 if (!
s->hrir_in[input_number].eof) {
339 int n_clippings[2] = { 0 };
363 if (n_clippings[0] + n_clippings[1] > 0) {
365 n_clippings[0] + n_clippings[1],
out->nb_samples * 2);
376 int nb_input_channels =
ctx->inputs[0]->ch_layout.nb_channels;
377 const int nb_hrir_channels =
s->nb_hrir_inputs == 1 ?
ctx->inputs[1]->ch_layout.nb_channels :
s->nb_hrir_inputs * 2;
378 float gain_lin =
expf((
s->gain - 3 * nb_input_channels) / 20 *
M_LN10);
388 s->buffer_length = 1 << (32 -
ff_clz(
s->air_len));
407 if (!
s->fft[0] || !
s->fft[1] || !
s->ifft[0] || !
s->ifft[1]) {
415 s->ringbuffer[0] =
av_calloc(
s->buffer_length,
sizeof(
float) * nb_input_channels);
416 s->ringbuffer[1] =
av_calloc(
s->buffer_length,
sizeof(
float) * nb_input_channels);
418 s->ringbuffer[0] =
av_calloc(
s->buffer_length,
sizeof(
float));
419 s->ringbuffer[1] =
av_calloc(
s->buffer_length,
sizeof(
float));
426 if (!
s->in_fft[0] || !
s->in_fft[1] ||
427 !
s->out_fft[0] || !
s->out_fft[1] ||
428 !
s->temp_afft[0] || !
s->temp_afft[1]) {
434 if (!
s->ringbuffer[0] || !
s->ringbuffer[1]) {
440 s->temp_src[0] =
av_calloc(
s->air_len,
sizeof(
float));
441 s->temp_src[1] =
av_calloc(
s->air_len,
sizeof(
float));
443 s->data_ir[0] =
av_calloc(nb_hrir_channels *
s->air_len,
sizeof(*
s->data_ir[0]));
444 s->data_ir[1] =
av_calloc(nb_hrir_channels *
s->air_len,
sizeof(*
s->data_ir[1]));
445 if (!
s->data_ir[0] || !
s->data_ir[1] || !
s->temp_src[0] || !
s->temp_src[1]) {
450 s->data_hrtf[0] =
av_calloc(
n_fft,
sizeof(*
s->data_hrtf[0]) * nb_hrir_channels);
451 s->data_hrtf[1] =
av_calloc(
n_fft,
sizeof(*
s->data_hrtf[1]) * nb_hrir_channels);
452 if (!
s->data_hrtf[0] || !
s->data_hrtf[1]) {
459 int len =
s->hrir_in[
i].ir_len;
465 ptr = (
float *)
frame->extended_data[0];
473 s->hrir_map[
i] = idx;
475 float *data_ir_l =
s->data_ir[0] + idx *
s->air_len;
476 float *data_ir_r =
s->data_ir[1] + idx *
s->air_len;
478 for (j = 0; j <
len; j++) {
479 data_ir_l[j] = ptr[
len * 2 - j * 2 - 2] * gain_lin;
480 data_ir_r[j] = ptr[
len * 2 - j * 2 - 1] * gain_lin;
488 for (j = 0; j <
len; j++) {
489 fft_in_l[j].
re = ptr[j * 2 ] * gain_lin;
490 fft_in_r[j].
re = ptr[j * 2 + 1] * gain_lin;
493 s->tx_fn[0](
s->fft[0], fft_out_l, fft_in_l,
sizeof(*fft_in_l));
494 s->tx_fn[0](
s->fft[0], fft_out_r, fft_in_r,
sizeof(*fft_in_r));
497 int I,
N =
ctx->inputs[1]->ch_layout.nb_channels;
499 for (k = 0; k <
N / 2; k++) {
505 s->hrir_map[k] = idx;
508 float *data_ir_l =
s->data_ir[0] + idx *
s->air_len;
509 float *data_ir_r =
s->data_ir[1] + idx *
s->air_len;
511 for (j = 0; j <
len; j++) {
512 data_ir_l[j] = ptr[
len *
N - j *
N -
N + I ] * gain_lin;
513 data_ir_r[j] = ptr[
len *
N - j *
N -
N + I + 1] * gain_lin;
521 for (j = 0; j <
len; j++) {
522 fft_in_l[j].
re = ptr[j *
N + I ] * gain_lin;
523 fft_in_r[j].
re = ptr[j *
N + I + 1] * gain_lin;
526 s->tx_fn[0](
s->fft[0], fft_out_l, fft_in_l,
sizeof(*fft_in_l));
527 s->tx_fn[0](
s->fft[0], fft_out_r, fft_in_r,
sizeof(*fft_in_r));
550 for (
i = 0;
i <
s->nb_hrir_inputs;
i++) {
553 if (
s->hrir_in[
i].eof)
559 if (
s->hrir_in[
i].eof) {
562 "HRIR stream %d.\n",
i);
578 }
else if (!
s->have_hrirs)
640 for (
i = 1;
i <=
s->nb_hrir_inputs;
i++) {
685 for (
i = 0;
i <
s->nb_hrir_inputs;
i++) {
752#define OFFSET(x) offsetof(HeadphoneContext, x)
753#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
780 .p.name =
"headphone",
781 .p.description =
NULL_IF_CONFIG_SMALL(
"Apply headphone binaural spatialization with HRTFs in additional streams."),
782 .p.priv_class = &headphone_class,
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
static int query_formats(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out)
static const AVFilterPad outputs[]
static int config_input(AVFilterLink *inlink)
static int convert_coeffs(AVFilterContext *ctx, AVFilterLink *inlink)
const FFFilter ff_af_headphone
static int headphone_convolute(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
static int headphone_frame(HeadphoneContext *s, AVFrame *in, AVFilterLink *outlink)
static int config_input(AVFilterLink *inlink)
static const AVOption headphone_options[]
static int check_ir(AVFilterLink *inlink, int input_number)
static int parse_channel_name(const char *arg, enum AVChannel *rchannel)
static int query_formats(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out)
static int activate(AVFilterContext *ctx)
static av_cold void uninit(AVFilterContext *ctx)
static void parse_map(AVFilterContext *ctx)
static int config_output(AVFilterLink *outlink)
static int headphone_fast_convolute(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
AVFrame * ff_get_audio_buffer(AVFilterLink *link, int nb_samples)
Request an audio samples buffer with a specific set of permissions.
int ff_append_inpad_free_name(AVFilterContext *f, AVFilterPad *p)
int ff_inlink_check_available_samples(AVFilterLink *link, unsigned min)
Test if enough samples are available on the link.
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
int ff_append_inpad(AVFilterContext *f, AVFilterPad *p)
Append a new input/output pad to the filter's list of such pads.
int ff_outlink_frame_wanted(AVFilterLink *link)
Test if a frame is wanted on an output link.
int ff_filter_execute(AVFilterContext *ctx, avfilter_action_func *func, void *arg, int *ret, int nb_jobs)
int ff_inlink_consume_samples(AVFilterLink *link, unsigned min, unsigned max, AVFrame **rframe)
Take samples from the link's FIFO and update the link's stats.
void ff_filter_set_ready(AVFilterContext *filter, unsigned priority)
Mark a filter ready and schedule it for activation.
int ff_inlink_queued_samples(AVFilterLink *link)
void ff_inlink_request_frame(AVFilterLink *link)
Mark that a frame is wanted on the link.
Main libavfilter public API header.
char * av_asprintf(const char *fmt,...)
static uint32_t BS_FUNC read(BSCTX *bc, unsigned int n)
Return n bits from the buffer, n has to be in the 0-32 range.
#define i(width, name, range_min, range_max)
Public libavutil channel layout APIs header.
static __device__ float fabsf(float a)
static const uint16_t channel_layouts[7]
int(* init)(AVBSFContext *ctx)
channel
Use these values when setting the channel map with ebur128_set_channel().
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
@ AV_OPT_TYPE_INT
Underlying C type is int.
@ AV_OPT_TYPE_FLOAT
Underlying C type is float.
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
#define AVFILTER_FLAG_DYNAMIC_INPUTS
The number of the filter inputs is not determined just by AVFilter.inputs.
int av_channel_layout_index_from_channel(const AVChannelLayout *channel_layout, enum AVChannel channel)
Get the index of a given channel in a channel layout.
#define AV_CHANNEL_LAYOUT_STEREO
int av_channel_layout_from_mask(AVChannelLayout *channel_layout, uint64_t mask)
Initialize a native channel layout from a bitmask indicating which channels are present.
enum AVChannel av_channel_from_string(const char *str)
This is the inverse function of av_channel_name().
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
#define AVERROR_EOF
End of file.
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
#define AV_LOG_WARNING
Something somehow does not look correct.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
AVSampleFormat
Audio sample formats.
char * av_strtok(char *s, const char *delim, char **saveptr)
Split the string into several tokens which can be accessed by successive calls to av_strtok().
const VDPAUPixFmtMap * map
static void scale(int *out, const int *in, const int w, const int h, const int shift)
static av_cold void uninit(AVBitStreamFilterContext *ctx)
static int activate(AVBitStreamFilterContext *ctx)
static int config_output(AVBitStreamFilterLink *outlink)
#define FILTER_OUTPUTS(array)
#define FF_FILTER_FORWARD_STATUS(inlink, outlink)
Acknowledge the status on an input link and forward it to an output link.
#define FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, filter)
Forward the status on an output link to all input links.
#define AVFILTER_DEFINE_CLASS(fname)
#define FILTER_QUERY_FUNC2(func)
av_cold AVFloatDSPContext * avpriv_float_dsp_alloc(int bit_exact)
Allocate a float DSP context.
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
void * av_calloc(size_t nmemb, size_t size)
Memory handling functions.
enum MovChannelLayoutTag * layouts
An AVChannelLayout holds information about the channel layout of audio data.
int nb_channels
Number of channels in this layout.
Describe the class of an AVClass context structure.
A list of supported channel layouts.
A link between two filters.
AVFilterContext * src
source filter
AVChannelLayout ch_layout
channel layout of current buffer (see libavutil/channel_layout.h)
AVFilterContext * dst
dest filter
A filter pad used for either input or output.
float(* scalarproduct_float)(const float *v1, const float *v2, int len)
Calculate the scalar product of two vectors of floats.
This structure describes decoded (raw) audio or video data.
int nb_samples
number of audio samples (per channel) described by this frame
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
AVChannelLayout ch_layout
Channel layout of the audio data.
AVComplexFloat * in_fft[2]
AVComplexFloat * temp_afft[2]
AVComplexFloat * data_hrtf[2]
enum AVChannel mapping[64]
struct HeadphoneContext::hrir_inputs hrir_in[64]
AVComplexFloat * out_fft[2]
AVChannelLayout map_channel_layout
float(* scalarproduct_float)(const float *v1, const float *v2, int len)
Used for passing data between threads.
AVComplexFloat ** out_fft
AVComplexFloat ** temp_afft
static AVFormatContext * ctx
av_cold void av_tx_uninit(AVTXContext **ctx)
Frees a context and sets *ctx to NULL, does nothing when *ctx == NULL.
av_cold int av_tx_init(AVTXContext **ctx, av_tx_fn *tx, enum AVTXType type, int inv, int len, const void *scale, uint64_t flags)
Initialize a transform context with the given configuration (i)MDCTs with an odd length are currently...
@ AV_TX_FLOAT_FFT
Standard complex to complex FFT with sample data type of AVComplexFloat, AVComplexDouble or AVComplex...
void(* av_tx_fn)(AVTXContext *s, void *out, void *in, ptrdiff_t stride)
Function pointer to a function to perform the transform.