rendered paste bodyIndex: xbmc/cores/dvdplayer/DVDAudio.cpp
===================================================================
--- xbmc/cores/dvdplayer/DVDAudio.cpp (revision 26651)
+++ 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 26651)
+++ 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/DVDAudioCodecLiba52.h
===================================================================
--- xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLiba52.h (revision 26651)
+++ 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 26651)
+++ 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/DVDAudioCodecFFmpeg.cpp
===================================================================
--- xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.cpp (revision 26651)
+++ xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.cpp (working copy)
@@ -78,6 +78,7 @@
m_pCodecContext->block_align = hints.blockalign;
m_pCodecContext->bit_rate = hints.bitrate;
m_pCodecContext->bits_per_coded_sample = hints.bitspersample;
+ m_pCodecContext->request_channel_layout = CH_LAYOUT_NATIVE;
if(m_pCodecContext->bits_per_coded_sample == 0)
m_pCodecContext->bits_per_coded_sample = 16;
@@ -218,6 +219,11 @@
return 0;
}
+uint8_t* CDVDAudioCodecFFmpeg::GetChannelMap()
+{
+
+}
+
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 26651)
+++ 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 26651)
+++ 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 26651)
+++ 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,56 @@
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[18][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(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 +280,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/DVDPlayerAudio.h
===================================================================
--- xbmc/cores/dvdplayer/DVDPlayerAudio.h (revision 26651)
+++ 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 26651)
+++ 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/NullDirectSound.cpp
===================================================================
--- xbmc/cores/AudioRenderers/NullDirectSound.cpp (revision 26651)
+++ 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/PulseAudioDirectSound.cpp
===================================================================
--- xbmc/cores/AudioRenderers/PulseAudioDirectSound.cpp (revision 26651)
+++ 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/AudioRendererFactory.cpp
===================================================================
--- xbmc/cores/AudioRenderers/AudioRendererFactory.cpp (revision 26651)
+++ 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/NullDirectSound.h
===================================================================
--- xbmc/cores/AudioRenderers/NullDirectSound.h (revision 26651)
+++ 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/PulseAudioDirectSound.h
===================================================================
--- xbmc/cores/AudioRenderers/PulseAudioDirectSound.h (revision 26651)
+++ 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/ALSADirectSound.cpp
===================================================================
--- xbmc/cores/AudioRenderers/ALSADirectSound.cpp (revision 26651)
+++ xbmc/cores/AudioRenderers/ALSADirectSound.cpp (working copy)
@@ -37,6 +37,13 @@
return result;
}
+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
+};
+
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
@@ -47,7 +54,7 @@
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)
{
CStdString deviceuse;
@@ -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);
@@ -471,7 +482,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 26651)
+++ 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 26651)
+++ 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 26651)
+++ 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 26651)
+++ 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/PCMRemap.h
===================================================================
--- xbmc/utils/PCMRemap.h (revision 0)
+++ xbmc/utils/PCMRemap.h (revision 0)
@@ -0,0 +1,65 @@
+#ifndef __PCM_REMAP__H__
+#define __PCM_REMAP__H__
+
+/*
+ * Copyright (C) 2005-2010 Team XBMC
+ * http://www.xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include <stdint.h>
+
+#define PCM_FRONT_LEFT 0
+#define PCM_FRONT_RIGHT 1
+#define PCM_FRONT_CENTER 2
+#define PCM_LOW_FREQUENCY 3
+#define PCM_BACK_LEFT 4
+#define PCM_BACK_RIGHT 5
+#define PCM_FRONT_LEFT_OF_CENTER 6
+#define PCM_FRONT_RIGHT_OF_CENTER 7
+#define PCM_BACK_CENTER 8
+#define PCM_SIDE_LEFT 9
+#define PCM_SIDE_RIGHT 10
+#define PCM_TOP_CENTER 11
+#define PCM_TOP_FRONT_LEFT 12
+#define PCM_TOP_FRONT_CENTER 13
+#define PCM_TOP_FRONT_RIGHT 14
+#define PCM_TOP_BACK_LEFT 15
+#define PCM_TOP_BACK_CENTER 16
+#define PCM_TOP_BACK_RIGHT 17
+
+class CPCMRemap
+{
+protected:
+ bool m_inSet , m_outSet;
+ uint8_t m_inChannels, m_outChannels;
+ uint8_t *m_inMap , *m_outMap;
+ uint8_t m_inSampleSize;
+ uint8_t *m_chLookup;
+
+ void BuildMap();
+public:
+ CPCMRemap();
+ ~CPCMRemap();
+
+ void SetInputFormat (uint8_t channels, uint8_t *channelMap, uint8_t sampleSize);
+ void SetOutputFormat(uint8_t channels, uint8_t *channelMap);
+ void Remap(void *data, void *out, unsigned int samples);
+};
+
+#endif
Index: xbmc/utils/PCMRemap.cpp
===================================================================
--- xbmc/utils/PCMRemap.cpp (revision 0)
+++ xbmc/utils/PCMRemap.cpp (revision 0)
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2005-2010 Team XBMC
+ * http://www.xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include "PCMRemap.h"
+#include <cstdlib>
+#include <string.h>
+#include <stdio.h>
+
+CPCMRemap::CPCMRemap() :
+ m_inSet (false),
+ m_outSet (false),
+ m_chLookup(NULL )
+{
+}
+
+CPCMRemap::~CPCMRemap()
+{
+ if (m_chLookup != NULL)
+ free(m_chLookup);
+}
+
+/*
+ builds a lookup table to convert from the input mapping to the output
+ mapping, this decreases the amount of work per sample to remap it.
+*/
+void CPCMRemap::BuildMap()
+{
+ unsigned int in_ch, out_ch;
+
+ if (!m_inSet || !m_outSet) return;
+ if (m_chLookup != NULL)
+ {
+ free(m_chLookup);
+ m_chLookup = NULL;
+ }
+
+ m_chLookup = (uint8_t*)malloc(m_inChannels);
+ for(in_ch = 0; in_ch < m_inChannels; ++in_ch)
+ {
+ for(out_ch = 0; out_ch < m_outChannels; ++out_ch)
+ {
+ if (m_outMap[out_ch] == m_inMap[in_ch])
+ {
+ m_chLookup[in_ch] = out_ch;
+ break;
+ }
+ }
+ }
+
+}
+
+/* sets the input format */
+void CPCMRemap::SetInputFormat(uint8_t channels, uint8_t *channelMap, uint8_t sampleSize)
+{
+ m_inChannels = channels;
+ m_inMap = channelMap;
+ m_inSampleSize = sampleSize;
+ m_inSet = true;
+
+ BuildMap();
+}
+
+/* sets the output format required */
+void CPCMRemap::SetOutputFormat(uint8_t channels, uint8_t *channelMap)
+{
+ m_outChannels = channels;
+ m_outMap = channelMap;
+ m_outSet = true;
+
+ BuildMap();
+}
+
+/* remap the supplied data into out, which must be pre-allocated */
+void CPCMRemap::Remap(void *data, void *out, unsigned int samples)
+{
+ unsigned int i, ch;
+ uint8_t *insample, *outsample;
+ uint8_t *src, *dst;
+
+ insample = (uint8_t*)data;
+ outsample = (uint8_t*)out;
+
+ /*
+ the output may have channels the input does not have, so zero the data
+ to stop random data being sent to them, it would be nice to add a
+ up/down mixer to this class to emulate the missing channels, anyone?.
+ */
+ memset(out, 0, m_inSampleSize * m_outChannels);
+
+ for(i = 0; i < samples; ++i)
+ {
+ for(ch = 0; ch < m_inChannels; ++ch)
+ {
+ if (m_chLookup[ch] != ch)
+ {
+ src = insample + m_chLookup[ch] * m_inSampleSize;
+ dst = outsample + ch * m_inSampleSize;
+ memcpy(dst, src, m_inSampleSize);
+ }
+ }
+ insample += m_inSampleSize * m_inChannels;
+ outsample += m_inSampleSize * m_outChannels;
+ }
+}
+
Index: xbmc/utils/Makefile
===================================================================
--- xbmc/utils/Makefile (revision 26657)
+++ xbmc/utils/Makefile (working copy)
@@ -32,6 +32,7 @@
Win32Exception.cpp \
CPUInfo.cpp \
PCMAmplifier.cpp \
+ PCMRemap.cpp \
LabelFormatter.cpp \
Network.cpp \
BitstreamStats.cpp \