GStreamer equalizer. Mostly working, just missing presets. Updates issue #166

This commit is contained in:
David Sansome 2010-04-07 16:26:04 +00:00
parent 256648f5e3
commit c6fe113e79
28 changed files with 1434 additions and 64 deletions

View File

@ -31,11 +31,13 @@ if(WIN32)
find_path(LIBXML_INCLUDE_DIRS libxml/parser.h
PATH_SUFFIXES libxml libxml2)
find_library(GSTREAMER_LIBRARIES gstreamer-0.10)
find_library(GSTREAMER_BASE_LIBRARIES gstbase-0.10)
find_library(GLIB_LIBRARIES glib-2.0)
find_library(GOBJECT_LIBRARIES gobject-2.0)
else(WIN32)
pkg_check_modules(TAGLIB taglib)
pkg_check_modules(GSTREAMER gstreamer-0.10)
pkg_check_modules(GSTREAMER_BASE gstreamer-base-0.10)
if (TAGLIB_VERSION VERSION_LESS 1.6)
message(FATAL_ERROR "Taglib version 1.6 or greater is required")

View File

@ -76,5 +76,6 @@
<file>osd_shadow_corner.png</file>
<file>osd_shadow_edge.png</file>
<file>schema-6.sql</file>
<file>list-add.png</file>
</qresource>
</RCC>

BIN
data/list-add.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 907 B

View File

