/* * DVD-Audio Decoder plugin * Copyright (c) 2009 Maxim V.Anisiutkin * * DVD-Audio Decoder is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * DVD-Audio Decoder is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "audio_stream_info.h" const MLPPCM_ASSIGNMENT audio_stream_info_t::mlppcm_table[21] = { /* 0 */ {{SPEAKER_FRONT_CENTER}, {}, {"M"}, {}, 1, 0}, /* 1 */ {{SPEAKER_FRONT_LEFT,SPEAKER_FRONT_RIGHT}, {}, {"L","R"}, {}, 2, 0}, /* 2 */ {{SPEAKER_FRONT_LEFT,SPEAKER_FRONT_RIGHT}, {SPEAKER_BACK_CENTER}, {"Lf","Rf"}, {"S"}, 2, 1}, /* 3 */ {{SPEAKER_FRONT_LEFT,SPEAKER_FRONT_RIGHT}, {SPEAKER_BACK_LEFT,SPEAKER_BACK_RIGHT}, {"Lf","Rf"}, {"Ls","Rs"}, 2, 2}, /* 4 */ {{SPEAKER_FRONT_LEFT,SPEAKER_FRONT_RIGHT}, {SPEAKER_LOW_FREQUENCY}, {"Lf","Rf"}, {"LFE"}, 2, 1}, /* 5 */ {{SPEAKER_FRONT_LEFT,SPEAKER_FRONT_RIGHT}, {SPEAKER_LOW_FREQUENCY,SPEAKER_BACK_CENTER}, {"Lf","Rf"}, {"LFE","S"}, 2, 2}, /* 6 */ {{SPEAKER_FRONT_LEFT,SPEAKER_FRONT_RIGHT}, {SPEAKER_LOW_FREQUENCY,SPEAKER_BACK_LEFT,SPEAKER_BACK_RIGHT}, {"Lf","Rf"}, {"LFE","Ls","Rs"}, 2, 3}, /* 7 */ {{SPEAKER_FRONT_LEFT,SPEAKER_FRONT_RIGHT}, {SPEAKER_FRONT_CENTER}, {"Lf","Rf"}, {"C"}, 2, 1}, /* 8 */ {{SPEAKER_FRONT_LEFT,SPEAKER_FRONT_RIGHT}, {SPEAKER_FRONT_CENTER,SPEAKER_BACK_CENTER}, {"Lf","Rf"}, {"C","S"}, 2, 2}, /* 9 */ {{SPEAKER_FRONT_LEFT,SPEAKER_FRONT_RIGHT}, {SPEAKER_FRONT_CENTER,SPEAKER_BACK_LEFT,SPEAKER_BACK_RIGHT}, {"Lf","Rf"}, {"C","Ls","Rs"}, 2, 3}, /* 10 */ {{SPEAKER_FRONT_LEFT,SPEAKER_FRONT_RIGHT}, {SPEAKER_FRONT_CENTER,SPEAKER_LOW_FREQUENCY}, {"Lf","Rf"}, {"C","LFE"}, 2, 2}, /* 11 */ {{SPEAKER_FRONT_LEFT,SPEAKER_FRONT_RIGHT}, {SPEAKER_FRONT_CENTER,SPEAKER_LOW_FREQUENCY,SPEAKER_BACK_CENTER}, {"Lf","Rf"}, {"C","LFE","S"}, 2, 3}, /* 12 */ {{SPEAKER_FRONT_LEFT,SPEAKER_FRONT_RIGHT}, {SPEAKER_FRONT_CENTER,SPEAKER_LOW_FREQUENCY,SPEAKER_BACK_LEFT,SPEAKER_BACK_RIGHT}, {"Lf","Rf"}, {"C","LFE","Ls","Rs"}, 2, 4}, /* 13 */ {{SPEAKER_FRONT_LEFT,SPEAKER_FRONT_RIGHT,SPEAKER_FRONT_CENTER}, {SPEAKER_BACK_CENTER}, {"Lf","Rf","C"}, {"S"}, 3, 1}, /* 14 */ {{SPEAKER_FRONT_LEFT,SPEAKER_FRONT_RIGHT,SPEAKER_FRONT_CENTER}, {SPEAKER_BACK_LEFT,SPEAKER_BACK_RIGHT}, {"Lf","Rf","C"}, {"Ls","Rs"}, 3, 2}, /* 15 */ {{SPEAKER_FRONT_LEFT,SPEAKER_FRONT_RIGHT,SPEAKER_FRONT_CENTER}, {SPEAKER_LOW_FREQUENCY}, {"Lf","Rf","C"}, {"LFE"}, 3, 1}, /* 16 */ {{SPEAKER_FRONT_LEFT,SPEAKER_FRONT_RIGHT,SPEAKER_FRONT_CENTER}, {SPEAKER_LOW_FREQUENCY,SPEAKER_BACK_CENTER}, {"Lf","Rf","C"}, {"LFE","S"}, 3, 2}, /* 17 */ {{SPEAKER_FRONT_LEFT,SPEAKER_FRONT_RIGHT,SPEAKER_FRONT_CENTER}, {SPEAKER_LOW_FREQUENCY,SPEAKER_BACK_LEFT,SPEAKER_BACK_RIGHT}, {"Lf","Rf","C"}, {"LFE","Ls","Rs"}, 3, 3}, /* 18 */ {{SPEAKER_FRONT_LEFT,SPEAKER_FRONT_RIGHT,SPEAKER_BACK_LEFT,SPEAKER_BACK_RIGHT}, {SPEAKER_LOW_FREQUENCY}, {"Lf","Rf","Ls","Rs"}, {"LFE"}, 4, 1}, /* 19 */ {{SPEAKER_FRONT_LEFT,SPEAKER_FRONT_RIGHT,SPEAKER_BACK_LEFT,SPEAKER_BACK_RIGHT}, {SPEAKER_FRONT_CENTER}, {"Lf","Rf","Ls","Rs"}, {"C"}, 4, 1}, /* 20 */ {{SPEAKER_FRONT_LEFT,SPEAKER_FRONT_RIGHT,SPEAKER_BACK_LEFT,SPEAKER_BACK_RIGHT}, {SPEAKER_FRONT_CENTER,SPEAKER_LOW_FREQUENCY}, {"Lf","Rf","Ls","Rs"}, {"C","LFE"}, 4, 2}, }; // TrueHD channel map // LR C LFE LRs LRvh LRc LRrs Cs Ts LRsd LRw Cvh LFE2 const TRUEHD_ASSIGNMENT audio_stream_info_t::truehd_table[13] = { /* 0 */ {{SPEAKER_FRONT_LEFT,SPEAKER_FRONT_RIGHT}, {"L","R"}, 2}, /* 1 */ {{SPEAKER_FRONT_CENTER}, {"C"}, 1}, /* 2 */ {{SPEAKER_LOW_FREQUENCY}, {"LFE"}, 1}, /* 3 */ {{SPEAKER_BACK_LEFT,SPEAKER_BACK_RIGHT}, {"Ls","Rs"}, 2}, /* 4 */ {{SPEAKER_TOP_FRONT_LEFT,SPEAKER_TOP_FRONT_RIGHT}, {"Lvh","Rvh"}, 2}, /* 5 */ {{SPEAKER_FRONT_LEFT_OF_CENTER,SPEAKER_FRONT_RIGHT_OF_CENTER}, {"Lc","Rc"}, 2}, /* 6 */ {{SPEAKER_TOP_BACK_LEFT,SPEAKER_TOP_BACK_RIGHT}, {"Lrs","Rrs"}, 2}, /* 7 */ {{SPEAKER_BACK_CENTER}, {"Cs"}, 1}, /* 8 */ {{SPEAKER_TOP_BACK_CENTER}, {"Ts"}, 1}, /* 9 */ {{SPEAKER_SIDE_LEFT,SPEAKER_SIDE_RIGHT}, {"Lsd","Rsd"}, 2}, /* 10 */ {{SPEAKER_SIDE_LEFT,SPEAKER_SIDE_RIGHT}, {"Lw","Rw"}, 2}, /* 11 */ {{SPEAKER_TOP_CENTER}, {"Cvh"}, 1}, /* 12 */ {{SPEAKER_LOW_FREQUENCY}, {"LFE2"}, 1} }; audio_stream_info_t::audio_stream_info_t() { stream_id = UNK_STREAM_ID; } audio_stream_info_t::operator bool() { return stream_id != UNK_STREAM_ID; } const char* audio_stream_info_t::get_channel_name(int channel) { if (((stream_id == MLP_STREAM_ID && stream_type == STREAM_TYPE_MLP) || stream_id == PCM_STREAM_ID) && channel_arrangement >= 0 && channel_arrangement <= 20) { if (channel >= 0 && channel < mlppcm_table[channel_arrangement].group1_channels) return mlppcm_table[channel_arrangement].group1_channel_name[channel]; if (channel >= mlppcm_table[channel_arrangement].group1_channels && channel < mlppcm_table[channel_arrangement].group1_channels + mlppcm_table[channel_arrangement].group2_channels) return mlppcm_table[channel_arrangement].group2_channel_name[channel - mlppcm_table[channel_arrangement].group1_channels]; } else if (stream_id == MLP_STREAM_ID && stream_type == STREAM_TYPE_TRUEHD) { int ch = 0; for (int i = 0; i < 13; i++) { if ((channel_arrangement >> i) & 1) { for (int j = 0; j < truehd_table[i].channels; j++) { if (ch++ == channel) return truehd_table[i].channel_name[j]; } } } } return ""; } uint32_t audio_stream_info_t::get_wfx_channels() { uint32_t wfx_channels = 0; if (((stream_id == MLP_STREAM_ID && stream_type == STREAM_TYPE_MLP) || stream_id == PCM_STREAM_ID) && channel_arrangement >= 0 && channel_arrangement <= 20) { for (int i = 0; i < mlppcm_table[channel_arrangement].group1_channels; i++) wfx_channels |= mlppcm_table[channel_arrangement].group1_channel_id[i]; for (int i = 0; i < mlppcm_table[channel_arrangement].group2_channels; i++) wfx_channels |= mlppcm_table[channel_arrangement].group2_channel_id[i]; } else if (stream_id == MLP_STREAM_ID && stream_type == STREAM_TYPE_TRUEHD) { for (int i = 0; i < 13; i++) { if ((channel_arrangement >> i) & 1) for (int j = 0; j < truehd_table[i].channels; j++) wfx_channels |= truehd_table[i].channel_id[j]; } } return wfx_channels; } double audio_stream_info_t::estimate_compression() { double compression = 1.0; if (stream_id == MLP_STREAM_ID) { switch (group1_samplerate) { case 44100: case 48000: compression = (double)group1_bits / ((double)group1_bits - 4.0); break; case 88200: case 96000: compression = (double)group1_bits / ((double)group1_bits - 8.0); break; case 176400: case 192000: compression = (double)group1_bits / ((double)group1_bits - 9.0); break; } } return compression; }