Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bring the default EQ into effect space #267

Merged
merged 24 commits into from
Jul 1, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
4f83970
Add eqeffect.cpp to sources list
badescunicu May 20, 2014
0240df2
Create an effect with a 3 band EQ
badescunicu May 20, 2014
30a76c8
Register EqEffect
badescunicu May 21, 2014
eea4913
Fix comment
badescunicu May 21, 2014
6261cd2
[Coding Style] Each member of a class should be on its own line
badescunicu May 21, 2014
644f539
Remove the link between the super knob and eq knobs
badescunicu May 21, 2014
039310d
Use the initializer list for old_low, old_mid, old_high, old_dry
badescunicu May 21, 2014
9814c14
Use a ControlObjectSlave to get the sample rate from the EqEffect
badescunicu May 23, 2014
5157f1b
Make the sample rate accessible from descendants of GroupEffectProcessor
badescunicu May 23, 2014
2d8edba
Connect the frequency corners from preferences to the EQ Effect
badescunicu May 23, 2014
4aedfad
Initialize m_loFreq and m_hiFreq with 0 in initializer list
badescunicu May 23, 2014
8a6546e
Fix typo in control.h
badescunicu May 24, 2014
b3d6c66
Do ramping after setFrequencyCorners() (not working properly yet)
badescunicu May 30, 2014
cdca2e1
Do a cross fade without using an additional buffer (not working prope…
badescunicu May 30, 2014
0f26499
Do not create new filters in setFilters(). Update previously created …
badescunicu Jun 1, 2014
986c970
Change the sample rate in setFrequencyCorners(). If frequency corners…
badescunicu Jun 1, 2014
5ca5d36
Pass the sample rate to setFrequencyCorners()
badescunicu Jun 1, 2014
120a805
Use memset and memcpy for copying and initializing buffers
badescunicu Jun 2, 2014
4236667
Rename EqEffect to EQDefault
badescunicu Jun 2, 2014
920f5f8
Rename EQ knobs to LOW, MID and HIGH
badescunicu Jun 2, 2014
1f16dce
Add descriptions to Default EQ and remove redundant includes
badescunicu Jun 2, 2014
dbec05d
Fix conflicts
badescunicu Jun 15, 2014
529b204
Remove RGBW mix; Daniel found out it is not working properly
badescunicu Jun 15, 2014
67408e3
Remove the dry mixing from EQDefault
badescunicu Jun 21, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build/depends.py
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,7 @@ def sources(self, build):

"effects/native/nativebackend.cpp",
"effects/native/bitcrushereffect.cpp",
"effects/native/eqdefault.cpp",
"effects/native/flangereffect.cpp",
"effects/native/filtereffect.cpp",
"effects/native/reverbeffect.cpp",
Expand Down
2 changes: 1 addition & 1 deletion src/control/control.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class ControlDoublePrivate : public QObject {

// Set the behavior to be used when setting values and translating between
// parameter and value space. Returns the previously set behavior (if any).
// The caller must nut delete the behavior at any time. The memory is managed
// The caller must not delete the behavior at any time. The memory is managed
// by this function.
void setBehavior(ControlNumericBehavior* pBehavior);

Expand Down
10 changes: 9 additions & 1 deletion src/effects/effectprocessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <QString>
#include <QMap>

#include "controlobjectslave.h"
#include "util/types.h"
#include "engine/effects/groupfeaturestate.h"

Expand Down Expand Up @@ -35,14 +36,17 @@ class EffectProcessor {
template <typename T>
class GroupEffectProcessor : public EffectProcessor {
public:
GroupEffectProcessor() {}
GroupEffectProcessor() {
m_pSampleRate = new ControlObjectSlave("[Master]", "samplerate");
}
virtual ~GroupEffectProcessor() {
for (typename QMap<QString, T*>::iterator it = m_groupState.begin();
it != m_groupState.end();) {
T* pState = it.value();
it = m_groupState.erase(it);
delete pState;
}
delete m_pSampleRate;
}

virtual void initialize(const QSet<QString>& registeredGroups) {
Expand Down Expand Up @@ -73,9 +77,13 @@ class GroupEffectProcessor : public EffectProcessor {
const CSAMPLE* pInput, CSAMPLE* pOutput,
const unsigned int numSamples,
const GroupFeatureState& groupFeatures) = 0;
int getSampleRate() {
return static_cast<int>(m_pSampleRate->get());
}

private:
QMap<QString, T*> m_groupState;
ControlObjectSlave* m_pSampleRate;
};

#endif /* EFFECTPROCESSOR_H */
180 changes: 180 additions & 0 deletions src/effects/native/eqdefault.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
#include "effects/native/eqdefault.h"
#include "util/math.h"

// static
QString EQDefault::getId() {
return "org.mixxx.effects.eqdefault";
}

// static
EffectManifest EQDefault::getManifest() {
EffectManifest manifest;
manifest.setId(getId());
manifest.setName(QObject::tr("Default EQ"));
manifest.setAuthor("The Mixxx Team");
manifest.setVersion("1.0");
manifest.setDescription("The default Equalizer featuring \
3 EngineFilterButterworth which can be modified from preferences");

EffectManifestParameter* low = manifest.addParameter();
low->setId("low");
low->setName(QObject::tr("Low"));
low->setDescription("Gain for Low Filter");
low->setControlHint(EffectManifestParameter::CONTROL_KNOB_LOGARITHMIC);
low->setValueHint(EffectManifestParameter::VALUE_FLOAT);
low->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN);
low->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN);
low->setDefault(1.0);
low->setMinimum(0);
low->setMaximum(4.0);

EffectManifestParameter* mid = manifest.addParameter();
mid->setId("mid");
mid->setName(QObject::tr("Mid"));
mid->setDescription("Gain for Band Filter");
mid->setControlHint(EffectManifestParameter::CONTROL_KNOB_LOGARITHMIC);
mid->setValueHint(EffectManifestParameter::VALUE_FLOAT);
mid->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN);
mid->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN);
mid->setDefault(1.0);
mid->setMinimum(0);
mid->setMaximum(4.0);

EffectManifestParameter* high = manifest.addParameter();
high->setId("high");
high->setName(QObject::tr("High"));
high->setDescription("Gain for High Filter");
high->setControlHint(EffectManifestParameter::CONTROL_KNOB_LOGARITHMIC);
high->setValueHint(EffectManifestParameter::VALUE_FLOAT);
high->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN);
high->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN);
high->setDefault(1.0);
high->setMinimum(0);
high->setMaximum(4.0);