@ -13,6 +13,7 @@ set(CLEMENTINE-SOURCES
playlistitem.cpp
engines/enginebase.cpp
engines/gstengine.cpp
engines/gstequalizer.cpp
analyzers/baranalyzer.cpp
analyzers/analyzerbase.cpp
fht.cpp
@ -68,6 +69,8 @@ set(CLEMENTINE-SOURCES
osdpretty.cpp
playlistdelegates.cpp
groupbydialog.cpp
equalizer.cpp
equalizerslider.cpp
)
# Header files that have Q_OBJECT in
@ -128,6 +131,8 @@ set(CLEMENTINE-MOC-HEADERS
osdpretty.h
playlistdelegates.h
groupbydialog.h
equalizer.h
equalizerslider.h
)
# UI files
@ -149,6 +154,8 @@ set(CLEMENTINE-UI
playlistsequence.ui
osdpretty.ui
groupbydialog.ui
equalizer.ui
equalizerslider.ui
)
# Resource files
@ -296,6 +303,7 @@ target_link_libraries(clementine_lib
${GOBJECT_LIBRARIES}
${GLIB_LIBRARIES}
${GSTREAMER_LIBRARIES}
${GSTREAMER_BASE_LIBRARIES}
${TAGLIB_LIBRARIES}
${QT_LIBRARIES}
)

View File

@ -204,20 +204,6 @@ namespace Engine
*/
void setXFadeNextTrack( bool enable ) { m_xfadeNextTrack = enable; }
/** Set whether equalizer is enabled
* You don't need to cache the parameters, setEqualizerParameters is called straight after this
* function, _always_.
*/
virtual void setEqualizerEnabled( bool ) {};
/** Set equalizer parameters, all in range -100..100, where 0 = no adjustment
* @param preamp the preamplification value
* @param bandGains a list of 10 integers, ascending in frequency, the exact frequencies you amplify
* are not too-important at this time
*/
virtual void setEqualizerParameters( int /*preamp*/, const QList<int> &/*bandGains*/ ) {};
/** Tries to retrieve metadata for the given url (called only if url
* is not in the collection). The intended usage is to retrieve
* information for AudiCD tracks when they are added to the playlist
@ -260,6 +246,19 @@ namespace Engine
public slots:
virtual void ReloadSettings() {}
/** Set whether equalizer is enabled
* You don't need to cache the parameters, setEqualizerParameters is called straight after this
* function, _always_.
*/
virtual void setEqualizerEnabled( bool ) {};
/** Set equalizer parameters, all in range -100..100, where 0 = no adjustment
* @param preamp the preamplification value
* @param bandGains a list of 10 integers, ascending in frequency, the exact frequencies you amplify
* are not too-important at this time
*/
virtual void setEqualizerParameters( int /*preamp*/, const QList<int> &/*bandGains*/ ) {};
protected:
Base();

View File

@ -21,8 +21,8 @@
#define DEBUG_PREFIX "Gst-Engine"
#include "enginebase.h"
#include "gstengine.h"
#include "gstequalizer.h"
#include <math.h>
#include <unistd.h>
@ -536,8 +536,7 @@ bool GstEngine::load(const QUrl& url, bool stream) {
setVolume(m_volume);
setEqualizerEnabled(equalizer_enabled_);
if (equalizer_enabled_)
setEqualizerParameters(equalizer_preamp_, equalizer_gains_);
setEqualizerParameters(equalizer_preamp_, equalizer_gains_);
return true;
}
@ -602,33 +601,31 @@ void GstEngine::seek( uint ms ) {
gst_element_get_state(gst_pipeline_, NULL, NULL, 100*GST_MSECOND);
}
void GstEngine::setEqualizerEnabled( bool enabled ) {
void GstEngine::setEqualizerEnabled(bool enabled) {
equalizer_enabled_= enabled;
RETURN_IF_PIPELINE_EMPTY;
//g_object_set( G_OBJECT( m_gst_equalizer ), "active", enabled, NULL );
g_object_set(G_OBJECT(gst_equalizer_), "active", enabled, NULL);
}
void GstEngine::setEqualizerParameters( int preamp, const QList<int>& bandGains ) {
void GstEngine::setEqualizerParameters( int preamp, const QList<int>& band_gains ) {
equalizer_preamp_ = preamp;
equalizer_gains_ = bandGains;
equalizer_gains_ = band_gains;
RETURN_IF_PIPELINE_EMPTY;
// BEGIN Preamp
//g_object_set( G_OBJECT( m_gst_equalizer ) , "preamp", ( preamp + 100 ) / 2 , NULL );
// END
// Preamp
g_object_set(G_OBJECT(gst_equalizer_), "preamp", ( preamp + 100 ) / 2, NULL);
// BEGIN Gains
// Gains
vector<int> gains_temp;
gains_temp.resize( bandGains.count() );
for ( int i = 0; i < bandGains.count(); i++ )
gains_temp[i] = ( bandGains.at( i ) + 100 ) / 2;
gains_temp.resize( band_gains.count() );
for ( int i = 0; i < band_gains.count(); i++ )
gains_temp[i] = band_gains.at( i ) + 100;
//g_object_set( G_OBJECT( m_gst_equalizer ), "gain", &gainsTemp, NULL );
// END
g_object_set(G_OBJECT(gst_equalizer_), "gain", &gains_temp, NULL);
}
void GstEngine::setVolumeSW( uint percent ) {
@ -763,8 +760,9 @@ bool GstEngine::CreatePipeline() {
return false;
}
/*m_gst_equalizer = GST_ELEMENT( gst_equalizer_new() );
gst_bin_add( GST_BIN( gst_audiobin_ ), m_gst_equalizer );*/
gst_equalizer_ = GST_ELEMENT(gst_equalizer_new());
gst_bin_add(GST_BIN(gst_audiobin_), gst_equalizer_);
if ( !( gst_audioconvert_ = CreateElement( "audioconvert", gst_audiobin_ ) ) ) { return false; }
if ( !( gst_identity_ = CreateElement( "identity", gst_audiobin_ ) ) ) { return false; }
if ( !( gst_volume_ = CreateElement( "volume", gst_audiobin_ ) ) ) { return false; }
@ -787,12 +785,12 @@ bool GstEngine::CreatePipeline() {
"width", G_TYPE_INT, 16,
"signed", G_TYPE_BOOLEAN, true,
NULL);
gst_element_link_filtered(gst_audioconvert_, gst_identity_, caps);
gst_element_link_filtered(gst_audioconvert_, gst_equalizer_, caps);
gst_caps_unref(caps);
/* link elements */
gst_element_link_many( gst_identity_, gst_volume_, gst_audioscale_,
gst_audiosink_, NULL );
gst_element_link_many( gst_equalizer_, gst_identity_, gst_volume_,
gst_audioscale_, gst_audiosink_, NULL );
gst_bin_add( GST_BIN(gst_pipeline_), gst_audiobin_);
//gst_bus_set_sync_handler(gst_pipeline_get_bus(GST_PIPELINE(gst_pipeline_)), bus_cb, NULL);

View File

@ -169,7 +169,7 @@ class GstEngine : public Engine::Base {
GstElement* gst_audiobin_;
GstElement* gst_audioconvert_;
//GstElement* gst_equalizer_;
GstElement* gst_equalizer_;
GstElement* gst_identity_;
GstElement* gst_volume_;
GstElement* gst_audioscale_;

View File

@ -0,0 +1,340 @@
// PCM time-domain equalizer
// (c) 2002 Felipe Rivera <liebremx at users sourceforge net>
// (c) 2004 Mark Kretschmann <markey@web.de>
// (c) 2006 Jakub Stachowski <qbast@go2.pl>
// License: GPL V2
#include "gstequalizer.h"
#include "iir_cf.h" // IIR filter coefficients
#include <cmath>
#include <cstring>
#include <vector>
#include <QtDebug>
GST_DEBUG_CATEGORY_STATIC ( gst_equalizer_debug );
#define GST_CAT_DEFAULT gst_equalizer_debug
/* signals and args */
enum {
LAST_SIGNAL
};
enum {
ARG_0,
ARG_ACTIVE,
ARG_PREAMP,
ARG_GAIN
};
static GstElementDetails gst_equalizer_details = {
const_cast<char*>("Equalizer"),
const_cast<char*>("Filter/Effect/Audio"),
const_cast<char*>("Parametric Equalizer"),
const_cast<char*>("Mark Kretschmann <markey@web.de>") };
GstStaticPadTemplate sink_template =
GST_STATIC_PAD_TEMPLATE ( (gchar*) "sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS (
"audio/x-raw-int, " \
"rate = (int) [ 1, MAX ], " \
"channels = (int) [ 1, MAX ], " \
"endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \
"width = (int) 16, " \
"depth = (int) 16, " \
"signed = (bool) TRUE "
)
);
GstStaticPadTemplate src_template =
GST_STATIC_PAD_TEMPLATE ( (gchar*) "src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_STATIC_CAPS (
"audio/x-raw-int, " \
"rate = (int) [ 1, MAX ], " \
"channels = (int) [ 1, MAX ], " \
"endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \
"width = (int) 16, " \
"depth = (int) 16, " \
"signed = (bool) TRUE"
)
);
// static guint gst_equalizer_signals[ LAST_SIGNAL ] = { 0 };
#define _do_init(bla) \
GST_DEBUG_CATEGORY_INIT (gst_equalizer_debug, "equalizer", 0, "equalizer element");
GST_BOILERPLATE_FULL ( GstEqualizer, gst_equalizer, GstBaseTransform, GST_TYPE_BASE_TRANSFORM, _do_init );
static gboolean gst_equalizer_set_caps (GstBaseTransform * base, GstCaps * incaps, GstCaps * outcaps);
static GstFlowReturn gst_equalizer_transform_ip (GstBaseTransform * base, GstBuffer * outbuf);
/////////////////////////////////////////////////////////////////////////////////////
// INIT
/////////////////////////////////////////////////////////////////////////////////////
void
gst_equalizer_base_init ( gpointer g_class )
{
qDebug() << __PRETTY_FUNCTION__;
GstElementClass * gstelement_class = GST_ELEMENT_CLASS ( g_class );
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&src_template));
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&sink_template));
gst_element_class_set_details ( gstelement_class, &gst_equalizer_details );
}
void
gst_equalizer_class_init ( GstEqualizerClass * klass )
{
qDebug() << __PRETTY_FUNCTION__;
GObjectClass* gobject_class;
gobject_class = G_OBJECT_CLASS( klass );
gobject_class->set_property = gst_equalizer_set_property;
gobject_class->get_property = gst_equalizer_get_property;
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ACTIVE, g_param_spec_boolean ("active", "active", "active", false, (GParamFlags)G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PREAMP, g_param_spec_int ("preamp", "preamp", "preamp", 0, 100, 0, (GParamFlags)G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_GAIN, g_param_spec_pointer ("gain", "gain", "gain", (GParamFlags)G_PARAM_WRITABLE));
GST_BASE_TRANSFORM_CLASS (klass)->transform_ip =
GST_DEBUG_FUNCPTR (gst_equalizer_transform_ip);
GST_BASE_TRANSFORM_CLASS (klass)->set_caps =
GST_DEBUG_FUNCPTR (gst_equalizer_set_caps);
}
void
gst_equalizer_init ( GstEqualizer* obj, GstEqualizerClass * klass )
{
qDebug() << __PRETTY_FUNCTION__;
// Properties
obj->active = false;
}
/////////////////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS
/////////////////////////////////////////////////////////////////////////////////////
static gboolean
gst_equalizer_set_caps (GstBaseTransform * base, GstCaps * incaps, GstCaps * outcaps)
{
GstEqualizer* obj = GST_EQUALIZER (base);
GstStructure* structure = gst_caps_get_structure (incaps, 0);
/* Since we're an audio filter, we want to handle raw audio
* and from that audio type, we need to get the samplerate and
* number of channels. */
gst_structure_get_int (structure, "rate", &obj->samplerate);
gst_structure_get_int (structure, "channels", &obj->channels);
// Load the correct filter table according to the sampling rate
set_filters( obj );
/* Zero the history arrays */
memset(obj->data_history, 0, sizeof(sXYData) * EQ_MAX_BANDS * EQ_CHANNELS);
qDebug() << "Samplerate " << obj->samplerate << ", channels: " << obj->channels;
return TRUE;
}
void
gst_equalizer_set_property ( GObject * object, guint prop_id, const GValue * value,
GParamSpec * pspec )
{
/* it's not null if we got it, but it might not be ours */
g_return_if_fail ( GST_IS_EQUALIZER ( object ) );
GstEqualizer* obj = GST_EQUALIZER ( object );
std::vector<int>* gains;
switch ( prop_id )
{
case ARG_ACTIVE:
obj->active = g_value_get_boolean (value);
break;
case ARG_PREAMP:
for ( int chan = 0; chan < EQ_CHANNELS; chan++ )
obj->preamp[chan] = (float)g_value_get_int(value) * 0.01;
break;
case ARG_GAIN:
gains = (std::vector<int>*) g_value_get_pointer(value);
for ( int band = 0; band < BAND_NUM; band++ )
for ( int chan = 0; chan < EQ_CHANNELS; chan++ )
obj->gain[band][chan] = (float)(*gains)[band] * 0.012 - 0.2;
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID ( object, prop_id, pspec );
break;
}
}
void
gst_equalizer_get_property ( GObject * object, guint prop_id, GValue * value, GParamSpec * pspec )
{
/* it's not null if we got it, but it might not be ours */
g_return_if_fail ( GST_IS_EQUALIZER ( object ) );
GstEqualizer* obj = GST_EQUALIZER ( object );
switch ( prop_id )
{
case ARG_ACTIVE:
g_value_set_boolean (value, obj->active);
break;
case ARG_PREAMP:
g_value_set_int(value, obj->preamp[0] * 100);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID ( object, prop_id, pspec );
break;
}
}
void
set_filters( GstEqualizer* obj )
{
switch(obj->samplerate)
{
case 11025:
obj->iir_cf = iir_cf10_11k_11025;
break;
case 22050:
obj->iir_cf = iir_cf10_22k_22050;
break;
case 48000:
obj->iir_cf = iir_cf10_48000;
break;
default:
obj->iir_cf = iir_cf10_44100;
break;
}
}
static GstFlowReturn
gst_equalizer_transform_ip (GstBaseTransform * base, GstBuffer * outbuf)
{
GstEqualizer* obj = GST_EQUALIZER ( base );
if ( !obj->active ) return GST_FLOW_OK;
gint16 *data = (gint16*)GST_BUFFER_DATA ( outbuf );
gint length = GST_BUFFER_SIZE( outbuf );
/* Indexes for the history arrays
* These have to be kept between calls to this function
* hence they are static */
static gint i = 0, j = 2, k = 1;
gint index, band, channel;
gint halflength;
float out[EQ_CHANNELS], pcm[EQ_CHANNELS];
float tempfloat;
/**
* IIR filter equation is
* y[n] = 2 * (alpha*(x[n]-x[n-2]) + gamma*y[n-1] - beta*y[n-2])
*
* NOTE: The 2 factor was introduced in the coefficients to save
* a multiplication
*
* This algorithm cascades two filters to get nice filtering
* at the expense of extra CPU cycles
*/
/* 16bit, 2 bytes per sample, so divide by two the length of
* the buffer (length is in bytes)
*/
halflength = (length >> 1);
for (index = 0; index < halflength; index+=2)
{
/* For each channel */
for (channel = 0; channel < obj->channels; channel++)
{
pcm[channel] = data[index+channel];
/* Preamp gain */
pcm[channel] *= obj->preamp[channel];
out[channel] = 0.;
/* For each band */
for (band = 0; band < BAND_NUM; band++)
{
/* Store Xi(n) */
obj->data_history[band][channel].x[i] = pcm[channel];
/* Calculate and store Yi(n) */
obj->data_history[band][channel].y[i] =
(
/* = alpha * [x(n)-x(n-2)] */
obj->iir_cf[band].alpha * ( obj->data_history[band][channel].x[i]
- obj->data_history[band][channel].x[k])
/* + gamma * y(n-1) */
+ obj->iir_cf[band].gamma * obj->data_history[band][channel].y[j]
/* - beta * y(n-2) */
- obj->iir_cf[band].beta * obj->data_history[band][channel].y[k]
);
/*
* The multiplication by 2.0 was 'moved' into the coefficients to save
* CPU cycles here */
/* Apply the gain */
out[channel] += obj->data_history[band][channel].y[i]*obj->gain[band][channel]; // * 2.0;
} /* For each band */
/* Volume stuff
Scale down original PCM sample and add it to the filters
output. This substitutes the multiplication by 0.25
Go back to use the floating point multiplication before the
conversion to give more dynamic range
*/
out[channel] += pcm[channel]*0.25;
/* Round and convert to integer and limit the output */
tempfloat = out[channel] < -32768.0 ? -32768.0 : out[channel];
tempfloat = tempfloat > 32767.0 ? 32767.0 : tempfloat;
data[index+channel] = (gint)rintf(tempfloat);
} /* For each channel */
i++; j++; k++;
/* Wrap around the indexes */
if (i == 3) i = 0;
else if (j == 3) j = 0;
else k = 0;
}/* For each pair of samples */
return GST_FLOW_OK;
}
GstEqualizer*
gst_equalizer_new ()
{
GstEqualizer* obj = GST_EQUALIZER ( g_object_new ( GST_TYPE_EQUALIZER, NULL ) );
gst_object_set_name( (GstObject*) obj, "Equalizer" );
return obj;
}

View File

@ -0,0 +1,91 @@
// PCM time-domain equalizer
// (c) 2002 Felipe Rivera <liebremx at users sourceforge net>
// (c) 2004 Mark Kretschmann <markey@web.de>
// License: GPL V2
#ifndef AMAROK_GST_EQUALIZER_H
#define AMAROK_GST_EQUALIZER_H
#include <gst/gst.h>
#include <gst/base/gstbasetransform.h>
G_BEGIN_DECLS
#define BAND_NUM 10
#define EQ_MAX_BANDS 10
#define EQ_CHANNELS 2
#define GST_TYPE_EQUALIZER \
(gst_equalizer_get_type())
#define GST_EQUALIZER(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_EQUALIZER,GstEqualizer))
#define GST_EQUALIZER_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_EQUALIZER,GstEqualizerClass))
#define GST_IS_EQUALIZER(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_EQUALIZER))
#define GST_IS_EQUALIZER_CLASS(obj) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_EQUALIZER))
typedef struct _GstEqualizer GstEqualizer;
typedef struct _GstEqualizerClass GstEqualizerClass;
// Floating point
typedef struct
{
float beta;
float alpha;
float gamma;
} sIIRCoefficients;
/* Coefficient history for the IIR filter */
typedef struct
{
float x[3]; /* x[n], x[n-1], x[n-2] */
float y[3]; /* y[n], y[n-1], y[n-2] */
} sXYData;
struct _GstEqualizer
{
// Do not remove
GstBaseTransform element;
GstPad *srcpad;
GstPad *sinkpad;
int samplerate;
int channels;
// Properties
bool active;
// Gain for each band
// values should be between -0.2 and 1.0
float gain[EQ_MAX_BANDS][EQ_CHANNELS] __attribute__((aligned));
// Volume gain
// values should be between 0.0 and 1.0
float preamp[EQ_CHANNELS] __attribute__((aligned));
// Coefficients
sIIRCoefficients* iir_cf;
sXYData data_history[EQ_MAX_BANDS][EQ_CHANNELS] __attribute__((aligned));
};
struct _GstEqualizerClass
{
GstBaseTransformClass parent_class;
/* signals */
};
void gst_equalizer_set_property( GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec );
void gst_equalizer_get_property( GObject * object, guint prop_id, GValue * value, GParamSpec * pspec );
void set_filters( GstEqualizer* obj );
GType gst_equalizer_get_type( void );
GstEqualizer* gst_equalizer_new();
G_END_DECLS
#endif /* AMAROK_GST_EQUALIZER_H */

433
src/engines/iir_cf.h Normal file
View File

@ -0,0 +1,433 @@
// IIR filter coefficient tables
/* BETA, ALPHA, GAMMA */
static sIIRCoefficients iir_cf10_11k_11025[] __attribute__((aligned)) = {
/* 31 Hz*/
{ 9.8758524689e-01, 6.2073765555e-03, 1.9872750693e+00 },
/* 62 Hz*/
{ 9.7532461998e-01, 1.2337690008e-02, 1.9740916593e+00 },
/* 125 Hz*/
{ 9.5087485437e-01, 2.4562572817e-02, 1.9459267562e+00 },
/* 250 Hz*/
{ 9.0416308662e-01, 4.7918456688e-02, 1.8848691023e+00 },
/* 500 Hz*/
{ 8.1751373987e-01, 9.1243130064e-02, 1.7442229115e+00 },
/* 1k Hz*/
{ 6.6840529852e-01, 1.6579735074e-01, 1.4047189863e+00 },
/* 2k Hz*/
{ 4.4858358977e-01, 2.7570820511e-01, 6.0517475334e-01 },
/* 3k Hz*/
{ 3.1012671838e-01, 3.4493664081e-01, -1.8141012760e-01 },
/* 4k Hz*/
{ 2.4198119087e-01, 3.7900940457e-01, -8.0845085113e-01 },
/* 5.5k Hz*/
{ 3.3453245058e-01, 3.3273377471e-01, -1.3344985880e+00 },
};
static sIIRCoefficients iir_cf10_22k_22050[] __attribute__((aligned)) = {
/* 31 Hz*/
{ 9.9377323686e-01, 3.1133815717e-03, 1.9936954495e+00 },
/* 62 Hz*/
{ 9.8758524689e-01, 6.2073765555e-03, 1.9872750693e+00 },
/* 125 Hz*/
{ 9.7512812040e-01, 1.2435939802e-02, 1.9738753198e+00 },
/* 250 Hz*/
{ 9.5087485437e-01, 2.4562572817e-02, 1.9459267562e+00 },
/* 500 Hz*/
{ 9.0416308662e-01, 4.7918456688e-02, 1.8848691023e+00 },
/* 1k Hz*/
{ 8.1751373987e-01, 9.1243130064e-02, 1.7442229115e+00 },
/* 2k Hz*/
{ 6.6840529852e-01, 1.6579735074e-01, 1.4047189863e+00 },
/* 4k Hz*/
{ 4.4858358977e-01, 2.7570820511e-01, 6.0517475334e-01 },
/* 8k Hz*/
{ 2.4198119087e-01, 3.7900940457e-01, -8.0845085113e-01 },
/* 11k Hz*/
{ 3.3453245058e-01, 3.3273377471e-01, -1.3344985880e+00 },
};
static sIIRCoefficients iir_cforiginal10_44100[] __attribute__((aligned)) = {
/* 60 Hz*/
{ 9.9397349481e-01, 3.0132525945e-03, 1.9939006377e+00 },
/* 170 Hz*/
{ 9.8301906957e-01, 8.4904652142e-03, 1.9824374272e+00 },
/* 310 Hz*/
{ 9.6925150511e-01, 1.5374247445e-02, 1.9673310395e+00 },
/* 600 Hz*/
{ 9.4134330314e-01, 2.9328348430e-02, 1.9342541736e+00 },
/* 1k Hz*/
{ 9.0416308662e-01, 4.7918456688e-02, 1.8848691023e+00 },
/* 3k Hz*/
{ 7.3918401009e-01, 1.3040799496e-01, 1.5827185140e+00 },
/* 6k Hz*/
{ 5.4688945509e-01, 2.2655527245e-01, 1.0152665639e+00 },
/* 12k Hz*/
{ 3.1012671838e-01, 3.4493664081e-01, -1.8141012760e-01 },
/* 14k Hz*/
{ 2.6712322292e-01, 3.6643838854e-01, -5.2115143966e-01 },
/* 16k Hz*/
{ 2.4198119087e-01, 3.7900940457e-01, -8.0845085113e-01 },
};
static sIIRCoefficients iir_cforiginal10_48000[] __attribute__((aligned)) = {
/* 60 Hz*/
{ 9.9446178985e-01, 2.7691050731e-03, 1.9944002760e+00 },
/* 170 Hz*/
{ 9.8438794122e-01, 7.8060293913e-03, 1.9838966333e+00 },
/* 310 Hz*/
{ 9.7171413384e-01, 1.4142933081e-02, 1.9700909975e+00 },
/* 600 Hz*/
{ 9.4597793866e-01, 2.7011030668e-02, 1.9399791381e+00 },
/* 1k Hz*/
{ 9.1159452679e-01, 4.4202736607e-02, 1.8952405706e+00 },
/* 3k Hz*/
{ 7.5755317065e-01, 1.2122341468e-01, 1.6237674017e+00 },
/* 6k Hz*/
{ 5.7422402554e-01, 2.1288798723e-01, 1.1131444836e+00 },
/* 12k Hz*/
{ 3.3730698905e-01, 3.3134650547e-01, 8.1883731790e-17 },
/* 14k Hz*/
{ 2.8947322018e-01, 3.5526338991e-01, -3.3374022753e-01 },
/* 16k Hz*/
{ 2.5620076154e-01, 3.7189961923e-01, -6.2810038077e-01 },
};
static sIIRCoefficients iir_cf10_44100[] __attribute__((aligned)) = {
/* 31 Hz*/
{ 9.9688176273e-01, 1.5591186337e-03, 1.9968622855e+00 },
/* 62 Hz*/
{ 9.9377323686e-01, 3.1133815717e-03, 1.9936954495e+00 },
/* 125 Hz*/
{ 9.8748575691e-01, 6.2571215431e-03, 1.9871705722e+00 },
/* 250 Hz*/
{ 9.7512812040e-01, 1.2435939802e-02, 1.9738753198e+00 },
/* 500 Hz*/
{ 9.5087485437e-01, 2.4562572817e-02, 1.9459267562e+00 },
/* 1k Hz*/
{ 9.0416308662e-01, 4.7918456688e-02, 1.8848691023e+00 },
/* 2k Hz*/
{ 8.1751373987e-01, 9.1243130064e-02, 1.7442229115e+00 },
/* 4k Hz*/
{ 6.6840529852e-01, 1.6579735074e-01, 1.4047189863e+00 },
/* 8k Hz*/
{ 4.4858358977e-01, 2.7570820511e-01, 6.0517475334e-01 },
/* 16k Hz*/
{ 2.4198119087e-01, 3.7900940457e-01, -8.0845085113e-01 },
};
static sIIRCoefficients iir_cf10_48000[] __attribute__((aligned)) = {
/* 31 Hz*/
{ 9.9713475915e-01, 1.4326204244e-03, 1.9971183163e+00 },
/* 62 Hz*/
{ 9.9427771143e-01, 2.8611442874e-03, 1.9942120343e+00 },
/* 125 Hz*/
{ 9.8849666727e-01, 5.7516663664e-03, 1.9882304829e+00 },
/* 250 Hz*/
{ 9.7712566171e-01, 1.1437169144e-02, 1.9760670839e+00 },
/* 500 Hz*/
{ 9.5477456091e-01, 2.2612719547e-02, 1.9505892385e+00 },
/* 1k Hz*/
{ 9.1159452679e-01, 4.4202736607e-02, 1.8952405706e+00 },
/* 2k Hz*/
{ 8.3100647694e-01, 8.4496761532e-02, 1.7686164442e+00 },
/* 4k Hz*/
{ 6.9062328809e-01, 1.5468835596e-01, 1.4641227157e+00 },
/* 8k Hz*/
{ 4.7820368352e-01, 2.6089815824e-01, 7.3910184176e-01 },
/* 16k Hz*/
{ 2.5620076154e-01, 3.7189961923e-01, -6.2810038077e-01 },
};
static sIIRCoefficients iir_cf15_44100[] __attribute__((aligned)) = {
/* 25 Hz*/
{ 9.9834072702e-01, 8.2963648917e-04, 1.9983280505e+00 },
/* 40 Hz*/
{ 9.9734652663e-01, 1.3267366865e-03, 1.9973140908e+00 },
/* 63 Hz*/
{ 9.9582396353e-01, 2.0880182333e-03, 1.9957435641e+00 },
/* 100 Hz*/
{ 9.9337951306e-01, 3.3102434709e-03, 1.9931771947e+00 },
/* 160 Hz*/
{ 9.8942832039e-01, 5.2858398053e-03, 1.9889114258e+00 },
/* 250 Hz*/
{ 9.8353109588e-01, 8.2344520610e-03, 1.9822729654e+00 },
/* 400 Hz*/
{ 9.7378088082e-01, 1.3109559588e-02, 1.9705764276e+00 },
/* 630 Hz*/
{ 9.5901979676e-01, 2.0490101620e-02, 1.9511333590e+00 },
/* 1k Hz*/
{ 9.3574903986e-01, 3.2125480071e-02, 1.9161350100e+00 },
/* 1.6k Hz*/
{ 8.9923630641e-01, 5.0381846793e-02, 1.8501014162e+00 },
/* 2.5k Hz*/
{ 8.4722457681e-01, 7.6387711593e-02, 1.7312785699e+00 },
/* 4k Hz*/
{ 7.6755471307e-01, 1.1622264346e-01, 1.4881981417e+00 },
/* 6.3k Hz*/
{ 6.6125377473e-01, 1.6937311263e-01, 1.0357747868e+00 },
/* 10k Hz*/
{ 5.2683267950e-01, 2.3658366025e-01, 2.2218349322e-01 },
/* 16k Hz*/
{ 4.0179628792e-01, 2.9910185604e-01, -9.1248032613e-01 },
};
static sIIRCoefficients iir_cf15_48000[] __attribute__((aligned)) = {
/* 25 Hz*/
{ 9.9847546664e-01, 7.6226668143e-04, 1.9984647656e+00 },
/* 40 Hz*/
{ 9.9756184654e-01, 1.2190767289e-03, 1.9975344645e+00 },
/* 63 Hz*/
{ 9.9616261379e-01, 1.9186931041e-03, 1.9960947369e+00 },
/* 100 Hz*/
{ 9.9391578543e-01, 3.0421072865e-03, 1.9937449618e+00 },
/* 160 Hz*/
{ 9.9028307215e-01, 4.8584639242e-03, 1.9898465702e+00 },
/* 250 Hz*/
{ 9.8485897264e-01, 7.5705136795e-03, 1.9837962543e+00 },
/* 400 Hz*/
{ 9.7588512657e-01, 1.2057436715e-02, 1.9731772447e+00 },
/* 630 Hz*/
{ 9.6228521814e-01, 1.8857390928e-02, 1.9556164694e+00 },
/* 1k Hz*/
{ 9.4080933132e-01, 2.9595334338e-02, 1.9242054384e+00 },
/* 1.6k Hz*/
{ 9.0702059196e-01, 4.6489704022e-02, 1.8653476166e+00 },
/* 2.5k Hz*/
{ 8.5868004289e-01, 7.0659978553e-02, 1.7600401337e+00 },
/* 4k Hz*/
{ 7.8409610788e-01, 1.0795194606e-01, 1.5450725522e+00 },
/* 6.3k Hz*/
{ 6.8332861002e-01, 1.5833569499e-01, 1.1426447155e+00 },
/* 10k Hz*/
{ 5.5267518228e-01, 2.2366240886e-01, 4.0186190803e-01 },
/* 16k Hz*/
{ 4.1811888447e-01, 2.9094055777e-01, -7.0905944223e-01 },
};
static sIIRCoefficients iir_cf25_44100[] __attribute__((aligned)) = {
/* 20 Hz*/
{ 9.9934037157e-01, 3.2981421662e-04, 1.9993322545e+00 },
/* 31.5 Hz*/
{ 9.9896129025e-01, 5.1935487310e-04, 1.9989411587e+00 },
/* 40 Hz*/
{ 9.9868118265e-01, 6.5940867495e-04, 1.9986487252e+00 },
/* 50 Hz*/
{ 9.9835175161e-01, 8.2412419683e-04, 1.9983010452e+00 },
/* 80 Hz*/
{ 9.9736411067e-01, 1.3179446674e-03, 1.9972343673e+00 },
/* 100 Hz*/
{ 9.9670622662e-01, 1.6468866919e-03, 1.9965035707e+00 },
/* 125 Hz*/
{ 9.9588448566e-01, 2.0577571681e-03, 1.9955679690e+00 },
/* 160 Hz*/
{ 9.9473519326e-01, 2.6324033689e-03, 1.9942169198e+00 },
/* 250 Hz*/
{ 9.9178600786e-01, 4.1069960678e-03, 1.9905226414e+00 },
/* 315 Hz*/
{ 9.8966154150e-01, 5.1692292513e-03, 1.9876580847e+00 },
/* 400 Hz*/
{ 9.8689036168e-01, 6.5548191616e-03, 1.9836646251e+00 },
/* 500 Hz*/
{ 9.8364027156e-01, 8.1798642207e-03, 1.9786090689e+00 },
/* 800 Hz*/
{ 9.7395577681e-01, 1.3022111597e-02, 1.9611472340e+00 },
/* 1k Hz*/
{ 9.6755437936e-01, 1.6222810321e-02, 1.9476180811e+00 },
/* 1.25k Hz*/
{ 9.5961458750e-01, 2.0192706249e-02, 1.9286193446e+00 },
/* 1.6k Hz*/
{ 9.4861481164e-01, 2.5692594182e-02, 1.8982024567e+00 },
/* 2.5k Hz*/
{ 9.2095325455e-01, 3.9523372724e-02, 1.8003794694e+00 },
/* 3.15k Hz*/
{ 9.0153642498e-01, 4.9231787512e-02, 1.7132251201e+00 },
/* 4k Hz*/
{ 8.7685876255e-01, 6.1570618727e-02, 1.5802270232e+00 },
/* 5k Hz*/
{ 8.4886734822e-01, 7.5566325889e-02, 1.3992391376e+00 },
/* 8k Hz*/
{ 7.7175298860e-01, 1.1412350570e-01, 7.4018523020e-01 },
/* 10k Hz*/
{ 7.2627049462e-01, 1.3686475269e-01, 2.5120552756e-01 },
/* 12.5k Hz*/
{ 6.7674787974e-01, 1.6162606013e-01, -3.4978377639e-01 },
/* 16k Hz*/
{ 6.2482197550e-01, 1.8758901225e-01, -1.0576558797e+00 },
/* 20k Hz*/
{ 6.1776148240e-01, 1.9111925880e-01, -1.5492465594e+00 },
};
static sIIRCoefficients iir_cf25_48000[] __attribute__((aligned)) = {
/* 20 Hz*/
{ 9.9939388451e-01, 3.0305774630e-04, 1.9993870327e+00 },
/* 31.5 Hz*/
{ 9.9904564663e-01, 4.7717668529e-04, 1.9990286528e+00 },
/* 40 Hz*/
{ 9.9878827195e-01, 6.0586402557e-04, 1.9987608731e+00 },
/* 50 Hz*/
{ 9.9848556942e-01, 7.5721528829e-04, 1.9984427652e+00 },
/* 80 Hz*/
{ 9.9757801538e-01, 1.2109923088e-03, 1.9974684869e+00 },
/* 100 Hz*/
{ 9.9697343933e-01, 1.5132803374e-03, 1.9968023538e+00 },
/* 125 Hz*/
{ 9.9621823598e-01, 1.8908820086e-03, 1.9959510180e+00 },
/* 160 Hz*/
{ 9.9516191728e-01, 2.4190413595e-03, 1.9947243453e+00 },
/* 250 Hz*/
{ 9.9245085008e-01, 3.7745749576e-03, 1.9913840669e+00 },
/* 315 Hz*/
{ 9.9049749914e-01, 4.7512504310e-03, 1.9888056233e+00 },
/* 400 Hz*/
{ 9.8794899744e-01, 6.0255012789e-03, 1.9852245824e+00 },
/* 500 Hz*/
{ 9.8495930023e-01, 7.5203498850e-03, 1.9807093500e+00 },
/* 800 Hz*/
{ 9.7604570090e-01, 1.1977149551e-02, 1.9652207158e+00 },
/* 1k Hz*/
{ 9.7014963927e-01, 1.4925180364e-02, 1.9532947360e+00 },
/* 1.25k Hz*/
{ 9.6283181641e-01, 1.8584091793e-02, 1.9366149237e+00 },
/* 1.6k Hz*/
{ 9.5268463224e-01, 2.3657683878e-02, 1.9100137880e+00 },
/* 2.5k Hz*/
{ 9.2711765003e-01, 3.6441174983e-02, 1.8248457659e+00 },
/* 3.15k Hz*/
{ 9.0912548757e-01, 4.5437256213e-02, 1.7491177803e+00 },
/* 4k Hz*/
{ 8.8619860800e-01, 5.6900696000e-02, 1.6334959111e+00 },
/* 5k Hz*/
{ 8.6010264114e-01, 6.9948679430e-02, 1.4757186436e+00 },
/* 8k Hz*/
{ 7.8757448309e-01, 1.0621275845e-01, 8.9378724155e-01 },
/* 10k Hz*/
{ 7.4415362476e-01, 1.2792318762e-01, 4.5142017567e-01 },
/* 12.5k Hz*/
{ 6.9581428034e-01, 1.5209285983e-01, -1.1091156053e-01 },
/* 16k Hz*/
{ 6.4120506488e-01, 1.7939746756e-01, -8.2060253244e-01 },
/* 20k Hz*/
{ 6.0884213704e-01, 1.9557893148e-01, -1.3932981614e+00 },
};
static sIIRCoefficients iir_cf31_44100[] __attribute__((aligned)) = {
/* 20 Hz*/
{ 9.9934037157e-01, 3.2981421662e-04, 1.9993322545e+00 },
/* 25 Hz*/
{ 9.9917555233e-01, 4.1222383516e-04, 1.9991628705e+00 },
/* 31.5 Hz*/
{ 9.9896129025e-01, 5.1935487310e-04, 1.9989411587e+00 },
/* 40 Hz*/
{ 9.9868118265e-01, 6.5940867495e-04, 1.9986487252e+00 },
/* 50 Hz*/
{ 9.9835175161e-01, 8.2412419683e-04, 1.9983010452e+00 },
/* 63 Hz*/
{ 9.9792365217e-01, 1.0381739160e-03, 1.9978431682e+00 },
/* 80 Hz*/
{ 9.9736411067e-01, 1.3179446674e-03, 1.9972343673e+00 },
/* 100 Hz*/
{ 9.9670622662e-01, 1.6468866919e-03, 1.9965035707e+00 },
/* 125 Hz*/
{ 9.9588448566e-01, 2.0577571681e-03, 1.9955679690e+00 },
/* 160 Hz*/
{ 9.9473519326e-01, 2.6324033689e-03, 1.9942169198e+00 },
/* 200 Hz*/
{ 9.9342335280e-01, 3.2883236020e-03, 1.9926141028e+00 },
/* 250 Hz*/
{ 9.9178600786e-01, 4.1069960678e-03, 1.9905226414e+00 },
/* 315 Hz*/
{ 9.8966154150e-01, 5.1692292513e-03, 1.9876580847e+00 },
/* 400 Hz*/
{ 9.8689036168e-01, 6.5548191616e-03, 1.9836646251e+00 },
/* 500 Hz*/
{ 9.8364027156e-01, 8.1798642207e-03, 1.9786090689e+00 },
/* 630 Hz*/
{ 9.7943153305e-01, 1.0284233476e-02, 1.9714629236e+00 },
/* 800 Hz*/
{ 9.7395577681e-01, 1.3022111597e-02, 1.9611472340e+00 },
/* 1k Hz*/
{ 9.6755437936e-01, 1.6222810321e-02, 1.9476180811e+00 },
/* 1.25k Hz*/
{ 9.5961458750e-01, 2.0192706249e-02, 1.9286193446e+00 },
/* 1.6k Hz*/
{ 9.4861481164e-01, 2.5692594182e-02, 1.8982024567e+00 },
/* 2k Hz*/
{ 9.3620971896e-01, 3.1895140519e-02, 1.8581325022e+00 },
/* 2.5k Hz*/
{ 9.2095325455e-01, 3.9523372724e-02, 1.8003794694e+00 },
/* 3.15k Hz*/
{ 9.0153642498e-01, 4.9231787512e-02, 1.7132251201e+00 },
/* 4k Hz*/
{ 8.7685876255e-01, 6.1570618727e-02, 1.5802270232e+00 },
/* 5k Hz*/
{ 8.4886734822e-01, 7.5566325889e-02, 1.3992391376e+00 },
/* 6.3k Hz*/
{ 8.1417575446e-01, 9.2912122771e-02, 1.1311200817e+00 },
/* 8k Hz*/
{ 7.7175298860e-01, 1.1412350570e-01, 7.4018523020e-01 },
/* 10k Hz*/
{ 7.2627049462e-01, 1.3686475269e-01, 2.5120552756e-01 },
/* 12.5k Hz*/
{ 6.7674787974e-01, 1.6162606013e-01, -3.4978377639e-01 },
/* 16k Hz*/
{ 6.2482197550e-01, 1.8758901225e-01, -1.0576558797e+00 },
/* 20k Hz*/
{ 6.1776148240e-01, 1.9111925880e-01, -1.5492465594e+00 },
};
static sIIRCoefficients iir_cf31_48000[] __attribute__((aligned)) = {
/* 20 Hz*/
{ 9.9939388451e-01, 3.0305774630e-04, 1.9993870327e+00 },
/* 25 Hz*/
{ 9.9924247917e-01, 3.7876041632e-04, 1.9992317740e+00 },
/* 31.5 Hz*/
{ 9.9904564663e-01, 4.7717668529e-04, 1.9990286528e+00 },
/* 40 Hz*/
{ 9.9878827195e-01, 6.0586402557e-04, 1.9987608731e+00 },
/* 50 Hz*/
{ 9.9848556942e-01, 7.5721528829e-04, 1.9984427652e+00 },
/* 63 Hz*/
{ 9.9809219264e-01, 9.5390367779e-04, 1.9980242502e+00 },
/* 80 Hz*/
{ 9.9757801538e-01, 1.2109923088e-03, 1.9974684869e+00 },
/* 100 Hz*/
{ 9.9697343933e-01, 1.5132803374e-03, 1.9968023538e+00 },
/* 125 Hz*/
{ 9.9621823598e-01, 1.8908820086e-03, 1.9959510180e+00 },
/* 160 Hz*/
{ 9.9516191728e-01, 2.4190413595e-03, 1.9947243453e+00 },
/* 200 Hz*/
{ 9.9395607757e-01, 3.0219612131e-03, 1.9932727986e+00 },
/* 250 Hz*/
{ 9.9245085008e-01, 3.7745749576e-03, 1.9913840669e+00 },
/* 315 Hz*/
{ 9.9049749914e-01, 4.7512504310e-03, 1.9888056233e+00 },
/* 400 Hz*/
{ 9.8794899744e-01, 6.0255012789e-03, 1.9852245824e+00 },
/* 500 Hz*/
{ 9.8495930023e-01, 7.5203498850e-03, 1.9807093500e+00 },
/* 630 Hz*/
{ 9.8108651246e-01, 9.4567437704e-03, 1.9743538683e+00 },
/* 800 Hz*/
{ 9.7604570090e-01, 1.1977149551e-02, 1.9652207158e+00 },
/* 1k Hz*/
{ 9.7014963927e-01, 1.4925180364e-02, 1.9532947360e+00 },
/* 1.25k Hz*/
{ 9.6283181641e-01, 1.8584091793e-02, 1.9366149237e+00 },
/* 1.6k Hz*/
{ 9.5268463224e-01, 2.3657683878e-02, 1.9100137880e+00 },
/* 2k Hz*/
{ 9.4122788957e-01, 2.9386055213e-02, 1.8750821533e+00 },
/* 2.5k Hz*/
{ 9.2711765003e-01, 3.6441174983e-02, 1.8248457659e+00 },
/* 3.15k Hz*/
{ 9.0912548757e-01, 4.5437256213e-02, 1.7491177803e+00 },
/* 4k Hz*/
{ 8.8619860800e-01, 5.6900696000e-02, 1.6334959111e+00 },
/* 5k Hz*/
{ 8.6010264114e-01, 6.9948679430e-02, 1.4757186436e+00 },
/* 6.3k Hz*/
{ 8.2760520925e-01, 8.6197395374e-02, 1.2405797786e+00 },
/* 8k Hz*/
{ 7.8757448309e-01, 1.0621275845e-01, 8.9378724155e-01 },
/* 10k Hz*/
{ 7.4415362476e-01, 1.2792318762e-01, 4.5142017567e-01 },
/* 12.5k Hz*/
{ 6.9581428034e-01, 1.5209285983e-01, -1.1091156053e-01 },
/* 16k Hz*/
{ 6.4120506488e-01, 1.7939746756e-01, -8.2060253244e-01 },
/* 20k Hz*/
{ 6.0884213704e-01, 1.9557893148e-01, -1.3932981614e+00 },
};

86
src/equalizer.cpp Normal file
View File

@ -0,0 +1,86 @@
/* This file is part of Clementine.
Clementine is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Clementine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "equalizer.h"
#include "equalizerslider.h"
#include <QSettings>
#include <QtDebug>
// We probably don't need to translate these, right?
const char* Equalizer::kGainText[] = {
"30", "60", "125", "250", "500", "1k", "2k", "4k", "8k", "16k"};
const char* Equalizer::kSettingsGroup = "Equalizer";
Equalizer::Equalizer(QWidget *parent)
: QDialog(parent)
{
ui_.setupUi(this);
connect(ui_.enable, SIGNAL(toggled(bool)), SIGNAL(EnabledChanged(bool)));
connect(ui_.enable, SIGNAL(toggled(bool)), ui_.slider_container, SLOT(setEnabled(bool)));
preamp_ = AddSlider(tr("Pre-amp"));
QFrame* line = new QFrame(ui_.slider_container);
line->setFrameShape(QFrame::VLine);
line->setFrameShadow(QFrame::Sunken);
ui_.slider_container->layout()->addWidget(line);
for (int i=0 ; i<kBands ; ++i)
gain_[i] = AddSlider(kGainText[i]);
}
void Equalizer::ReloadSettings() {
QSettings s;
s.beginGroup(kSettingsGroup);
ui_.enable->setChecked(s.value("enabled", false).toBool());
preamp_->set_value(s.value("preamp", 0).toInt());
for (int i=0 ; i<kBands ; ++i) {
gain_[i]->set_value(s.value("gain_" + QString::number(i+1), 0).toInt());
}
emit EnabledChanged(ui_.enable->isChecked());
ParametersChanged();
}
EqualizerSlider* Equalizer::AddSlider(const QString &label) {
EqualizerSlider* ret = new EqualizerSlider(label, ui_.slider_container);
ui_.slider_container->layout()->addWidget(ret);
connect(ret, SIGNAL(ValueChanged(int)), SLOT(ParametersChanged()));
return ret;
}
int Equalizer::preamp_value() const {
return preamp_->value();
}
QList<int> Equalizer::gain_values() const {
QList<int> ret;
for (int i=0 ; i<kBands ; ++i) {
ret << gain_[i]->value();
}
return ret;
}
void Equalizer::ParametersChanged() {
emit ParametersChanged(preamp_value(), gain_values());
}

59
src/equalizer.h Normal file
View File

@ -0,0 +1,59 @@
/* This file is part of Clementine.
Clementine is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Clementine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef EQUALIZER_H
#define EQUALIZER_H
#include <QDialog>
#include "ui_equalizer.h"
class EqualizerSlider;
class Equalizer : public QDialog {
Q_OBJECT
public:
Equalizer(QWidget *parent = 0);
static const int kBands = 10;
static const char* kGainText[kBands];
static const char* kSettingsGroup;
int preamp_value() const;
QList<int> gain_values() const;
public slots:
void ReloadSettings();
signals:
void EnabledChanged(bool enabled);
void ParametersChanged(int preamp, const QList<int>& band_gains);
private slots:
void ParametersChanged();
private:
EqualizerSlider* AddSlider(const QString& label);
private:
Ui::Equalizer ui_;
EqualizerSlider* preamp_;
EqualizerSlider* gain_[kBands];
};
#endif // EQUALIZER_H

90
src/equalizer.ui Normal file
View File

@ -0,0 +1,90 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Equalizer</class>
<widget class="QDialog" name="Equalizer">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>435</width>
<height>265</height>
</rect>
</property>
<property name="windowTitle">
<string>Equalizer</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Preset:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="preset">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="preset_add">
<property name="icon">
<iconset resource="../data/data.qrc">
<normaloff>:/list-add.png</normaloff>:/list-add.png</iconset>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="enable">
<property name="text">
<string>Enable equalizer</string>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="slider_container" native="true">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2"/>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>preset</tabstop>
<tabstop>preset_add</tabstop>
</tabstops>
<resources>
<include location="../data/data.qrc"/>
</resources>
<connections/>
</ui>

34
src/equalizerslider.cpp Normal file
View File

@ -0,0 +1,34 @@
/* This file is part of Clementine.
Clementine is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Clementine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "equalizerslider.h"
EqualizerSlider::EqualizerSlider(const QString& label, QWidget *parent)
: QWidget(parent)
{
ui_.setupUi(this);
ui_.label->setText(label);
connect(ui_.slider, SIGNAL(valueChanged(int)), SIGNAL(ValueChanged(int)));
}
int EqualizerSlider::value() const {
return ui_.slider->value();
}
void EqualizerSlider::set_value(int value) {
ui_.slider->setValue(value);
}

40
src/equalizerslider.h Normal file
View File

@ -0,0 +1,40 @@
/* This file is part of Clementine.
Clementine is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Clementine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef EQUALISERSLIDER_H
#define EQUALISERSLIDER_H
#include <QWidget>
#include "ui_equalizerslider.h"
class EqualizerSlider : public QWidget {
Q_OBJECT
public:
EqualizerSlider(const QString& label, QWidget *parent = 0);
int value() const;
void set_value(int value);
signals:
void ValueChanged(int value);
private:
Ui::EqualizerSlider ui_;
};
#endif // EQUALISERSLIDER_H

74
src/equalizerslider.ui Normal file
View File

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>EqualizerSlider</class>
<widget class="QWidget" name="EqualizerSlider">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>33</width>
<height>224</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="margin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QSlider" name="slider">
<property name="minimum">
<number>-100</number>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="label">
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -81,6 +81,7 @@ int main(int argc, char *argv[]) {
lastfm::ws::SharedSecret = LastFMService::kSecret;
QtSingleApplication a(argc, argv);
a.setQuitOnLastWindowClosed(false);
if (a.isRunning()) {
qDebug() << "Clementine is already running - activating existing window";

View File

@ -39,6 +39,7 @@
#include "playlistsequence.h"
#include "groupbydialog.h"
#include "engines/gstengine.h"
#include "equalizer.h"
#include "globalshortcuts/globalshortcuts.h"
@ -81,6 +82,7 @@ MainWindow::MainWindow(QNetworkAccessManager* network, QWidget *parent)
add_stream_dialog_(new AddStreamDialog(this)),
cover_manager_(new AlbumCoverManager(network, this)),
group_by_dialog_(new GroupByDialog(this)),
equalizer_(new Equalizer(this)),
playlist_menu_(new QMenu(this)),
library_sort_model_(new QSortFilterProxyModel(this)),
track_position_timer_(new QTimer(this))
@ -149,6 +151,7 @@ MainWindow::MainWindow(QNetworkAccessManager* network, QWidget *parent)
connect(ui_.action_add_media, SIGNAL(triggered()), SLOT(AddMedia()));
connect(ui_.action_add_stream, SIGNAL(triggered()), SLOT(AddStream()));
connect(ui_.action_cover_manager, SIGNAL(triggered()), cover_manager_, SLOT(show()));
connect(ui_.action_equalizer, SIGNAL(triggered()), equalizer_, SLOT(show()));
// Give actions to buttons
ui_.forward_button->setDefaultAction(ui_.action_next_track);
@ -339,6 +342,13 @@ MainWindow::MainWindow(QNetworkAccessManager* network, QWidget *parent)
// Analyzer
ui_.analyzer->set_engine(player_->GetEngine());
// Equalizer
connect(equalizer_, SIGNAL(ParametersChanged(int,QList<int>)),
player_->GetEngine(), SLOT(setEqualizerParameters(int,QList<int>)));
connect(equalizer_, SIGNAL(EnabledChanged(bool)),
player_->GetEngine(), SLOT(setEqualizerEnabled(bool)));
equalizer_->ReloadSettings();
// Statusbar widgets
playlist_->set_sequence(playlist_sequence_);
ui_.statusBar->addPermanentWidget(playlist_sequence_);
@ -536,9 +546,8 @@ void MainWindow::closeEvent(QCloseEvent* event) {
if (tray_icon_->isVisible()) {
event->ignore();
SetHiddenInTray(true);
}
else {
settings_.setValue("showtray", tray_icon_->isVisible());
} else {
QApplication::quit();
}
}

View File

@ -41,6 +41,7 @@ class AlbumCoverManager;
class PlaylistSequence;
class GlobalShortcuts;
class GroupByDialog;
class Equalizer;
class QSortFilterProxyModel;
class SystemTrayIcon;
@ -141,6 +142,7 @@ class MainWindow : public QMainWindow {
AddStreamDialog* add_stream_dialog_;
AlbumCoverManager* cover_manager_;
GroupByDialog* group_by_dialog_;
Equalizer* equalizer_;
QMenu* playlist_menu_;
QAction* playlist_play_pause_;

View File

@ -14,7 +14,7 @@
<string>Clementine</string>
</property>
<property name="windowIcon">
<iconset resource="../data/data.qrc">
<iconset>
<normaloff>:/icon.png</normaloff>:/icon.png</iconset>
</property>
<widget class="QWidget" name="centralWidget">
@ -298,7 +298,7 @@
<item>
<widget class="QToolButton" name="library_filter_clear">
<property name="icon">
<iconset resource="../data/data.qrc">
<iconset>
<normaloff>:/clear.png</normaloff>:/clear.png</iconset>
</property>
<property name="iconSize">
@ -322,7 +322,7 @@
<item>
<widget class="QToolButton" name="library_options">
<property name="icon">
<iconset resource="../data/data.qrc">
<iconset>
<normaloff>:/configure.png</normaloff>:/configure.png</iconset>
</property>
<property name="iconSize">
@ -492,6 +492,7 @@
<string>Tools</string>
</property>
<addaction name="action_cover_manager"/>
<addaction name="action_equalizer"/>
</widget>
<addaction name="menuMusic"/>
<addaction name="menuPlaylist"/>
@ -501,7 +502,7 @@
</widget>
<action name="action_previous_track">
<property name="icon">
<iconset resource="../data/data.qrc">
<iconset>
<normaloff>:/media-skip-backward.png</normaloff>:/media-skip-backward.png</iconset>
</property>
<property name="text">
@ -510,7 +511,7 @@
</action>
<action name="action_play_pause">
<property name="icon">
<iconset resource="../data/data.qrc">
<iconset>
<normaloff>:/media-playback-start.png</normaloff>:/media-playback-start.png</iconset>
</property>
<property name="text">
@ -522,7 +523,7 @@
<bool>false</bool>
</property>
<property name="icon">
<iconset resource="../data/data.qrc">
<iconset>
<normaloff>:/media-playback-stop.png</normaloff>:/media-playback-stop.png</iconset>
</property>
<property name="text">
@ -531,7 +532,7 @@
</action>
<action name="action_next_track">
<property name="icon">
<iconset resource="../data/data.qrc">
<iconset>
<normaloff>:/media-skip-forward.png</normaloff>:/media-skip-forward.png</iconset>
</property>
<property name="text">
@ -540,7 +541,7 @@
</action>
<action name="action_quit">
<property name="icon">
<iconset resource="../data/data.qrc">
<iconset>
<normaloff>:/exit.png</normaloff>:/exit.png</iconset>
</property>
<property name="text">
@ -552,7 +553,7 @@
</action>
<action name="action_stop_after_this_track">
<property name="icon">
<iconset resource="../data/data.qrc">
<iconset>
<normaloff>:/media-playback-stop.png</normaloff>:/media-playback-stop.png</iconset>
</property>
<property name="text">
@ -618,7 +619,7 @@
<bool>false</bool>
</property>
<property name="icon">
<iconset resource="../data/data.qrc">
<iconset>
<normaloff>:/last.fm/love.png</normaloff>:/last.fm/love.png</iconset>
</property>
<property name="text">
@ -630,7 +631,7 @@
<bool>false</bool>
</property>
<property name="icon">
<iconset resource="../data/data.qrc">
<iconset>
<normaloff>:/last.fm/ban.png</normaloff>:/last.fm/ban.png</iconset>
</property>
<property name="text">
@ -639,7 +640,7 @@
</action>
<action name="action_clear_playlist">
<property name="icon">
<iconset resource="../data/data.qrc">
<iconset>
<normaloff>:/clear-list.png</normaloff>:/clear-list.png</iconset>
</property>
<property name="text">
@ -651,7 +652,7 @@
</action>
<action name="action_edit_track">
<property name="icon">
<iconset resource="../data/data.qrc">
<iconset>
<normaloff>:/edit-track.png</normaloff>:/edit-track.png</iconset>
</property>
<property name="text">
@ -675,7 +676,7 @@
</action>
<action name="action_configure">
<property name="icon">
<iconset resource="../data/data.qrc">
<iconset>
<normaloff>:/configure.png</normaloff>:/configure.png</iconset>
</property>
<property name="text">
@ -689,7 +690,7 @@
</action>
<action name="action_shuffle">
<property name="icon">
<iconset resource="../data/data.qrc">
<iconset>
<normaloff>:/shuffle.png</normaloff>:/shuffle.png</iconset>
</property>
<property name="text">
@ -698,7 +699,7 @@
</action>
<action name="action_add_media">
<property name="icon">
<iconset resource="../data/data.qrc">
<iconset>
<normaloff>:/open_media.png</normaloff>:/open_media.png</iconset>
</property>
<property name="text">
@ -707,7 +708,7 @@
</action>
<action name="action_add_stream">
<property name="icon">
<iconset resource="../data/data.qrc">
<iconset>
<normaloff>:/open_stream.png</normaloff>:/open_stream.png</iconset>
</property>
<property name="text">
@ -716,7 +717,7 @@
</action>
<action name="action_open_media">
<property name="icon">
<iconset resource="../data/data.qrc">
<iconset>
<normaloff>:/open_media.png</normaloff>:/open_media.png</iconset>
</property>
<property name="text">
@ -725,7 +726,7 @@
</action>
<action name="action_cover_manager">
<property name="icon">
<iconset resource="../data/data.qrc">
<iconset>
<normaloff>:/download.png</normaloff>:/download.png</iconset>
</property>
<property name="text">
@ -734,7 +735,7 @@
</action>
<action name="action_shuffle_mode">
<property name="icon">
<iconset resource="../data/data.qrc">
<iconset>
<normaloff>:/media-playlist-shuffle.png</normaloff>:/media-playlist-shuffle.png</iconset>
</property>
<property name="text">
@ -743,7 +744,7 @@
</action>
<action name="action_repeat_mode">
<property name="icon">
<iconset resource="../data/data.qrc">
<iconset>
<normaloff>:/media-playlist-repeat.png</normaloff>:/media-playlist-repeat.png</iconset>
</property>
<property name="text">
@ -752,7 +753,7 @@
</action>
<action name="action_remove_from_playlist">
<property name="icon">
<iconset resource="../data/data.qrc">
<iconset>
<normaloff>:/list-remove.png</normaloff>:/list-remove.png</iconset>
</property>
<property name="text">
@ -815,6 +816,11 @@
<string>Advanced grouping...</string>
</property>
</action>
<action name="action_equalizer">
<property name="text">
<string>Equalizer</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
@ -856,8 +862,6 @@
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="../data/data.qrc"/>
</resources>
<resources/>
<connections/>
</ui>

View File

@ -400,6 +400,10 @@ msgstr "TrueAudio"
msgid "Stream"
msgstr "Proud"
#, fuzzy
msgid "Pre-amp"
msgstr "Proud"
msgid "Clementine"
msgstr "Clementine"
@ -508,6 +512,9 @@ msgstr ""
msgid "Advanced grouping..."
msgstr ""
msgid "Equalizer"
msgstr ""
msgid "Library"
msgstr "Knihovna"
@ -871,6 +878,12 @@ msgstr ""
msgid "Third level"
msgstr ""
msgid "Preset:"
msgstr ""
msgid "Enable equalizer"
msgstr ""
#~ msgid "&Hide tray icon"
#~ msgstr "S&krýt ikonu v systémovém panelu"

View File

@ -401,6 +401,10 @@ msgstr "TrueAudio"
msgid "Stream"
msgstr "Stream"
#, fuzzy
msgid "Pre-amp"
msgstr "Stream"
msgid "Clementine"
msgstr "Clementine"
@ -509,6 +513,9 @@ msgstr "Ομαδοποίηση κατά Είδος/Καλλιντέχνη/Άλμ
msgid "Advanced grouping..."
msgstr "Προχωρημένη ομαδοποίηση..."
msgid "Equalizer"
msgstr ""
msgid "Library"
msgstr "Βιβλιοθήκη"
@ -836,6 +843,12 @@ msgstr "Δεύτερο επίπεδο"
msgid "Third level"
msgstr "Τρίτο επίπεδο"
msgid "Preset:"
msgstr ""
msgid "Enable equalizer"
msgstr ""
#~ msgid "&Hide tray icon"
#~ msgstr "&Απόκρυψη εικονιδίου συστήματος"

View File

@ -401,6 +401,9 @@ msgstr ""
msgid "Stream"
msgstr ""
msgid "Pre-amp"
msgstr ""
msgid "Clementine"
msgstr "Clementine"
@ -509,6 +512,9 @@ msgstr "Agrupar por Género/Artista/Álbum"
msgid "Advanced grouping..."
msgstr "Agrupamiento avanzado..."
msgid "Equalizer"
msgstr ""
msgid "Library"
msgstr "Colección"
@ -879,6 +885,12 @@ msgstr "Segundo nivel"
msgid "Third level"
msgstr "Tercer nivel"
msgid "Preset:"
msgstr ""
msgid "Enable equalizer"
msgstr ""
#~ msgid "&Hide tray icon"
#~ msgstr "&Ocultar icono de la bandeja"

View File

@ -402,6 +402,10 @@ msgstr "TrueAudio"
msgid "Stream"
msgstr "Flux"
#, fuzzy
msgid "Pre-amp"
msgstr "Flux"
msgid "Clementine"
msgstr "Clementine"
@ -510,6 +514,9 @@ msgstr ""
msgid "Advanced grouping..."
msgstr ""
msgid "Equalizer"
msgstr ""
msgid "Library"
msgstr "Bibliothèque"
@ -876,6 +883,12 @@ msgstr ""
msgid "Third level"
msgstr ""
msgid "Preset:"
msgstr ""
msgid "Enable equalizer"
msgstr ""
#~ msgid "&Hide tray icon"
#~ msgstr "&Masquer l'icône"

View File

@ -399,6 +399,9 @@ msgstr ""
msgid "Stream"
msgstr ""
msgid "Pre-amp"
msgstr ""
msgid "Clementine"
msgstr ""
@ -507,6 +510,9 @@ msgstr "Grupuj według Gatunek/Artysta/Album"
msgid "Advanced grouping..."
msgstr "Zaawansowane grupowanie..."
msgid "Equalizer"
msgstr ""
msgid "Library"
msgstr "Biblioteka"
@ -869,5 +875,11 @@ msgstr "Drugi poziom"
msgid "Third level"
msgstr "Trzeci poziom"
msgid "Preset:"
msgstr ""
msgid "Enable equalizer"
msgstr ""
#~ msgid "&Hide tray icon"
#~ msgstr "&Ukryj ikonę w trayu"

View File

@ -400,6 +400,9 @@ msgstr ""
msgid "Stream"
msgstr ""
msgid "Pre-amp"
msgstr ""
msgid "Clementine"
msgstr "Clementine"
@ -508,6 +511,9 @@ msgstr ""
msgid "Advanced grouping..."
msgstr ""
msgid "Equalizer"
msgstr ""
msgid "Library"
msgstr "Коллекция"
@ -869,5 +875,11 @@ msgstr ""
msgid "Third level"
msgstr ""
msgid "Preset:"
msgstr ""
msgid "Enable equalizer"
msgstr ""
#~ msgid "Don't show notifications"
#~ msgstr "Не показывать"

View File

@ -400,6 +400,9 @@ msgstr ""
msgid "Stream"
msgstr ""
msgid "Pre-amp"
msgstr ""
msgid "Clementine"
msgstr ""
@ -508,6 +511,9 @@ msgstr "Zoradiť podľa žáner/interprét/album"
msgid "Advanced grouping..."
msgstr "Pokročilé zoraďovanie..."
msgid "Equalizer"
msgstr ""
msgid "Library"
msgstr "Zbierka"
@ -872,6 +878,12 @@ msgstr "Druhá úroveň"
msgid "Third level"
msgstr "Tretia úroveň"
msgid "Preset:"
msgstr ""
msgid "Enable equalizer"
msgstr ""
#~ msgid "&Hide tray icon"
#~ msgstr "&Skryť tray ikonu"

View File

@ -398,6 +398,9 @@ msgstr ""
msgid "Stream"
msgstr ""
msgid "Pre-amp"
msgstr ""
msgid "Clementine"
msgstr ""
@ -506,6 +509,9 @@ msgstr ""
msgid "Advanced grouping..."
msgstr ""
msgid "Equalizer"
msgstr ""
msgid "Library"
msgstr ""
@ -822,3 +828,9 @@ msgstr ""
msgid "Third level"
msgstr ""
msgid "Preset:"
msgstr ""
msgid "Enable equalizer"
msgstr ""