diff options
| -rw-r--r-- | src/plugins/Ui/Ui.pro | 3 | ||||
| -rw-r--r-- | src/plugins/Ui/qsui/fft.c | 15 | ||||
| -rw-r--r-- | src/plugins/Ui/qsui/fft.h | 9 | ||||
| -rw-r--r-- | src/plugins/Ui/qsui/inlines.h | 31 | ||||
| -rw-r--r-- | src/plugins/Ui/qsui/logo.cpp | 25 | ||||
| -rw-r--r-- | src/plugins/Ui/qsui/logo.h | 6 | ||||
| -rw-r--r-- | src/plugins/Ui/qsui/qsuianalyzer.cpp | 44 | ||||
| -rw-r--r-- | src/plugins/Ui/qsui/qsuianalyzer.h | 10 |
8 files changed, 83 insertions, 60 deletions
diff --git a/src/plugins/Ui/Ui.pro b/src/plugins/Ui/Ui.pro index cf206d974..011ce94e7 100644 --- a/src/plugins/Ui/Ui.pro +++ b/src/plugins/Ui/Ui.pro @@ -7,6 +7,5 @@ SUBDIRS += skinned } contains(CONFIG, WITH_QSUI){ -#SUBDIRS += qsui +SUBDIRS += qsui } - diff --git a/src/plugins/Ui/qsui/fft.c b/src/plugins/Ui/qsui/fft.c index 0ea89eae6..2865e878e 100644 --- a/src/plugins/Ui/qsui/fft.c +++ b/src/plugins/Ui/qsui/fft.c @@ -25,6 +25,11 @@ * More optimisations. */ +/* + modifications compared to original code: + using float format for input data +*/ + #ifdef HAVE_CONFIG_H # include "config.h" #endif @@ -56,7 +61,7 @@ struct _struct_fft_state { /* # Local function prototypes # */ /* ############################# */ -static void fft_prepare(const sound_sample * input, float *re, float *im); +static void fft_prepare(const float *input, float *re, float *im); static void fft_calculate(float *re, float *im); static void fft_output(const float *re, const float *im, float *output); static int reverseBits(unsigned int initial); @@ -126,7 +131,7 @@ fft_init(void) * state is a (non-NULL) pointer returned by fft_init. */ void -fft_perform(const sound_sample * input, float *output, fft_state * state) +fft_perform(const float *input, float *output, fft_state * state) { /* Convert data from sound format to be ready for FFT */ fft_prepare(input, state->real, state->imag); @@ -156,7 +161,7 @@ fft_close(fft_state * state) * Prepare data to perform an FFT on */ static void -fft_prepare(const sound_sample * input, float *re, float *im) +fft_prepare(const float *input, float *re, float *im) { unsigned int i; float *realptr = re; @@ -164,7 +169,7 @@ fft_prepare(const sound_sample * input, float *re, float *im) /* Get input, in reverse bit order */ for (i = 0; i < FFT_BUFFER_SIZE; i++) { - *realptr++ = input[bitReverse[i]]; + *realptr++ = input[bitReverse[i]] * 32767.0; *imagptr++ = 0; } } @@ -174,7 +179,7 @@ fft_prepare(const sound_sample * input, float *re, float *im) * Note: only produces half as many data points as the input had. * This is roughly a consequence of the Nyquist sampling theorm thingy. * (FIXME - make this comment better, and helpful.) - * + * * The two divisions by 4 are also a consequence of this: the contributions * returned for each frequency are split into two parts, one at i in the * table, and the other at FFT_BUFFER_SIZE - i, except for i = 0 and diff --git a/src/plugins/Ui/qsui/fft.h b/src/plugins/Ui/qsui/fft.h index 915bccaf6..c24e2e584 100644 --- a/src/plugins/Ui/qsui/fft.h +++ b/src/plugins/Ui/qsui/fft.h @@ -23,8 +23,11 @@ #define FFT_BUFFER_SIZE (1 << FFT_BUFFER_SIZE_LOG) -/* sound sample - should be an signed 16 bit value */ -typedef short int sound_sample; +/* + modifications compared to original code: + using float format for input data +*/ + #ifdef __cplusplus extern "C" { @@ -33,7 +36,7 @@ extern "C" { /* FFT library */ typedef struct _struct_fft_state fft_state; fft_state *fft_init(void); - void fft_perform(const sound_sample * input, float *output, + void fft_perform(const float *input, float *output, fft_state * state); void fft_close(fft_state * state); diff --git a/src/plugins/Ui/qsui/inlines.h b/src/plugins/Ui/qsui/inlines.h index 39b81bd57..8203de336 100644 --- a/src/plugins/Ui/qsui/inlines.h +++ b/src/plugins/Ui/qsui/inlines.h @@ -4,13 +4,20 @@ // warranty, or liability of any kind. // +/* + modifications compared to original code: + using float format +*/ + #ifndef INLINES_H #define INLINES_H #include "fft.h" +#include <math.h> +#include <string.h> // *fast* convenience functions -static inline void calc_freq(short* dest, short *src) +static inline void calc_freq(short* dest, float *src) { static fft_state *state = NULL; float tmp_out[257]; @@ -25,11 +32,17 @@ static inline void calc_freq(short* dest, short *src) dest[i] = ((int) sqrt(tmp_out[i + 1])) >> 8; } -static inline void stereo16_from_multichannel(register short *l, - register short *r, - register short *s, +static inline void stereo_from_multichannel(float *l, + float *r, + float *s, long cnt, int chan) { + if(chan == 1) + { + memcpy(l, s, cnt * sizeof(float)); + memcpy(r, s, cnt * sizeof(float)); + return; + } while (cnt > 0) { l[0] = s[0]; @@ -41,10 +54,16 @@ static inline void stereo16_from_multichannel(register short *l, } } -static inline void mono16_from_multichannel(register short *l, - register short *s, +static inline void mono_from_multichannel(float *l, + float *s, long cnt, int chan) { + if(chan == 1) + { + memcpy(l, s, cnt * sizeof(float)); + return; + } + while (cnt > 0) { l[0] = s[0]; diff --git a/src/plugins/Ui/qsui/logo.cpp b/src/plugins/Ui/qsui/logo.cpp index 49ec2f275..1de6c663a 100644 --- a/src/plugins/Ui/qsui/logo.cpp +++ b/src/plugins/Ui/qsui/logo.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2011-2014 by Ilya Kotov * + * Copyright (C) 2011-2015 by Ilya Kotov * * forkotov02@hotmail.ru * * * * This program is free software; you can redistribute it and/or modify * @@ -23,6 +23,7 @@ #include <QTimer> #include <stdlib.h> #include <qmmp/qmmp.h> +#include "inlines.h" #include "logo.h" #define VISUAL_NODE_SIZE 128 //samples @@ -73,7 +74,7 @@ Logo::Logo(QWidget *parent) : Visual(parent) m_buffer_at = 0; m_value = 0; m_elapsed = 0; - m_buffer = new short[VISUAL_BUFFER_SIZE]; + m_buffer = new float[VISUAL_BUFFER_SIZE]; updateLetters(); Visual::add(this); @@ -82,20 +83,22 @@ Logo::Logo(QWidget *parent) : Visual(parent) Logo::~Logo() { Visual::remove(this); + delete[] m_buffer; } -void Logo::add(unsigned char *data, qint64 size, int chan) +void Logo::add(float *data, size_t samples, int chan) { Q_UNUSED(chan); if(VISUAL_BUFFER_SIZE == m_buffer_at) { m_buffer_at -= VISUAL_NODE_SIZE; - memmove(m_buffer, (short*) (m_buffer + VISUAL_NODE_SIZE), m_buffer_at * 2); + memmove(m_buffer, (m_buffer + VISUAL_NODE_SIZE), m_buffer_at * sizeof(float)); return; } - int size_2 = qMin((int)size/2, VISUAL_BUFFER_SIZE - m_buffer_at); - memcpy((ushort*)(m_buffer + m_buffer_at), (short*) data, size_2 * 2); - m_buffer_at += size_2; + int frames = qMin(int(samples/chan), VISUAL_BUFFER_SIZE - m_buffer_at); + + mono_from_multichannel(m_buffer + m_buffer_at, data, frames, chan); + m_buffer_at += frames; } void Logo::clear() @@ -239,11 +242,11 @@ void Logo::processPreset4() for(int j = 0; j < VISUAL_NODE_SIZE; j+=8) { if(m_buffer[j] > max) - max = m_buffer[j]; + max = abs(m_buffer[j] * 65536.0); } m_buffer_at -= VISUAL_NODE_SIZE; - memmove(m_buffer, m_buffer + VISUAL_NODE_SIZE, m_buffer_at * 2); + memmove(m_buffer, m_buffer + VISUAL_NODE_SIZE, m_buffer_at * sizeof(float)); m_value -= 512; m_value = qMax(m_value, max); } @@ -258,7 +261,7 @@ void Logo::processPreset4() while(k < m_value * count / 2048 / 16 / 2) { - int value = abs(m_buffer[qMin(at++, m_buffer_at)] / 2048); + int value = abs(m_buffer[qMin(at++, m_buffer_at)] * 16); line.replace(line.indexOf("X"), 1, QString("%1").arg(value, 0, 16).toUpper()); k++; } @@ -267,7 +270,7 @@ void Logo::processPreset4() while(k < m_value * count / 2048 / 16 / 2) { - int value = abs(m_buffer[qMin(at++, m_buffer_at)] / 2048); + int value = abs(m_buffer[qMin(at++, m_buffer_at)] * 16); line.replace(line.lastIndexOf("X"), 1, QString("%1").arg(value, 0, 16).toUpper()); k++; } diff --git a/src/plugins/Ui/qsui/logo.h b/src/plugins/Ui/qsui/logo.h index 9b2c6284b..15b50b539 100644 --- a/src/plugins/Ui/qsui/logo.h +++ b/src/plugins/Ui/qsui/logo.h @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2011-2014 by Ilya Kotov * + * Copyright (C) 2011-2015 by Ilya Kotov * * forkotov02@hotmail.ru * * * * This program is free software; you can redistribute it and/or modify * @@ -39,7 +39,7 @@ public: explicit Logo(QWidget *parent = 0); virtual ~Logo(); - void add(unsigned char *data, qint64 size, int chan); + void add(float *data, size_t samples, int chan); void clear(); private slots: @@ -55,7 +55,7 @@ private: QHash <QChar, QPixmap> m_letters; QStringList m_lines; QStringList m_source_lines; - short *m_buffer; + float *m_buffer; int m_buffer_at; int m_value; qint64 m_elapsed; diff --git a/src/plugins/Ui/qsui/qsuianalyzer.cpp b/src/plugins/Ui/qsui/qsuianalyzer.cpp index 04c867ce7..df3e733d6 100644 --- a/src/plugins/Ui/qsui/qsuianalyzer.cpp +++ b/src/plugins/Ui/qsui/qsuianalyzer.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2012-2014 by Ilya Kotov * + * Copyright (C) 2012-2015 by Ilya Kotov * * forkotov02@hotmail.ru * * * * This program is free software; you can redistribute it and/or modify * @@ -51,8 +51,8 @@ QSUiAnalyzer::QSUiAnalyzer (QWidget *parent) : Visual (parent) m_timer = new QTimer (this); connect(m_timer, SIGNAL (timeout()), this, SLOT (timeout())); - m_left_buffer = new short[VISUAL_BUFFER_SIZE]; - m_right_buffer = new short[VISUAL_BUFFER_SIZE]; + m_left_buffer = new float[VISUAL_BUFFER_SIZE]; + m_right_buffer = new float[VISUAL_BUFFER_SIZE]; readSettings(); clear(); @@ -91,7 +91,7 @@ QSize QSUiAnalyzer::sizeHint() const return QSize(200, 100); } -void QSUiAnalyzer::add (unsigned char *data, qint64 size, int chan) +void QSUiAnalyzer::add (float *data, size_t samples, int chan) { if (!m_timer->isActive ()) return; @@ -99,23 +99,16 @@ void QSUiAnalyzer::add (unsigned char *data, qint64 size, int chan) if(VISUAL_BUFFER_SIZE == m_buffer_at) { 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); + memmove(m_left_buffer, m_left_buffer + VISUAL_NODE_SIZE, m_buffer_at * sizeof(float)); + memmove(m_right_buffer, m_right_buffer + VISUAL_NODE_SIZE, m_buffer_at * sizeof(float)); return; } - int frames = qMin((int)size/chan >> 1, VISUAL_BUFFER_SIZE - m_buffer_at); + int frames = qMin(int(samples/chan), VISUAL_BUFFER_SIZE - m_buffer_at); + + stereo_from_multichannel(m_left_buffer + m_buffer_at, + m_right_buffer + m_buffer_at, data, frames, chan); - if (chan >= 2) - { - 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); - } m_buffer_at += frames; } @@ -157,8 +150,8 @@ void QSUiAnalyzer::hideEvent (QHideEvent *) void QSUiAnalyzer::showEvent (QShowEvent *) { - if(m_running) - m_timer->start(); + if(m_running) + m_timer->start(); } void QSUiAnalyzer::resizeEvent(QResizeEvent *) @@ -166,7 +159,7 @@ void QSUiAnalyzer::resizeEvent(QResizeEvent *) updateCover(); } -void QSUiAnalyzer::process (short *left, short *right) +void QSUiAnalyzer::process (float *left, float *right) { int rows = qMax((height() - 2) / m_cell_size.height(),2); int cols = qMax((width() - m_offset - 2) / m_cell_size.width(),1); @@ -196,11 +189,12 @@ void QSUiAnalyzer::process (short *left, short *right) short dest[256]; short y; int k, magnitude; - short data[512]; + float data[512]; for(int i = 0; i < VISUAL_NODE_SIZE; ++i) { - data[i] = (left[i] >> 1) + (right[i] >> 1); + data[i] = left[i] / 2 + right[i] / 2; + data[i] = qBound(-1.0f, data[i], 1.0f); } calc_freq (dest, data); @@ -407,13 +401,13 @@ void QSUiAnalyzer::writeSettings() void QSUiAnalyzer::start() { - m_running = true; + m_running = true; if(isVisible()) m_timer->start(); } void QSUiAnalyzer::stop() { - m_running = false; - m_timer->stop(); + m_running = false; + m_timer->stop(); } diff --git a/src/plugins/Ui/qsui/qsuianalyzer.h b/src/plugins/Ui/qsui/qsuianalyzer.h index 1c68e84f9..9dae2f9f1 100644 --- a/src/plugins/Ui/qsui/qsuianalyzer.h +++ b/src/plugins/Ui/qsui/qsuianalyzer.h @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2012-2013 by Ilya Kotov * + * Copyright (C) 2012-2015 by Ilya Kotov * * forkotov02@hotmail.ru * * * * This program is free software; you can redistribute it and/or modify * @@ -37,7 +37,7 @@ public: QSUiAnalyzer( QWidget *parent = 0); virtual ~QSUiAnalyzer(); - void add(unsigned char *data, qint64 size, int chan); + void add(float *data, size_t samples, int chan); void setCover(const QPixmap &pixmap); void clear(); void clearCover(); @@ -58,7 +58,7 @@ private: void hideEvent(QHideEvent *); void showEvent(QShowEvent *); void resizeEvent(QResizeEvent *); - void process(short *l, short *r); + void process(float *l, float *r); void draw(QPainter *p); void createMenu(); void updateCover(); @@ -73,8 +73,8 @@ private: double m_analyzer_falloff; bool m_show_peaks; bool m_show_cover; - short *m_left_buffer; - short *m_right_buffer; + float *m_left_buffer; + float *m_right_buffer; int m_buffer_at; int m_cols, m_rows; int m_offset; |