return manifest;
}

EQDefaultGroupState::EQDefaultGroupState()
: low(NULL), band(NULL), high(NULL),old_low(1.0),
old_mid(1.0), old_high(1.0) {
m_pLowBuf = new CSAMPLE[MAX_BUFFER_LEN];
m_pBandBuf = new CSAMPLE[MAX_BUFFER_LEN];
m_pHighBuf = new CSAMPLE[MAX_BUFFER_LEN];

// Initialize filters with the default values
low = new EngineFilterButterworth8Low(44100, 246);
band = new EngineFilterButterworth8Band(44100, 246, 2484);
high = new EngineFilterButterworth8High(44100, 2484);
}

EQDefaultGroupState::~EQDefaultGroupState() {
delete low;
delete band;
delete high;
delete m_pLowBuf;
delete m_pBandBuf;
delete m_pHighBuf;
}

void EQDefaultGroupState::setFilters(int sampleRate, int lowFreq, int highFreq) {
low->setFrequencyCorners(sampleRate, lowFreq);
band->setFrequencyCorners(sampleRate, lowFreq, highFreq);
high->setFrequencyCorners(sampleRate, highFreq);
}

EQDefault::EQDefault(EngineEffect* pEffect,
const EffectManifest& manifest)
: m_pPotLow(pEffect->getParameterById("low")),
m_pPotMid(pEffect->getParameterById("mid")),
m_pPotHigh(pEffect->getParameterById("high")),
m_oldSampleRate(0), m_loFreq(0), m_hiFreq(0) {
Q_UNUSED(manifest);
m_pLoFreqCorner = new ControlObjectSlave("[Mixer Profile]", "LoEQFrequency");
m_pHiFreqCorner = new ControlObjectSlave("[Mixer Profile]", "HiEQFrequency");
}

