aboutsummaryrefslogtreecommitdiff
path: root/src/qmmp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qmmp')
-rw-r--r--src/qmmp/buffer.h10
-rw-r--r--src/qmmp/output.cpp27
-rw-r--r--src/qmmp/output.h4
-rw-r--r--src/qmmp/qmmpaudioengine.cpp17
-rw-r--r--src/qmmp/qmmpaudioengine.h2
-rw-r--r--src/qmmp/qmmpsettings.cpp13
-rw-r--r--src/qmmp/qmmpsettings.h19
-rw-r--r--src/qmmp/recycler.cpp100
-rw-r--r--src/qmmp/recycler.h26
9 files changed, 143 insertions, 75 deletions
diff --git a/src/qmmp/buffer.h b/src/qmmp/buffer.h
index 910615f1f..161af5692 100644
--- a/src/qmmp/buffer.h
+++ b/src/qmmp/buffer.h
@@ -7,8 +7,7 @@
#ifndef __buffer_h
#define __buffer_h
-#define QMMP_BLOCK_SIZE (2048*6) //512*4*6
-#define QMMP_BUFFER_SIZE (QMMP_BLOCK_SIZE*32)
+#define QMMP_BLOCK_FRAMES 512
/*! @brief Audio buffer class.
* @author Brad Hughes <bhughes@trolltech.com>
@@ -18,13 +17,14 @@ class Buffer
public:
/*!
* Constructs an empty buffer object.
+ * @param sz Size in bytes;
*/
- Buffer()
+ Buffer(unsigned long sz)
{
- data = new unsigned char[QMMP_BLOCK_SIZE];
+ data = new unsigned char[sz];
nbytes = 0;
rate = 0;
- size = QMMP_BLOCK_SIZE;
+ size = sz;
}
/*!
* Destructor.
diff --git a/src/qmmp/output.cpp b/src/qmmp/output.cpp
index b81f2d708..c8b4f3758 100644
--- a/src/qmmp/output.cpp
+++ b/src/qmmp/output.cpp
@@ -39,7 +39,7 @@ static inline void s32_to_s16(qint32 *in, qint16 *out, qint64 samples)
return;
}
-Output::Output (QObject* parent) : QThread (parent), m_recycler (QMMP_BUFFER_SIZE)
+Output::Output (QObject* parent) : QThread (parent)
{
m_handler = StateHandler::instance();
m_frequency = 0;
@@ -68,25 +68,15 @@ void Output::configure(quint32 freq, int chan, Qmmp::AudioFormat format)
formatNames.insert(Qmmp::PCM_S16LE, "s16le");
formatNames.insert(Qmmp::PCM_S24LE, "s24le");
formatNames.insert(Qmmp::PCM_S32LE, "s32le");
- qDebug("Output: %d Hz, %d ch, %s", freq, chan, qPrintable(formatNames.value(format)));
+ qDebug("Output: [%s] %d Hz, %d ch, %s", qPrintable(Output::currentFactory()->properties().shortName),
+ freq, chan, qPrintable(formatNames.value(format)));
m_bytesPerMillisecond = freq * chan * AudioParameters::sampleSize(format) / 1000;
+ m_recycler.configure(freq, chan, format); //calculate output buffer size
//visual buffer
if(m_visBuffer)
- {
delete [] m_visBuffer;
- m_visBuffer = 0;
- m_visBufferSize = 0;
- }
- if(format == Qmmp::PCM_S8)
- {
- m_visBufferSize = QMMP_BLOCK_SIZE * 2;
- m_visBuffer = new unsigned char [m_visBufferSize];
- }
- else if(format == Qmmp::PCM_S24LE || format == Qmmp::PCM_S32LE)
- {
- m_visBufferSize = QMMP_BLOCK_SIZE / 2;
- m_visBuffer = new unsigned char [m_visBufferSize];
- }
+ m_visBufferSize = QMMP_BLOCK_FRAMES * 2 * chan; //16-bit samples
+ m_visBuffer = new unsigned char [m_visBufferSize];
}
void Output::pause()
@@ -160,6 +150,11 @@ int Output::sampleSize() const
return AudioParameters::sampleSize(m_format);
}
+qint64 Output::bufferSize() const
+{
+ return m_recycler.size();
+}
+
void Output::suspend()
{}
diff --git a/src/qmmp/output.h b/src/qmmp/output.h
index 088de8779..4947b0d5b 100644
--- a/src/qmmp/output.h
+++ b/src/qmmp/output.h
@@ -115,6 +115,10 @@ public:
*/
int sampleSize() const;
/*!
+ * Returns buffer size in bytes.
+ */
+ qint64 bufferSize() const;
+ /*!
* Creates selected output.
* @param parent Parent object.
* @return Output subclass object.
diff --git a/src/qmmp/qmmpaudioengine.cpp b/src/qmmp/qmmpaudioengine.cpp
index 03baaed0c..25f872951 100644
--- a/src/qmmp/qmmpaudioengine.cpp
+++ b/src/qmmp/qmmpaudioengine.cpp
@@ -42,9 +42,10 @@ QmmpAudioEngine::QmmpAudioEngine(QObject *parent)
: AbstractEngine(parent), m_factory(0), m_output(0),
m_useEq(false), m_eqEnabled(false)
{
- m_output_buf = new unsigned char[QMMP_BUFFER_SIZE];
qRegisterMetaType<Qmmp::State>("Qmmp::State");
- m_bks = QMMP_BLOCK_SIZE;
+ m_output_buf = 0;
+ m_output_size = 0;
+ m_bks = 0;
m_decoder = 0;
m_output = 0;
m_replayGain = new ReplayGain;
@@ -289,9 +290,9 @@ void QmmpAudioEngine::stop()
qint64 QmmpAudioEngine::produceSound(char *data, qint64 size, quint32 brate, int chan)
{
+ Buffer *b = m_output->recycler()->get();
uint sz = size < m_bks ? size : m_bks;
m_replayGain->applyReplayGain(data, sz);
- Buffer *b = m_output->recycler()->get();
memcpy(b->data, data, sz);
b->nbytes = sz;
b->rate = brate;
@@ -380,8 +381,7 @@ void QmmpAudioEngine::run()
m_output_at = 0;
}
- len = m_decoder->read((char *)(m_output_buf + m_output_at),
- QMMP_BUFFER_SIZE - m_output_at);
+ len = m_decoder->read((char *)(m_output_buf + m_output_at), m_output_size - m_output_at);
if (len > 0)
{
@@ -442,7 +442,7 @@ void QmmpAudioEngine::run()
delete m_output;
m_output = createOutput();
if(m_output)
- {
+ {
m_output->start();
sendMetaData();
addOffset(); //offset
@@ -570,6 +570,11 @@ Output *QmmpAudioEngine::createOutput()
return false;
}
output->configure(m_ap.sampleRate(), m_ap.channels(), m_ap.format());
+ if(m_output_buf)
+ delete [] m_output_buf;
+ m_bks = QMMP_BLOCK_FRAMES * m_ap.channels() * m_ap.sampleSize();
+ m_output_size = m_bks * 4;
+ m_output_buf = new unsigned char[m_output_size];
return output;
}
diff --git a/src/qmmp/qmmpaudioengine.h b/src/qmmp/qmmpaudioengine.h
index bf924e5fa..537c7dc5e 100644
--- a/src/qmmp/qmmpaudioengine.h
+++ b/src/qmmp/qmmpaudioengine.h
@@ -83,7 +83,7 @@ private:
bool m_done, m_finish, m_user_stop;
uint m_bks;
qint64 m_totalTime, m_seekTime;
- qint64 m_output_at;
+ qint64 m_output_at, m_output_size;
int m_bitrate, m_chan, m_bps;
unsigned char *m_output_buf;
Decoder *m_decoder;
diff --git a/src/qmmp/qmmpsettings.cpp b/src/qmmp/qmmpsettings.cpp
index 7c4c3c6dc..170f75df8 100644
--- a/src/qmmp/qmmpsettings.cpp
+++ b/src/qmmp/qmmpsettings.cpp
@@ -56,6 +56,7 @@ QmmpSettings::QmmpSettings(QObject *parent) : QObject(parent)
m_eq_settings.setGain(i, settings.value("Equalizer/band_"+ QString("%1").arg(i), 0).toDouble());
m_eq_settings.setPreamp(settings.value("Equalizer/preamp", 0).toDouble());
m_eq_settings.setEnabled(settings.value("Equalizer/enabled", true).toBool());
+ m_buffer_size = settings.value("Output/buffer_size", 500).toInt();
}
QmmpSettings::~QmmpSettings()
@@ -169,6 +170,16 @@ void QmmpSettings::setEqSettings(const EqSettings &settings)
emit eqSettingsChanged();
}
+int QmmpSettings:: bufferSize() const
+{
+ return m_buffer_size;
+}
+
+void QmmpSettings::setBufferSize(int msec)
+{
+ m_buffer_size = msec;
+}
+
void QmmpSettings::sync()
{
QSettings settings (Qmmp::configFile(), QSettings::IniFormat);
@@ -198,6 +209,8 @@ void QmmpSettings::sync()
settings.setValue("Equalizer/band_"+ QString("%1").arg(i), m_eq_settings.gain(i));
settings.setValue("Equalizer/preamp", m_eq_settings.preamp());
settings.setValue("Equalizer/enabled", m_eq_settings.isEnabled());
+ //buffer size
+ settings.setValue("Output/buffer_size", m_buffer_size);
}
QmmpSettings* QmmpSettings::instance()
diff --git a/src/qmmp/qmmpsettings.h b/src/qmmp/qmmpsettings.h
index 7dac60da7..8b77bfb1f 100644
--- a/src/qmmp/qmmpsettings.h
+++ b/src/qmmp/qmmpsettings.h
@@ -132,11 +132,24 @@ public:
* @param proxy Proxy url.
*/
void setNetworkSettings(bool use_proxy, bool auth, const QUrl &proxy);
-
-
+ /*!
+ * Returns equalizer settings.
+ */
EqSettings eqSettings() const;
+ /*!
+ * Changes equalizer settings to \b settings
+ */
void setEqSettings(const EqSettings &settings);
/*!
+ * Returns buffer size in milliseconds
+ */
+ int bufferSize() const;
+ /*!
+ * Sets buffer size
+ * @param msec Buffer size in milliseconds
+ */
+ void setBufferSize(int msec);
+ /*!
* Returns a pointer to the QmmpSettings instance.
*/
static QmmpSettings* instance();
@@ -186,6 +199,8 @@ private:
QUrl m_proxy_url;
//equalizer settings
EqSettings m_eq_settings;
+ //buffer size
+ int m_buffer_size;
static QmmpSettings* m_instance;
diff --git a/src/qmmp/recycler.cpp b/src/qmmp/recycler.cpp
index 9ac95d774..6c91be5e7 100644
--- a/src/qmmp/recycler.cpp
+++ b/src/qmmp/recycler.cpp
@@ -5,62 +5,91 @@
//
#include "recycler.h"
+#include "qmmpsettings.h"
+#include "audioparameters.h"
#include "buffer.h"
-Recycler::Recycler (unsigned int sz)
- : add_index (0), done_index (0), current_count (0)
+Recycler::Recycler ()
{
- buffer_count = sz / QMMP_BLOCK_SIZE;
- if (buffer_count < 4)
- buffer_count = 4;
-
- buffers = new Buffer*[buffer_count];
+ m_add_index = 0;
+ m_done_index = 0;
+ m_current_count = 0;
+ m_buffer_count = 0;
+ m_blocked = 0;
+ m_block_size = 0;
+ m_buffers = 0;
+}
- for (unsigned int i = 0; i < buffer_count; i++)
+Recycler::~Recycler()
+{
+ for (unsigned int i = 0; i < m_buffer_count; i++)
{
- buffers[i] = new Buffer;
+ delete m_buffers[i];
+ m_buffers[i] = 0;
}
+ if(m_buffer_count)
+ delete [] m_buffers;
m_blocked = 0;
}
-
-Recycler::~Recycler()
+void Recycler::configure(quint32 freq, int chan, Qmmp::AudioFormat format)
{
- for (unsigned int i = 0; i < buffer_count; i++)
+ unsigned long block_size = AudioParameters::sampleSize(format) * chan * QMMP_BLOCK_FRAMES;
+ unsigned int buffer_count = freq * QmmpSettings::instance()->bufferSize() / 1000 / QMMP_BLOCK_FRAMES;
+ if(block_size == m_block_size && buffer_count == m_buffer_count)
+ return;
+
+ for (unsigned int i = 0; i < m_buffer_count; i++)
{
- delete buffers[i];
- buffers[i] = 0;
+ delete m_buffers[i];
+ m_buffers[i] = 0;
}
- delete [] buffers;
+ if(m_buffer_count)
+ delete [] m_buffers;
+ m_add_index = 0;
+ m_done_index = 0;
+ m_current_count = 0;
m_blocked = 0;
-}
+ m_block_size = block_size;
+ m_buffer_count = buffer_count;
+
+
+ if (m_buffer_count < 4)
+ m_buffer_count = 4;
+
+ m_buffers = new Buffer*[m_buffer_count];
+ for (unsigned int i = 0; i < m_buffer_count; i++)
+ {
+ m_buffers[i] = new Buffer(m_block_size);
+ }
+}
bool Recycler::full() const
{
- return current_count == buffer_count;
+ return m_current_count == m_buffer_count;
}
bool Recycler::blocked()
{
- return buffers[add_index] == m_blocked;
+ return m_buffers[m_add_index] == m_blocked;
}
bool Recycler::empty() const
{
- return current_count == 0;
+ return m_current_count == 0;
}
int Recycler::available() const
{
- return buffer_count - current_count;
+ return m_buffer_count - m_current_count;
}
int Recycler::used() const
{
- return current_count;
+ return m_current_count;
}
@@ -68,24 +97,23 @@ Buffer *Recycler::get()
{
if (full())
return 0;
- return buffers[add_index];
+ return m_buffers[m_add_index];
}
-
void Recycler::add()
{
- if(buffers[add_index]->nbytes)
+ if(m_buffers[m_add_index]->nbytes)
{
- add_index = (add_index + 1) % buffer_count;
- current_count++;
+ m_add_index = (m_add_index + 1) % m_buffer_count;
+ m_current_count++;
}
}
Buffer *Recycler::next()
{
- if(current_count)
+ if(m_current_count)
{
- m_blocked = buffers[done_index];
+ m_blocked = m_buffers[m_done_index];
return m_blocked;
}
return 0;
@@ -94,21 +122,21 @@ Buffer *Recycler::next()
void Recycler::done()
{
m_blocked = 0;
- if (current_count)
+ if (m_current_count)
{
- current_count--;
- done_index = (done_index + 1) % buffer_count;
+ m_current_count--;
+ m_done_index = (m_done_index + 1) % m_buffer_count;
}
}
void Recycler::clear()
{
- current_count = 0;
- add_index = 0;
- done_index = 0;
+ m_current_count = 0;
+ m_add_index = 0;
+ m_done_index = 0;
}
-unsigned int Recycler::size() const
+unsigned long Recycler::size() const
{
- return buffer_count * QMMP_BLOCK_SIZE;
+ return m_buffer_count * m_block_size;
}
diff --git a/src/qmmp/recycler.h b/src/qmmp/recycler.h
index a52e37143..fc143779d 100644
--- a/src/qmmp/recycler.h
+++ b/src/qmmp/recycler.h
@@ -9,6 +9,7 @@
#include <QMutex>
#include <QWaitCondition>
+#include "qmmp.h"
class Buffer;
@@ -20,14 +21,20 @@ class Recycler
public:
/*!
* Constructor.
- * @param sz Preferd total size of the all buffers in bytes.
*/
- Recycler(unsigned int sz);
+ Recycler();
/*!
* Destructor.
*/
~Recycler();
/*!
+ * Setups audio parameters of output interface.
+ * @param freq Sample rate.
+ * @param chan Number of channels.
+ * @param format Audio format
+ */
+ void configure(quint32 freq, int chan, Qmmp::AudioFormat format);
+ /*!
* Returns \b true if queue if full, otherwise returns \b false
*/
bool full() const;
@@ -66,20 +73,20 @@ public:
/*!
* Returns size of all buffers in bytes.
*/
- unsigned int size() const; // size in bytes
+ unsigned long size() const; // size in bytes
/*!
* Returns mutex pointer.
*/
QMutex *mutex()
{
- return &mtx;
+ return &m_mtx;
}
/*!
* Returns wait condition pointer.
*/
QWaitCondition *cond()
{
- return &cnd;
+ return &m_cnd;
}
/*!
* Returns \b true if the next buffer is used by output. Otherwise returns \b false.
@@ -87,10 +94,11 @@ public:
bool blocked();
private:
- unsigned int buffer_count, add_index, done_index, current_count;
- Buffer **buffers;
- QMutex mtx;
- QWaitCondition cnd;
+ unsigned int m_buffer_count, m_add_index, m_done_index, m_current_count;
+ unsigned long m_block_size;
+ Buffer **m_buffers;
+ QMutex m_mtx;
+ QWaitCondition m_cnd;
Buffer *m_blocked;
};