rendered paste bodyIndex: xbmc/cores/dvdplayer/DVDAudio.cpp
===================================================================
--- xbmc/cores/dvdplayer/DVDAudio.cpp (revision 26715)
+++ xbmc/cores/dvdplayer/DVDAudio.cpp (working copy)
@@ -92,7 +92,7 @@
else
codecstring = "PCM";
- m_pAudioDecoder = CAudioRendererFactory::Create(m_pCallback, audioframe.channels, audioframe.sample_rate, audioframe.bits_per_sample, false, codecstring, false, audioframe.passthrough);
+ m_pAudioDecoder = CAudioRendererFactory::Create(m_pCallback, audioframe.channels, audioframe.channel_map, audioframe.sample_rate, audioframe.bits_per_sample, false, codecstring, false, audioframe.passthrough);
if (!m_pAudioDecoder) return false;
@@ -345,4 +345,4 @@
if(!m_pAudioDecoder)
return 0.0;
return m_pAudioDecoder->GetCacheTotal();
-}
\ No newline at end of file
+}
Index: xbmc/cores/dvdplayer/DVDPlayerAudio.cpp
===================================================================
--- xbmc/cores/dvdplayer/DVDPlayerAudio.cpp (revision 26715)
+++ xbmc/cores/dvdplayer/DVDPlayerAudio.cpp (working copy)
@@ -316,6 +316,7 @@
audioframe.size = m_pAudioCodec->GetData(&audioframe.data);
audioframe.pts = m_audioClock;
audioframe.channels = m_pAudioCodec->GetChannels();
+ audioframe.channel_map = m_pAudioCodec->GetChannelMap();
audioframe.bits_per_sample = m_pAudioCodec->GetBitsPerSample();
audioframe.sample_rate = m_pAudioCodec->GetSampleRate();
audioframe.passthrough = m_pAudioCodec->NeedPassthrough();
Index: xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLibDts.cpp
===================================================================
--- xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLibDts.cpp (revision 26715)
+++ xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLibDts.cpp (working copy)
@@ -37,112 +37,24 @@
return (i > 32767) ? 32767 : ((i < -32768) ? -32768 : i);
}
-void CDVDAudioCodecLibDts::convert2s16_multi(convert_t * _f, int16_t * s16, int flags)
+/**
+ * \brief Function to convert the "planar" float format used by libdts
+ * into the interleaved int16 format used by us.
+ * \param in the input buffer containing the planar samples.
+ * \param out the output buffer where the interleaved result is stored.
+ * \param channels the total number of channels in the decoded data
+ */
+static int resample_int16(sample_t * in, int16_t *out, unsigned int channels)
{
- register int i;
- register int32_t * f = (int32_t *) _f;
-
- switch (flags)
- {
- case DTS_MONO:
- for (i = 0; i < 256; i++)
- {
- s16[2*i ] = convert (f[i]);
- s16[2*i+1] = convert (f[i]);
+ unsigned int i, ch;
+ int16_t *p = out;
+ for(i = 0; i < 256; ++i) {
+ for(ch = 0; ch < channels; ++ch) {
+ *p = convert( ((int32_t*)in)[i + (ch << 8)] );
+ ++p;
}
- break;
- case DTS_CHANNEL:
- case DTS_STEREO:
- case DTS_DOLBY:
- for (i = 0; i < 256; i++)
- {
- s16[2*i ] = convert (f[i]);
- s16[2*i+1] = convert (f[i+256]);
- }
- break;
- case DTS_3F:
- for (i = 0; i < 256; i++)
- {
- s16[6*i ] = convert (f[i+256]);
- s16[6*i+1] = convert (f[i+512]);
- s16[6*i+2] = 0;
- s16[6*i+3] = 0;
- s16[6*i+4] = convert (f[i]);
- s16[6*i+4] = 0;
- }
- break;
- case DTS_2F2R:
- for (i = 0; i < 256; i++)
- {
- s16[4*i ] = convert (f[i]);
- s16[4*i+1] = convert (f[i+256]);
- s16[4*i+2] = convert (f[i+512]);
- s16[4*i+3] = convert (f[i+768]);
- }
- break;
- case DTS_3F2R:
- for (i = 0; i < 256; i++)
- {
- s16[6*i ] = convert (f[i]);
- s16[6*i+1] = convert (f[i+256]);
- s16[6*i+2] = convert (f[i+512]);
- s16[6*i+3] = convert (f[i+768]);
- s16[6*i+4] = convert (f[i+1024]);
- s16[6*i+5] = 0;
- }
- break;
- case DTS_MONO | DTS_LFE:
- for (i = 0; i < 256; i++)
- {
- s16[6*i ] = s16[6*i+1] = s16[6*i+2] = s16[6*i+3] = 0;
- s16[6*i+4] = convert (f[i]);
- s16[6*i+5] = convert (f[i+256]);
- }
- break;
- case DTS_CHANNEL | DTS_LFE:
- case DTS_STEREO | DTS_LFE:
- case DTS_DOLBY | DTS_LFE:
- for (i = 0; i < 256; i++)
- {
- s16[6*i ] = convert (f[i]);
- s16[6*i+1] = convert (f[i+256]);
- s16[6*i+2] = s16[6*i+3] = s16[6*i+4] = 0;
- s16[6*i+5] = convert (f[i+512]);
- }
- break;
- case DTS_3F | DTS_LFE:
- for (i = 0; i < 256; i++)
- {
- s16[6*i ] = convert (f[i+256]);
- s16[6*i+1] = convert (f[i+512]);
- s16[6*i+2] = s16[6*i+3] = 0;
- s16[6*i+4] = convert (f[i]);
- s16[6*i+5] = convert (f[i+768]);
- }
- break;
- case DTS_2F2R | DTS_LFE:
- for (i = 0; i < 256; i++)
- {
- s16[6*i ] = convert (f[i]);
- s16[6*i+1] = convert (f[i+256]);
- s16[6*i+2] = convert (f[i+512]);
- s16[6*i+3] = convert (f[i+768]);
- s16[6*i+4] = 0;
- s16[6*i+5] = convert (f[i+1024]);
- }
- break;
- case DTS_3F2R | DTS_LFE:
- for (i = 0; i < 256; i++)
- {
- s16[6*i ] = convert (f[i+256]);
- s16[6*i+1] = convert (f[i+512]);
- s16[6*i+2] = convert (f[i+768]);
- s16[6*i+3] = convert (f[i+1024]);
- s16[6*i+4] = convert (f[i]);
- s16[6*i+5] = convert (f[i+1280]);
- }
- break;
- }
+ }
+ return p - out;
}
CDVDAudioCodecLibDts::CDVDAudioCodecLibDts() : CDVDAudioCodec()
@@ -184,34 +96,60 @@
m_pState = NULL;
}
-int CDVDAudioCodecLibDts::GetNrOfChannels(int iFlags)
-{
- if(iFlags & DTS_LFE)
- return 6;
- if(iFlags & DTS_CHANNEL)
- return 6;
- else if ((iFlags & DTS_CHANNEL_MASK) == DTS_2F2R)
- return 4;
- else
- return 2;
-}
-
void CDVDAudioCodecLibDts::SetupChannels(int flags)
{
- m_iSourceFlags = flags;
- m_iSourceChannels = GetNrOfChannels(flags);
- if (g_guiSettings.GetBool("audiooutput.downmixmultichannel"))
- m_iOutputChannels = 2;
- else
- m_iOutputChannels = m_iSourceChannels;
+ /* These are channel mappings that libdts outputs */
+ static uint8_t channelMaps[14][6] =
+ {
+ /* Without LFE */
+ {/* DTS_MONO */ PCM_FRONT_CENTER },
+ {/* DTS_STEREO */ PCM_FRONT_LEFT , PCM_FRONT_RIGHT },
+ {/* DTS_3F */ PCM_FRONT_CENTER, PCM_FRONT_LEFT , PCM_FRONT_RIGHT },
+ {/* DTS_2F1R */ PCM_FRONT_LEFT , PCM_FRONT_RIGHT , PCM_BACK_CENTER },
+ {/* DTS_3F1R */ PCM_FRONT_CENTER, PCM_FRONT_LEFT , PCM_FRONT_RIGHT , PCM_BACK_CENTER },
+ {/* DTS_2F2R */ PCM_FRONT_LEFT , PCM_FRONT_RIGHT , PCM_BACK_LEFT , PCM_BACK_RIGHT },
+ {/* DTS_3F2R */ PCM_FRONT_CENTER, PCM_FRONT_LEFT , PCM_FRONT_RIGHT , PCM_BACK_LEFT , PCM_BACK_RIGHT },
+ /* With LFE */
+ {/* DTS_MONO */ PCM_FRONT_CENTER, PCM_LOW_FREQUENCY },
+ {/* DTS_STEREO */ PCM_FRONT_LEFT , PCM_FRONT_RIGHT , PCM_LOW_FREQUENCY },
+ {/* DTS_3F */ PCM_FRONT_CENTER, PCM_FRONT_LEFT , PCM_FRONT_RIGHT , PCM_LOW_FREQUENCY },
+ {/* DTS_2F1R */ PCM_FRONT_LEFT , PCM_FRONT_RIGHT , PCM_BACK_CENTER },
+ {/* DTS_3F1R */ PCM_FRONT_CENTER, PCM_FRONT_LEFT , PCM_FRONT_RIGHT , PCM_BACK_CENTER, PCM_LOW_FREQUENCY },
+ {/* DTS_2F2R */ PCM_FRONT_LEFT , PCM_FRONT_RIGHT , PCM_BACK_LEFT , PCM_BACK_RIGHT , PCM_LOW_FREQUENCY },
+ {/* DTS_3F2R */ PCM_FRONT_CENTER, PCM_FRONT_LEFT , PCM_FRONT_RIGHT , PCM_BACK_LEFT , PCM_BACK_RIGHT , PCM_LOW_FREQUENCY},
+ };
- if (m_iOutputChannels == 1)
- m_iOutputFlags = DTS_MONO;
- else if (m_iOutputChannels == 2)
- m_iOutputFlags = DTS_STEREO;
- else
- m_iOutputFlags = m_iSourceFlags;
+ m_iSourceFlags = flags;
+ // setup channel map
+ int channels = 0;
+ int chOffset = (flags & DTS_LFE) ? 7 : 0;
+ switch (m_iSourceFlags &~ DTS_LFE)
+ {
+ case DTS_MONO : m_pChannelMap = channelMaps[chOffset + 0]; channels = 1; break;
+ case DTS_CHANNEL:
+ case DTS_DOLBY :
+ case DTS_STEREO : m_pChannelMap = channelMaps[chOffset + 1]; channels = 2; break;
+ case DTS_3F : m_pChannelMap = channelMaps[chOffset + 2]; channels = 3; break;
+ case DTS_2F1R : m_pChannelMap = channelMaps[chOffset + 3]; channels = 3; break;
+ case DTS_3F1R : m_pChannelMap = channelMaps[chOffset + 4]; channels = 4; break;
+ case DTS_2F2R : m_pChannelMap = channelMaps[chOffset + 5]; channels = 4; break;
+ case DTS_3F2R : m_pChannelMap = channelMaps[chOffset + 6]; channels = 5; break;
+ default : m_pChannelMap = NULL; break;
+ }
+
+ if(m_pChannelMap == NULL)
+ CLog::Log(LOGERROR, "CDVDAudioCodecLibDts::SetupChannels - Invalid channel mapping");
+
+ if(m_iSourceChannels > 0 && m_iSourceChannels != channels)
+ CLog::Log(LOGINFO, "%s - Number of channels changed in stream from %d to %d, data might be truncated", __FUNCTION__, m_iOutputChannels, channels);
+
+ m_iSourceChannels = channels;
+ m_iOutputChannels = m_iSourceChannels;
+ m_iOutputFlags = m_iSourceFlags;
+
+ /* adjust level should always be set, to keep samples in proper range */
+ /* after any downmixing has been done */
m_iOutputFlags |= DTS_ADJUST_LEVEL;
}
@@ -330,8 +268,7 @@
CLog::Log(LOGERROR, "CDVDAudioCodecLibDts::Decode : dts_block != 0");
break;
}
- convert2s16_multi(m_fSamples, (int16_t*)(m_decodedData + m_decodedSize), flags & (DTS_CHANNEL_MASK | DTS_LFE));
- m_decodedSize += 2 * 256 * m_iOutputChannels;
+ m_decodedSize += 2*resample_int16(m_fSamples, (int16_t*)(m_decodedData + m_decodedSize), m_iSourceChannels);
}
return len;
Index: xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLibFaad.cpp
===================================================================
--- xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLibFaad.cpp (revision 26715)
+++ xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLibFaad.cpp (working copy)
@@ -103,6 +103,24 @@
return false;
}
+uint8_t* CDVDAudioCodecLibFaad::GetChannelMap()
+{
+ for(int i = 0; i < m_iSourceChannels; ++i) {
+ switch(m_frameInfo.channel_position[i]) {
+ case FRONT_CHANNEL_CENTER: m_pChannelMap[i] = PCM_FRONT_CENTER ; break;
+ case FRONT_CHANNEL_LEFT : m_pChannelMap[i] = PCM_FRONT_LEFT ; break;
+ case FRONT_CHANNEL_RIGHT : m_pChannelMap[i] = PCM_FRONT_RIGHT ; break;
+ case SIDE_CHANNEL_LEFT : m_pChannelMap[i] = PCM_SIDE_LEFT ; break;
+ case SIDE_CHANNEL_RIGHT : m_pChannelMap[i] = PCM_SIDE_RIGHT ; break;
+ case BACK_CHANNEL_LEFT : m_pChannelMap[i] = PCM_BACK_LEFT ; break;
+ case BACK_CHANNEL_RIGHT : m_pChannelMap[i] = PCM_BACK_RIGHT ; break;
+ case BACK_CHANNEL_CENTER : m_pChannelMap[i] = PCM_BACK_CENTER ; break;
+ case LFE_CHANNEL : m_pChannelMap[i] = PCM_LOW_FREQUENCY; break;
+ }
+ }
+ return m_pChannelMap;
+}
+
int CDVDAudioCodecLibFaad::Decode(BYTE* pData, int iSize)
{
m_DecodedDataSize = 0;
@@ -217,7 +235,7 @@
// modify some stuff here
pConfiguration->outputFormat = FAAD_FMT_16BIT; // already default
- pConfiguration->downMatrix = g_guiSettings.GetBool("audiooutput.downmixmultichannel") ? 1 : 0;
+ pConfiguration->downMatrix = 0; //g_guiSettings.GetBool("audiooutput.downmixmultichannel") ? 1 : 0;
m_dll.faacDecSetConfiguration(m_pHandle, pConfiguration);
Index: xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLiba52.h
===================================================================
--- xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLiba52.h (revision 26715)
+++ xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLiba52.h (working copy)
@@ -40,11 +40,12 @@
virtual int Decode(BYTE* pData, int iSize);
virtual int GetData(BYTE** dst);
virtual void Reset();
- virtual int GetChannels() { return m_iOutputChannels; }
- virtual int GetSampleRate() { return m_iSourceSampleRate; }
- virtual int GetBufferSize() { return m_inputSize; }
- virtual int GetBitsPerSample() { return 16; }
- virtual const char* GetName() { return "liba52"; }
+ virtual int GetChannels() { return m_iOutputChannels; }
+ virtual uint8_t *GetChannelMap() { return m_pChannelMap; }
+ virtual int GetSampleRate() { return m_iSourceSampleRate; }
+ virtual int GetBufferSize() { return m_inputSize; }
+ virtual int GetBitsPerSample() { return 16; }
+ virtual const char* GetName() { return "liba52"; }
protected:
void SetDefault();
@@ -64,7 +65,7 @@
int m_iOutputFlags;
int m_iOutputChannels;
- unsigned int m_iOutputMapping;
+ uint8_t *m_pChannelMap;
DllLiba52 m_dll;
Index: xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodec.h
===================================================================
--- xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodec.h (revision 26715)
+++ xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodec.h (working copy)
@@ -22,6 +22,7 @@
*/
#include "system.h"
+#include "../../../../utils/PCMRemap.h"
#if (defined HAVE_CONFIG_H) && (!defined WIN32)
#include "config.h"
@@ -90,6 +91,11 @@
virtual int GetChannels() = 0;
/*
+ * returns the channel mapping
+ */
+ virtual uint8_t* GetChannelMap() = 0;
+
+ /*
* returns the samplerate for the decoded audio stream
*/
virtual int GetSampleRate() = 0;
Index: xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPcm.h
===================================================================
--- xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPcm.h (revision 26715)
+++ xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPcm.h (working copy)
@@ -34,6 +34,7 @@
virtual int GetData(BYTE** dst);
virtual void Reset();
virtual int GetChannels();
+ virtual uint8_t* GetChannelMap();
virtual int GetSampleRate();
virtual int GetBitsPerSample();
virtual const char* GetName() { return "pcm"; }
Index: xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLibDts.h
===================================================================
--- xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLibDts.h (revision 26715)
+++ xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLibDts.h (working copy)
@@ -34,15 +34,15 @@
virtual int Decode(BYTE* pData, int iSize);
virtual int GetData(BYTE** dst);
virtual void Reset();
- virtual int GetChannels() { return m_iOutputChannels; }
- virtual int GetSampleRate() { return m_iSourceSampleRate; }
- virtual int GetBufferSize() { return m_inputSize; }
- virtual int GetBitsPerSample() { return 16; }
- virtual const char* GetName() { return "libdts"; }
+ virtual int GetChannels() { return m_iOutputChannels; }
+ virtual uint8_t *GetChannelMap() { return m_pChannelMap; }
+ virtual int GetSampleRate() { return m_iSourceSampleRate; }
+ virtual int GetBufferSize() { return m_inputSize; }
+ virtual int GetBitsPerSample() { return 16; }
+ virtual const char* GetName() { return "libdts"; }
protected:
void SetDefault();
- int GetNrOfChannels(int flags);
void SetupChannels(int flags);
int ParseFrame(BYTE* data, int size, BYTE** frame, int* framesize);
@@ -61,6 +61,7 @@
int m_iOutputFlags;
int m_iOutputChannels;
+ uint8_t *m_pChannelMap;
DllLibDts m_dll;
Index: xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLibFaad.h
===================================================================
--- xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLibFaad.h (revision 26715)
+++ xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLibFaad.h (working copy)
@@ -37,11 +37,12 @@
virtual int Decode(BYTE* pData, int iSize);
virtual int GetData(BYTE** dst);
virtual void Reset();
- virtual int GetChannels() { return m_iSourceChannels; }
- virtual int GetSampleRate() { return m_iSourceSampleRate; }
- virtual int GetBitsPerSample() { return 16; }
- virtual const char* GetName() { return "libfaad"; }
- virtual int GetBufferSize() { return m_InputBufferSize; }
+ virtual int GetChannels() { return m_iSourceChannels; }
+ virtual uint8_t* GetChannelMap();
+ virtual int GetSampleRate() { return m_iSourceSampleRate; }
+ virtual int GetBitsPerSample() { return 16; }
+ virtual const char* GetName() { return "libfaad"; }
+ virtual int GetBufferSize() { return m_InputBufferSize; }
private:
@@ -52,6 +53,7 @@
int m_iSourceSampleRate;
int m_iSourceChannels;
+ uint8_t m_pChannelMap[64];
int m_iSourceBitrate;
bool m_bInitializedDecoder;
Index: xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLibMad.h
===================================================================
--- xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLibMad.h (revision 26715)
+++ xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLibMad.h (working copy)
@@ -37,11 +37,12 @@
virtual int Decode(BYTE* pData, int iSize);
virtual int GetData(BYTE** dst);
virtual void Reset();
- virtual int GetChannels() { return m_iSourceChannels; }
- virtual int GetSampleRate() { return m_iSourceSampleRate; }
- virtual int GetBitsPerSample() { return 16; }
- virtual const char* GetName() { return "libmad"; }
- virtual int GetBufferSize() { return m_iInputBufferSize; }
+ virtual int GetChannels() { return m_iSourceChannels; }
+ virtual uint8_t* GetChannelMap() { static uint8_t map[2] = {PCM_FRONT_LEFT, PCM_FRONT_RIGHT}; return map; }
+ virtual int GetSampleRate() { return m_iSourceSampleRate; }
+ virtual int GetBitsPerSample() { return 16; }
+ virtual const char* GetName() { return "libmad"; }
+ virtual int GetBufferSize() { return m_iInputBufferSize; }
private:
Index: xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.cpp
===================================================================
--- xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.cpp (revision 26715)
+++ xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.cpp (working copy)
@@ -218,6 +218,46 @@
return 0;
}
+uint8_t* CDVDAudioCodecFFmpeg::GetChannelMap()
+{
+ static uint8_t map[14][8] =
+ {
+ {/* MONO */ PCM_FRONT_CENTER },
+ {/* STEREO */ PCM_FRONT_LEFT, PCM_FRONT_RIGHT },
+ {/* 2_1 */ PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_BACK_CENTER },
+ {/* SURROUND */ PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_FRONT_CENTER },
+ {/* 4POINT0 */ PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_FRONT_CENTER, PCM_BACK_CENTER },
+ {/* 2_2 */ PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_SIDE_LEFT , PCM_SIDE_RIGHT },
+ {/* QUAD */ PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_BACK_LEFT , PCM_BACK_RIGHT },
+ {/* 5POINT0 */ PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_FRONT_CENTER, PCM_SIDE_LEFT , PCM_SIDE_RIGHT },
+ {/* 5POINT1 */ PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_FRONT_CENTER, PCM_LOW_FREQUENCY, PCM_SIDE_LEFT , PCM_SIDE_RIGHT },
+ {/* 5POINT0_BACK */ PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_FRONT_CENTER, PCM_BACK_LEFT , PCM_BACK_RIGHT },
+ {/* 5POINT1_BACK */ PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_FRONT_CENTER, PCM_LOW_FREQUENCY, PCM_BACK_LEFT , PCM_BACK_RIGHT },
+ {/* 7POINT0 */ PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_FRONT_CENTER, PCM_BACK_LEFT , PCM_BACK_RIGHT, PCM_SIDE_LEFT , PCM_SIDE_RIGHT },
+ {/* 7POINT1 */ PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_FRONT_CENTER, PCM_LOW_FREQUENCY, PCM_BACK_LEFT , PCM_BACK_RIGHT, PCM_SIDE_LEFT , PCM_SIDE_RIGHT },
+ {/* 7POINT1_WIDE */ PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_FRONT_CENTER, PCM_LOW_FREQUENCY, PCM_BACK_LEFT , PCM_BACK_RIGHT, PCM_FRONT_LEFT_OF_CENTER , PCM_FRONT_RIGHT_OF_CENTER}
+ };
+
+ switch(m_pCodecContext->channel_layout &~ CH_LAYOUT_STEREO_DOWNMIX) {
+ case CH_LAYOUT_MONO : return map[ 0];
+ case CH_LAYOUT_STEREO : return map[ 1];
+ case CH_LAYOUT_2_1 : return map[ 2];
+ case CH_LAYOUT_SURROUND : return map[ 3];
+ case CH_LAYOUT_4POINT0 : return map[ 4];
+ case CH_LAYOUT_2_2 : return map[ 5];
+ case CH_LAYOUT_QUAD : return map[ 6];
+ case CH_LAYOUT_5POINT0 : return map[ 7];
+ case CH_LAYOUT_5POINT1 : return map[ 8];
+ case CH_LAYOUT_5POINT0_BACK: return map[ 9];
+ case CH_LAYOUT_5POINT1_BACK: return map[10];
+ case CH_LAYOUT_7POINT0 : return map[11];
+ case CH_LAYOUT_7POINT1 : return map[12];
+ case CH_LAYOUT_7POINT1_WIDE: return map[13];
+ default:
+ return NULL;
+ }
+}
+
int CDVDAudioCodecFFmpeg::GetSampleRate()
{
if (m_pCodecContext) return m_pCodecContext->sample_rate;
Index: xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.h
===================================================================
--- xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.h (revision 26715)
+++ xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.h (working copy)
@@ -36,6 +36,7 @@
virtual int GetData(BYTE** dst);
virtual void Reset();
virtual int GetChannels();
+ virtual uint8_t *GetChannelMap();
virtual int GetSampleRate();
virtual int GetBitsPerSample();
virtual const char* GetName() { return "FFmpeg"; }
Index: xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthrough.h
===================================================================
--- xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthrough.h (revision 26715)
+++ xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthrough.h (working copy)
@@ -37,6 +37,7 @@
virtual int GetData(BYTE** dst);
virtual void Reset();
virtual int GetChannels();
+ virtual uint8_t *GetChannelMap() { static uint8_t map[2] = {PCM_FRONT_LEFT, PCM_FRONT_RIGHT}; return map; }
virtual int GetSampleRate();
virtual int GetBitsPerSample();
virtual bool NeedPassthrough() { return true; }
Index: xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLiba52.cpp
===================================================================
--- xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLiba52.cpp (revision 26715)
+++ xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLiba52.cpp (working copy)
@@ -47,23 +47,19 @@
* into the interleaved int16 format used by us.
* \param in the input buffer containing the planar samples.
* \param out the output buffer where the interleaved result is stored.
+ * \param channels the total number of channels in the decoded data
*/
-static int resample_int16(sample_t * in, int16_t *out, int32_t channel_map)
+static int resample_int16(sample_t * in, int16_t *out, unsigned int channels)
{
- unsigned long i;
+ unsigned int i, ch;
int16_t *p = out;
- for (i = 0; i != 256; i++) {
- unsigned long map = channel_map;
- do {
- unsigned long ch = map & 15;
- if (ch == 15)
- *p = 0;
- else
- *p = convert( ((int32_t*)in)[i + ((ch-1)<<8)] );
- p++;
- } while ((map >>= 4));
+ for(i = 0; i < 256; ++i) {
+ for(ch = 0; ch < channels; ++ch) {
+ *p = convert( ((int32_t*)in)[i + (ch << 8)] );
+ ++p;
+ }
}
- return (int16_t*) p - out;
+ return p - out;
}
@@ -109,90 +105,58 @@
void CDVDAudioCodecLiba52::SetupChannels(int flags)
{
-/* Internal AC3 ordering for different configs
- * A52_CHANNEL: 1+1 2 Ch1, Ch2
- * A52_MONO : 1/0 1 C
- * A52_STEREO : 2/0 2 L, R
- * A52_3F : 3/0 3 L, C, R
- * A52_2F1R : 2/1 3 L, R, S
- * A52_3F1R : 3/1 4 L, C, R, S
- * A52_2F2R : 2/2 4 L, R, SL, SR
- * A52_3F2R : 3/2 5 L, C, R, SL, SR
-*/
+ /* These are channel mappings that liba52 outputs */
+ static uint8_t channelMaps[14][6] =
+ {
+ /* Without LFE */
+ {/* A52_MONO */ PCM_FRONT_CENTER },
+ {/* A52_STEREO */ PCM_FRONT_LEFT , PCM_FRONT_RIGHT },
+ {/* A52_3F */ PCM_FRONT_LEFT , PCM_FRONT_CENTER , PCM_FRONT_RIGHT },
+ {/* A52_2F1R */ PCM_FRONT_LEFT , PCM_FRONT_RIGHT , PCM_BACK_CENTER },
+ {/* A52_3F1R */ PCM_FRONT_LEFT , PCM_FRONT_CENTER , PCM_FRONT_RIGHT, PCM_BACK_CENTER },
+ {/* A52_2F2R */ PCM_FRONT_LEFT , PCM_FRONT_RIGHT , PCM_BACK_LEFT , PCM_BACK_RIGHT },
+ {/* A52_3F2R */ PCM_FRONT_LEFT , PCM_FRONT_CENTER , PCM_FRONT_RIGHT, PCM_BACK_LEFT , PCM_BACK_RIGHT },
+ /* With LFE */
+ {/* A52_MONO */ PCM_LOW_FREQUENCY, PCM_FRONT_CENTER },
+ {/* A52_STEREO */ PCM_LOW_FREQUENCY, PCM_FRONT_LEFT , PCM_FRONT_RIGHT },
+ {/* A52_3F */ PCM_LOW_FREQUENCY, PCM_FRONT_LEFT , PCM_FRONT_CENTER , PCM_FRONT_RIGHT },
+ {/* A52_2F1R */ PCM_LOW_FREQUENCY, PCM_FRONT_LEFT , PCM_FRONT_RIGHT , PCM_BACK_CENTER },
+ {/* A52_3F1R */ PCM_LOW_FREQUENCY, PCM_FRONT_LEFT , PCM_FRONT_CENTER , PCM_FRONT_RIGHT, PCM_BACK_CENTER },
+ {/* A52_2F2R */ PCM_LOW_FREQUENCY, PCM_FRONT_LEFT , PCM_FRONT_RIGHT , PCM_BACK_LEFT , PCM_BACK_RIGHT },
+ {/* A52_3F2R */ PCM_LOW_FREQUENCY, PCM_FRONT_LEFT , PCM_FRONT_CENTER , PCM_FRONT_RIGHT, PCM_BACK_LEFT , PCM_BACK_RIGHT }
+ };
m_iSourceFlags = flags;
- // setup channel map for how to translate to linear format
- // standard windows format
- if(m_iSourceFlags & A52_LFE)
+
+ // setup channel map
+ int channels = 0;
+ int chOffset = (flags & A52_LFE) ? 7 : 0;
+ switch (m_iSourceFlags &~ A52_LFE)
{
- switch (m_iSourceFlags&~A52_LFE) {
- case A52_MONO : m_iOutputMapping = 0x12ffff; break;
- case A52_CHANNEL:
- case A52_STEREO :
- case A52_DOLBY : m_iOutputMapping = 0x1fff32; break;
- case A52_2F1R : m_iOutputMapping = 0x1f5542; break;
- case A52_2F2R : m_iOutputMapping = 0x1f5432; break;
- case A52_3F : m_iOutputMapping = 0x13ff42; break;
- case A52_3F1R : m_iOutputMapping = 0x135542; break;
- case A52_3F2R : m_iOutputMapping = 0x136542; break;
- default : m_iOutputMapping = 0x000000; break;
- }
+ case A52_MONO : m_pChannelMap = channelMaps[chOffset + 0]; channels = 1; break;
+ case A52_CHANNEL:
+ case A52_DOLBY :
+ case A52_STEREO : m_pChannelMap = channelMaps[chOffset + 1]; channels = 2; break;
+ case A52_3F : m_pChannelMap = channelMaps[chOffset + 2]; channels = 3; break;
+ case A52_2F1R : m_pChannelMap = channelMaps[chOffset + 3]; channels = 3; break;
+ case A52_3F1R : m_pChannelMap = channelMaps[chOffset + 4]; channels = 4; break;
+ case A52_2F2R : m_pChannelMap = channelMaps[chOffset + 5]; channels = 4; break;
+ case A52_3F2R : m_pChannelMap = channelMaps[chOffset + 6]; channels = 5; break;
+ default : m_pChannelMap = NULL; break;
}
- else
- {
- switch (m_iSourceFlags) {
- case A52_MONO : m_iOutputMapping = 0x1; break;
- case A52_CHANNEL:
- case A52_STEREO :
- case A52_DOLBY : m_iOutputMapping = 0x21; break;
- case A52_2F1R : m_iOutputMapping = 0x2231; break;
- case A52_2F2R : m_iOutputMapping = 0x4321; break;
- case A52_3F : m_iOutputMapping = 0x2ff31; break;
- case A52_3F1R : m_iOutputMapping = 0x24431; break;
- case A52_3F2R : m_iOutputMapping = 0x25431; break;
- default : m_iOutputMapping = 0x0; break;
- }
- }
- if(m_iOutputMapping == 0x0)
+ if(flags & A52_LFE) ++channels;
+
+ if(m_pChannelMap == NULL)
CLog::Log(LOGERROR, "CDVDAudioCodecLiba52::SetupChannels - Invalid channel mapping");
- int channels = 0;
- unsigned int m = m_iOutputMapping<<4;
- while(m>>=4) channels++;
-
- // xbox can't handle these
- if(channels == 5 || channels == 3)
- channels = 6;
-
if(m_iSourceChannels > 0 && m_iSourceChannels != channels)
CLog::Log(LOGINFO, "%s - Number of channels changed in stream from %d to %d, data might be truncated", __FUNCTION__, m_iOutputChannels, channels);
m_iSourceChannels = channels;
-
- // make sure map contains enough channels
- for(int i=0;i<m_iSourceChannels;i++)
- {
- if((m_iOutputMapping & (0xf<<(i*4))) == 0)
- m_iOutputMapping |= 0xf<<(i*4);
- }
- // and nothing more
- m_iOutputMapping &= ~(0xffffffff<<(m_iSourceChannels*4));
-
-
m_iOutputChannels = m_iSourceChannels;
m_iOutputFlags = m_iSourceFlags;
- // If we can't support multichannel output downmix
- if (g_guiSettings.GetBool("audiooutput.downmixmultichannel"))
- {
- m_iOutputChannels = 2;
- m_iOutputMapping = 0x21;
- m_iOutputFlags = A52_STEREO;
- if (m_iSourceChannels > 2)
- m_Gain = pow(2.0f, g_advancedSettings.m_ac3Gain/6.0f); // Hack for downmix attenuation
- }
-
/* adjust level should always be set, to keep samples in proper range */
/* after any downmixing has been done */
m_iOutputFlags |= A52_ADJUST_LEVEL;
@@ -318,7 +282,7 @@
CLog::Log(LOGERROR, "CDVDAudioCodecLiba52::Decode - a52_block failed");
break;
}
- m_decodedSize += 2*resample_int16(m_fSamples, (int16_t*)(m_decodedData + m_decodedSize), m_iOutputMapping);
+ m_decodedSize += 2*resample_int16(m_fSamples, (int16_t*)(m_decodedData + m_decodedSize), m_iSourceChannels);
}
return len;
}
Index: xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPcm.cpp
===================================================================
--- xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPcm.cpp (revision 26715)
+++ xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPcm.cpp (working copy)
@@ -293,6 +293,24 @@
return m_iOutputChannels;
}
+uint8_t* CDVDAudioCodecPcm::GetChannelMap()
+{
+ /* ? = probarbly wrong, just a guess */
+ static uint8_t map[8][8] =
+ {
+ /* MONO */ {PCM_FRONT_CENTER },
+ /* STEREO */ {PCM_FRONT_LEFT, PCM_FRONT_RIGHT },
+ /* 3.0 ? */ {PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_FRONT_CENTER },
+ /* 4.0 ? */ {PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_BACK_LEFT , PCM_BACK_RIGHT },
+ /* 5.0 */ {PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_FRONT_CENTER, PCM_BACK_LEFT, PCM_BACK_RIGHT },
+ /* 5.1 ? */ {PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_FRONT_CENTER, PCM_BACK_LEFT, PCM_BACK_RIGHT, PCM_LOW_FREQUENCY },
+ /* 7.0 ? */ {PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_FRONT_CENTER, PCM_BACK_LEFT, PCM_BACK_RIGHT, PCM_FRONT_LEFT_OF_CENTER, PCM_FRONT_RIGHT_OF_CENTER },
+ /* 7.1 ? */ {PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_FRONT_CENTER, PCM_BACK_LEFT, PCM_BACK_RIGHT, PCM_LOW_FREQUENCY , PCM_FRONT_LEFT_OF_CENTER , PCM_FRONT_RIGHT_OF_CENTER}
+ };
+
+ return map[m_iOutputChannels - 1];
+}
+
int CDVDAudioCodecPcm::GetSampleRate()
{
return m_iSourceSampleRate;
Index: xbmc/cores/dvdplayer/DVDPlayerAudio.h
===================================================================
--- xbmc/cores/dvdplayer/DVDPlayerAudio.h (revision 26715)
+++ xbmc/cores/dvdplayer/DVDPlayerAudio.h (working copy)
@@ -54,6 +54,7 @@
unsigned int size;
int channels;
+ uint8_t *channel_map;
int bits_per_sample;
int sample_rate;
bool passthrough;
Index: xbmc/cores/AudioRenderers/IAudioRenderer.h
===================================================================
--- xbmc/cores/AudioRenderers/IAudioRenderer.h (revision 26715)
+++ xbmc/cores/AudioRenderers/IAudioRenderer.h (working copy)
@@ -31,6 +31,7 @@
#include "StdString.h"
#include "IAudioCallback.h"
+#include "PCMRemap.h"
extern void RegisterAudioCallback(IAudioCallback* pCallback);
extern void UnRegisterAudioCallback();
@@ -42,7 +43,7 @@
public:
IAudioRenderer() {};
virtual ~IAudioRenderer() {};
- virtual bool Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec = "", bool bIsMusic=false, bool bPassthrough = false) = 0;
+ virtual bool Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, uint8_t *channelMap, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec = "", bool bIsMusic=false, bool bPassthrough = false) = 0;
virtual void UnRegisterAudioCallback() = 0;
virtual void RegisterAudioCallback(IAudioCallback* pCallback) = 0;
virtual float GetDelay() = 0;
@@ -66,6 +67,9 @@
virtual void WaitCompletion() = 0;
virtual void SwitchChannels(int iAudioStream, bool bAudioOnAllSpeakers) = 0;
+protected:
+ CPCMRemap m_remap;
+
private:
};
Index: xbmc/cores/AudioRenderers/PulseAudioDirectSound.cpp
===================================================================
--- xbmc/cores/AudioRenderers/PulseAudioDirectSound.cpp (revision 26715)
+++ xbmc/cores/AudioRenderers/PulseAudioDirectSound.cpp (working copy)
@@ -143,7 +143,7 @@
{
}
-bool CPulseAudioDirectSound::Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec, bool bIsMusic, bool bPassthrough)
+bool CPulseAudioDirectSound::Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, uint8_t *channelMap, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec, bool bIsMusic, bool bPassthrough)
{
CLog::Log(LOGDEBUG,"PulseAudio: Opening Channels: %i - SampleRate: %i - SampleBit: %i - Resample %s - Codec %s - IsMusic %s - IsPassthrough %s - device: %s", iChannels, uiSamplesPerSec, uiBitsPerSample, bResample ? "true" : "false", strAudioCodec, bIsMusic ? "true" : "false", bPassthrough ? "true" : "false", device.c_str());
if (iChannels == 0)
Index: xbmc/cores/AudioRenderers/NullDirectSound.cpp
===================================================================
--- xbmc/cores/AudioRenderers/NullDirectSound.cpp (revision 26715)
+++ xbmc/cores/AudioRenderers/NullDirectSound.cpp (working copy)
@@ -41,7 +41,7 @@
CNullDirectSound::CNullDirectSound()
{
}
-bool CNullDirectSound::Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec, bool bIsMusic, bool bPassthrough)
+bool CNullDirectSound::Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, uint8_t *channelMap, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec, bool bIsMusic, bool bPassthrough)
{
CLog::Log(LOGERROR,"Creating a Null Audio Renderer, Check your audio settings as this should not happen");
if (iChannels == 0)
Index: xbmc/cores/AudioRenderers/AudioRendererFactory.cpp
===================================================================
--- xbmc/cores/AudioRenderers/AudioRendererFactory.cpp (revision 26715)
+++ xbmc/cores/AudioRenderers/AudioRendererFactory.cpp (working copy)
@@ -41,7 +41,7 @@
#define ReturnOnValidInitialize() \
{ \
- if (audioSink->Initialize(pCallback, device, iChannels, uiSamplesPerSec, uiBitsPerSample, bResample, strAudioCodec, bIsMusic, bPassthrough)) \
+ if (audioSink->Initialize(pCallback, device, iChannels, channelMap, uiSamplesPerSec, uiBitsPerSample, bResample, strAudioCodec, bIsMusic, bPassthrough)) \
return audioSink; \
else \
{ \
@@ -51,7 +51,7 @@
} \
}\
-IAudioRenderer* CAudioRendererFactory::Create(IAudioCallback* pCallback, int iChannels, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec, bool bIsMusic, bool bPassthrough)
+IAudioRenderer* CAudioRendererFactory::Create(IAudioCallback* pCallback, int iChannels, uint8_t *channelMap, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec, bool bIsMusic, bool bPassthrough)
{
IAudioRenderer* audioSink = NULL;
@@ -91,7 +91,7 @@
#endif
audioSink = new CNullDirectSound();
- audioSink->Initialize(pCallback, device, iChannels, uiSamplesPerSec, uiBitsPerSample, bResample, strAudioCodec, bIsMusic, bPassthrough);
+ audioSink->Initialize(pCallback, device, iChannels, channelMap, uiSamplesPerSec, uiBitsPerSample, bResample, strAudioCodec, bIsMusic, bPassthrough);
return audioSink;
}
}
@@ -119,7 +119,7 @@
#endif
audioSink = new CNullDirectSound();
- audioSink->Initialize(pCallback, device, iChannels, uiSamplesPerSec, uiBitsPerSample, bResample, strAudioCodec, bIsMusic, bPassthrough);
+ audioSink->Initialize(pCallback, device, iChannels, channelMap, uiSamplesPerSec, uiBitsPerSample, bResample, strAudioCodec, bIsMusic, bPassthrough);
return audioSink;
}
Index: xbmc/cores/AudioRenderers/PulseAudioDirectSound.h
===================================================================
--- xbmc/cores/AudioRenderers/PulseAudioDirectSound.h (revision 26715)
+++ xbmc/cores/AudioRenderers/PulseAudioDirectSound.h (working copy)
@@ -47,7 +47,7 @@
virtual float GetCacheTime();
virtual float GetCacheTotal();
CPulseAudioDirectSound();
- virtual bool Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec = "", bool bIsMusic=false, bool bPassthrough = false);
+ virtual bool Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, uint8_t *channelMap, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec = "", bool bIsMusic=false, bool bPassthrough = false);
virtual ~CPulseAudioDirectSound();
virtual unsigned int AddPackets(const void* data, unsigned int len);
Index: xbmc/cores/AudioRenderers/NullDirectSound.h
===================================================================
--- xbmc/cores/AudioRenderers/NullDirectSound.h (revision 26715)
+++ xbmc/cores/AudioRenderers/NullDirectSound.h (working copy)
@@ -41,7 +41,7 @@
virtual float GetDelay();
virtual float GetCacheTime();
CNullDirectSound();
- virtual bool Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec = "", bool bIsMusic=false, bool bPassthrough = false);
+ virtual bool Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, uint8_t *channelMap, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec = "", bool bIsMusic=false, bool bPassthrough = false);
virtual ~CNullDirectSound();
virtual unsigned int AddPackets(const void* data, unsigned int len);
Index: xbmc/cores/AudioRenderers/ALSADirectSound.cpp
===================================================================
--- xbmc/cores/AudioRenderers/ALSADirectSound.cpp (revision 26715)
+++ xbmc/cores/AudioRenderers/ALSADirectSound.cpp (working copy)
@@ -47,8 +47,15 @@
m_bIsAllocated = false;
}
-bool CALSADirectSound::Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec, bool bIsMusic, bool bPassthrough)
+bool CALSADirectSound::Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, uint8_t *channelMap, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec, bool bIsMusic, bool bPassthrough)
{
+ static uint8_t ALSAChannelMap[8] = {
+ PCM_FRONT_LEFT , PCM_FRONT_RIGHT ,
+ PCM_BACK_LEFT , PCM_BACK_RIGHT ,
+ PCM_FRONT_CENTER, PCM_LOW_FREQUENCY,
+ PCM_SIDE_LEFT , PCM_SIDE_RIGHT
+ };
+
CStdString deviceuse;
CLog::Log(LOGDEBUG,"CALSADirectSound::CALSADirectSound - Channels: %i - SampleRate: %i - SampleBit: %i - Resample %s - Codec %s - IsMusic %s - IsPassthrough %s - audioDevice: %s", iChannels, uiSamplesPerSec, uiBitsPerSample, bResample ? "true" : "false", strAudioCodec, bIsMusic ? "true" : "false", bPassthrough ? "true" : "false", device.c_str());
@@ -56,6 +63,10 @@
if (iChannels == 0)
iChannels = 2;
+ /* setup the channel mapping */
+ m_remap.SetInputFormat (iChannels, channelMap, uiBitsPerSample / 8);
+ m_remap.SetOutputFormat(iChannels, ALSAChannelMap);
+
bool bAudioOnAllSpeakers(false);
g_audioContext.SetupSpeakerConfig(iChannels, bAudioOnAllSpeakers, bIsMusic);
g_audioContext.SetActiveDevice(CAudioContext::DIRECTSOUND_DEVICE);
@@ -124,6 +135,7 @@
|| deviceuse == "spdif")
deviceuse = "plug:" + deviceuse;
+/*
if(g_guiSettings.GetBool("audiooutput.downmixmultichannel"))
{
if(iChannels == 6)
@@ -133,6 +145,7 @@
}
else
{
+*/
if(deviceuse == "default")
{
if(iChannels == 6)
@@ -142,6 +155,7 @@
else if(iChannels == 4)
deviceuse = "surround40";
}
+/*
}
// setup channel mapping to linux default
@@ -167,7 +181,6 @@
deviceuse = "xbmc_ogg50:'" + EscapeDevice(deviceuse) + "'";
}
-
if(deviceuse != device)
{
snd_input_t* input;
@@ -186,6 +199,7 @@
deviceuse = device;
}
}
+*/
}
CLog::Log(LOGDEBUG, "%s - using alsa device %s", __FUNCTION__, deviceuse.c_str());
@@ -471,7 +485,14 @@
writeResult = snd_pcm_writei(m_pPlayHandle, dummy, framesToWrite);
}
else
- writeResult = snd_pcm_writei(m_pPlayHandle, pcmPtr, framesToWrite);
+ {
+ /* remap the data to the correct channels */
+ uint8_t outData[bytesToWrite];
+ m_remap.Remap((void*)pcmPtr, outData, framesToWrite);
+
+ /* write it out */
+ writeResult = snd_pcm_writei(m_pPlayHandle, outData, framesToWrite);
+ }
if ( writeResult == -EPIPE ) {
CLog::Log(LOGDEBUG, "CALSADirectSound::AddPackets - buffer underun (tried to write %d frames)",
framesToWrite);
Index: xbmc/cores/AudioRenderers/AudioRendererFactory.h
===================================================================
--- xbmc/cores/AudioRenderers/AudioRendererFactory.h (revision 26715)
+++ xbmc/cores/AudioRenderers/AudioRendererFactory.h (working copy)
@@ -31,7 +31,7 @@
class CAudioRendererFactory
{
public:
- static IAudioRenderer *Create(IAudioCallback* pCallback, int iChannels, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec, bool bIsMusic, bool bPassthrough);
+ static IAudioRenderer *Create(IAudioCallback* pCallback, int iChannels, uint8_t *channelMap, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec, bool bIsMusic, bool bPassthrough);
static void EnumerateAudioSinks(AudioSinkList& vAudioSinks, bool passthrough);
private:
static IAudioRenderer *CreateFromUri(const CStdString &soundsystem);
Index: xbmc/cores/AudioRenderers/ALSADirectSound.h
===================================================================
--- xbmc/cores/AudioRenderers/ALSADirectSound.h (revision 26715)
+++ xbmc/cores/AudioRenderers/ALSADirectSound.h (working copy)
@@ -51,7 +51,7 @@
virtual float GetCacheTime();
virtual float GetCacheTotal();
CALSADirectSound();
- virtual bool Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec = "", bool bIsMusic=false, bool bPassthrough = false);
+ virtual bool Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, uint8_t *channelMap, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec = "", bool bIsMusic=false, bool bPassthrough = false);
virtual ~CALSADirectSound();
virtual unsigned int AddPackets(const void* data, unsigned int len);
Index: xbmc/cores/paplayer/PAPlayer.h
===================================================================
--- xbmc/cores/paplayer/PAPlayer.h (revision 26715)
+++ xbmc/cores/paplayer/PAPlayer.h (working copy)
@@ -166,6 +166,7 @@
unsigned int m_SampleRate;
unsigned int m_Channels;
+ uint8_t* m_ChannelMap;
unsigned int m_BitsPerSample;
unsigned int m_SampleRateOutput;
@@ -179,6 +180,7 @@
// format (this should be stored/retrieved from the audio device object probably)
unsigned int m_channelCount[2];
+ uint8_t* m_channelMap[2];
unsigned int m_sampleRate[2];
unsigned int m_bitsPerSample[2];
unsigned int m_BytesPerSecond;
Index: xbmc/cores/paplayer/PAPlayer.cpp
===================================================================
--- xbmc/cores/paplayer/PAPlayer.cpp (revision 26715)
+++ xbmc/cores/paplayer/PAPlayer.cpp (working copy)
@@ -372,7 +372,7 @@
m_BytesPerSecond = (m_bitsPerSample[num] / 8)* outputSampleRate * channels;
/* Open the device */
- m_pAudioDecoder[num] = CAudioRendererFactory::Create(m_pCallback, m_channelCount[num], m_sampleRate[num], m_bitsPerSample[num], false, codec.c_str(), true, false);
+ m_pAudioDecoder[num] = CAudioRendererFactory::Create(m_pCallback, m_channelCount[num], m_channelMap[num], m_sampleRate[num], m_bitsPerSample[num], false, codec.c_str(), true, false);
if (!m_pAudioDecoder[num]) return false;
Index: xbmc/utils/Makefile
===================================================================
--- xbmc/utils/Makefile (revision 26715)
+++ xbmc/utils/Makefile (working copy)
@@ -32,6 +32,7 @@
Win32Exception.cpp \
CPUInfo.cpp \
PCMAmplifier.cpp \
+ PCMRemap.cpp \
LabelFormatter.cpp \
Network.cpp \
BitstreamStats.cpp \