EQDefault::~EQDefault() {
delete m_pLoFreqCorner;
delete m_pHiFreqCorner;
}

void EQDefault::processGroup(const QString& group,
EQDefaultGroupState* pState,
const CSAMPLE* pInput, CSAMPLE* pOutput,
const unsigned int numSamples,
const GroupFeatureState& groupFeatures) {
Q_UNUSED(group);
Q_UNUSED(groupFeatures);

float fLow = 0.f, fMid = 0.f, fHigh = 0.f;
fLow = m_pPotLow->value().toDouble();
fMid = m_pPotMid->value().toDouble();
fHigh = m_pPotHigh->value().toDouble();

int sampleRate = getSampleRate();
if (m_oldSampleRate != sampleRate ||
(m_loFreq != static_cast<int>(m_pLoFreqCorner->get())) ||
(m_hiFreq != static_cast<int>(m_pHiFreqCorner->get()))) {
m_loFreq = static_cast<int>(m_pLoFreqCorner->get());
m_hiFreq = static_cast<int>(m_pHiFreqCorner->get());
m_oldSampleRate = sampleRate;
pState->setFilters(sampleRate, m_loFreq, m_hiFreq);
}

// Process the new EQ'd signals.
// They use up to 16 frames history so in case we are just starting,
// 16 frames are junk, this is handled by ramp_delay
int ramp_delay = 0;
if (fLow || pState->old_low) {
pState->low->process(pInput, pState->m_pLowBuf, numSamples);
if(pState->old_low == 0) {
ramp_delay = 30;
}
}
if (fMid || pState->old_mid) {
pState->band->process(pInput, pState->m_pBandBuf, numSamples);
if(pState->old_mid== 0) {
ramp_delay = 30;
}
}
if (fHigh || pState->old_high) {
pState->high->process(pInput, pState->m_pHighBuf, numSamples);
if(pState->old_high == 0) {
ramp_delay = 30;
}
}

if (ramp_delay) {
// first use old gains
SampleUtil::copy3WithGain(pOutput,
pState->m_pLowBuf, pState->old_low,
pState->m_pBandBuf, pState->old_mid,
pState->m_pHighBuf, pState->old_high,
ramp_delay);
// Now ramp the remaining frames
SampleUtil::copy3WithRampingGain(&pOutput[ramp_delay],
&pState->m_pLowBuf[ramp_delay], pState->old_low, fLow,
&pState->m_pBandBuf[ramp_delay], pState->old_mid, fMid,
&pState->m_pHighBuf[ramp_delay], pState->old_high, fHigh,
numSamples - ramp_delay);
} else if (fLow != pState->old_low ||
fMid != pState->old_mid ||
fHigh != pState->old_high) {
SampleUtil::copy3WithRampingGain(pOutput,
pState->m_pLowBuf, pState->old_low, fLow,
pState->m_pBandBuf, pState->old_mid, fMid,
pState->m_pHighBuf, pState->old_high, fHigh,
numSamples);
} else {
SampleUtil::copy3WithGain(pOutput,
pState->m_pLowBuf, fLow,
pState->m_pBandBuf, fMid,
pState->m_pHighBuf, fHigh,
numSamples);
}

pState->old_low = fLow;
pState->old_mid = fMid;
pState->old_high = fHigh;
}
71 changes: 71 additions & 0 deletions src/effects/native/eqdefault.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#ifndef EQDEFAULT_H
#define EQDEFAULT_H

#include <QMap>

#include "controlobjectslave.h"
#include "effects/effect.h"
#include "effects/effectprocessor.h"
#include "engine/effects/engineeffect.h"
#include "engine/effects/engineeffectparameter.h"
#include "engine/enginefilterbutterworth8.h"
#include "util.h"
#include "util/types.h"
#include "util/defs.h"
#include "sampleutil.h"

