int a52_downmix_init (int input, int flags, level_t * level, level_t clev, level_t slev) { static uint8_t table[11][8] = { {A52_CHANNEL, A52_DOLBY, A52_STEREO, A52_STEREO, A52_STEREO, A52_STEREO, A52_STEREO, A52_STEREO}, {A52_MONO, A52_MONO, A52_MONO, A52_MONO, A52_MONO, A52_MONO, A52_MONO, A52_MONO}, {A52_CHANNEL, A52_DOLBY, A52_STEREO, A52_STEREO, A52_STEREO, A52_STEREO, A52_STEREO, A52_STEREO}, {A52_CHANNEL, A52_DOLBY, A52_STEREO, A52_3F, A52_STEREO, A52_3F, A52_STEREO, A52_3F}, {A52_CHANNEL, A52_DOLBY, A52_STEREO, A52_STEREO, A52_2F1R, A52_2F1R, A52_2F1R, A52_2F1R}, {A52_CHANNEL, A52_DOLBY, A52_STEREO, A52_STEREO, A52_2F1R, A52_3F1R, A52_2F1R, A52_3F1R}, {A52_CHANNEL, A52_DOLBY, A52_STEREO, A52_3F, A52_2F2R, A52_2F2R, A52_2F2R, A52_2F2R}, {A52_CHANNEL, A52_DOLBY, A52_STEREO, A52_3F, A52_2F2R, A52_3F2R, A52_2F2R, A52_3F2R}, {A52_CHANNEL1, A52_MONO, A52_MONO, A52_MONO, A52_MONO, A52_MONO, A52_MONO, A52_MONO}, {A52_CHANNEL2, A52_MONO, A52_MONO, A52_MONO, A52_MONO, A52_MONO, A52_MONO, A52_MONO}, {A52_CHANNEL, A52_DOLBY, A52_STEREO, A52_DOLBY, A52_DOLBY, A52_DOLBY, A52_DOLBY, A52_DOLBY} }; int output; output = flags & A52_CHANNEL_MASK; if (output > A52_DOLBY) return -1; output = table[output][input & 7]; if (output == A52_STEREO && (input == A52_DOLBY || (input == A52_3F && clev == LEVEL (LEVEL_3DB)))) output = A52_DOLBY; if (flags & A52_ADJUST_LEVEL) { level_t adjust; switch (CONVERT (input & 7, output)) { case CONVERT (A52_3F, A52_MONO): adjust = DIV (LEVEL_3DB, LEVEL (1) + clev); break; case CONVERT (A52_STEREO, A52_MONO): case CONVERT (A52_2F2R, A52_2F1R): case CONVERT (A52_3F2R, A52_3F1R): level_3db: adjust = LEVEL (LEVEL_3DB); break; case CONVERT (A52_3F2R, A52_2F1R): if (clev < LEVEL (LEVEL_PLUS3DB - 1)) goto level_3db; /* break thru */ case CONVERT (A52_3F, A52_STEREO): case CONVERT (A52_3F1R, A52_2F1R): case CONVERT (A52_3F1R, A52_2F2R): case CONVERT (A52_3F2R, A52_2F2R): adjust = DIV (1, LEVEL (1) + clev); break; case CONVERT (A52_2F1R, A52_MONO): adjust = DIV (LEVEL_PLUS3DB, LEVEL (2) + slev); break; case CONVERT (A52_2F1R, A52_STEREO): case CONVERT (A52_3F1R, A52_3F): adjust = DIV (1, LEVEL (1) + MUL_C (slev, LEVEL_3DB)); break; case CONVERT (A52_3F1R, A52_MONO): adjust = DIV (LEVEL_3DB, LEVEL (1) + clev + MUL_C (slev, 0.5)); break; case CONVERT (A52_3F1R, A52_STEREO): adjust = DIV (1, LEVEL (1) + clev + MUL_C (slev, LEVEL_3DB)); break; case CONVERT (A52_2F2R, A52_MONO): adjust = DIV (LEVEL_3DB, LEVEL (1) + slev); break; case CONVERT (A52_2F2R, A52_STEREO): case CONVERT (A52_3F2R, A52_3F): adjust = DIV (1, LEVEL (1) + slev); break; case CONVERT (A52_3F2R, A52_MONO): adjust = DIV (LEVEL_3DB, LEVEL (1) + clev + slev); break; case CONVERT (A52_3F2R, A52_STEREO): adjust = DIV (1, LEVEL (1) + clev + slev); break; case CONVERT (A52_MONO, A52_DOLBY): adjust = LEVEL (LEVEL_PLUS3DB); break; case CONVERT (A52_3F, A52_DOLBY): case CONVERT (A52_2F1R, A52_DOLBY): adjust = LEVEL (1 / (1 + LEVEL_3DB)); break; case CONVERT (A52_3F1R, A52_DOLBY): case CONVERT (A52_2F2R, A52_DOLBY): adjust = LEVEL (1 / (1 + 2 * LEVEL_3DB)); break; case CONVERT (A52_3F2R, A52_DOLBY): adjust = LEVEL (1 / (1 + 3 * LEVEL_3DB)); break; default: return output; } *level = MUL_L (*level, adjust); } return output; }
int dts_downmix_init (int input, int flags, level_t * level, level_t clev, level_t slev) { static uint8_t table[11][10] = { /* DTS_MONO */ {DTS_MONO, DTS_MONO, DTS_MONO, DTS_MONO, DTS_MONO, DTS_MONO, DTS_MONO, DTS_MONO, DTS_MONO, DTS_MONO}, /* DTS_CHANNEL */ {DTS_MONO, DTS_CHANNEL, DTS_STEREO, DTS_STEREO, DTS_STEREO, DTS_STEREO, DTS_STEREO, DTS_STEREO, DTS_STEREO, DTS_STEREO}, /* DTS_STEREO */ {DTS_MONO, DTS_CHANNEL, DTS_STEREO, DTS_STEREO, DTS_STEREO, DTS_STEREO, DTS_STEREO, DTS_STEREO, DTS_STEREO, DTS_STEREO}, /* DTS_STEREO_SUMDIFF */ {DTS_MONO, DTS_CHANNEL, DTS_STEREO, DTS_STEREO, DTS_STEREO, DTS_STEREO, DTS_STEREO, DTS_STEREO, DTS_STEREO, DTS_STEREO}, /* DTS_STEREO_TOTAL */ {DTS_MONO, DTS_CHANNEL, DTS_STEREO, DTS_STEREO, DTS_STEREO, DTS_STEREO, DTS_STEREO, DTS_STEREO, DTS_STEREO, DTS_STEREO}, /* DTS_3F */ {DTS_MONO, DTS_CHANNEL, DTS_STEREO, DTS_STEREO, DTS_STEREO, DTS_3F, DTS_3F, DTS_3F, DTS_3F, DTS_3F}, /* DTS_2F1R */ {DTS_MONO, DTS_CHANNEL, DTS_STEREO, DTS_STEREO, DTS_STEREO, DTS_2F1R, DTS_2F1R, DTS_2F1R, DTS_2F1R, DTS_2F1R}, /* DTS_3F1R */ {DTS_MONO, DTS_CHANNEL, DTS_STEREO, DTS_STEREO, DTS_STEREO, DTS_3F, DTS_3F1R, DTS_3F1R, DTS_3F1R, DTS_3F1R}, /* DTS_2F2R */ {DTS_MONO, DTS_CHANNEL, DTS_STEREO, DTS_STEREO, DTS_STEREO, DTS_STEREO, DTS_2F2R, DTS_2F2R, DTS_2F2R, DTS_2F2R}, /* DTS_3F2R */ {DTS_MONO, DTS_CHANNEL, DTS_STEREO, DTS_STEREO, DTS_STEREO, DTS_3F, DTS_3F2R, DTS_3F2R, DTS_3F2R, DTS_3F2R}, /* DTS_4F2R */ {DTS_MONO, DTS_CHANNEL, DTS_STEREO, DTS_STEREO, DTS_STEREO, DTS_4F2R, DTS_4F2R, DTS_4F2R, DTS_4F2R, DTS_4F2R}, }; int output; output = flags & DTS_CHANNEL_MASK; if (output > DTS_CHANNEL_MAX) return -1; output = table[output][input]; if (output == DTS_STEREO && (input == DTS_DOLBY || (input == DTS_3F && clev == LEVEL (LEVEL_3DB)))) output = DTS_DOLBY; if (flags & DTS_ADJUST_LEVEL) { level_t adjust; switch (CONVERT (input & 7, output)) { case CONVERT (DTS_3F, DTS_MONO): adjust = (sample_t)(DIV (LEVEL_3DB, LEVEL (1) + clev)); break; case CONVERT (DTS_STEREO, DTS_MONO): case CONVERT (DTS_2F2R, DTS_2F1R): case CONVERT (DTS_3F2R, DTS_3F1R): level_3db: adjust = (sample_t)(LEVEL (LEVEL_3DB)); break; case CONVERT (DTS_3F2R, DTS_2F1R): if (clev < LEVEL (LEVEL_PLUS3DB - 1)) goto level_3db; /* break thru */ case CONVERT (DTS_3F, DTS_STEREO): case CONVERT (DTS_3F1R, DTS_2F1R): case CONVERT (DTS_3F1R, DTS_2F2R): case CONVERT (DTS_3F2R, DTS_2F2R): adjust = DIV (1, LEVEL (1) + clev); break; case CONVERT (DTS_2F1R, DTS_MONO): adjust = (sample_t)(DIV (LEVEL_PLUS3DB, LEVEL (2) + slev)); break; case CONVERT (DTS_2F1R, DTS_STEREO): case CONVERT (DTS_3F1R, DTS_3F): adjust = (sample_t)(DIV (1, LEVEL (1) + MUL_C (slev, LEVEL_3DB))); break; case CONVERT (DTS_3F1R, DTS_MONO): adjust = (sample_t)(DIV (LEVEL_3DB, LEVEL (1) + clev + MUL_C (slev, 0.5))); break; case CONVERT (DTS_3F1R, DTS_STEREO): adjust = (sample_t)(DIV (1, LEVEL (1) + clev + MUL_C (slev, LEVEL_3DB))); break; case CONVERT (DTS_2F2R, DTS_MONO): adjust = (sample_t)(DIV (LEVEL_3DB, LEVEL (1) + slev)); break; case CONVERT (DTS_2F2R, DTS_STEREO): case CONVERT (DTS_3F2R, DTS_3F): adjust = DIV (1, LEVEL (1) + slev); break; case CONVERT (DTS_3F2R, DTS_MONO): adjust = (sample_t)(DIV (LEVEL_3DB, LEVEL (1) + clev + slev)); break; case CONVERT (DTS_3F2R, DTS_STEREO): adjust = DIV (1, LEVEL (1) + clev + slev); break; case CONVERT (DTS_MONO, DTS_DOLBY): adjust = (sample_t)(LEVEL (LEVEL_PLUS3DB)); break; case CONVERT (DTS_3F, DTS_DOLBY): case CONVERT (DTS_2F1R, DTS_DOLBY): adjust = (sample_t)(LEVEL (1 / (1 + LEVEL_3DB))); break; case CONVERT (DTS_3F1R, DTS_DOLBY): case CONVERT (DTS_2F2R, DTS_DOLBY): adjust = (sample_t)(LEVEL (1 / (1 + 2 * LEVEL_3DB))); break; case CONVERT (DTS_3F2R, DTS_DOLBY): adjust = (sample_t)(LEVEL (1 / (1 + 3 * LEVEL_3DB))); break; default: return output; } *level = MUL_L (*level, adjust); } return output; }
int a52_downmix_coeff (level_t * coeff, int acmod, int output, level_t level, level_t clev, level_t slev) { level_t level_3db; level_3db = MUL_C (level, LEVEL_3DB); switch (CONVERT (acmod, output & A52_CHANNEL_MASK)) { case CONVERT (A52_CHANNEL, A52_CHANNEL): case CONVERT (A52_MONO, A52_MONO): case CONVERT (A52_STEREO, A52_STEREO): case CONVERT (A52_3F, A52_3F): case CONVERT (A52_2F1R, A52_2F1R): case CONVERT (A52_3F1R, A52_3F1R): case CONVERT (A52_2F2R, A52_2F2R): case CONVERT (A52_3F2R, A52_3F2R): case CONVERT (A52_STEREO, A52_DOLBY): coeff[0] = coeff[1] = coeff[2] = coeff[3] = coeff[4] = level; return 0; case CONVERT (A52_CHANNEL, A52_MONO): coeff[0] = coeff[1] = MUL_C (level, LEVEL_6DB); return 3; case CONVERT (A52_STEREO, A52_MONO): coeff[0] = coeff[1] = level_3db; return 3; case CONVERT (A52_3F, A52_MONO): coeff[0] = coeff[2] = level_3db; coeff[1] = MUL_C (MUL_L (level_3db, clev), LEVEL_PLUS6DB); return 7; case CONVERT (A52_2F1R, A52_MONO): coeff[0] = coeff[1] = level_3db; coeff[2] = MUL_L (level_3db, slev); return 7; case CONVERT (A52_2F2R, A52_MONO): coeff[0] = coeff[1] = level_3db; coeff[2] = coeff[3] = MUL_L (level_3db, slev); return 15; case CONVERT (A52_3F1R, A52_MONO): coeff[0] = coeff[2] = level_3db; coeff[1] = MUL_C (MUL_L (level_3db, clev), LEVEL_PLUS6DB); coeff[3] = MUL_L (level_3db, slev); return 15; case CONVERT (A52_3F2R, A52_MONO): coeff[0] = coeff[2] = level_3db; coeff[1] = MUL_C (MUL_L (level_3db, clev), LEVEL_PLUS6DB); coeff[3] = coeff[4] = MUL_L (level_3db, slev); return 31; case CONVERT (A52_MONO, A52_DOLBY): coeff[0] = level_3db; return 0; case CONVERT (A52_3F, A52_DOLBY): coeff[0] = coeff[2] = coeff[3] = coeff[4] = level; coeff[1] = level_3db; return 7; case CONVERT (A52_3F, A52_STEREO): case CONVERT (A52_3F1R, A52_2F1R): case CONVERT (A52_3F2R, A52_2F2R): coeff[0] = coeff[2] = coeff[3] = coeff[4] = level; coeff[1] = MUL_L (level, clev); return 7; case CONVERT (A52_2F1R, A52_DOLBY): coeff[0] = coeff[1] = level; coeff[2] = level_3db; return 7; case CONVERT (A52_2F1R, A52_STEREO): coeff[0] = coeff[1] = level; coeff[2] = MUL_L (level_3db, slev); return 7; case CONVERT (A52_3F1R, A52_DOLBY): coeff[0] = coeff[2] = level; coeff[1] = coeff[3] = level_3db; return 15; case CONVERT (A52_3F1R, A52_STEREO): coeff[0] = coeff[2] = level; coeff[1] = MUL_L (level, clev); coeff[3] = MUL_L (level_3db, slev); return 15; case CONVERT (A52_2F2R, A52_DOLBY): coeff[0] = coeff[1] = level; coeff[2] = coeff[3] = level_3db; return 15; case CONVERT (A52_2F2R, A52_STEREO): coeff[0] = coeff[1] = level; coeff[2] = coeff[3] = MUL_L (level, slev); return 15; case CONVERT (A52_3F2R, A52_DOLBY): coeff[0] = coeff[2] = level; coeff[1] = coeff[3] = coeff[4] = level_3db; return 31; case CONVERT (A52_3F2R, A52_2F1R): coeff[0] = coeff[2] = level; coeff[1] = MUL_L (level, clev); coeff[3] = coeff[4] = level_3db; return 31; case CONVERT (A52_3F2R, A52_STEREO): coeff[0] = coeff[2] = level; coeff[1] = MUL_L (level, clev); coeff[3] = coeff[4] = MUL_L (level, slev); return 31; case CONVERT (A52_3F1R, A52_3F): coeff[0] = coeff[1] = coeff[2] = level; coeff[3] = MUL_L (level_3db, slev); return 13; case CONVERT (A52_3F2R, A52_3F): coeff[0] = coeff[1] = coeff[2] = level; coeff[3] = coeff[4] = MUL_L (level, slev); return 29; case CONVERT (A52_2F2R, A52_2F1R): coeff[0] = coeff[1] = level; coeff[2] = coeff[3] = level_3db; return 12; case CONVERT (A52_3F2R, A52_3F1R): coeff[0] = coeff[1] = coeff[2] = level; coeff[3] = coeff[4] = level_3db; return 24; case CONVERT (A52_2F1R, A52_2F2R): coeff[0] = coeff[1] = level; coeff[2] = level_3db; return 0; case CONVERT (A52_3F1R, A52_2F2R): coeff[0] = coeff[2] = level; coeff[1] = MUL_L (level, clev); coeff[3] = level_3db; return 7; case CONVERT (A52_3F1R, A52_3F2R): coeff[0] = coeff[1] = coeff[2] = level; coeff[3] = level_3db; return 0; case CONVERT (A52_CHANNEL, A52_CHANNEL1): coeff[0] = level; coeff[1] = 0; return 0; case CONVERT (A52_CHANNEL, A52_CHANNEL2): coeff[0] = 0; coeff[1] = level; return 0; } return -1; /* NOTREACHED */ }
int dts_downmix_coeff (level_t * coeff, int acmod, int output, level_t level, level_t clev, level_t slev) { level_t level_3db; level_3db = (sample_t)(MUL_C (level, LEVEL_3DB)); switch (CONVERT (acmod, output & DTS_CHANNEL_MASK)) { case CONVERT (DTS_CHANNEL, DTS_CHANNEL): case CONVERT (DTS_MONO, DTS_MONO): case CONVERT (DTS_STEREO, DTS_STEREO): case CONVERT (DTS_3F, DTS_3F): case CONVERT (DTS_2F1R, DTS_2F1R): case CONVERT (DTS_3F1R, DTS_3F1R): case CONVERT (DTS_2F2R, DTS_2F2R): case CONVERT (DTS_3F2R, DTS_3F2R): case CONVERT (DTS_STEREO, DTS_DOLBY): coeff[0] = coeff[1] = coeff[2] = coeff[3] = coeff[4] = level; return 0; case CONVERT (DTS_CHANNEL, DTS_MONO): coeff[0] = coeff[1] = (sample_t)(MUL_C (level, LEVEL_6DB)); return 3; case CONVERT (DTS_STEREO, DTS_MONO): coeff[0] = coeff[1] = level_3db; return 3; case CONVERT (DTS_3F, DTS_MONO): coeff[0] = coeff[2] = level_3db; coeff[1] = (sample_t)(MUL_C (MUL_L (level_3db, clev), LEVEL_PLUS6DB)); return 7; case CONVERT (DTS_2F1R, DTS_MONO): coeff[0] = coeff[1] = level_3db; coeff[2] = MUL_L (level_3db, slev); return 7; case CONVERT (DTS_2F2R, DTS_MONO): coeff[0] = coeff[1] = level_3db; coeff[2] = coeff[3] = MUL_L (level_3db, slev); return 15; case CONVERT (DTS_3F1R, DTS_MONO): coeff[0] = coeff[2] = level_3db; coeff[1] = (sample_t)(MUL_C (MUL_L (level_3db, clev), LEVEL_PLUS6DB)); coeff[3] = MUL_L (level_3db, slev); return 15; case CONVERT (DTS_3F2R, DTS_MONO): coeff[0] = coeff[2] = level_3db; coeff[1] = (sample_t)(MUL_C (MUL_L (level_3db, clev), LEVEL_PLUS6DB)); coeff[3] = coeff[4] = MUL_L (level_3db, slev); return 31; case CONVERT (DTS_MONO, DTS_DOLBY): coeff[0] = level_3db; return 0; case CONVERT (DTS_3F, DTS_DOLBY): coeff[0] = coeff[2] = coeff[3] = coeff[4] = level; coeff[1] = level_3db; return 7; case CONVERT (DTS_3F, DTS_STEREO): case CONVERT (DTS_3F1R, DTS_2F1R): case CONVERT (DTS_3F2R, DTS_2F2R): coeff[0] = coeff[2] = coeff[3] = coeff[4] = level; coeff[1] = MUL_L (level, clev); return 7; case CONVERT (DTS_2F1R, DTS_DOLBY): coeff[0] = coeff[1] = level; coeff[2] = level_3db; return 7; case CONVERT (DTS_2F1R, DTS_STEREO): coeff[0] = coeff[1] = level; coeff[2] = MUL_L (level_3db, slev); return 7; case CONVERT (DTS_3F1R, DTS_DOLBY): coeff[0] = coeff[2] = level; coeff[1] = coeff[3] = level_3db; return 15; case CONVERT (DTS_3F1R, DTS_STEREO): coeff[0] = coeff[2] = level; coeff[1] = MUL_L (level, clev); coeff[3] = MUL_L (level_3db, slev); return 15; case CONVERT (DTS_2F2R, DTS_DOLBY): coeff[0] = coeff[1] = level; coeff[2] = coeff[3] = level_3db; return 15; case CONVERT (DTS_2F2R, DTS_STEREO): coeff[0] = coeff[1] = level; coeff[2] = coeff[3] = MUL_L (level, slev); return 15; case CONVERT (DTS_3F2R, DTS_DOLBY): coeff[0] = coeff[2] = level; coeff[1] = coeff[3] = coeff[4] = level_3db; return 31; case CONVERT (DTS_3F2R, DTS_2F1R): coeff[0] = coeff[2] = level; coeff[1] = MUL_L (level, clev); coeff[3] = coeff[4] = level_3db; return 31; case CONVERT (DTS_3F2R, DTS_STEREO): coeff[0] = coeff[2] = level; coeff[1] = MUL_L (level, clev); coeff[3] = coeff[4] = MUL_L (level, slev); return 31; case CONVERT (DTS_3F1R, DTS_3F): coeff[0] = coeff[1] = coeff[2] = level; coeff[3] = MUL_L (level_3db, slev); return 13; case CONVERT (DTS_3F2R, DTS_3F): coeff[0] = coeff[1] = coeff[2] = level; coeff[3] = coeff[4] = MUL_L (level, slev); return 29; case CONVERT (DTS_2F2R, DTS_2F1R): coeff[0] = coeff[1] = level; coeff[2] = coeff[3] = level_3db; return 12; case CONVERT (DTS_3F2R, DTS_3F1R): coeff[0] = coeff[1] = coeff[2] = level; coeff[3] = coeff[4] = level_3db; return 24; case CONVERT (DTS_2F1R, DTS_2F2R): coeff[0] = coeff[1] = level; coeff[2] = level_3db; return 0; case CONVERT (DTS_3F1R, DTS_2F2R): coeff[0] = coeff[2] = level; coeff[1] = MUL_L (level, clev); coeff[3] = level_3db; return 7; case CONVERT (DTS_3F1R, DTS_3F2R): coeff[0] = coeff[1] = coeff[2] = level; coeff[3] = level_3db; return 0; } return -1; /* NOTREACHED */ }