2 * Copyright (C) 2010-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
21 #include "AEChannelInfo.h"
24 CAEChannelInfo::CAEChannelInfo()
29 CAEChannelInfo::CAEChannelInfo(const enum AEChannel* rhs)
34 CAEChannelInfo::CAEChannelInfo(const AEStdChLayout rhs)
39 CAEChannelInfo::~CAEChannelInfo()
43 void CAEChannelInfo::ResolveChannels(const CAEChannelInfo& rhs)
45 /* mono gets upmixed to dual mono */
46 if (m_channelCount == 1 && m_channels[0] == AE_CH_FC)
54 bool srcHasSL = false;
55 bool srcHasSR = false;
56 bool srcHasRL = false;
57 bool srcHasRR = false;
59 bool dstHasSL = false;
60 bool dstHasSR = false;
61 bool dstHasRL = false;
62 bool dstHasRR = false;
64 for (unsigned int c = 0; c < rhs.m_channelCount; ++c)
65 switch(rhs.m_channels[c])
67 case AE_CH_SL: dstHasSL = true; break;
68 case AE_CH_SR: dstHasSR = true; break;
69 case AE_CH_BL: dstHasRL = true; break;
70 case AE_CH_BR: dstHasRR = true; break;
75 CAEChannelInfo newInfo;
76 for (unsigned int i = 0; i < m_channelCount; ++i)
78 switch (m_channels[i])
80 case AE_CH_SL: srcHasSL = true; break;
81 case AE_CH_SR: srcHasSR = true; break;
82 case AE_CH_BL: srcHasRL = true; break;
83 case AE_CH_BR: srcHasRR = true; break;
89 for (unsigned int c = 0; c < rhs.m_channelCount; ++c)
90 if (m_channels[i] == rhs.m_channels[c])
97 newInfo += m_channels[i];
100 /* we need to ensure we end up with rear or side channels for downmix to work */
101 if (srcHasSL && !dstHasSL && dstHasRL)
103 if (srcHasSR && !dstHasSR && dstHasRR)
105 if (srcHasRL && !dstHasRL && dstHasSL)
107 if (srcHasRR && !dstHasRR && dstHasSR)
113 void CAEChannelInfo::Reset()
116 for (unsigned int i = 0; i < AE_CH_MAX; ++i)
117 m_channels[i] = AE_CH_NULL;
120 CAEChannelInfo& CAEChannelInfo::operator=(const CAEChannelInfo& rhs)
125 /* clone the information */
126 m_channelCount = rhs.m_channelCount;
127 memcpy(m_channels, rhs.m_channels, sizeof(enum AEChannel) * rhs.m_channelCount);
132 CAEChannelInfo& CAEChannelInfo::operator=(const enum AEChannel* rhs)
138 while (m_channelCount < AE_CH_MAX && rhs[m_channelCount] != AE_CH_NULL)
140 m_channels[m_channelCount] = rhs[m_channelCount];
144 /* the last entry should be NULL, if not we were passed a non null terminated list */
145 ASSERT(rhs[m_channelCount] == AE_CH_NULL);
150 CAEChannelInfo& CAEChannelInfo::operator=(const enum AEStdChLayout rhs)
152 ASSERT(rhs > AE_CH_LAYOUT_INVALID && rhs < AE_CH_LAYOUT_MAX);
154 static enum AEChannel layouts[AE_CH_LAYOUT_MAX][9] = {
155 {AE_CH_FC, AE_CH_NULL},
156 {AE_CH_FL, AE_CH_FR, AE_CH_NULL},
157 {AE_CH_FL, AE_CH_FR, AE_CH_LFE, AE_CH_NULL},
158 {AE_CH_FL, AE_CH_FR, AE_CH_FC , AE_CH_NULL},
159 {AE_CH_FL, AE_CH_FR, AE_CH_FC , AE_CH_LFE, AE_CH_NULL},
160 {AE_CH_FL, AE_CH_FR, AE_CH_BL , AE_CH_BR , AE_CH_NULL},
161 {AE_CH_FL, AE_CH_FR, AE_CH_BL , AE_CH_BR , AE_CH_LFE, AE_CH_NULL},
162 {AE_CH_FL, AE_CH_FR, AE_CH_FC , AE_CH_BL , AE_CH_BR , AE_CH_NULL},
163 {AE_CH_FL, AE_CH_FR, AE_CH_FC , AE_CH_BL , AE_CH_BR , AE_CH_LFE, AE_CH_NULL},
164 {AE_CH_FL, AE_CH_FR, AE_CH_FC , AE_CH_BL , AE_CH_BR , AE_CH_SL , AE_CH_SR, AE_CH_NULL},
165 {AE_CH_FL, AE_CH_FR, AE_CH_FC , AE_CH_BL , AE_CH_BR , AE_CH_SL , AE_CH_SR, AE_CH_LFE, AE_CH_NULL}
168 *this = layouts[rhs];
172 bool CAEChannelInfo::operator==(const CAEChannelInfo& rhs)
174 /* if the channel count doesnt match, no need to check further */
175 if (m_channelCount != rhs.m_channelCount)
178 /* make sure the channel order is the same */
179 for (unsigned int i = 0; i < m_channelCount; ++i)
180 if (m_channels[i] != rhs.m_channels[i])
186 bool CAEChannelInfo::operator!=(const CAEChannelInfo& rhs)
188 return !(*this == rhs);
191 CAEChannelInfo& CAEChannelInfo::operator+=(const enum AEChannel& rhs)
193 ASSERT(m_channelCount < AE_CH_MAX);
194 ASSERT(rhs > AE_CH_NULL && rhs < AE_CH_MAX);
196 m_channels[m_channelCount++] = rhs;
200 CAEChannelInfo& CAEChannelInfo::operator-=(const enum AEChannel& rhs)
202 ASSERT(rhs > AE_CH_NULL && rhs < AE_CH_MAX);
205 while(i < m_channelCount && m_channels[i] != rhs)
207 if (i >= m_channelCount)
208 return *this; // Channel not found
210 for(; i < m_channelCount-1; i++)
211 m_channels[i] = m_channels[i+1];
213 m_channels[i] = AE_CH_NULL;
218 const enum AEChannel CAEChannelInfo::operator[](unsigned int i) const
220 ASSERT(i < m_channelCount);
221 return m_channels[i];
224 CAEChannelInfo::operator std::string() const
226 if (m_channelCount == 0)
230 for (unsigned int i = 0; i < m_channelCount - 1; ++i)
232 s.append(GetChName(m_channels[i]));
235 s.append(GetChName(m_channels[m_channelCount-1]));
240 const char* CAEChannelInfo::GetChName(const enum AEChannel ch)
242 ASSERT(ch >= 0 && ch < AE_CH_MAX);
244 static const char* channels[AE_CH_MAX] =
247 "FL" , "FR" , "FC" , "LFE", "BL" , "BR" , "FLOC",
248 "FROC", "BC" , "SL" , "SR" , "TFL" , "TFR" , "TFC" ,
249 "TC" , "TBL", "TBR", "TBC", "BLOC", "BROC",
265 bool CAEChannelInfo::HasChannel(const enum AEChannel ch) const
267 for (unsigned int i = 0; i < m_channelCount; ++i)
268 if (m_channels[i] == ch)
273 bool CAEChannelInfo::ContainsChannels(CAEChannelInfo& rhs) const
275 for (unsigned int i = 0; i < rhs.m_channelCount; ++i)
277 if (!HasChannel(rhs.m_channels[i]))