aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortrialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38>2010-10-08 18:06:38 +0000
committertrialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38>2010-10-08 18:06:38 +0000
commitc4749f20a5ad31ed8c68c11547120a0d1da45a8f (patch)
tree805248511deeea91f7da2d2881f9afefe9f21b1a
parent767150cfe9403eb432ea82377664abda214d6e04 (diff)
downloadqmmp-c4749f20a5ad31ed8c68c11547120a0d1da45a8f.tar.gz
qmmp-c4749f20a5ad31ed8c68c11547120a0d1da45a8f.tar.bz2
qmmp-c4749f20a5ad31ed8c68c11547120a0d1da45a8f.zip
dynamic buffer size
git-svn-id: http://svn.code.sf.net/p/qmmp-dev/code/trunk/qmmp@1928 90c681e8-e032-0410-971d-27865f9a5e38
-rw-r--r--src/plugins/Input/ffmpeg/decoder_ffmpeg.cpp2
-rw-r--r--src/plugins/Input/modplug/decoder_modplug.cpp2
-rw-r--r--src/plugins/Input/wavpack/decoder_wavpack.cpp10
-rw-r--r--src/plugins/Input/wavpack/decoder_wavpack.h2
-rw-r--r--src/plugins/Output/alsa/outputalsa.cpp2
-rw-r--r--src/plugins/Visual/analyzer/analyzer.cpp125
-rw-r--r--src/plugins/Visual/analyzer/analyzer.h32
-rw-r--r--src/plugins/Visual/analyzer/inlines.h93
-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
-rw-r--r--src/ui/CMakeLists.txt2
-rw-r--r--src/ui/inlines.h93
-rw-r--r--src/ui/logscale.cpp74
-rw-r--r--src/ui/logscale.h31
-rw-r--r--src/ui/mainvisual.cpp91
-rw-r--r--src/ui/mainvisual.h33
-rw-r--r--src/ui/mp3player.cpp5
-rw-r--r--src/ui/shadedvisual.cpp89
-rw-r--r--src/ui/shadedvisual.h8
-rw-r--r--src/ui/ui.pro2
27 files changed, 321 insertions, 593 deletions
diff --git a/src/plugins/Input/ffmpeg/decoder_ffmpeg.cpp b/src/plugins/Input/ffmpeg/decoder_ffmpeg.cpp
index 25e2ab04c..988d534d4 100644
--- a/src/plugins/Input/ffmpeg/decoder_ffmpeg.cpp
+++ b/src/plugins/Input/ffmpeg/decoder_ffmpeg.cpp
@@ -169,7 +169,7 @@ bool DecoderFFmpeg::initialize()
}
m_totalTime = input()->isSequential() ? 0 : ic->duration * 1000 / AV_TIME_BASE;
- m_output_buf = (uint8_t *)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3 / 2 + QMMP_BUFFER_SIZE);
+ m_output_buf = (uint8_t *)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3 / 2/* + QMMP_BUFFER_SIZE*/);
#if (LIBAVCODEC_VERSION_INT >= ((52<<16)+(20<<8)+0))
if(c->codec_id == CODEC_ID_SHORTEN) //ffmpeg bug workaround
diff --git a/src/plugins/Input/modplug/decoder_modplug.cpp b/src/plugins/Input/modplug/decoder_modplug.cpp
index fe92d90f4..969731bdc 100644
--- a/src/plugins/Input/modplug/decoder_modplug.cpp
+++ b/src/plugins/Input/modplug/decoder_modplug.cpp
@@ -111,7 +111,7 @@ int DecoderModPlug::bitrate()
qint64 DecoderModPlug::read(char *audio, qint64 maxSize)
{
- long len = m_soundFile->Read (audio, qMin((qint64)QMMP_BLOCK_SIZE, maxSize)) * m_sampleSize;
+ long len = m_soundFile->Read (audio, maxSize) * m_sampleSize;
if (m_usePreamp)
{
{
diff --git a/src/plugins/Input/wavpack/decoder_wavpack.cpp b/src/plugins/Input/wavpack/decoder_wavpack.cpp
index 75b09dff0..071b18004 100644
--- a/src/plugins/Input/wavpack/decoder_wavpack.cpp
+++ b/src/plugins/Input/wavpack/decoder_wavpack.cpp
@@ -1,5 +1,5 @@
/***************************************************************************
- * Copyright (C) 2008-2009 by Ilya Kotov *
+ * Copyright (C) 2008-2010 by Ilya Kotov *
* forkotov02@hotmail.ru *
* *
* This program is free software; you can redistribute it and/or modify *
@@ -24,12 +24,9 @@
#include <QFile>
#include <math.h>
#include <stdint.h>
-
#include <qmmp/buffer.h>
#include <qmmp/output.h>
#include <qmmp/recycler.h>
-#include "QtDebug"
-
#include "decoder_wavpack.h"
#include "cueparser.h"
@@ -107,7 +104,7 @@ bool DecoderWavPack::initialize()
m_freq = WavpackGetSampleRate (m_context);
m_bps = WavpackGetBitsPerSample (m_context);
if (!m_output_buf)
- m_output_buf = new int32_t[QMMP_BUFFER_SIZE/4];
+ m_output_buf = new int32_t[QMMP_BLOCK_FRAMES * m_chan];
switch(m_bps)
{
case 8:
@@ -249,7 +246,8 @@ void DecoderWavPack::next()
qint64 DecoderWavPack::wavpack_decode(char *data, qint64 size)
{
- ulong len = WavpackUnpackSamples (m_context, m_output_buf, size / m_chan / 4);
+ ulong len = qMin(QMMP_BLOCK_FRAMES, (int)size / m_chan / 4);
+ len = WavpackUnpackSamples (m_context, m_output_buf, len);
//convert 32 to 16
qint8 *data8 = (qint8 *)data;
qint16 *data16 = (qint16 *)data;
diff --git a/src/plugins/Input/wavpack/decoder_wavpack.h b/src/plugins/Input/wavpack/decoder_wavpack.h
index 1f2e034ea..a44ca090f 100644
--- a/src/plugins/Input/wavpack/decoder_wavpack.h
+++ b/src/plugins/Input/wavpack/decoder_wavpack.h
@@ -1,5 +1,5 @@
/***************************************************************************
- * Copyright (C) 2008-2009 by Ilya Kotov *
+ * Copyright (C) 2008-2010 by Ilya Kotov *
* forkotov02@hotmail.ru *
* *
* This program is free software; you can redistribute it and/or modify *
diff --git a/src/plugins/Output/alsa/outputalsa.cpp b/src/plugins/Output/alsa/outputalsa.cpp
index 9ae4d5db2..905d58a20 100644
--- a/src/plugins/Output/alsa/outputalsa.cpp
+++ b/src/plugins/Output/alsa/outputalsa.cpp
@@ -185,7 +185,7 @@ void OutputALSA::configure(quint32 freq, int chan, Qmmp::AudioFormat format)
qDebug("OutputALSA: can pause: %d", m_can_pause);
Output::configure(freq, chan, format); //apply configuration
//create alsa prebuffer;
- m_prebuf_size = QMMP_BUFFER_SIZE + m_bits_per_frame * m_chunk_size / 8;
+ m_prebuf_size = /*QMMP_BUFFER_SIZE + */m_bits_per_frame * m_chunk_size / 8;
m_prebuf = (uchar *)malloc(m_prebuf_size);
}
diff --git a/src/plugins/Visual/analyzer/analyzer.cpp b/src/plugins/Visual/analyzer/analyzer.cpp
index c071b12f2..22941892f 100644
--- a/src/plugins/Visual/analyzer/analyzer.cpp
+++ b/src/plugins/Visual/analyzer/analyzer.cpp
@@ -1,5 +1,5 @@
/***************************************************************************
- * Copyright (C) 2007 by Ilya Kotov *
+ * Copyright (C) 2007-2010 by Ilya Kotov *
* forkotov02@hotmail.ru *
* *
* This program is free software; you can redistribute it and/or modify *
@@ -32,6 +32,8 @@
#include "inlines.h"
#include "analyzer.h"
+#define VISUAL_NODE_SIZE 512 //samples
+#define VISUAL_BUFFER_SIZE (5*VISUAL_NODE_SIZE)
Analyzer::Analyzer (QWidget *parent)
: Visual (parent), m_fps (20)
@@ -42,8 +44,9 @@ Analyzer::Analyzer (QWidget *parent)
m_pixmap = QPixmap (75,20);
m_timer = new QTimer (this);
connect(m_timer, SIGNAL (timeout()), this, SLOT (timeout()));
- m_nodes.clear();
-
+ m_left_buffer = new short[VISUAL_BUFFER_SIZE];
+ m_right_buffer = new short[VISUAL_BUFFER_SIZE];
+ m_buffer_at = 0;
clear();
setWindowTitle (tr("Qmmp Analyzer"));
@@ -66,14 +69,13 @@ Analyzer::Analyzer (QWidget *parent)
Analyzer::~Analyzer()
{
- while (!m_nodes.isEmpty())
- m_nodes.removeFirst();
+ delete [] m_left_buffer;
+ delete [] m_right_buffer;
}
void Analyzer::clear()
{
- while (!m_nodes.isEmpty())
- m_nodes.removeFirst();
+ m_buffer_at = 0;
for (int i = 0; i< 75; ++i)
{
m_intern_vis_data[i] = 0;
@@ -87,50 +89,44 @@ void Analyzer::add (unsigned char *data, qint64 size, int chan)
if (!m_timer->isActive ())
return;
- short *l = 0, *r = 0;
- qint64 samples = size/chan >> 1;
- int frames = samples/512;
- for (int i = 0; i < frames; ++i)
+ if(VISUAL_BUFFER_SIZE == m_buffer_at)
{
- l = new short[512];
- r = 0;
- if (chan == 2)
- {
- r = new short[512];
- stereo16_from_stereopcm16 (l, r, (short *) (data + i*4*512), 512);
- }
- else if (chan == 1)
- mono16_from_monopcm16 (l, (short *) (data + i*2*512), 512);
- else
- {
- r = new short[512];
- stereo16_from_multichannel(l, r, (short *) (data + i*2*chan*512), 512, chan);
- }
- m_nodes.append (new VisualNode (l, r, 512));
+ m_buffer_at -= VISUAL_NODE_SIZE;
+ memmove(m_left_buffer, m_left_buffer + VISUAL_NODE_SIZE, m_buffer_at << 1);
+ memmove(m_right_buffer, m_right_buffer + VISUAL_NODE_SIZE, m_buffer_at << 1);
+ return;
}
-}
-void Analyzer::timeout()
-{
- VisualNode *node = 0;
- mutex()->lock ();
+ int frames = qMin((int)size/chan >> 1, VISUAL_BUFFER_SIZE - m_buffer_at);
- while(m_nodes.size() > 5)
+ if (chan >= 2)
{
- delete m_nodes.takeFirst();
+ stereo16_from_multichannel(m_left_buffer + m_buffer_at,
+ m_right_buffer + m_buffer_at,(short *) data, frames, chan);
+ }
+ else
+ {
+ memcpy(m_left_buffer + m_buffer_at, (short *) data, frames << 1);
+ memcpy(m_right_buffer + m_buffer_at, (short *) data, frames << 1);
}
- if(!m_nodes.isEmpty())
- node = m_nodes.takeFirst();
-
- mutex()->unlock();
+ m_buffer_at += frames;
+}
- if (node)
+void Analyzer::timeout()
+{
+ mutex()->lock ();
+ if(m_buffer_at < VISUAL_NODE_SIZE)
{
- process (node);
- delete node;
- update();
+ mutex()->unlock ();
+ return;
}
+
+ process (m_left_buffer, m_right_buffer);
+ m_buffer_at -= VISUAL_NODE_SIZE;
+ memmove(m_left_buffer, m_left_buffer + VISUAL_NODE_SIZE, m_buffer_at << 1);
+ memmove(m_right_buffer, m_right_buffer + VISUAL_NODE_SIZE, m_buffer_at << 1);
+ mutex()->unlock ();
update();
}
@@ -159,7 +155,7 @@ void Analyzer::closeEvent (QCloseEvent *event)
Visual::closeEvent(event); //removes visualization before class deleting
}
-bool Analyzer::process (VisualNode *node)
+void Analyzer::process (short *left, short *right)
{
static fft_state *state = 0;
if (!state)
@@ -174,15 +170,9 @@ bool Analyzer::process (VisualNode *node)
36, 47, 62, 82, 107, 141, 184, 255
};
- if (node)
- {
- //i = node->length;
- calc_freq (dest_l, node->left);
- if (node->right)
- calc_freq (dest_r, node->right);
- }
- else
- return false;
+ calc_freq (dest_l, left);
+ calc_freq (dest_r, right);
+
const double y_scale = 3.60673760222; /* 20.0 / log(256) */
int yl,yr, j;
@@ -194,16 +184,14 @@ bool Analyzer::process (VisualNode *node)
{
if (dest_l[j] > yl)
yl = dest_l[j];
- if (dest_r[j] > yr && node->right)
+ if (dest_r[j] > yr)
yr = dest_r[j];
}
yl >>= 7;
+ yr >>= 7;
int magnitude_l = 0;
int magnitude_r = 0;
- if (node->right)
- {
- yr >>= 7;
- }
+
if (yl)
{
magnitude_l = int(log (yl) * y_scale);
@@ -212,7 +200,7 @@ bool Analyzer::process (VisualNode *node)
if (magnitude_l < 0)
magnitude_l = 0;
}
- if (yr && node->right)
+ if (yr)
{
magnitude_r = int(log (yr) * y_scale);
if (magnitude_r > 15)
@@ -224,27 +212,20 @@ bool Analyzer::process (VisualNode *node)
m_intern_vis_data[i] -= m_analyzer_falloff;
m_intern_vis_data[i] = magnitude_l > m_intern_vis_data[i]
? magnitude_l : m_intern_vis_data[i];
- if (node->right)
- {
- m_intern_vis_data[37-i] -= m_analyzer_falloff;
- m_intern_vis_data[37-i] = magnitude_r > m_intern_vis_data[37-i]
- ? magnitude_r : m_intern_vis_data[37-i];
- }
+
+ m_intern_vis_data[37-i] -= m_analyzer_falloff;
+ m_intern_vis_data[37-i] = magnitude_r > m_intern_vis_data[37-i]
+ ? magnitude_r : m_intern_vis_data[37-i];
if (m_show_peaks)
{
m_peaks[i] -= m_peaks_falloff;
- m_peaks[i] = magnitude_l > m_peaks[i]
- ? magnitude_l : m_peaks[i];
- if (node->right)
- {
- m_peaks[37-i] -= m_peaks_falloff;
- m_peaks[37-i] = magnitude_r > m_peaks[37-i]
- ? magnitude_r : m_peaks[37-i];
- }
+ m_peaks[i] = magnitude_l > m_peaks[i] ? magnitude_l : m_peaks[i];
+
+ m_peaks[37-i] -= m_peaks_falloff;
+ m_peaks[37-i] = magnitude_r > m_peaks[37-i] ? magnitude_r : m_peaks[37-i];
}
}
- return true;
}
void Analyzer::draw (QPainter *p)
diff --git a/src/plugins/Visual/analyzer/analyzer.h b/src/plugins/Visual/analyzer/analyzer.h
index 1c0e8974e..d2ff0469a 100644
--- a/src/plugins/Visual/analyzer/analyzer.h
+++ b/src/plugins/Visual/analyzer/analyzer.h
@@ -1,5 +1,5 @@
/***************************************************************************
- * Copyright (C) 2007 by Ilya Kotov *
+ * Copyright (C) 2007-2010 by Ilya Kotov *
* forkotov02@hotmail.ru *
* *
* This program is free software; you can redistribute it and/or modify *
@@ -23,35 +23,11 @@
#include <QWidget>
#include <QResizeEvent>
#include <qmmp/visual.h>
-#include <QDir>
-class QSettings;
class QTimer;
class QMenu;
class QActionGroup;
-class Buffer;
-
-
-class VisualNode
-{
-public:
- VisualNode(short *l, short *r, unsigned long n)
- : left(l), right(r), length(n)
- {
- // left and right are allocated and then passed to this class
- // the code that allocated left and right should give up all ownership
- }
-
- ~VisualNode()
- {
- delete [] left;
- delete [] right;
- }
-
- short *left, *right;
- long length;
-};
class Analyzer : public Visual
{
@@ -74,11 +50,10 @@ public slots:
void timeout();
private:
- bool process(VisualNode *node);
+ void process(short *l, short *r);
void draw(QPainter *p);
QPixmap m_pixmap;
QPixmap m_bg;
- QList <VisualNode*> m_nodes;
QTimer *m_timer;
int m_fps;
double m_intern_vis_data[75];
@@ -86,6 +61,9 @@ private:
double m_peaks_falloff;
double m_analyzer_falloff;
bool m_show_peaks;
+ short *m_left_buffer;
+ short *m_right_buffer;
+ int m_buffer_at;
//colors
QColor m_color1;
QColor m_color2;
diff --git a/src/plugins/Visual/analyzer/inlines.h b/src/plugins/Visual/analyzer/inlines.h
index e2c48d019..39b81bd57 100644
--- a/src/plugins/Visual/analyzer/inlines.h
+++ b/src/plugins/Visual/analyzer/inlines.h
@@ -10,8 +10,7 @@
#include "fft.h"
// *fast* convenience functions
-static inline void
-calc_freq(short* dest, short *src)
+static inline void calc_freq(short* dest, short *src)
{
static fft_state *state = NULL;
float tmp_out[257];
@@ -26,27 +25,6 @@ calc_freq(short* dest, short *src)
dest[i] = ((int) sqrt(tmp_out[i + 1])) >> 8;
}
-static inline void
-calc_mono_freq(short dest[2][256], short src[2][512], int nch)
-{
- int i;
- short *d, *sl, *sr, tmp[512];
-
- if (nch == 1)
- calc_freq(dest[0], src[0]);
- else
- {
- d = tmp;
- sl = src[0];
- sr = src[1];
- for (i = 0; i < 512; i++)
- {
- *(d++) = (*(sl++) + *(sr++)) >> 1;
- }
- calc_freq(dest[0], tmp);
- }
-}
-
static inline void stereo16_from_multichannel(register short *l,
register short *r,
register short *s,
@@ -63,71 +41,16 @@ static inline void stereo16_from_multichannel(register short *l,
}
}
-
-static inline void stereo16_from_stereopcm16(register short *l,
- register short *r,
- register short *s,
- long cnt)
-{
- while (cnt >= 4l)
- {
- l[0] = s[0];
- r[0] = s[1];
- l[1] = s[2];
- r[1] = s[3];
- l[2] = s[4];
- r[2] = s[5];
- l[3] = s[6];
- r[3] = s[7];
- l += 4;
- r += 4;
- s += 8;
- cnt -= 4l;
- }
-
- if (cnt > 0l)
- {
- l[0] = s[0];
- r[0] = s[1];
- if (cnt > 1l)
- {
- l[1] = s[2];
- r[1] = s[3];
- if (cnt > 2l)
- {
- l[2] = s[4];
- r[2] = s[5];
- }
- }
- }
-}
-
-static inline void mono16_from_monopcm16(register short *l,
- register short *s,
- long cnt)
+static inline void mono16_from_multichannel(register short *l,
+ register short *s,
+ long cnt, int chan)
{
- while (cnt >= 4l)
- {
- l[0] = s[0];
- l[1] = s[1];
- l[2] = s[2];
- l[3] = s[3];
- l += 4;
- s += 4;
- cnt -= 4l;
- }
-
- if (cnt > 0l)
+ while (cnt > 0)
{
l[0] = s[0];
- if (cnt > 1l)
- {
- l[1] = s[1];
- if (cnt > 2l)
- {
- l[2] = s[2];
- }
- }
+ s += chan;
+ l++;
+ cnt--;
}
}
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;
};
diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt
index 5275ad98f..9f9a31774 100644
--- a/src/ui/CMakeLists.txt
+++ b/src/ui/CMakeLists.txt
@@ -50,7 +50,6 @@ SET(ui_SRCS
jumptotrackdialog.cpp
keyboardmanager.cpp
listwidget.cpp
- logscale.cpp
mainvisual.cpp
mainwindow.cpp
monostereo.cpp
@@ -107,7 +106,6 @@ SET(ui_MOC_HDRS
jumptotrackdialog.h
keyboardmanager.h
listwidget.h
- logscale.h
mainvisual.h
mainwindow.h
monostereo.h
diff --git a/src/ui/inlines.h b/src/ui/inlines.h
index e2c48d019..39b81bd57 100644
--- a/src/ui/inlines.h
+++ b/src/ui/inlines.h
@@ -10,8 +10,7 @@
#include "fft.h"
// *fast* convenience functions
-static inline void
-calc_freq(short* dest, short *src)
+static inline void calc_freq(short* dest, short *src)
{
static fft_state *state = NULL;
float tmp_out[257];
@@ -26,27 +25,6 @@ calc_freq(short* dest, short *src)
dest[i] = ((int) sqrt(tmp_out[i + 1])) >> 8;
}
-static inline void
-calc_mono_freq(short dest[2][256], short src[2][512], int nch)
-{
- int i;
- short *d, *sl, *sr, tmp[512];
-
- if (nch == 1)
- calc_freq(dest[0], src[0]);
- else
- {
- d = tmp;
- sl = src[0];
- sr = src[1];
- for (i = 0; i < 512; i++)
- {
- *(d++) = (*(sl++) + *(sr++)) >> 1;
- }
- calc_freq(dest[0], tmp);
- }
-}
-
static inline void stereo16_from_multichannel(register short *l,
register short *r,
register short *s,
@@ -63,71 +41,16 @@ static inline void stereo16_from_multichannel(register short *l,
}
}
-
-static inline void stereo16_from_stereopcm16(register short *l,
- register short *r,
- register short *s,
- long cnt)
-{
- while (cnt >= 4l)
- {
- l[0] = s[0];
- r[0] = s[1];
- l[1] = s[2];
- r[1] = s[3];
- l[2] = s[4];
- r[2] = s[5];
- l[3] = s[6];
- r[3] = s[7];
- l += 4;
- r += 4;
- s += 8;
- cnt -= 4l;
- }
-
- if (cnt > 0l)
- {
- l[0] = s[0];
- r[0] = s[1];
- if (cnt > 1l)
- {
- l[1] = s[2];
- r[1] = s[3];
- if (cnt > 2l)
- {
- l[2] = s[4];
- r[2] = s[5];
- }
- }
- }
-}
-
-static inline void mono16_from_monopcm16(register short *l,
- register short *s,
- long cnt)
+static inline void mono16_from_multichannel(register short *l,
+ register short *s,
+ long cnt, int chan)
{
- while (cnt >= 4l)
- {
- l[0] = s[0];
- l[1] = s[1];
- l[2] = s[2];
- l[3] = s[3];
- l += 4;
- s += 4;
- cnt -= 4l;
- }
-
- if (cnt > 0l)
+ while (cnt > 0)
{
l[0] = s[0];
- if (cnt > 1l)
- {
- l[1] = s[1];
- if (cnt > 2l)
- {
- l[2] = s[2];
- }
- }
+ s += chan;
+ l++;
+ cnt--;
}
}
diff --git a/src/ui/logscale.cpp b/src/ui/logscale.cpp
deleted file mode 100644
index 921004fd9..000000000
--- a/src/ui/logscale.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (c) 2000-2001 Brad Hughes <bhughes@trolltech.com>
-//
-// Use, modification and distribution is allowed without limitation,
-// warranty, or liability of any kind.
-//
-
-#include "logscale.h"
-
-#include <math.h>
-#include <stdio.h>
-
-
-LogScale::LogScale(int maxscale, int maxrange)
- : indices(0), s(0), r(0)
-{
- setMax(maxscale, maxrange);
-}
-
-
-LogScale::~LogScale()
-{
- if (indices)
- delete [] indices;
-}
-
-
-void LogScale::setMax(int maxscale, int maxrange)
-{
- if (maxscale == 0 || maxrange == 0)
- return;
-
- s = maxscale;
- r = maxrange;
-
- if (indices)
- delete [] indices;
-
- double alpha;
- int i, scaled;
- double domain = double(maxscale),
- range = double(maxrange),
- x = 1.0,
- dx = 1.0,
- y = 0.0,
- yy = 0.0,
- t = 0.0,
- e4 = double(1.0E-8);
-
- indices = new int[maxrange];
- for (i = 0; i < maxrange; i++)
- indices[i] = 0;
-
- // initialize log scale
- while (fabs(dx) > e4) {
- t = log((domain + x) / x);
- y = (x * t) - range;
- yy = t - (domain / (x + domain));
- dx = y / yy;
- x -= dx;
- }
-
- alpha = x;
- for (i = 1; i < (int) domain; i++) {
- scaled = (int) floor(0.5 + (alpha * log((double(i) + alpha) / alpha)));
- if (indices[scaled - 1] < i)
- indices[scaled - 1] = i;
- }
-}
-
-
-int LogScale::operator[](int index)
-{
- return indices[index];
-}
diff --git a/src/ui/logscale.h b/src/ui/logscale.h
deleted file mode 100644
index d74d25207..000000000
--- a/src/ui/logscale.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2000-2001 Brad Hughes <bhughes@trolltech.com>
-//
-// Use, modification and distribution is allowed without limitation,
-// warranty, or liability of any kind.
-//
-
-#ifndef __logscale_h
-#define __logscale_h
-
-
-class LogScale
-{
-public:
- LogScale(int = 0, int = 0);
- ~LogScale();
-
- int scale() const { return s; }
- int range() const { return r; }
-
- void setMax(int, int);
-
- int operator[](int);
-
-
-private:
- int *indices;
- int s, r;
-};
-
-
-#endif // __logscale_h
diff --git a/src/ui/mainvisual.cpp b/src/ui/mainvisual.cpp
index fdf7076e7..222878e36 100644
--- a/src/ui/mainvisual.cpp
+++ b/src/ui/mainvisual.cpp
@@ -31,6 +31,9 @@
#include "inlines.h"
#include "mainvisual.h"
+#define VISUAL_NODE_SIZE 512 //samples
+#define VISUAL_BUFFER_SIZE (5*VISUAL_NODE_SIZE)
+
MainVisual *MainVisual::m_instance = 0;
@@ -49,9 +52,10 @@ MainVisual::MainVisual (QWidget *parent)
connect(m_skin, SIGNAL(skinChanged()), this, SLOT(updateSettings()));
m_timer = new QTimer (this);
connect(m_timer, SIGNAL (timeout()), this, SLOT (timeout()));
- m_nodes.clear();
createMenu();
readSettings();
+ m_left_buffer = new short[VISUAL_BUFFER_SIZE];
+ m_buffer_at = 0;
m_instance = this;
}
@@ -67,8 +71,7 @@ MainVisual::~MainVisual()
else
settings.setValue("Visualization/type", "None");
settings.setValue("Visualization/rate", 1000/m_timer->interval());
- while (!m_nodes.isEmpty())
- delete m_nodes.takeFirst();
+ delete [] m_left_buffer;
m_instance = 0;
}
@@ -89,8 +92,7 @@ void MainVisual::setVisual (VisualBase *newvis)
void MainVisual::clear()
{
- while (!m_nodes.isEmpty())
- delete m_nodes.takeFirst();
+ m_buffer_at = 0;
if (m_vis)
m_vis->clear();
m_pixmap = m_bg;
@@ -102,52 +104,47 @@ void MainVisual::add (unsigned char *data, qint64 size, int chan)
if (!m_timer->isActive () || !m_vis)
return;
- short *l = 0, *r = 0;
- qint64 samples = size/chan >> 1;
- int frames = samples/512;
- for (int i = 0; i < frames; ++i)
+ if(VISUAL_BUFFER_SIZE == m_buffer_at)
{
- l = new short[512];
- r = 0;
- if (chan == 2)
- {
- r = new short[512];
- stereo16_from_stereopcm16 (l, r, (short *) (data + i*4*512), 512);
- }
- else if (chan == 1)
- mono16_from_monopcm16 (l, (short *) (data + i*2*512), 512);
- else
- {
- r = new short[512];
- stereo16_from_multichannel(l, r, (short *) (data + i*2*chan*512), 512, chan);
- }
- m_nodes.append (new VisualNode (l, r, 512));
+ m_buffer_at -= VISUAL_NODE_SIZE;
+ memmove(m_left_buffer, m_left_buffer + VISUAL_NODE_SIZE, m_buffer_at << 1);
+ return;
+ }
+
+ int frames = qMin((int)size/chan >> 1, VISUAL_BUFFER_SIZE - m_buffer_at);
+
+ if (chan >= 2)
+ {
+ mono16_from_multichannel(m_left_buffer + m_buffer_at, (short *) data, frames, chan);
+ }
+ else
+ {
+ memcpy(m_left_buffer + m_buffer_at, (short *) data, frames << 1);
}
+
+ m_buffer_at += frames;
}
void MainVisual::timeout()
{
- VisualNode *node = 0;
mutex()->lock ();
- while(m_nodes.size() > 5)
+ if(m_buffer_at < VISUAL_NODE_SIZE)
{
- delete m_nodes.takeFirst();
+ mutex()->unlock ();
+ return;
}
- if(!m_nodes.isEmpty())
- node = m_nodes.takeFirst();
-
- mutex()->unlock();
-
- if (m_vis && node)
+ if (m_vis)
{
- m_vis->process (node);
+ m_vis->process (m_left_buffer);
+ m_buffer_at -= VISUAL_NODE_SIZE;
+ memmove(m_left_buffer, m_left_buffer + VISUAL_NODE_SIZE, m_buffer_at << 1);
m_pixmap = m_bg;
QPainter p(&m_pixmap);
m_vis->draw (&p);
- delete node;
}
+ mutex()->unlock ();
update();
}
@@ -447,14 +444,14 @@ void Analyzer::clear()
}
}
-bool Analyzer::process (VisualNode *node)
+bool Analyzer::process (short *l)
{
static fft_state *state = 0;
if (!state)
state = fft_init();
short dest[256];
- const int xscale_long[] =
+ static const int xscale_long[] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
@@ -463,19 +460,14 @@ bool Analyzer::process (VisualNode *node)
114, 122, 131, 140, 150, 161, 172, 184, 255
};
- const int xscale_short[] =
+ static const int xscale_short[] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 11, 15, 20, 27,
36, 47, 62, 82, 107, 141, 184, 255
};
- if (node)
- {
- //i = node->length;
- calc_freq (dest, node->left);
- }
- else
- return false;
+ calc_freq (dest, l);
+
const double y_scale = 3.60673760222; /* 20.0 / log(256) */
int max = m_lines ? 75 : 19, y, j;
@@ -587,18 +579,15 @@ void Scope::clear()
Scope::~Scope()
{}
-bool Scope::process(VisualNode *node)
+bool Scope::process(short *l)
{
- if (!node)
- return false;
-
- int step = (node->length << 8)/76;
+ int step = (VISUAL_NODE_SIZE << 8)/76;
int pos = 0;
for (int i = 0; i < 76; ++i)
{
pos += step;
- m_intern_vis_data[i] = (node->left[pos >> 8] >> 12);
+ m_intern_vis_data[i] = (l[pos >> 8] >> 12);
if (m_intern_vis_data[i] > 4)
m_intern_vis_data[i] = 4;
diff --git a/src/ui/mainvisual.h b/src/ui/mainvisual.h
index dbd3cd9c0..9807483d7 100644
--- a/src/ui/mainvisual.h
+++ b/src/ui/mainvisual.h
@@ -23,40 +23,17 @@
#include <QWidget>
#include <QResizeEvent>
#include <qmmp/visual.h>
-#include "logscale.h"
-class QSettings;
class QTimer;
class QMenu;
class QActionGroup;
-class Buffer;
-
-class VisualNode
-{
-public:
- VisualNode(short *l, short *r, unsigned long n)
- : left(l), right(r), length(n)
- {
- // left and right are allocated and then passed to this class
- // the code that allocated left and right should give up all ownership
- }
-
- ~VisualNode()
- {
- delete [] left;
- delete [] right;
- }
-
- short *left, *right;
- long length;
-};
class VisualBase
{
public:
virtual ~VisualBase(){}
virtual void clear() = 0;
- virtual bool process(VisualNode *node) = 0;
+ virtual bool process(short *l) = 0;
virtual void draw(QPainter *) = 0;
virtual const QString name() = 0;
};
@@ -96,7 +73,6 @@ private:
VisualBase *m_vis;
QPixmap m_pixmap;
QPixmap m_bg;
- QList <VisualNode*> m_nodes;
QTimer *m_timer;
bool m_playing;
Skin *m_skin;
@@ -112,6 +88,9 @@ private:
QAction *m_peaksAction;
QAction *m_transparentAction;
int m_ratio;
+ short *m_left_buffer;
+ short *m_right_buffer;
+ int m_buffer_at;
};
namespace mainvisual
@@ -123,7 +102,7 @@ public:
virtual ~Analyzer();
void clear();
- bool process(VisualNode *node);
+ bool process(short *l);
void draw(QPainter *p);
const QString name()
{
@@ -149,7 +128,7 @@ public:
Scope();
virtual ~Scope();
void clear();
- bool process(VisualNode *node);
+ bool process(short *l);
void draw(QPainter *p);
const QString name()
{
diff --git a/src/ui/mp3player.cpp b/src/ui/mp3player.cpp
index 1d20377e7..b42b52632 100644
--- a/src/ui/mp3player.cpp
+++ b/src/ui/mp3player.cpp
@@ -38,13 +38,14 @@ int main(int argc, char *argv[])
{
QApplication a (argc, argv );
a.setApplicationName("qmmp");
+
+ LXDESupport::load(); //load lxde icons
+
QTranslator translator;
QString locale = Qmmp::systemLanguageID();
translator.load(QString(":/qmmp_") + locale);
a.installTranslator(&translator);
- LXDESupport::load(); //lxde icons
-
QTranslator qt_translator;
qt_translator.load(QLibraryInfo::location (QLibraryInfo::TranslationsPath) + "/qt_" + locale);
a.installTranslator(&qt_translator);
diff --git a/src/ui/shadedvisual.cpp b/src/ui/shadedvisual.cpp
index fdc487c7c..e249752ca 100644
--- a/src/ui/shadedvisual.cpp
+++ b/src/ui/shadedvisual.cpp
@@ -1,5 +1,5 @@
/***************************************************************************
- * Copyright (C) 2007-2009 by Ilya Kotov *
+ * Copyright (C) 2007-2010 by Ilya Kotov *
* forkotov02@hotmail.ru *
* *
* This program is free software; you can redistribute it and/or modify *
@@ -25,6 +25,9 @@
#include "inlines.h"
#include "shadedvisual.h"
+#define VISUAL_NODE_SIZE 512 //samples
+#define VISUAL_BUFFER_SIZE (5*VISUAL_NODE_SIZE)
+
ShadedVisual::ShadedVisual(QWidget *parent) : Visual(parent)
{
m_skin = Skin::instance();
@@ -34,49 +37,52 @@ ShadedVisual::ShadedVisual(QWidget *parent) : Visual(parent)
m_timer = new QTimer(this);
connect(m_timer, SIGNAL (timeout()), this, SLOT (timeout()));
connect(m_skin, SIGNAL(skinChanged()), this, SLOT(updateSkin()));
+ m_left_buffer = new short[VISUAL_BUFFER_SIZE];
+ m_right_buffer = new short[VISUAL_BUFFER_SIZE];
+ m_buffer_at = 0;
m_timer->setInterval(50);
m_timer->start();
clear();
}
ShadedVisual::~ShadedVisual()
-{}
+{
+ delete [] m_left_buffer;
+ delete [] m_right_buffer;
+}
void ShadedVisual::add(unsigned char *data, qint64 size, int chan)
{
if (!m_timer->isActive ())
return;
- long len = size, cnt;
- short *l = 0, *r = 0;
-
- len /= chan;
- len /= 2;
- if ( len > 512 )
- len = 512;
- cnt = len;
- if (chan == 2)
+ if(VISUAL_BUFFER_SIZE == m_buffer_at)
{
- l = new short[len];
- r = new short[len];
- stereo16_from_stereopcm16 ( l, r, (short *) data, cnt);
+ m_buffer_at -= VISUAL_NODE_SIZE;
+ memmove(m_left_buffer, m_left_buffer + VISUAL_NODE_SIZE, m_buffer_at << 1);
+ memmove(m_right_buffer, m_right_buffer + VISUAL_NODE_SIZE, m_buffer_at << 1);
+ return;
}
- else if (chan == 1)
+
+ int frames = qMin((int)size/chan >> 1, VISUAL_BUFFER_SIZE - m_buffer_at);
+
+ if (chan >= 2)
{
- l = new short[len];
- mono16_from_monopcm16 (l, (short *) data, cnt);
+ stereo16_from_multichannel(m_left_buffer + m_buffer_at,
+ m_right_buffer + m_buffer_at,(short *) data, frames, chan);
}
else
- len = 0;
+ {
+ memcpy(m_left_buffer + m_buffer_at, (short *) data, frames << 1);
+ memcpy(m_right_buffer + m_buffer_at, (short *) data, frames << 1);
+ }
- if (len)
- m_nodes.append (new VisualNode (l, r, len));
+ m_buffer_at += frames;
}
void ShadedVisual::clear()
{
- while (!m_nodes.isEmpty())
- m_nodes.removeFirst();
+ m_buffer_at = 0;
m_l = 0;
m_r = 0;
m_pixmap.fill(m_skin->getVisColor(0));
@@ -85,39 +91,28 @@ void ShadedVisual::clear()
void ShadedVisual::timeout()
{
- VisualNode *node = 0;
m_pixmap.fill(m_skin->getVisColor(0));
mutex()->lock ();
- VisualNode *prev = 0;
- while ((!m_nodes.isEmpty()))
+ if(m_buffer_at < VISUAL_NODE_SIZE)
{
- node = m_nodes.takeFirst();
- /*if ( node->offset > synctime )
- break;*/
-
- if (prev)
- delete prev;
- prev = node;
+ mutex()->unlock ();
+ return;
}
- mutex()->unlock();
- node = prev;
- if (!node)
- return;
- process (node);
- delete node;
+ process (m_left_buffer, m_right_buffer);
+ m_buffer_at -= VISUAL_NODE_SIZE;
+ memmove(m_left_buffer, m_left_buffer + VISUAL_NODE_SIZE, m_buffer_at << 1);
+ memmove(m_right_buffer, m_right_buffer + VISUAL_NODE_SIZE, m_buffer_at << 1);
QPainter p(&m_pixmap);
draw (&p);
+ mutex()->unlock ();
update();
}
-void ShadedVisual::process (VisualNode *node)
+void ShadedVisual::process (short *left, short *right)
{
- if (!node)
- return;
-
- int step = (node->length << 8)/74;
+ int step = (VISUAL_NODE_SIZE << 8)/74;
int pos = 0;
int l = 0;
int r = 0;
@@ -127,17 +122,17 @@ void ShadedVisual::process (VisualNode *node)
{
pos += step;
- if (node->left)
+ if (left)
{
- j_l = abs((node->left[pos >> 8] >> 12));
+ j_l = abs((left[pos >> 8] >> 12));
if (j_l > 15)
j_l = 15;
l = qMax(l, j_l);
}
- if (node->right)
+ if (right)
{
- j_r = abs((node->right[pos >> 8] >> 12));
+ j_r = abs((right[pos >> 8] >> 12));
if (j_r > 15)
j_r = 15;
r = qMax(r, j_r);
diff --git a/src/ui/shadedvisual.h b/src/ui/shadedvisual.h
index e276b8b24..0592ec78f 100644
--- a/src/ui/shadedvisual.h
+++ b/src/ui/shadedvisual.h
@@ -27,7 +27,7 @@
class QTimer;
class QPixmap;
class Skin;
-class VisualNode;
+//class VisualNode;
/**
@author Ilya Kotov <forkotov02@hotmail.ru>
@@ -54,12 +54,14 @@ private slots:
void updateSkin();
private:
- void process (VisualNode *node);
+ void process (short *l, short *r);
void draw (QPainter *);
Skin *m_skin;
QTimer *m_timer;
QPixmap m_pixmap;
- QList <VisualNode*> m_nodes;
+ short *m_left_buffer;
+ short *m_right_buffer;
+ int m_buffer_at;
double m_l, m_r;
int m_ratio;
diff --git a/src/ui/ui.pro b/src/ui/ui.pro
index c4c0ee861..3cabae11e 100644
--- a/src/ui/ui.pro
+++ b/src/ui/ui.pro
@@ -28,7 +28,6 @@ HEADERS += mainwindow.h \
mainvisual.h \
inlines.h \
fft.h \
- logscale.h \
textscroller.h \
monostereo.h \
playstatus.h \
@@ -81,7 +80,6 @@ SOURCES += mainwindow.cpp \
eqgraph.cpp \
mainvisual.cpp \
fft.c \
- logscale.cpp \
textscroller.cpp \
monostereo.cpp \
playstatus.cpp \