aboutsummaryrefslogtreecommitdiff
path: root/src/plugins
diff options
context:
space:
mode:
authortrialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38>2014-10-06 07:50:56 +0000
committertrialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38>2014-10-06 07:50:56 +0000
commit76f436c36cdec74e73c12cea8d81051a7d75ec96 (patch)
tree03fe155b5311f6dccbf0dfb2a9cb0954484a138c /src/plugins
parent67e825df80708f31daf7a4f4cd6045ecf010efa6 (diff)
downloadqmmp-76f436c36cdec74e73c12cea8d81051a7d75ec96.tar.gz
qmmp-76f436c36cdec74e73c12cea8d81051a7d75ec96.tar.bz2
qmmp-76f436c36cdec74e73c12cea8d81051a7d75ec96.zip
added multichannel support
git-svn-id: http://svn.code.sf.net/p/qmmp-dev/code/trunk/qmmp@4530 90c681e8-e032-0410-971d-27865f9a5e38
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/Effect/Effect.pro6
-rw-r--r--src/plugins/Effect/srconverter/srconverter.cpp8
-rw-r--r--src/plugins/Effect/srconverter/srconverter.h4
-rw-r--r--src/plugins/Input/Input.pro28
-rw-r--r--src/plugins/Input/flac/decoder_flac.cpp77
-rw-r--r--src/plugins/Input/flac/decoder_flac.h1
-rw-r--r--src/plugins/Input/mad/decoder_mad.cpp7
-rw-r--r--src/plugins/Output/Output.pro10
-rw-r--r--src/plugins/Output/alsa/outputalsa.cpp44
-rw-r--r--src/plugins/Output/alsa/outputalsa.h9
10 files changed, 155 insertions, 39 deletions
diff --git a/src/plugins/Effect/Effect.pro b/src/plugins/Effect/Effect.pro
index 336647a4b..b073f08f3 100644
--- a/src/plugins/Effect/Effect.pro
+++ b/src/plugins/Effect/Effect.pro
@@ -1,15 +1,15 @@
include (../../../qmmp.pri)
TEMPLATE = subdirs
-SUBDIRS += crossfade stereo
+#SUBDIRS += crossfade stereo
contains(CONFIG, BS2B_PLUGIN){
-SUBDIRS += bs2b
+#SUBDIRS += bs2b
}
unix {
SUBDIRS += srconverter
contains(CONFIG, LADSPA_PLUGIN){
- SUBDIRS += ladspa
+# SUBDIRS += ladspa
}
}
diff --git a/src/plugins/Effect/srconverter/srconverter.cpp b/src/plugins/Effect/srconverter/srconverter.cpp
index fcd77bc04..324dbb051 100644
--- a/src/plugins/Effect/srconverter/srconverter.cpp
+++ b/src/plugins/Effect/srconverter/srconverter.cpp
@@ -1,5 +1,5 @@
/***************************************************************************
- * Copyright (C) 2007-2013 by Ilya Kotov *
+ * Copyright (C) 2007-2014 by Ilya Kotov *
* forkotov02@hotmail.ru *
* *
* This program is free software; you can redistribute it and/or modify *
@@ -115,12 +115,12 @@ void SRConverter::applyEffect(Buffer *b)
}
}
-void SRConverter::configure(quint32 freq, int chan, Qmmp::AudioFormat format)
+void SRConverter::configure(quint32 freq, ChannelMap map, Qmmp::AudioFormat format)
{
freeSRC();
if(freq != m_overSamplingFs && format != Qmmp::PCM_S8)
{
- m_src_state = src_new(m_converter_type, chan, &m_srcError);
+ m_src_state = src_new(m_converter_type, map.count(), &m_srcError);
if (m_src_state)
{
m_src_data.src_ratio = (float)m_overSamplingFs/(float)freq;
@@ -129,7 +129,7 @@ void SRConverter::configure(quint32 freq, int chan, Qmmp::AudioFormat format)
else
qDebug("SRConverter: src_new(): %s", src_strerror(m_srcError));
}
- Effect::configure(m_overSamplingFs, chan, format);
+ Effect::configure(m_overSamplingFs, map, format);
m_sz = audioParameters().sampleSize();
}
diff --git a/src/plugins/Effect/srconverter/srconverter.h b/src/plugins/Effect/srconverter/srconverter.h
index f25ebc491..b214c866f 100644
--- a/src/plugins/Effect/srconverter/srconverter.h
+++ b/src/plugins/Effect/srconverter/srconverter.h
@@ -1,5 +1,5 @@
/***************************************************************************
- * Copyright (C) 2007-2013 by Ilya Kotov *
+ * Copyright (C) 2007-2014 by Ilya Kotov *
* forkotov02@hotmail.ru *
* *
* This program is free software; you can redistribute it and/or modify *
@@ -34,7 +34,7 @@ public:
virtual ~SRConverter();
void applyEffect(Buffer *b);
- void configure(quint32 freq, int chan, Qmmp::AudioFormat format);
+ void configure(quint32 freq, ChannelMap map, Qmmp::AudioFormat format);
private:
void freeSRC();
diff --git a/src/plugins/Input/Input.pro b/src/plugins/Input/Input.pro
index 9b00864e6..0149aa949 100644
--- a/src/plugins/Input/Input.pro
+++ b/src/plugins/Input/Input.pro
@@ -1,53 +1,53 @@
include(../../../qmmp.pri)
-SUBDIRS += mad cue vorbis sndfile wavpack
TEMPLATE = subdirs
+SUBDIRS += mad #cue vorbis sndfile wavpack
contains(CONFIG, FLAC_PLUGIN){
SUBDIRS += flac
}
contains(CONFIG, MUSEPACK_PLUGIN){
- SUBDIRS += mpc
+# SUBDIRS += mpc
}
contains(CONFIG, MODPLUG_PLUGIN){
- SUBDIRS += modplug
+# SUBDIRS += modplug
}
contains(CONFIG, FFMPEG_PLUGIN){
- contains(CONFIG, FFMPEG_LEGACY){
- SUBDIRS += ffmpeg_legacy
- }else{
- SUBDIRS += ffmpeg
- }
+# contains(CONFIG, FFMPEG_LEGACY){
+# SUBDIRS += ffmpeg_legacy
+# }else{
+# SUBDIRS += ffmpeg
+# }
}
contains(CONFIG, GME_PLUGIN){
- SUBDIRS += gme
+# SUBDIRS += gme
}
contains(CONFIG, OPUS_PLUGIN){
- SUBDIRS += opus
+# SUBDIRS += opus
}
contains(CONFIG, CDAUDIO_PLUGIN){
- SUBDIRS += cdaudio
+# SUBDIRS += cdaudio
}
contains(CONFIG, SID_PLUGIN){
- SUBDIRS += sid
+# SUBDIRS += sid
}
unix{
contains(CONFIG, AAC_PLUGIN){
- SUBDIRS += aac
+# SUBDIRS += aac
}
contains(CONFIG, WILDMIDI_PLUGIN){
- SUBDIRS += wildmidi
+# SUBDIRS += wildmidi
}
diff --git a/src/plugins/Input/flac/decoder_flac.cpp b/src/plugins/Input/flac/decoder_flac.cpp
index acd76f159..4dfca6839 100644
--- a/src/plugins/Input/flac/decoder_flac.cpp
+++ b/src/plugins/Input/flac/decoder_flac.cpp
@@ -393,17 +393,25 @@ bool DecoderFLAC::initialize()
data()->ok = 0;
return false;
}
+ ChannelMap channel_map = findChannelMap(data()->channels);
+
+ if(channel_map.isEmpty())
+ {
+ qWarning("DecoderFLAC: unsupported number of channels: %d", data()->channels);
+ return false;
+ }
+
switch(data()->bits_per_sample)
{
case 8:
- configure(data()->sample_rate, data()->channels, Qmmp::PCM_S8);
+ configure(data()->sample_rate, channel_map, Qmmp::PCM_S8);
break;
case 16:
- configure(data()->sample_rate, data()->channels, Qmmp::PCM_S16LE);
+ configure(data()->sample_rate, channel_map, Qmmp::PCM_S16LE);
break;
case 24:
case 32:
- configure(data()->sample_rate, data()->channels, Qmmp::PCM_S32LE);
+ configure(data()->sample_rate, channel_map, Qmmp::PCM_S32LE);
break;
default:
return false;
@@ -555,3 +563,66 @@ uint DecoderFLAC::findID3v2(char *data, ulong size) //retuns ID3v2 tag size
}
return 0;
}
+
+ChannelMap DecoderFLAC::findChannelMap(int channels)
+{
+ ChannelMap map;
+ switch (channels)
+ {
+ case 1:
+ map << Qmmp::CHAN_FRONT_LEFT;
+ break;
+ case 2:
+ map << Qmmp::CHAN_FRONT_LEFT
+ << Qmmp::CHAN_FRONT_RIGHT;
+ break;
+ case 3:
+ map << Qmmp::CHAN_FRONT_LEFT
+ << Qmmp::CHAN_FRONT_RIGHT
+ << Qmmp::CHAN_FRONT_CENTER;
+ break;
+ case 4:
+ map << Qmmp::CHAN_FRONT_LEFT
+ << Qmmp::CHAN_FRONT_RIGHT
+ << Qmmp::CHAN_REAR_LEFT
+ << Qmmp::CHAN_REAR_RIGHT;
+ break;
+ case 5:
+ map << Qmmp::CHAN_FRONT_LEFT
+ << Qmmp::CHAN_FRONT_RIGHT
+ << Qmmp::CHAN_FRONT_CENTER
+ << Qmmp::CHAN_REAR_LEFT
+ << Qmmp::CHAN_REAR_RIGHT;
+ break;
+ case 6:
+ map << Qmmp::CHAN_FRONT_LEFT
+ << Qmmp::CHAN_FRONT_RIGHT
+ << Qmmp::CHAN_FRONT_CENTER
+ << Qmmp::CHAN_LFE
+ << Qmmp::CHAN_REAR_LEFT
+ << Qmmp::CHAN_REAR_RIGHT;
+ break;
+ case 7:
+ map << Qmmp::CHAN_FRONT_LEFT
+ << Qmmp::CHAN_FRONT_RIGHT
+ << Qmmp::CHAN_FRONT_CENTER
+ << Qmmp::CHAN_LFE
+ << Qmmp::CHAN_REAR_CENTER
+ << Qmmp::CHAN_SIDE_LEFT
+ << Qmmp::CHAN_SIDE_RIGHT;
+ break;
+ case 8:
+ map << Qmmp::CHAN_FRONT_LEFT
+ << Qmmp::CHAN_FRONT_RIGHT
+ << Qmmp::CHAN_FRONT_CENTER
+ << Qmmp::CHAN_LFE
+ << Qmmp::CHAN_REAR_LEFT
+ << Qmmp::CHAN_REAR_RIGHT
+ << Qmmp::CHAN_SIDE_LEFT
+ << Qmmp::CHAN_SIDE_RIGHT;
+ break;
+ default:
+ ;
+ }
+ return map;
+}
diff --git a/src/plugins/Input/flac/decoder_flac.h b/src/plugins/Input/flac/decoder_flac.h
index e64e376eb..4b4a2f668 100644
--- a/src/plugins/Input/flac/decoder_flac.h
+++ b/src/plugins/Input/flac/decoder_flac.h
@@ -82,6 +82,7 @@ private:
// helper functions
void deinit();
uint findID3v2(char *data, ulong size); //retuns ID3v2 tag size
+ ChannelMap findChannelMap(int channels);
struct flac_data *m_data;
qint64 length_in_bytes;
diff --git a/src/plugins/Input/mad/decoder_mad.cpp b/src/plugins/Input/mad/decoder_mad.cpp
index b4087c06b..08b2486fb 100644
--- a/src/plugins/Input/mad/decoder_mad.cpp
+++ b/src/plugins/Input/mad/decoder_mad.cpp
@@ -120,7 +120,12 @@ bool DecoderMAD::initialize()
mad_frame_mute (&m_frame);
m_stream.next_frame = 0;
m_stream.sync = 0;
- configure(m_freq, m_channels, Qmmp::PCM_S16LE);
+ ChannelMap map;
+ if(m_channels == 1)
+ map << Qmmp::CHAN_FRONT_LEFT;
+ else
+ map << Qmmp::CHAN_FRONT_LEFT << Qmmp::CHAN_FRONT_RIGHT;
+ configure(m_freq, map, Qmmp::PCM_S16LE);
m_inited = true;
return true;
}
diff --git a/src/plugins/Output/Output.pro b/src/plugins/Output/Output.pro
index d07513257..7dc1f0ddb 100644
--- a/src/plugins/Output/Output.pro
+++ b/src/plugins/Output/Output.pro
@@ -4,20 +4,20 @@ TEMPLATE = subdirs
win32:SUBDIRS += waveout
win32:SUBDIRS += directsound
-SUBDIRS += null
+#SUBDIRS += null
unix{
contains(CONFIG, JACK_PLUGIN){
- SUBDIRS += jack
+# SUBDIRS += jack
}
contains(CONFIG, OSS_PLUGIN){
- SUBDIRS += oss
+# SUBDIRS += oss
}
contains(CONFIG, PULSE_AUDIO_PLUGIN){
- SUBDIRS += pulseaudio
+# SUBDIRS += pulseaudio
}
contains(CONFIG, ALSA_PLUGIN){
@@ -25,7 +25,7 @@ contains(CONFIG, ALSA_PLUGIN){
}
contains(CONFIG, OSS4_PLUGIN){
- SUBDIRS += oss4
+# SUBDIRS += oss4
}
}
diff --git a/src/plugins/Output/alsa/outputalsa.cpp b/src/plugins/Output/alsa/outputalsa.cpp
index 5774579f5..f12f02060 100644
--- a/src/plugins/Output/alsa/outputalsa.cpp
+++ b/src/plugins/Output/alsa/outputalsa.cpp
@@ -44,6 +44,18 @@ OutputALSA::OutputALSA() : m_inited(false)
m_prebuf_size = 0;
m_prebuf_fill = 0;
m_can_pause = false;
+
+ m_alsa_channels[SND_CHMAP_NA] = Qmmp::CHAN_NULL;
+ m_alsa_channels[SND_CHMAP_MONO] = Qmmp::CHAN_FRONT_CENTER;
+ m_alsa_channels[SND_CHMAP_FL] = Qmmp::CHAN_FRONT_LEFT;
+ m_alsa_channels[SND_CHMAP_FR] = Qmmp::CHAN_FRONT_RIGHT;
+ m_alsa_channels[SND_CHMAP_RL] = Qmmp::CHAN_REAR_LEFT;
+ m_alsa_channels[SND_CHMAP_RR] = Qmmp::CHAN_REAR_RIGHT;
+ m_alsa_channels[SND_CHMAP_FC] = Qmmp::CHAN_FRONT_CENTER;
+ m_alsa_channels[SND_CHMAP_LFE] = Qmmp::CHAN_LFE;
+ m_alsa_channels[SND_CHMAP_SL] = Qmmp::CHAN_SIDE_LEFT;
+ m_alsa_channels[SND_CHMAP_SR] = Qmmp::CHAN_SIDE_RIGHT;
+ m_alsa_channels[SND_CHMAP_RC] = Qmmp::CHAN_REAR_CENTER;
}
OutputALSA::~OutputALSA()
@@ -52,7 +64,7 @@ OutputALSA::~OutputALSA()
free (pcm_name);
}
-bool OutputALSA::initialize(quint32 freq, int chan, Qmmp::AudioFormat format)
+bool OutputALSA::initialize(quint32 freq, ChannelMap map, Qmmp::AudioFormat format)
{
m_inited = false;
@@ -141,12 +153,17 @@ bool OutputALSA::initialize(quint32 freq, int chan, Qmmp::AudioFormat format)
qWarning("OutputALSA: The rate %d Hz is not supported by your hardware.\n==> Using %d Hz instead.", rate, exact_rate);
rate = exact_rate;
}
- uint c = chan;
+ uint c = map.count();
if ((err = snd_pcm_hw_params_set_channels_near(pcm_handle, hwparams, &c)) < 0)
{
qWarning("OutputALSA: Error setting channels: %s", snd_strerror(err));
return false;
}
+ if (c != (uint)map.count())
+ {
+ qWarning("OutputALSA: The channel number %d is not supported by your hardware", map.count());
+ qWarning("==> Using %d instead.", c);
+ }
if ((err = snd_pcm_hw_params_set_period_time_near(pcm_handle, hwparams, &period_time ,0)) < 0)
{
qWarning("OutputALSA: Error setting period time: %s", snd_strerror(err));
@@ -190,11 +207,30 @@ bool OutputALSA::initialize(quint32 freq, int chan, Qmmp::AudioFormat format)
m_chunk_size = period_size;
m_can_pause = snd_pcm_hw_params_can_pause(hwparams) && use_pause;
qDebug("OutputALSA: can pause: %d", m_can_pause);
- configure(rate, chan, format); //apply configuration
+
+ //channel map configuration
+ snd_pcm_chmap_t *chmap = snd_pcm_get_chmap(pcm_handle);
+ if(!chmap)
+ {
+ qWarning("OutputALSA: Unable to receive current channel map: %s", snd_strerror(err));
+ return false;
+ }
+ char tmp[256];
+ memset(tmp,0,256);
+ snd_pcm_chmap_print(chmap, 256, tmp);
+ qDebug("OutputALSA: received channel map: %s",tmp);
+ ChannelMap out_map;
+ for(uint i = 0; i < chmap->channels; ++i)
+ {
+ if(m_alsa_channels.keys().contains(chmap->pos[i]))
+ out_map.append(m_alsa_channels.value(chmap->pos[i]));
+ else
+ out_map.append(Qmmp::CHAN_NULL);
+ }
+ configure(exact_rate, out_map, format); //apply configuration
//create alsa prebuffer;
m_prebuf_size = 2 * snd_pcm_frames_to_bytes(pcm_handle, m_chunk_size); //buffer for two periods
m_prebuf = (uchar *)malloc(m_prebuf_size);
-
m_inited = true;
return true;
}
diff --git a/src/plugins/Output/alsa/outputalsa.h b/src/plugins/Output/alsa/outputalsa.h
index 1600e3b29..d378b813c 100644
--- a/src/plugins/Output/alsa/outputalsa.h
+++ b/src/plugins/Output/alsa/outputalsa.h
@@ -18,8 +18,8 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
-#ifndef OUTPUTALSA_H
-#define OUTPUTALSA_H
+#ifndef OUTPUTALSA_H
+#define OUTPUTALSA_H
class OutputALSA;
@@ -28,6 +28,7 @@ extern "C"
#include <alsa/asoundlib.h>
}
+#include <QHash>
#include <qmmp/output.h>
#include <qmmp/volume.h>
@@ -38,7 +39,7 @@ public:
OutputALSA();
~OutputALSA();
- bool initialize(quint32, int, Qmmp::AudioFormat format);
+ bool initialize(quint32, ChannelMap map, Qmmp::AudioFormat format);
//output api
qint64 latency();
qint64 writeAudio(unsigned char *data, qint64 maxSize);
@@ -63,6 +64,8 @@ private:
qint64 m_prebuf_size;
qint64 m_prebuf_fill;
bool m_can_pause;
+ //channel conversions
+ QHash <quint16, Qmmp::ChannelPosition> m_alsa_channels;
};
class VolumeALSA : public Volume