summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libhb/decavcodec.c10
-rw-r--r--libhb/downmix.c482
-rw-r--r--libhb/downmix.h31
3 files changed, 404 insertions, 119 deletions
diff --git a/libhb/decavcodec.c b/libhb/decavcodec.c
index 9f3196a85..17d320657 100644
--- a/libhb/decavcodec.c
+++ b/libhb/decavcodec.c
@@ -209,6 +209,7 @@ static int decavcodecInit( hb_work_object_t * w, hb_job_t * job )
{
pv->downmix = hb_downmix_init(w->audio->config.in.channel_layout,
w->audio->config.out.mixdown);
+ hb_downmix_set_chan_map( pv->downmix, &hb_smpte_chan_map, &hb_qt_chan_map );
}
return 0;
@@ -1081,6 +1082,7 @@ static int decavcodecviInit( hb_work_object_t * w, hb_job_t * job )
{
pv->downmix = hb_downmix_init(w->audio->config.in.channel_layout,
w->audio->config.out.mixdown);
+ hb_downmix_set_chan_map( pv->downmix, &hb_smpte_chan_map, &hb_qt_chan_map );
}
return 0;
@@ -1228,9 +1230,6 @@ static void decodeAudio( hb_audio_t * audio, hb_work_private_t *pv, uint8_t *dat
}
int n_ch_samples = nsamples / context->channels;
- hb_layout_remap( hb_smpte_chan_map, pv->downmix_buffer,
- audio->config.in.channel_layout, n_ch_samples );
-
int channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown);
buf = hb_buffer_init( n_ch_samples * channels * sizeof(float) );
@@ -1247,8 +1246,9 @@ static void decodeAudio( hb_audio_t * audio, hb_work_private_t *pv, uint8_t *dat
fl32[i] = buffer[i];
}
int n_ch_samples = nsamples / context->channels;
- hb_layout_remap( hb_smpte_chan_map, fl32,
- audio->config.in.channel_layout, n_ch_samples );
+ hb_layout_remap( &hb_smpte_chan_map, &hb_qt_chan_map,
+ audio->config.in.channel_layout,
+ fl32, n_ch_samples );
}
double pts = pv->pts_next;
diff --git a/libhb/downmix.c b/libhb/downmix.c
index 0ab9b90f3..2b57324c1 100644
--- a/libhb/downmix.c
+++ b/libhb/downmix.c
@@ -888,6 +888,7 @@ int hb_mixdown_to_mode(uint32_t mixdown)
}
}
+
// ffmpeg gives us SMPTE channel layout
// We could use this layout and remap channels in encfaac,
// but VLC may have problems with remapping, so lets
@@ -924,47 +925,232 @@ int hb_mixdown_to_mode(uint32_t mixdown)
// 3F4-LFE L R C LFE Rls Rrs LS RS
//
-// Map Indicies are mode, lfe, channel respectively
-int hb_ac3_chan_map[10][2][8] =
+#define CH_C 0
+#define CH_L 1
+#define CH_R 2
+#define CH_CS 3
+#define CH_LS 3
+#define CH_RS 4
+#define CH_Rls 5
+#define CH_Rrs 6
+#define CH_LFE 7
+
+hb_chan_map_t hb_qt_chan_map =
+{
{
-// w/o LFE w/ LFE
-// C L R LS RS Rls Rrs L R C LS RS Rls Rls LFE
- {{ 0, }, { 1, 0, }}, // MONO
- {{ 0, 1, }, { 1, 2, 0, }}, // STEREO
- {{ 1, 0, 2, }, { 2, 1, 3, 0, }}, // 3F
- {{ 0, 1, 2, }, { 1, 2, 3, 0, }}, // 2F1R
- {{ 1, 0, 2, 3, }, { 2, 1, 3, 4, 0, }}, // 3F1R
- {{ 0, 1, 2, 3, }, { 1, 2, 3, 4, 0, }}, // 2F2R
- {{ 1, 0, 2, 3, 4, }, { 2, 1, 3, 4, 5, 0, }}, // 3F2R
- {{ 1, 0, 2, 3, 4, 5, 6, }, { 2, 1, 3, 4, 5, 6, 7, 0 }}, // 3F4R
- {{ 0, 1, }, { 0, 1, }}, // DOLBY
- {{ 0, 1, }, { 0, 1, }} // DPLII
+ {{ CH_C, },
+ { CH_C, CH_LFE, }}, // MONO
+
+ {{ CH_L, CH_R, },
+ { CH_L, CH_R, CH_LFE, }}, // STEREO
+
+ {{ CH_C, CH_L, CH_R, },
+ { CH_C, CH_L, CH_R, CH_LFE, }}, // 3F
+
+ {{ CH_L, CH_R, CH_CS, },
+ { CH_L, CH_R, CH_CS, CH_LFE, }}, // 2F1R
+
+ {{ CH_C, CH_L, CH_R, CH_CS, },
+ { CH_C, CH_L, CH_R, CH_CS, CH_LFE, }}, // 3F1R
+
+ {{ CH_L, CH_R, CH_LS, CH_RS, },
+ { CH_L, CH_R, CH_LS, CH_RS, CH_LFE, }}, // 2F2R
+
+ {{ CH_C, CH_L, CH_R, CH_LS, CH_RS, },
+ { CH_C, CH_L, CH_R, CH_LS, CH_RS, CH_LFE, }}, // 3F2R
+
+ {{ CH_C, CH_L, CH_R, CH_LS, CH_RS, CH_Rls, CH_Rrs, },
+ { CH_C, CH_L, CH_R, CH_LS, CH_RS, CH_Rls, CH_Rrs, CH_LFE }}, // 3F4R
+
+ {{ CH_L, CH_R, },
+ { CH_L, CH_R, }}, // DOLBY
+
+ {{ CH_L, CH_R, },
+ { CH_L, CH_R, }} // DPLII
+},
+{
+ // CH_C CH_L CH_R CH_LS/CS CH_RS CH_Rls CH_Rrs CH_LFE
+ {{ 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 1 }}, // MONO
+
+ {{ 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 2 }}, // STEREO
+
+ {{ 0, 1, 2, 0, 0, 0, 0, 0 },
+ { 0, 1, 2, 0, 0, 0, 0, 3 }}, // 3F
+
+ {{ 0, 0, 1, 2, 0, 0, 0, 0 },
+ { 0, 0, 1, 2, 0, 0, 0, 3 }}, // 2F1R
+
+ {{ 0, 1, 2, 3, 0, 0, 0, 0 },
+ { 0, 1, 2, 3, 0, 0, 0, 4 }}, // 3F1R
+
+ {{ 0, 0, 1, 2, 3, 0, 0, 0 },
+ { 0, 0, 1, 2, 3, 0, 0, 4 }}, // 2F2R
+
+ {{ 0, 1, 2, 3, 4, 0, 0, 0 },
+ { 0, 1, 2, 3, 4, 0, 0, 5 }}, // 3F2R
+
+ {{ 0, 1, 2, 3, 4, 5, 6, 0 },
+ { 0, 1, 2, 3, 4, 5, 6, 7 }}, // 3F4R
+
+ {{ 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 }}, // DOLBY
+
+ {{ 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 }} // DPLII
+}
+};
+
+hb_chan_map_t hb_smpte_chan_map =
+{
+{
+ {{ CH_C, },
+ { CH_C, CH_LFE, }}, // MONO
+
+ {{ CH_L, CH_R, },
+ { CH_L, CH_R, CH_LFE, }}, // STEREO
+
+ {{ CH_L, CH_R, CH_C, },
+ { CH_L, CH_R, CH_C, CH_LFE, }}, // 3F
+
+ {{ CH_L, CH_R, CH_CS, },
+ { CH_L, CH_R, CH_LFE, CH_CS, }}, // 2F1R
+
+ {{ CH_L, CH_R, CH_C, CH_CS, },
+ { CH_L, CH_R, CH_LFE, CH_CS, }}, // 3F1R
+
+ {{ CH_L, CH_R, CH_LS, CH_RS, },
+ { CH_L, CH_R, CH_LFE, CH_LS, CH_RS, }}, // 2F2R
+
+ {{ CH_L, CH_R, CH_C, CH_LS, CH_RS, },
+ { CH_L, CH_R, CH_C, CH_LFE, CH_LS, CH_RS, }}, // 3F2R
+
+ {{ CH_L, CH_R, CH_C, CH_Rls, CH_Rrs, CH_LS, CH_RS },
+ { CH_L, CH_R, CH_C, CH_LFE, CH_Rls, CH_Rrs, CH_LS, CH_RS }}, // 3F4R
+
+ {{ CH_L, CH_R, },
+ { CH_L, CH_R, }}, // DOLBY
+
+ {{ CH_L, CH_R, },
+ { CH_L, CH_R, }} // DPLII
+},
+{
+ // CH_C CH_L CH_R CH_LS/CS CH_RS CH_Rls CH_Rrs CH_LFE
+ {{ 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 1 }}, // MONO
+
+ {{ 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 2 }}, // STEREO
+
+ {{ 2, 0, 1, 0, 0, 0, 0, 0 },
+ { 2, 0, 1, 0, 0, 0, 0, 3 }}, // 3F
+
+ {{ 0, 0, 1, 2, 0, 0, 0, 0 },
+ { 0, 0, 1, 3, 0, 0, 0, 2 }}, // 2F1R
+
+ {{ 2, 0, 1, 3, 0, 0, 0, 0 },
+ { 2, 0, 1, 4, 0, 0, 0, 3 }}, // 3F1R
+
+ {{ 0, 0, 1, 2, 3, 0, 0, 0 },
+ { 0, 0, 1, 3, 4, 0, 0, 2 }}, // 2F2R
+
+ {{ 2, 0, 1, 3, 4, 0, 0, 0 },
+ { 2, 0, 1, 4, 5, 0, 0, 3 }}, // 3F2R
+
+ {{ 2, 0, 1, 5, 6, 3, 4, 0 },
+ { 2, 0, 1, 6, 7, 4, 5, 3 }}, // 3F4R
+
+ {{ 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 }}, // DOLBY
+
+ {{ 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 }} // DPLII
+}
};
-int hb_smpte_chan_map[10][2][8] =
+hb_chan_map_t hb_ac3_chan_map =
{
-// w/o LFE w/ LFE
-// L R C LS RS Rls Rrs L R C LS RS Rls Rls LFE
- {{ 0, }, { 0, 1, }}, // MONO
- {{ 0, 1, }, { 0, 1, 2, }}, // STEREO
- {{ 2, 0, 1, }, { 2, 0, 1, 3, }}, // 3F
- {{ 0, 1, 2, }, { 0, 1, 3, 2, }}, // 2F1R
- {{ 2, 0, 1, 3, }, { 2, 0, 1, 4, 3, }}, // 3F1R
- {{ 0, 1, 2, 3, }, { 0, 1, 3, 4, 2, }}, // 2F2R
- {{ 2, 0, 1, 3, 4, }, { 2, 0, 1, 4, 5, 3, }}, // 3F2R
- {{ 2, 0, 1, 5, 6, 3, 4, }, { 2, 0, 1, 6, 7, 4, 5, 3 }}, // 3F4R
- {{ 0, 1, }, { 0, 1, }}, // DOLBY
- {{ 0, 1, }, { 0, 1, }} // DPLII
+{
+ {{ CH_C, },
+ { CH_LFE, CH_C, }}, // MONO
+
+ {{ CH_L, CH_R, },
+ { CH_LFE, CH_L, CH_R, }}, // STEREO
+
+ {{ CH_L, CH_C, CH_R, },
+ { CH_LFE, CH_L, CH_C, CH_R, }}, // 3F
+
+ {{ CH_L, CH_R, CH_CS, },
+ { CH_LFE, CH_L, CH_R, CH_CS, }}, // 2F1R
+
+ {{ CH_L, CH_C, CH_R, CH_CS, },
+ { CH_LFE, CH_L, CH_C, CH_R, CH_CS, }}, // 3F1R
+
+ {{ CH_L, CH_R, CH_LS, CH_RS, },
+ { CH_LFE, CH_L, CH_R, CH_LS, CH_RS, }}, // 2F2R
+
+ {{ CH_L, CH_C, CH_R, CH_LS, CH_RS, },
+ { CH_LFE, CH_L, CH_C, CH_R, CH_LS, CH_RS, }}, // 3F2R
+
+ {{ CH_L, CH_C, CH_R, CH_LS, CH_RS, CH_Rls, CH_Rrs, },
+ { CH_LFE, CH_L, CH_C, CH_R, CH_LS, CH_RS, CH_Rls, CH_Rrs }}, // 3F4R
+
+ {{ CH_L, CH_R, },
+ { CH_L, CH_R, }}, // DOLBY
+
+ {{ CH_L, CH_R, },
+ { CH_L, CH_R, }} // DPLII
+},
+{
+ // CH_C CH_L CH_R CH_LS/CS CH_RS CH_Rls CH_Rrs CH_LFE
+ {{ 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 1, 0, 0, 0, 0, 0, 0, 0 }}, // MONO
+
+ {{ 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 1, 2, 0, 0, 0, 0, 0 }}, // STEREO
+
+ {{ 1, 0, 2, 0, 0, 0, 0, 0 },
+ { 2, 1, 3, 0, 0, 0, 0, 0 }}, // 3F
+
+ {{ 0, 0, 1, 2, 0, 0, 0, 0 },
+ { 0, 1, 2, 3, 0, 0, 0, 0 }}, // 2F1R
+
+ {{ 1, 0, 2, 3, 0, 0, 0, 0 },
+ { 2, 1, 3, 4, 0, 0, 0, 0 }}, // 3F1R
+
+ {{ 0, 0, 1, 2, 3, 0, 0, 0 },
+ { 0, 1, 2, 3, 4, 0, 0, 0 }}, // 2F2R
+
+ {{ 1, 0, 2, 3, 4, 0, 0, 0 },
+ { 2, 1, 3, 4, 5, 0, 0, 0 }}, // 3F2R
+
+ {{ 1, 0, 2, 3, 4, 5, 6, 0 },
+ { 2, 1, 3, 4, 5, 6, 7, 0 }}, // 3F4R
+
+ {{ 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 }}, // DOLBY
+
+ {{ 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 }} // DPLII
+}
};
+
static const uint8_t nchans_tbl[] = {1, 2, 3, 3, 4, 4, 5, 7, 2, 2};
// Takes a set of samples and remaps the channel layout
-void hb_layout_remap( int (*layouts)[2][8], hb_sample_t * samples, int layout, int nsamples )
+void hb_layout_remap(
+ hb_chan_map_t * map_in,
+ hb_chan_map_t * map_out,
+ int layout,
+ hb_sample_t * samples,
+ int nsamples )
{
int nchans;
int ii, jj;
int lfe;
int * map;
+ int * inv_map;
int mode;
hb_sample_t tmp[6];
@@ -972,7 +1158,8 @@ void hb_layout_remap( int (*layouts)[2][8], hb_sample_t * samples, int layout, i
lfe = ((mode & DOWNMIX_LFE_FLAG) != 0);
mode = mode & DOWNMIX_CHANNEL_MASK;
nchans = nchans_tbl[mode] + lfe;
- map = layouts[mode][lfe];
+ inv_map = map_in->inv_chan_map[mode][lfe];
+ map = map_out->chan_map[mode][lfe];
for (ii = 0; ii < nsamples; ii++)
{
@@ -982,7 +1169,8 @@ void hb_layout_remap( int (*layouts)[2][8], hb_sample_t * samples, int layout, i
}
for (jj = 0; jj < nchans; jj++)
{
- samples[jj] = tmp[map[jj]];
+ int ord = map[jj];
+ samples[jj] = tmp[inv_map[ord]];
}
samples += nchans;
}
@@ -1016,43 +1204,36 @@ static void matrix_mul(
}
}
-static void set_level(
- hb_sample_t (*matrix)[8],
- hb_sample_t clev,
- hb_sample_t slev,
- hb_sample_t level,
- int mode_in,
- int mode_out)
+static void set_level( hb_downmix_t * downmix )
{
int ii, jj;
- int spos;
int layout_in, layout_out;
+ int mode_in;
+ int mode_out;
+
+ mode_in = downmix->mode_in & ~DOWNMIX_FLAGS_MASK;
+ mode_out = downmix->mode_out & ~DOWNMIX_FLAGS_MASK;
for (ii = 0; ii < 8; ii++)
{
for (jj = 0; jj < 8; jj++)
{
- matrix[ii][jj] *= level;
+ downmix->matrix[ii][jj] *= downmix->level;
}
}
if (mode_out >= DOWNMIX_DOLBY)
return;
- spos = 3;
layout_in = channel_layout_map[mode_in];
layout_out = channel_layout_map[mode_out];
- if (!(layout_in & HB_CH_FRONT_CENTER))
- {
- spos--;
- }
- else
+ if (layout_in & HB_CH_FRONT_CENTER)
{
if (!(layout_out & HB_CH_FRONT_CENTER))
{
for (jj = 0; jj < 8; jj++)
{
- matrix[0][jj] *= clev;
+ downmix->matrix[downmix->center][jj] *= downmix->clev;
}
}
}
@@ -1064,29 +1245,16 @@ static void set_level(
return;
}
}
- if (layout_in & (HB_CH_SIDE_LEFT|HB_CH_SIDE_RIGHT))
- {
- for (jj = 0; jj < 8; jj++)
- {
- matrix[spos][jj] *= slev;
- matrix[spos+1][jj] *= slev;
- }
- spos += 2;
- }
- else if (layout_in & (HB_CH_BACK_CENTER))
+ for (jj = 0; jj < 8; jj++)
{
- for (jj = 0; jj < 8; jj++)
- {
- matrix[spos][jj] *= slev;
- }
- }
- if (layout_in & (HB_CH_BACK_LEFT|HB_CH_BACK_RIGHT))
- {
- for (jj = 0; jj < 8; jj++)
- {
- matrix[spos][jj] *= slev;
- matrix[spos+1][jj] *= slev;
- }
+ if ( downmix->left_surround >= 0 )
+ downmix->matrix[downmix->left_surround][jj] *= downmix->slev;
+ if ( downmix->right_surround >= 0 )
+ downmix->matrix[downmix->right_surround][jj] *= downmix->slev;
+ if ( downmix->rear_left_surround >= 0 )
+ downmix->matrix[downmix->rear_left_surround][jj] *= downmix->slev;
+ if ( downmix->rear_right_surround >= 0 )
+ downmix->matrix[downmix->rear_right_surround][jj] *= downmix->slev;
}
}
@@ -1101,9 +1269,8 @@ static void set_level(
// in the resulting downmixed audio.
void hb_downmix_adjust_level( hb_downmix_t * downmix )
{
- int ii, jj;
int mode_in, mode_out;
- hb_sample_t level = 1.0;
+ hb_sample_t level = downmix->level;
hb_sample_t clev = downmix->clev;
hb_sample_t slev = downmix->slev;
@@ -1218,27 +1385,41 @@ void hb_downmix_adjust_level( hb_downmix_t * downmix )
level /= 1 + LVL_3DB + 2 * LVL_SQRT_1_3 + 2 * LVL_SQRT_2_3;
}
+ downmix->level = level;
+ downmix->matrix_initialized = 0;
+}
+
+void hb_downmix_set_bias( hb_downmix_t * downmix, hb_sample_t bias )
+{
+ downmix->bias = bias;
+}
+
+// Changes the downmix mode if it needs changing after initialization
+static void set_mode( hb_downmix_t * downmix )
+{
+ int ii, jj;
+ int mode_in, mode_out;
+ hb_sample_t (*matrix)[8];
+
+ mode_in = downmix->mode_in & ~DOWNMIX_FLAGS_MASK;
+ mode_out = downmix->mode_out & ~DOWNMIX_FLAGS_MASK;
+
+ matrix = downmix_matrix[mode_in][mode_out];
+
for (ii = 0; ii < 8; ii++)
{
for (jj = 0; jj < 8; jj++)
{
- downmix->matrix[ii][jj] *= level;
+ downmix->matrix[ii][jj] = matrix[ii][jj];
}
}
}
-void hb_downmix_set_bias( hb_downmix_t * downmix, hb_sample_t bias )
-{
- downmix->bias = bias;
-}
-
// Changes the downmix mode if it needs changing after initialization
int hb_downmix_set_mode( hb_downmix_t * downmix, int layout, int mixdown )
{
- int ii, jj;
int lfe_in, lfe_out;
int mode_in, mode_out;
- hb_sample_t (*matrix)[8];
if ( downmix == NULL )
return -1;
@@ -1254,53 +1435,121 @@ int hb_downmix_set_mode( hb_downmix_t * downmix, int layout, int mixdown )
if (mode_in >= DOWNMIX_NUM_MODES || mode_out >= DOWNMIX_NUM_MODES)
return -1;
- matrix = downmix_matrix[mode_in][mode_out];
-
- for (ii = 0; ii < 8; ii++)
- {
- for (jj = 0; jj < 8; jj++)
- {
- downmix->matrix[ii][jj] = matrix[ii][jj];
- }
- }
-
lfe_in = ((downmix->mode_in & DOWNMIX_LFE_FLAG) != 0);
lfe_out = ((downmix->mode_out & DOWNMIX_LFE_FLAG) != 0);
downmix->nchans_in = nchans_tbl[mode_in] + lfe_in;
downmix->nchans_out = nchans_tbl[mode_out] + lfe_out;
+
+ downmix->matrix_initialized = 0;
return 0;
}
// Changes the downmix levels if they need changing after initialization
void hb_downmix_set_level( hb_downmix_t * downmix, hb_sample_t clev, hb_sample_t slev, hb_sample_t level )
{
- int ii, jj;
- int mode_in, mode_out;
- hb_sample_t (*matrix)[8];
-
if ( downmix == NULL )
return;
- mode_in = downmix->mode_in & ~DOWNMIX_FLAGS_MASK;
- mode_out = downmix->mode_out & ~DOWNMIX_FLAGS_MASK;
+ downmix->clev = clev;
+ downmix->slev = slev;
+ downmix->level = level;
+ downmix->matrix_initialized = 0;
+}
- if (mode_in >= DOWNMIX_NUM_MODES || mode_out >= DOWNMIX_NUM_MODES)
- return;
+static void set_chan_map( hb_downmix_t * downmix )
+{
+ int nchans;
+ int ii, jj;
+ int lfe;
+ int * map;
+ int * inv_map;
+ int mode;
+ hb_sample_t matrix[8][8];
- matrix = downmix_matrix[mode_in][mode_out];
+ // Copy the matrix
+ for ( ii = 0; ii < 8; ii++ )
+ {
+ for ( jj = 0; jj < 8; jj++ )
+ {
+ matrix[ii][jj] = downmix->matrix[ii][jj];
+ }
+ }
- for (ii = 0; ii < 8; ii++)
+ // Rearrange the rows to correspond to the input channel order
+ lfe = ((downmix->mode_in & DOWNMIX_LFE_FLAG) != 0);
+ mode = downmix->mode_in & DOWNMIX_CHANNEL_MASK;
+ nchans = nchans_tbl[mode] + lfe;
+ map = downmix->map_in.chan_map[mode][lfe];
+ inv_map = hb_qt_chan_map.inv_chan_map[mode][lfe];
+
+ downmix->center = -1;
+ downmix->left_surround = -1;
+ downmix->right_surround = -1;
+ downmix->rear_left_surround = -1;
+ downmix->rear_right_surround = -1;
+ for ( ii = 0; ii < nchans; ii++ )
{
- for (jj = 0; jj < 8; jj++)
+ int ord = map[ii];
+ int row = inv_map[ord];
+ switch (ord)
{
- downmix->matrix[ii][jj] = matrix[ii][jj];
+ case CH_C:
+ downmix->center = ii;
+ break;
+ case CH_LS:
+ downmix->left_surround = ii;
+ break;
+ case CH_RS:
+ downmix->right_surround = ii;
+ break;
+ case CH_Rls:
+ downmix->rear_right_surround = ii;
+ break;
+ case CH_Rrs:
+ downmix->rear_left_surround = ii;
+ break;
+ }
+ for ( jj = 0; jj < 8; jj++ )
+ {
+ downmix->matrix[ii][jj] = matrix[row][jj];
}
}
- downmix->clev = clev;
- downmix->slev = slev;
- downmix->level = level;
- set_level(downmix->matrix, clev, slev, level, mode_in, mode_out);
+
+ // Copy the matrix
+ for ( ii = 0; ii < 8; ii++ )
+ {
+ for ( jj = 0; jj < 8; jj++ )
+ {
+ matrix[ii][jj] = downmix->matrix[ii][jj];
+ }
+ }
+
+ // Rearrange the columns to correspond to the output channel order
+ lfe = ((downmix->mode_out & DOWNMIX_LFE_FLAG) != 0);
+ mode = downmix->mode_out & DOWNMIX_CHANNEL_MASK;
+ nchans = nchans_tbl[mode] + lfe;
+ map = downmix->map_out.chan_map[mode][lfe];
+ inv_map = hb_qt_chan_map.inv_chan_map[mode][lfe];
+ for ( ii = 0; ii < nchans; ii++ )
+ {
+ int ord = map[ii];
+ int col = inv_map[ord];
+ for ( jj = 0; jj < 8; jj++ )
+ {
+ downmix->matrix[jj][ii] = matrix[jj][col];
+ }
+ }
+}
+
+void hb_downmix_set_chan_map(
+ hb_downmix_t * downmix,
+ hb_chan_map_t * map_in,
+ hb_chan_map_t * map_out )
+{
+ downmix->map_in = *map_in;
+ downmix->map_out = *map_out;
+ downmix->matrix_initialized = 0;
}
hb_downmix_t * hb_downmix_init(int layout, int mixdown)
@@ -1315,12 +1564,11 @@ hb_downmix_t * hb_downmix_init(int layout, int mixdown)
return NULL;
}
// Set some good default values
- downmix->clev = LVL_3DB;
- downmix->slev = LVL_3DB;
- downmix->level = 1.0;
+ hb_downmix_set_level( downmix, LVL_3DB, LVL_3DB, 1.0 );
downmix->bias = 0.0;
- set_level(downmix->matrix, LVL_3DB, LVL_3DB, 1.0,
- downmix->mode_in, downmix->mode_out);
+ downmix->matrix_initialized = 0;
+ // The default input and output channel order is QT
+ hb_downmix_set_chan_map( downmix, &hb_qt_chan_map, &hb_qt_chan_map );
return downmix;
}
@@ -1331,10 +1579,22 @@ void hb_downmix_close( hb_downmix_t **downmix )
*downmix = NULL;
}
+static void init_matrix( hb_downmix_t * downmix )
+{
+ if ( !downmix->matrix_initialized )
+ {
+ set_mode( downmix );
+ set_chan_map( downmix );
+ set_level(downmix);
+ downmix->matrix_initialized = 1;
+ }
+}
+
void hb_downmix( hb_downmix_t * downmix, hb_sample_t * dst, hb_sample_t * src, int nsamples)
{
- matrix_mul(dst, src, downmix->nchans_out, downmix->nchans_in,
- nsamples, downmix->matrix, downmix->bias);
+ init_matrix( downmix );
+ matrix_mul( dst, src, downmix->nchans_out, downmix->nchans_in,
+ nsamples, downmix->matrix, downmix->bias );
}
int hb_need_downmix( int layout, int mixdown )
diff --git a/libhb/downmix.h b/libhb/downmix.h
index f9710488b..5a6ec0bf5 100644
--- a/libhb/downmix.h
+++ b/libhb/downmix.h
@@ -11,22 +11,38 @@ typedef float hb_sample_t;
typedef struct
{
+ int chan_map[10][2][8];
+ int inv_chan_map[10][2][8];
+} hb_chan_map_t;
+
+typedef struct
+{
int mode_in;
int mode_out;
int nchans_in;
int nchans_out;
hb_sample_t matrix[8][8];
+ int matrix_initialized;
hb_sample_t clev;
hb_sample_t slev;
hb_sample_t level;
hb_sample_t bias;
+ hb_chan_map_t map_in;
+ hb_chan_map_t map_out;
+
+ int center;
+ int left_surround;
+ int right_surround;
+ int rear_left_surround;
+ int rear_right_surround;
} hb_downmix_t;
// For convenience, a map to convert smpte channel layout
// to QuickTime channel layout.
// Map Indicies are mode, lfe, channel respectively
-extern int hb_smpte_chan_map[10][2][8];
-extern int hb_ac3_chan_map[10][2][8];
+extern hb_chan_map_t hb_smpte_chan_map;
+extern hb_chan_map_t hb_ac3_chan_map;
+extern hb_chan_map_t hb_qt_chan_map;
hb_downmix_t * hb_downmix_init(int layout, int mixdown);
void hb_downmix_close( hb_downmix_t **downmix );
@@ -34,8 +50,17 @@ int hb_downmix_set_mode( hb_downmix_t * downmix, int layout, int mixdown );
void hb_downmix_set_level( hb_downmix_t * downmix, hb_sample_t clev, hb_sample_t slev, hb_sample_t level );
void hb_downmix_adjust_level( hb_downmix_t * downmix );
void hb_downmix_set_bias( hb_downmix_t * downmix, hb_sample_t bias );
+void hb_downmix_set_chan_map(
+ hb_downmix_t * downmix,
+ hb_chan_map_t * map_in,
+ hb_chan_map_t * map_out );
void hb_downmix( hb_downmix_t * downmix, hb_sample_t * dst, hb_sample_t * src, int nsamples);
-void hb_layout_remap( int (*layouts)[2][8], hb_sample_t * samples, int layout, int nsamples );
+void hb_layout_remap(
+ hb_chan_map_t * map_in,
+ hb_chan_map_t * map_out,
+ int layout,
+ hb_sample_t * samples,
+ int nsamples );
int hb_need_downmix( int layout, int mixdown );
#endif /* DOWNMIX_H */