summaryrefslogtreecommitdiffstats
path: root/audio/filter
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-03-23 17:49:52 +0100
committerwm4 <wm4@nowhere>2013-04-13 04:21:28 +0200
commit41aefce730efd7da6068b7f61697c65759cd3f84 (patch)
tree30d045f278ba768952277e0da09386a023b91907 /audio/filter
parentf54909d4df1e1f00481e3ca4aae02f9bf7b78668 (diff)
downloadmpv-41aefce730efd7da6068b7f61697c65759cd3f84.tar.bz2
mpv-41aefce730efd7da6068b7f61697c65759cd3f84.tar.xz
audio: switch to libavcodec channel order, use libavresample for mixing
Switch the internal channel order to libavcodec's. If the channel number mismatches at some point, use libavresample for up- or downmixing. Remove the old af_pan automatic downmixing. The libavcodec channel order should be equivalent to WAVEFORMATEX order, at least nowadays. reorder_ch.h assumes that WAVEFORMATEX and libavcodec might be different, but all defined channels have the same mappings. Remove the downmixing with af_pan as well as the channel conversion with af_channels from af.c, and prefer af_lavrresample for this. The automatic downmixing behavior should be the same as before (if the --channels option is set to 2, which is the default, the audio output is forced to 2 channels, and libavresample does all downmixing). Note that mpv still can't do channel layouts. It will pick the default channel layout according to the channel count. This will be fixed later by passing down the channel layout as well. af_hrtf depends on the order of the input channels, so reorder to ALSA (for which this code was written). This is better than changing the filter code, which is more risky. ao_pulse can accept waveext order directly, so set that as channel mapping.
Diffstat (limited to 'audio/filter')
-rw-r--r--audio/filter/af.c32
-rw-r--r--audio/filter/af_hrtf.c8
-rw-r--r--audio/filter/af_lavrresample.c44
3 files changed, 42 insertions, 42 deletions
diff --git a/audio/filter/af.c b/audio/filter/af.c
index 4af1929505..c36c8f6e8f 100644
--- a/audio/filter/af.c
+++ b/audio/filter/af.c
@@ -372,15 +372,16 @@ static int af_fix_channels(struct af_stream *s, struct af_instance **p_af,
}
if (actual.nch == in.nch)
return AF_FALSE;
+ const char *filter = "lavrresample";
struct af_instance *new;
if (af) {
- new = af_prepend(s, af, "channels");
+ new = af_prepend(s, af, filter);
new->auto_inserted = true;
} else {
- if (strcmp(s->last->info->name, "channels") == 0) {
+ if (strcmp(s->last->info->name, filter) == 0) {
new = s->last;
} else {
- new = af_append(s, s->last, "channels");
+ new = af_append(s, s->last, filter);
new->auto_inserted = true;
}
}
@@ -516,26 +517,6 @@ static int fixup_output_format(struct af_stream *s)
return AF_OK;
}
-/**
- * Automatic downmix to stereo in case the codec does not implement it.
- */
-static void af_downmix(struct af_stream *s)
-{
- static const char *const downmix_strs[AF_NCH + 1] = {
- /* FL FR RL RR FC LF AL AR */
- [3] = "pan=2:" "0.6:0:" "0:0.6:" "0.4:0.4",
- [4] = "pan=2:" "0.6:0:" "0:0.6:" "0.4:0:" "0:0.4",
- [5] = "pan=2:" "0.5:0:" "0:0.5:" "0.2:0:" "0:0.2:" "0.3:0.3",
- [6] = "pan=2:" "0.4:0:" "0:0.4:" "0.2:0:" "0:0.2:" "0.3:0.3:" "0.1:0.1",
- [7] = "pan=2:" "0.4:0:" "0:0.4:" "0.2:0:" "0:0.2:" "0.3:0.3:" "0.1:0:" "0:0.1",
- [8] = "pan=2:" "0.4:0:" "0:0.4:" "0.15:0:" "0:0.15:" "0.25:0.25:" "0.1:0.1:" "0.1:0:" "0:0.1",
- };
- const char *af_pan_str = downmix_strs[s->input.nch];
-
- if (af_pan_str)
- af_append(s, s->first, af_pan_str);
-}
-
/* Initialize the stream "s". This function creates a new filter list
if necessary according to the values set in input and output. Input
and output should contain the format of the current movie and the
@@ -547,7 +528,6 @@ static void af_downmix(struct af_stream *s)
The return value is 0 if success and -1 if failure */
int af_init(struct af_stream *s)
{
- struct MPOpts *opts = s->opts;
int i = 0;
// Sanity check
@@ -564,10 +544,6 @@ int af_init(struct af_stream *s)
// Check if this is the first call
if (!s->first) {
- // Append a downmix pan filter at the beginning of the chain if needed
- if (s->input.nch != opts->audio_output_channels
- && opts->audio_output_channels == 2)
- af_downmix(s);
// Add all filters in the list (if there are any)
if (s->cfg.list) {
while (s->cfg.list[i]) {
diff --git a/audio/filter/af_hrtf.c b/audio/filter/af_hrtf.c
index 4f5eedb29d..72e2ec7c66 100644
--- a/audio/filter/af_hrtf.c
+++ b/audio/filter/af_hrtf.c
@@ -31,6 +31,8 @@
#include "af.h"
#include "dsp.h"
+#include "audio/reorder_ch.h"
+
/* HRTF filter coefficients and adjustable parameters */
#include "af_hrtf.h"
@@ -390,6 +392,12 @@ static struct mp_audio* play(struct af_instance *af, struct mp_audio *data)
float common, left, right, diff, left_b, right_b;
const int dblen = s->dlbuflen, hlen = s->hrflen, blen = s->basslen;
+ // This was written against the old mplayer channel order, which was ALSA.
+ // Feel free to fix the otuput code below to output proper order.
+ reorder_channel_nch(data->audio, AF_CHANNEL_LAYOUT_MPLAYER_DEFAULT,
+ AF_CHANNEL_LAYOUT_ALSA_DEFAULT,
+ data->nch, data->len / data->bps, data->bps);
+
if(AF_OK != RESIZE_LOCAL_BUFFER(af, data))
return NULL;
diff --git a/audio/filter/af_lavrresample.c b/audio/filter/af_lavrresample.c
index b95c3e5f69..1d3b7639bd 100644
--- a/audio/filter/af_lavrresample.c
+++ b/audio/filter/af_lavrresample.c
@@ -58,11 +58,12 @@ struct af_resample_opts {
int linear;
double cutoff;
- int out_rate;
int in_rate;
- int out_format;
int in_format;
- int channels;
+ int in_channels;
+ int out_rate;
+ int out_format;
+ int out_channels;
};
struct af_resample {
@@ -92,11 +93,12 @@ static bool needs_lavrctx_reconfigure(struct af_resample *s,
struct mp_audio *in,
struct mp_audio *out)
{
- return s->ctx.out_rate != out->rate ||
- s->ctx.in_rate != in->rate ||
+ return s->ctx.in_rate != in->rate ||
s->ctx.in_format != in->format ||
+ s->ctx.in_channels != in->nch ||
+ s->ctx.out_rate != out->rate ||
s->ctx.out_format != out->format ||
- s->ctx.channels != out->nch ||
+ s->ctx.out_channels!= out->nch ||
s->ctx.filter_size != s->opts.filter_size ||
s->ctx.phase_shift != s->opts.phase_shift ||
s->ctx.linear != s->opts.linear ||
@@ -125,12 +127,16 @@ static int control(struct af_instance *af, int cmd, void *arg)
if (((out->rate == in->rate) || (out->rate == 0)) &&
(out->format == in->format) &&
- (out->bps == in->bps))
+ (out->bps == in->bps) &&
+ ((out->nch == in->nch) || out->nch == 0))
return AF_DETACH;
if (out->rate == 0)
out->rate = in->rate;
+ if (out->nch == 0)
+ out->nch = in->nch;
+
enum AVSampleFormat in_samplefmt = af_to_avformat(in->format);
if (in_samplefmt == AV_SAMPLE_FMT_NONE) {
in->format = AF_FORMAT_FLOAT_NE;
@@ -142,10 +148,9 @@ static int control(struct af_instance *af, int cmd, void *arg)
out_samplefmt = in_samplefmt;
}
- out->nch = FFMIN(in->nch, AF_NCH);
out->bps = af_fmt2bits(out->format) / 8;
in->bps = af_fmt2bits(in->format) / 8;
- af->mul = (double) out->rate / in->rate;
+ af->mul = (double) (out->rate * out->nch) / (in->rate * in->nch);
af->delay = out->nch * s->opts.filter_size / FFMIN(af->mul, 1);
if (needs_lavrctx_reconfigure(s, in, out)) {
@@ -156,16 +161,18 @@ static int control(struct af_instance *af, int cmd, void *arg)
s->ctx.in_rate = in->rate;
s->ctx.out_format = out->format;
s->ctx.in_format = in->format;
- s->ctx.channels = out->nch;
+ s->ctx.out_channels= out->nch;
+ s->ctx.in_channels = in->nch;
s->ctx.filter_size = s->opts.filter_size;
s->ctx.phase_shift = s->opts.phase_shift;
s->ctx.linear = s->opts.linear;
s->ctx.cutoff = s->opts.cutoff;
- int ch_layout = av_get_default_channel_layout(out->nch);
+ int in_ch_layout = av_get_default_channel_layout(in->nch);
+ int out_ch_layout = av_get_default_channel_layout(out->nch);
- ctx_opt_set_int("in_channel_layout", ch_layout);
- ctx_opt_set_int("out_channel_layout", ch_layout);
+ ctx_opt_set_int("in_channel_layout", in_ch_layout);
+ ctx_opt_set_int("out_channel_layout", out_ch_layout);
ctx_opt_set_int("in_sample_rate", s->ctx.in_rate);
ctx_opt_set_int("out_sample_rate", s->ctx.out_rate);
@@ -187,7 +194,7 @@ static int control(struct af_instance *af, int cmd, void *arg)
}
return ((in->format == orig_in.format) &&
- (in->bps == orig_in.bps) &&
+ (in->bps == orig_in.bps) &&
(in->nch == orig_in.nch))
? AF_OK : AF_FALSE;
}
@@ -199,6 +206,15 @@ static int control(struct af_instance *af, int cmd, void *arg)
af->data->bps = af_fmt2bits(af->data->format)/8;
return AF_OK;
}
+ case AF_CONTROL_CHANNELS | AF_CONTROL_SET: {
+ int nch = *(int *)arg;
+
+ if (nch < 1 || nch > AF_NCH)
+ return AF_ERROR;
+
+ af->data->nch = nch;
+ return AF_OK;
+ }
case AF_CONTROL_COMMAND_LINE: {
s->opts.cutoff = 0.0;