diff options
Diffstat (limited to 'src/qmmp')
| -rw-r--r-- | src/qmmp/buffer.h | 10 | ||||
| -rw-r--r-- | src/qmmp/output.cpp | 27 | ||||
| -rw-r--r-- | src/qmmp/output.h | 4 | ||||
| -rw-r--r-- | src/qmmp/qmmpaudioengine.cpp | 17 | ||||
| -rw-r--r-- | src/qmmp/qmmpaudioengine.h | 2 | ||||
| -rw-r--r-- | src/qmmp/qmmpsettings.cpp | 13 | ||||
| -rw-r--r-- | src/qmmp/qmmpsettings.h | 19 | ||||
| -rw-r--r-- | src/qmmp/recycler.cpp | 100 | ||||
| -rw-r--r-- | src/qmmp/recycler.h | 26 |
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; }; |