class EQDefaultGroupState {
public:
EQDefaultGroupState();
~EQDefaultGroupState();

void setFilters(int sampleRate, int lowFreq, int highFreq);

EngineFilterButterworth8Low* low;
EngineFilterButterworth8Band* band;
EngineFilterButterworth8High* high;

double old_low;
double old_mid;
double old_high;

CSAMPLE* m_pLowBuf;
CSAMPLE* m_pBandBuf;
CSAMPLE* m_pHighBuf;
};

class EQDefault : public GroupEffectProcessor<EQDefaultGroupState> {
public:
EQDefault(EngineEffect* pEffect, const EffectManifest& manifest);
virtual ~EQDefault();

static QString getId();
static EffectManifest getManifest();

// See effectprocessor.h
void processGroup(const QString& group,
EQDefaultGroupState* pState,
const CSAMPLE* pInput, CSAMPLE *pOutput,
const unsigned int numSamples,
const GroupFeatureState& groupFeatureState);

private:
QString debugString() const {
return getId();
}

EngineEffectParameter* m_pPotLow;
EngineEffectParameter* m_pPotMid;
EngineEffectParameter* m_pPotHigh;

ControlObjectSlave* m_pLoFreqCorner;
ControlObjectSlave* m_pHiFreqCorner;

int m_oldSampleRate;
int m_loFreq;
int m_hiFreq;

DISALLOW_COPY_AND_ASSIGN(EQDefault);
};

#endif /* EQDEFAULT_H */
8 changes: 4 additions & 4 deletions src/effects/native/filtereffect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,14 +113,14 @@ void FilterEffect::processGroup(const QString& group,
// Freq from 2^5=32Hz to 2^(5+9)=16384
double freq = getLowFrequencyCorner(depth + 1.0);
double freq2 = getHighFrequencyCorner(depth + 1.0, bandpass_width);
pState->lowFilter.setFrequencyCorners(freq2);
pState->bandpassFilter.setFrequencyCorners(freq, freq2);
pState->lowFilter.setFrequencyCorners(44100, freq2);
pState->bandpassFilter.setFrequencyCorners(44100, freq, freq2);
} else if (depth > 0.0) {
// Highpass + bandpass
double freq = getLowFrequencyCorner(depth);
double freq2 = getHighFrequencyCorner(depth, bandpass_width);
pState->highFilter.setFrequencyCorners(freq);
pState->bandpassFilter.setFrequencyCorners(freq, freq2);
pState->highFilter.setFrequencyCorners(44100, freq);
pState->bandpassFilter.setFrequencyCorners(44100, freq, freq2);
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/effects/native/nativebackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "effects/native/nativebackend.h"
#include "effects/native/flangereffect.h"
#include "effects/native/bitcrushereffect.h"
#include "effects/native/eqdefault.h"
#include "effects/native/filtereffect.h"
#include "effects/native/reverbeffect.h"
#include "effects/native/echoeffect.h"
Expand All @@ -14,6 +15,7 @@ NativeBackend::NativeBackend(QObject* pParent)
registerEffect<FilterEffect>();
registerEffect<ReverbEffect>();
registerEffect<EchoEffect>();
registerEffect<EQDefault>();
}

NativeBackend::~NativeBackend() {
Expand Down
4 changes: 2 additions & 2 deletions src/engine/enginefilterblock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ EngineFilterBlock::EngineFilterBlock(const char* group)
m_pSampleRate = new ControlObjectSlave("[Master]", "samplerate");
m_iOldSampleRate = 0;

//Setup Filter Controls
// Setup Filter Controls

if (s_loEqFreq == NULL) {
s_loEqFreq = new ControlPotmeter(ConfigKey("[Mixer Profile]", "LoEQFrequency"), 0., 22040);
Expand All @@ -54,7 +54,7 @@ EngineFilterBlock::EngineFilterBlock(const char* group)

high = band = low = NULL;

//Load Defaults
// Load Defaults
setFilters(true);

/*
Expand Down
Loading