New Spectrum Analyzer (#4950)

Replace old spectrum analyzer by new one with higher resolution and
many new features.

Resolves #2847.
This commit is contained in:
Martin Pavelek
2019-07-17 22:45:26 +02:00
committed by Johannes Lorenz
parent 73c2c70d96
commit c3b4d5188a
42 changed files with 5329 additions and 751 deletions

View File

@@ -40,6 +40,8 @@ public:
EffectControlDialog( EffectControls * _controls );
virtual ~EffectControlDialog();
virtual bool isResizable() const {return false;}
signals:
void closed();

View File

@@ -30,7 +30,6 @@
#include <QGraphicsDropShadowEffect>
#include <QMdiSubWindow>
#include <QLabel>
#include <QPainter>
#include <QPushButton>
#include <QString>

View File

@@ -2,6 +2,7 @@
* fft_helpers.h - some functions around FFT analysis
*
* Copyright (c) 2008-2012 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2019 Martin Pavelek <he29.HS/at/gmail.com>
*
* This file is part of LMMS - https://lmms.io
*
@@ -28,57 +29,90 @@
#include "lmms_export.h"
#include <vector>
#include <fftw3.h>
const int FFT_BUFFER_SIZE = 2048;
// NOTE: FFT_BUFFER_SIZE should be considered deprecated!
// It is used by Eq plugin and some older code here, but this should be a user
// switchable parameter, not a constant. Use a value from FFT_BLOCK_SIZES
const unsigned int FFT_BUFFER_SIZE = 2048;
enum WINDOWS
// Allowed FFT block sizes. Ranging from barely useful to barely acceptable
// because of performance and latency reasons.
const std::vector<unsigned int> FFT_BLOCK_SIZES = {256, 512, 1024, 2048, 4096, 8192, 16384};
// List of FFT window functions supported by precomputeWindow()
enum FFT_WINDOWS
{
KAISER=1,
RECTANGLE,
HANNING,
HAMMING
RECTANGULAR = 0,
BLACKMAN_HARRIS,
HAMMING,
HANNING
};
/* returns biggest value from abs_spectrum[spec_size] array
/** Returns biggest value from abs_spectrum[spec_size] array.
*
* returns -1 on error
* @return -1 on error, 0 on success
*/
float LMMS_EXPORT maximum( float * _abs_spectrum, unsigned int _spec_size );
float LMMS_EXPORT maximum(const float *abs_spectrum, unsigned int spec_size);
float LMMS_EXPORT maximum(const std::vector<float> &abs_spectrum);
/* apply hanning or hamming window to channel
/** Normalize the abs_spectrum array of absolute values to a 0..1 range
* based on supplied energy and stores it in the norm_spectrum array.
*
* returns -1 on error
* @return -1 on error
*/
int LMMS_EXPORT hanming( float * _timebuffer, int _length, WINDOWS _type );
int LMMS_EXPORT normalize(const float *abs_spectrum, float *norm_spectrum, unsigned int bin_count, unsigned int block_size);
int LMMS_EXPORT normalize(const std::vector<float> &abs_spectrum, std::vector<float> &norm_spectrum, unsigned int block_size);
/* compute absolute values of complex_buffer, save to absspec_buffer
* take care that - compl_len is not bigger than complex_buffer!
* - absspec buffer is big enough!
/** Check if the spectrum contains any non-zero value.
*
* returns 0 on success, else -1
* @return 1 if spectrum contains any non-zero value
* @return 0 otherwise
*/
int LMMS_EXPORT absspec( fftwf_complex * _complex_buffer, float * _absspec_buffer,
int _compl_length );
int LMMS_EXPORT notEmpty(const std::vector<float> &spectrum);
/* build fewer subbands from many absolute spectrum values
* take care that - compressedbands[] array num_new elements long
* - num_old > num_new
/** Precompute a window function for later real-time use.
* Set normalized to false if you do not want to apply amplitude correction.
*
* returns 0 on success, else -1
* @return -1 on error
*/
int LMMS_EXPORT compressbands( float * _absspec_buffer, float * _compressedband,
int _num_old, int _num_new, int _bottom, int _top );
int LMMS_EXPORT precomputeWindow(float *window, unsigned int length, FFT_WINDOWS type, bool normalized = true);
int LMMS_EXPORT calc13octaveband31( float * _absspec_buffer, float * _subbands,
int _num_spec, float _max_frequency );
/* compute power of finite time sequence
* take care num_values is length of timesignal[]
/** Compute absolute values of complex_buffer, save to absspec_buffer.
* Take care that - compl_len is not bigger than complex_buffer!
* - absspec buffer is big enough!
*
* returns power on success, else -1
* @return 0 on success, else -1
*/
float LMMS_EXPORT signalpower(float *timesignal, int num_values);
int LMMS_EXPORT absspec(const fftwf_complex *complex_buffer, float *absspec_buffer,
unsigned int compl_length);
/** Build fewer subbands from many absolute spectrum values.
* Take care that - compressedbands[] array num_new elements long
* - num_old > num_new
*
* @return 0 on success, else -1
*/
int LMMS_EXPORT compressbands(const float * _absspec_buffer, float * _compressedband,
int _num_old, int _num_new, int _bottom, int _top);
int LMMS_EXPORT calc13octaveband31(float * _absspec_buffer, float * _subbands,
int _num_spec, float _max_frequency);
/** Compute power of finite time sequence.
* Take care num_values is length of timesignal[].
*
* @return power on success, else -1
*/
float LMMS_EXPORT signalpower(const float *timesignal, int num_values);
#endif