diff --git a/CMakeLists.txt b/CMakeLists.txt
index b49cd58218f..278fca7b278 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -527,41 +527,51 @@ add_library(mixxx-lib STATIC EXCLUDE_FROM_ALL
src/dialog/dlgkeywheel.ui
src/dialog/dlgreplacecuecolor.cpp
src/dialog/dlgreplacecuecolordlg.ui
- src/effects/builtin/autopaneffect.cpp
- src/effects/builtin/balanceeffect.cpp
- src/effects/builtin/bessel4lvmixeqeffect.cpp
- src/effects/builtin/bessel8lvmixeqeffect.cpp
- src/effects/builtin/biquadfullkilleqeffect.cpp
- src/effects/builtin/bitcrushereffect.cpp
- src/effects/builtin/builtinbackend.cpp
- src/effects/builtin/echoeffect.cpp
- src/effects/builtin/filtereffect.cpp
- src/effects/builtin/flangereffect.cpp
- src/effects/builtin/graphiceqeffect.cpp
- src/effects/builtin/linkwitzriley8eqeffect.cpp
- src/effects/builtin/loudnesscontoureffect.cpp
- src/effects/builtin/metronomeeffect.cpp
- src/effects/builtin/whitenoiseeffect.cpp
- src/effects/builtin/moogladder4filtereffect.cpp
- src/effects/builtin/parametriceqeffect.cpp
- src/effects/builtin/phasereffect.cpp
- src/effects/builtin/reverbeffect.cpp
- src/effects/builtin/threebandbiquadeqeffect.cpp
- src/effects/builtin/tremoloeffect.cpp
- src/effects/effect.cpp
src/effects/effectbuttonparameterslot.cpp
src/effects/effectchain.cpp
- src/effects/effectchainmanager.cpp
- src/effects/effectchainslot.cpp
- src/effects/effectmanifest.cpp
- src/effects/effectmanifestparameter.cpp
+ src/effects/effectchainmixmode.cpp
src/effects/effectparameter.cpp
- src/effects/effectparameterslot.cpp
+ src/effects/effectknobparameterslot.cpp
src/effects/effectparameterslotbase.cpp
- src/effects/effectrack.cpp
- src/effects/effectsbackend.cpp
src/effects/effectslot.cpp
src/effects/effectsmanager.cpp
+ src/effects/effectsmessenger.cpp
+ src/effects/visibleeffectslist.cpp
+ src/effects/backends/effectsbackend.cpp
+ src/effects/backends/effectmanifest.cpp
+ src/effects/backends/effectmanifestparameter.cpp
+ src/effects/backends/builtin/autopaneffect.cpp
+ src/effects/backends/builtin/balanceeffect.cpp
+ src/effects/backends/builtin/bessel4lvmixeqeffect.cpp
+ src/effects/backends/builtin/bessel8lvmixeqeffect.cpp
+ src/effects/backends/builtin/biquadfullkilleqeffect.cpp
+ src/effects/backends/builtin/bitcrushereffect.cpp
+ src/effects/backends/builtin/builtinbackend.cpp
+ src/effects/backends/builtin/echoeffect.cpp
+ src/effects/backends/builtin/filtereffect.cpp
+ src/effects/backends/builtin/flangereffect.cpp
+ src/effects/backends/builtin/graphiceqeffect.cpp
+ src/effects/backends/builtin/linkwitzriley8eqeffect.cpp
+ src/effects/backends/builtin/loudnesscontoureffect.cpp
+ src/effects/backends/builtin/metronomeeffect.cpp
+ src/effects/backends/builtin/moogladder4filtereffect.cpp
+ src/effects/backends/builtin/parametriceqeffect.cpp
+ src/effects/backends/builtin/phasereffect.cpp
+ src/effects/backends/builtin/reverbeffect.cpp
+ src/effects/backends/builtin/threebandbiquadeqeffect.cpp
+ src/effects/backends/builtin/tremoloeffect.cpp
+ src/effects/backends/builtin/whitenoiseeffect.cpp
+ src/effects/backends/effectsbackendmanager.cpp
+ src/effects/chains/equalizereffectchain.cpp
+ src/effects/chains/outputeffectchain.cpp
+ src/effects/chains/pergroupeffectchain.cpp
+ src/effects/chains/quickeffectchain.cpp
+ src/effects/chains/standardeffectchain.cpp
+ src/effects/presets/effectchainpreset.cpp
+ src/effects/presets/effectchainpresetmanager.cpp
+ src/effects/presets/effectparameterpreset.cpp
+ src/effects/presets/effectpreset.cpp
+ src/effects/presets/effectpresetmanager.cpp
src/encoder/encoder.cpp
src/encoder/encoderfdkaac.cpp
src/encoder/encoderfdkaacsettings.cpp
@@ -595,7 +605,6 @@ add_library(mixxx-lib STATIC EXCLUDE_FROM_ALL
src/engine/controls/ratecontrol.cpp
src/engine/effects/engineeffect.cpp
src/engine/effects/engineeffectchain.cpp
- src/engine/effects/engineeffectrack.cpp
src/engine/effects/engineeffectsmanager.cpp
src/engine/enginebuffer.cpp
src/engine/enginedelay.cpp
@@ -756,7 +765,6 @@ add_library(mixxx-lib STATIC EXCLUDE_FROM_ALL
src/preferences/dialog/dlgprefkeydlg.ui
src/preferences/dialog/dlgpreflibrary.cpp
src/preferences/dialog/dlgpreflibrarydlg.ui
- src/preferences/dialog/dlgpreflv2dlg.ui
src/preferences/dialog/dlgprefrecord.cpp
src/preferences/dialog/dlgprefrecorddlg.ui
src/preferences/dialog/dlgprefreplaygain.cpp
@@ -768,7 +776,8 @@ add_library(mixxx-lib STATIC EXCLUDE_FROM_ALL
src/preferences/dialog/dlgprefvinyldlg.ui
src/preferences/dialog/dlgprefwaveform.cpp
src/preferences/dialog/dlgprefwaveformdlg.ui
- src/preferences/effectsettingsmodel.cpp
+ src/preferences/effectchainpresetlistmodel.cpp
+ src/preferences/effectmanifesttablemodel.cpp
src/preferences/colorpaletteeditor.cpp
src/preferences/colorpaletteeditormodel.cpp
src/preferences/colorpalettesettings.cpp
@@ -868,6 +877,7 @@ add_library(mixxx-lib STATIC EXCLUDE_FROM_ALL
src/util/experiment.cpp
src/util/fileaccess.cpp
src/util/fileinfo.cpp
+ src/util/filename.cpp
src/util/imageutils.cpp
src/util/indexrange.cpp
src/util/logger.cpp
@@ -1006,13 +1016,15 @@ if(NOT QT6)
src/widget/wcoverartmenu.cpp
src/widget/wcuemenupopup.cpp
src/widget/wdisplay.cpp
- src/widget/weffect.cpp
- src/widget/weffectbuttonparameter.cpp
+ src/widget/weffectbuttonparametername.cpp
src/widget/weffectchain.cpp
- src/widget/weffectparameter.cpp
- src/widget/weffectparameterbase.cpp
+ src/widget/weffectchainpresetbutton.cpp
+ src/widget/weffectchainpresetselector.cpp
+ src/widget/weffectknobparametername.cpp
+ src/widget/weffectname.cpp
src/widget/weffectparameterknob.cpp
src/widget/weffectparameterknobcomposed.cpp
+ src/widget/weffectparameternamebase.cpp
src/widget/weffectpushbutton.cpp
src/widget/weffectselector.cpp
src/widget/whotcuebutton.cpp
@@ -1348,6 +1360,14 @@ install(
"${MIXXX_INSTALL_DATADIR}"
)
+# Effect presets
+install(
+ DIRECTORY
+ "${CMAKE_CURRENT_SOURCE_DIR}/res/effects"
+ DESTINATION
+ "${MIXXX_INSTALL_DATADIR}"
+)
+
# Translation files
install(
DIRECTORY
@@ -1552,7 +1572,6 @@ add_executable(mixxx-test
src/test/analyzersilence_test.cpp
src/test/audiotaperpot_test.cpp
src/test/autodjprocessor_test.cpp
- src/test/baseeffecttest.cpp
src/test/beatgridtest.cpp
src/test/beatmaptest.cpp
src/test/beatstest.cpp
@@ -1581,9 +1600,8 @@ add_executable(mixxx-test
src/test/directorydaotest.cpp
src/test/duration_test.cpp
src/test/durationutiltest.cpp
- src/test/effectchainslottest.cpp
- src/test/effectslottest.cpp
- src/test/effectsmanagertest.cpp
+ #TODO: write useful tests for refactored effects system
+ #src/test/effectchainslottest.cpp
src/test/enginebufferscalelineartest.cpp
src/test/enginebuffertest.cpp
src/test/enginefilterbiquadtest.cpp
@@ -1605,7 +1623,8 @@ add_executable(mixxx-test
src/test/main.cpp
src/test/mathutiltest.cpp
src/test/metadatatest.cpp
- src/test/metaknob_link_test.cpp
+ #TODO: make this build again
+ #src/test/metaknob_link_test.cpp
src/test/midicontrollertest.cpp
src/test/mixxxtest.cpp
src/test/movinginterquartilemean_test.cpp
@@ -2579,10 +2598,9 @@ if(LILV)
message(FATAL_ERROR "Lilv (LV2) support requires the liblilv-0 and its development headers.")
endif()
target_sources(mixxx-lib PRIVATE
- src/effects/lv2/lv2backend.cpp
- src/effects/lv2/lv2effectprocessor.cpp
- src/effects/lv2/lv2manifest.cpp
- src/preferences/dialog/dlgpreflv2.cpp
+ src/effects/backends/lv2/lv2backend.cpp
+ src/effects/backends/lv2/lv2effectprocessor.cpp
+ src/effects/backends/lv2/lv2manifest.cpp
)
target_compile_definitions(mixxx-lib PUBLIC __LILV__)
target_link_libraries(mixxx-lib PRIVATE lilv::lilv)
diff --git a/res/effects/chains/Echoverb HP.xml b/res/effects/chains/Echoverb HP.xml
new file mode 100644
index 00000000000..7c9a8db2b1f
--- /dev/null
+++ b/res/effects/chains/Echoverb HP.xml
@@ -0,0 +1,142 @@
+
+
+ Echoverb HP
+ DRY+WET
+ 0
+
+
+ 0
+ org.mixxx.effects.threebandbiquadeq
+ Built-In
+
+
+ low
+ 0.34375
+ NONE
+ 0
+ 0
+
+
+ mid
+ 1
+ NONE
+ 0
+ 0
+
+
+ high
+ 1
+ NONE
+ 0
+ 0
+
+
+ killLow
+ 0
+ NONE
+ 0
+ 0
+
+
+ killMid
+ 0
+ NONE
+ 0
+ 0
+
+
+ killHigh
+ 0
+ NONE
+ 0
+ 0
+
+
+
+
+ 0
+ org.mixxx.effects.echo
+ Built-In
+
+
+ delay_time
+ 0.5
+ NONE
+ 0
+ 0
+
+
+ feedback_amount
+ 0.707946
+ NONE
+ 0
+ 0
+
+
+ pingpong_amount
+ 0
+ NONE
+ 0
+ 0
+
+
+ send_amount
+ 0
+ LINKED
+ 0
+ 0
+
+
+ quantize
+ 1
+ NONE
+ 0
+ 0
+
+
+ triplet
+ 0
+ NONE
+ 0
+ 0
+
+
+
+
+ 0
+ org.mixxx.effects.reverb
+ Built-In
+
+
+ decay
+ 0.5
+ NONE
+ 0
+ 0
+
+
+ bandwidth
+ 1
+ NONE
+ 0
+ 0
+
+
+ damping
+ 0.277905
+ NONE
+ 0
+ 0
+
+
+ send_amount
+ 1
+ NONE
+ 0
+ 0
+
+
+
+
+
+
diff --git a/res/effects/chains/Filter Echo.xml b/res/effects/chains/Filter Echo.xml
new file mode 100644
index 00000000000..5dc15ccfa8c
--- /dev/null
+++ b/res/effects/chains/Filter Echo.xml
@@ -0,0 +1,87 @@
+
+
+ Filter Echo
+ DRY/WET
+ 0.5
+
+
+ 0.5
+ org.mixxx.effects.filter
+ Built-In
+
+
+ lpf
+ 22050
+ LINKED_LEFT
+ 0
+ 0
+
+
+ q
+ 0.707107
+ NONE
+ 0
+ 0
+
+
+ hpf
+ 13
+ LINKED_RIGHT
+ 0
+ 0
+
+
+
+
+ 0.5
+ org.mixxx.effects.echo
+ Built-In
+
+
+ delay_time
+ 1.0
+ NONE
+ 0
+ 0
+
+
+ feedback_amount
+ 0.707946
+ NONE
+ 0
+ 0
+
+
+ pingpong_amount
+ 0
+ NONE
+ 0
+ 0
+
+
+ send_amount
+ 0
+ LINKED_LEFT_RIGHT
+ 0
+ 0
+
+
+ quantize
+ 1
+ NONE
+ 0
+ 0
+
+
+ triplet
+ 0
+ NONE
+ 0
+ 0
+
+
+
+
+
+
+
diff --git a/res/effects/chains/Mid-Side.xml b/res/effects/chains/Mid-Side.xml
new file mode 100644
index 00000000000..2c7735b6fc6
--- /dev/null
+++ b/res/effects/chains/Mid-Side.xml
@@ -0,0 +1,39 @@
+
+
+ Mid/Side
+ DRY/WET
+ 0.5
+
+
+ 0.5
+ org.mixxx.effects.balance
+ Built-In
+
+
+ balance
+ 0
+ NONE
+ 0
+ 0
+
+
+ midSide
+ 0
+ LINKED
+ 0
+ 0
+
+
+ bypassFreq
+ 16
+ NONE
+ 0
+ 0
+
+
+
+
+
+
+
+
diff --git a/res/effects/chains/Side Reverb HP.xml b/res/effects/chains/Side Reverb HP.xml
new file mode 100644
index 00000000000..ba39975e88e
--- /dev/null
+++ b/res/effects/chains/Side Reverb HP.xml
@@ -0,0 +1,121 @@
+
+
+ Side Reverb HP
+ DRY+WET
+ 0
+
+
+ 0
+ org.mixxx.effects.threebandbiquadeq
+ Built-In
+
+
+ low
+ 0.28125
+ NONE
+ 0
+ 0
+
+
+ mid
+ 0.96875
+ NONE
+ 0
+ 0
+
+
+ high
+ 0.984375
+ NONE
+ 0
+ 0
+
+
+ killLow
+ 0
+ NONE
+ 0
+ 0
+
+
+ killMid
+ 0
+ NONE
+ 0
+ 0
+
+
+ killHigh
+ 0
+ NONE
+ 0
+ 0
+
+
+
+
+ 0
+ org.mixxx.effects.reverb
+ Built-In
+
+
+ decay
+ 0.690476
+ NONE
+ 0
+ 0
+
+
+ bandwidth
+ 1
+ NONE
+ 0
+ 0
+
+
+ damping
+ 0.15625
+ NONE
+ 0
+ 0
+
+
+ send_amount
+ 0
+ LINKED
+ 0
+ 0
+
+
+
+
+ 0
+ org.mixxx.effects.balance
+ Built-In
+
+
+ balance
+ -0.015625
+ NONE
+ 0
+ 0
+
+
+ midSide
+ 0.508312
+ NONE
+ 0
+ 0
+
+
+ bypassFreq
+ 26.0248
+ NONE
+ 0
+ 0
+
+
+
+
+
+
diff --git a/res/effects/chains/Smooth Growl.xml b/res/effects/chains/Smooth Growl.xml
new file mode 100644
index 00000000000..6f8ef614581
--- /dev/null
+++ b/res/effects/chains/Smooth Growl.xml
@@ -0,0 +1,107 @@
+
+
+ Smooth Growl
+ DRY/WET
+ 0
+
+
+ 0
+ org.mixxx.effects.bitcrusher
+ Built-In
+
+
+ bit_depth
+ 16
+ LINKED
+ 1
+ 0
+
+
+ downsample
+ 1
+ LINKED
+ 1
+ 0
+
+
+
+
+ 0
+ org.mixxx.effects.moogladder4filter
+ Built-In
+
+
+ lpf
+ 0.5
+ LINKED
+ 1
+ 0
+
+
+ resonance
+ 1.54534
+ NONE
+ 0
+ 0
+
+
+ hpf
+ 0.0003
+ NONE
+ 0
+ 0
+
+
+
+
+ 0
+ org.mixxx.effects.echo
+ Built-In
+
+
+ delay_time
+ 0.996914
+ NONE
+ 0
+ 0
+
+
+ feedback_amount
+ 0.707946
+ NONE
+ 0
+ 0
+
+
+ pingpong_amount
+ 0.169252
+ NONE
+ 0
+ 0
+
+
+ send_amount
+ 0
+ LINKED
+ 0
+ 0
+
+
+ quantize
+ 1
+ NONE
+ 0
+ 0
+
+
+ triplet
+ 0
+ NONE
+ 0
+ 0
+
+
+
+
+
+
diff --git a/res/qml/EffectSlot.qml b/res/qml/EffectSlot.qml
index f3004d376ba..da767a616bf 100644
--- a/res/qml/EffectSlot.qml
+++ b/res/qml/EffectSlot.qml
@@ -6,7 +6,7 @@ import "Theme"
Item {
id: root
- property Mixxx.EffectSlotProxy slot: Mixxx.EffectsManager.getEffectSlot(1, unitNumber, effectNumber)
+ property Mixxx.EffectSlotProxy slot: Mixxx.EffectsManager.getEffectSlot(unitNumber, effectNumber)
property int unitNumber // required
property int effectNumber // required
property bool expanded: false
@@ -111,8 +111,8 @@ Item {
// TODO: Use null coalescing when we switch to Qt >= 5.15
property string label: shortName ? shortName : name
property string key: controlKey
- property bool isButton: controlHint > 0 && controlHint == 6
- property bool isKnob: controlHint > 0 && controlHint < 6
+ property bool isKnob: type == 0
+ property bool isButton: type == 1
width: 50
height: 50
diff --git a/res/skins/Deere/effect_parameter_button.xml b/res/skins/Deere/effect_parameter_button.xml
index 220679253be..0a65466d64e 100644
--- a/res/skins/Deere/effect_parameter_button.xml
+++ b/res/skins/Deere/effect_parameter_button.xml
@@ -9,6 +9,7 @@
EffectButtonParameter: the button parameter
-->
+ [EffectRack_EffectUnit]
vertical
EffectButtonParameter
@@ -21,6 +22,9 @@
58,15
me,f
EffectButton
+
+
+
2
0
diff --git a/res/skins/Deere/effect_parameter_knob.xml b/res/skins/Deere/effect_parameter_knob.xml
index 2ca30c55852..2f73f9b4454 100644
--- a/res/skins/Deere/effect_parameter_knob.xml
+++ b/res/skins/Deere/effect_parameter_knob.xml
@@ -9,6 +9,7 @@
EffectParameter: the parameter
-->
+ [EffectRack_EffectUnit]
vertical
34,
@@ -26,6 +27,9 @@
knob_small.svg
-230
50
+
+
+
[EffectRack_EffectUnit_Effect],parameter
diff --git a/res/skins/Deere/equalizer_rack_parameter_left.xml b/res/skins/Deere/equalizer_rack_parameter_left.xml
index d0e67f0f5fe..ad2df1b208e 100644
--- a/res/skins/Deere/equalizer_rack_parameter_left.xml
+++ b/res/skins/Deere/equalizer_rack_parameter_left.xml
@@ -24,6 +24,9 @@
15f,20f
EQKillButton
2
+
+
+
0
@@ -63,6 +66,9 @@
-135
135
1.602
+
+
+
,parameter
diff --git a/res/skins/Deere/equalizer_rack_parameter_right.xml b/res/skins/Deere/equalizer_rack_parameter_right.xml
index 2ce0e4087c1..2e33904572b 100644
--- a/res/skins/Deere/equalizer_rack_parameter_right.xml
+++ b/res/skins/Deere/equalizer_rack_parameter_right.xml
@@ -32,6 +32,9 @@
-135
135
1.602
+
+
+
,parameter
@@ -44,6 +47,9 @@
15f,20f
EQKillButton
2
+
+
+
0
diff --git a/res/skins/Deere/style.qss b/res/skins/Deere/style.qss
index 33e40b8510c..db763b0ea9b 100644
--- a/res/skins/Deere/style.qss
+++ b/res/skins/Deere/style.qss
@@ -818,7 +818,7 @@ WTrackMenu,
WTrackMenu QMenu,
WTrackMenu QMenu QCheckBox,
WOverview /* Hotcue labels in the overview */,
-WEffect,
+WEffectName,
WEffectSelector,
WEffectSelector QAbstractScrollArea,
#fadeModeCombobox,
@@ -1230,7 +1230,7 @@ WBeatSpinBox,
qproperty-layoutSpacing: 2;
}
-#EffectMetaKnob, WEffect {
+#EffectMetaKnob, WEffectName {
font-size: 12px;
background-color: none;
border: none;
diff --git a/res/skins/LateNight/fx/parameter_button.xml b/res/skins/LateNight/fx/parameter_button.xml
index 3175bf4448a..275797f3d11 100644
--- a/res/skins/LateNight/fx/parameter_button.xml
+++ b/res/skins/LateNight/fx/parameter_button.xml
@@ -9,6 +9,7 @@
EffectParameter: the parameter
-->
+ [EffectRack1_EffectUnit]
[_Effect]
@@ -28,6 +29,9 @@
35f,20f
2
false
+
+
+
0
skin://buttons/btn__fx_parameter.svg
@@ -58,8 +62,7 @@
1me,0min
FxButtonLabel
- 1
-
+
center
diff --git a/res/skins/LateNight/fx/parameter_knob.xml b/res/skins/LateNight/fx/parameter_knob.xml
index a8e0f35ba2f..84ee2aa9087 100644
--- a/res/skins/LateNight/fx/parameter_knob.xml
+++ b/res/skins/LateNight/fx/parameter_knob.xml
@@ -9,6 +9,7 @@
EffectParameter: the parameter
-->
+ [EffectRack1_EffectUnit]
_Effect
@@ -29,6 +30,9 @@
skin://knobs/knob_bg_fx.svg
+
+
+
diff --git a/res/skins/LateNight/mixer/channel_4decks.xml b/res/skins/LateNight/mixer/channel_4decks.xml
index 0754836a817..9f665a85b03 100644
--- a/res/skins/LateNight/mixer/channel_4decks.xml
+++ b/res/skins/LateNight/mixer/channel_4decks.xml
@@ -1,5 +1,6 @@
[Channel]
+ [EqualizerRack1_]
[EqualizerRack1__Effect1]
regular
diff --git a/res/skins/LateNight/mixer/channel_left.xml b/res/skins/LateNight/mixer/channel_left.xml
index 492ab1f8ad7..a4c08f47a83 100644
--- a/res/skins/LateNight/mixer/channel_left.xml
+++ b/res/skins/LateNight/mixer/channel_left.xml
@@ -3,6 +3,7 @@ vertical layout and a side-by-side layout for two-deck mode -->
[Channel]
+ [EqualizerRack1_]
[EqualizerRack1__Effect1]
regular
diff --git a/res/skins/LateNight/mixer/channel_right.xml b/res/skins/LateNight/mixer/channel_right.xml
index 95b0fe58308..d49e0d3284b 100644
--- a/res/skins/LateNight/mixer/channel_right.xml
+++ b/res/skins/LateNight/mixer/channel_right.xml
@@ -3,6 +3,7 @@ vertical layout and a reversed side-by-side layout for two-deck mode -->
[Channel]
+ [EqualizerRack1_]
[EqualizerRack1__Effect1]
regular
diff --git a/res/skins/LateNight/mixer/eq_knob_4decks.xml b/res/skins/LateNight/mixer/eq_knob_4decks.xml
index 3402d5fa9e1..e048da3acf4 100644
--- a/res/skins/LateNight/mixer/eq_knob_4decks.xml
+++ b/res/skins/LateNight/mixer/eq_knob_4decks.xml
@@ -32,6 +32,9 @@
EQKillButton_
18f,18f
2
+
+ 1
+
0
skin://buttons/btn__eqkill.svg
@@ -81,6 +84,9 @@
1.998
+
+ 1
+
,parameter
diff --git a/res/skins/LateNight/mixer/eq_knob_left.xml b/res/skins/LateNight/mixer/eq_knob_left.xml
index b630f75cdf1..551f9788f41 100644
--- a/res/skins/LateNight/mixer/eq_knob_left.xml
+++ b/res/skins/LateNight/mixer/eq_knob_left.xml
@@ -23,6 +23,9 @@
EQKillButton_
18f,18f
2
+
+ 1
+
0
skin://buttons/btn__eqkill.svg
@@ -61,6 +64,9 @@
1.998
+
+ 1
+
,parameter
diff --git a/res/skins/LateNight/mixer/eq_knob_right.xml b/res/skins/LateNight/mixer/eq_knob_right.xml
index 4b2082421e5..cb2ed24d228 100644
--- a/res/skins/LateNight/mixer/eq_knob_right.xml
+++ b/res/skins/LateNight/mixer/eq_knob_right.xml
@@ -27,6 +27,9 @@
1.998
+
+ 1
+
,parameter
@@ -70,6 +73,9 @@
EQKillButton_
18f,18f
2
+
+ 1
+
0
skin://buttons/btn__eqkill.svg
diff --git a/res/skins/LateNight/style.qss b/res/skins/LateNight/style.qss
index b20fc09cb9c..3d0d17072be 100644
--- a/res/skins/LateNight/style.qss
+++ b/res/skins/LateNight/style.qss
@@ -19,7 +19,7 @@ WCueMenuPopup,
WCueMenuPopup QLabel,
WCueMenuPopup QLineEdit,
WOverview, /* Hotcue labels in the overview */
-WEffect,
+WEffectName,
WEffectSelector,
WEffectSelector QAbstractScrollArea,
#fadeModeCombobox,
diff --git a/res/skins/Shade/effect_parameter_button.xml b/res/skins/Shade/effect_parameter_button.xml
index a3d5bc249bb..c330878e682 100644
--- a/res/skins/Shade/effect_parameter_button.xml
+++ b/res/skins/Shade/effect_parameter_button.xml
@@ -9,59 +9,61 @@
EffectParameter: the parameter
-->
-
- EffectParameterButton
- vertical
- me,f
- 38,45
- 60,45
-
-
-
- right
- ButtonLabel
- 1
-
-
-
-
-
- vertical
- 38,26
-
-
- 2
-
- 0
- skin:/btn/btn_kill_down.png
- skin:/btn/btn_kill.png
-
-
- 1
- skin:/btn/btn_kill_overdown.png
- skin:/btn/btn_kill_over.png
-
- 11,57
-
- [EffectRack1_EffectUnit_Effect],button_parameter
- LeftButton
-
-
-
-
-
-
- [EffectRack1_EffectUnit_Effect],button_parameter_loaded
- visible
-
-
+ background-color: transparent;
+ color: #191F24;
+ padding-left: 1px;
+ }
+ QLabel { qproperty-alignment: AlignCenter; }
+
+ ButtonLabel
+ 1
+
+
+
+
+
+ vertical
+ 38,26
+
+
+
+
+
+ 2
+
+ 0
+ skin:/btn/btn_kill_down.png
+ skin:/btn/btn_kill.png
+
+
+ 1
+ skin:/btn/btn_kill_overdown.png
+ skin:/btn/btn_kill_over.png
+
+ 11,57
+
+ [EffectRack1_EffectUnit_Effect],button_parameter
+ LeftButton
+
+
+
+
+
+
+ [EffectRack1_EffectUnit_Effect],button_parameter_loaded
+ visible
+
+
diff --git a/res/skins/Shade/effect_parameter_knob.xml b/res/skins/Shade/effect_parameter_knob.xml
index 7a64bfefd42..709901caa0d 100644
--- a/res/skins/Shade/effect_parameter_knob.xml
+++ b/res/skins/Shade/effect_parameter_knob.xml
@@ -9,115 +9,115 @@
EffectParameter: the parameter
-->
-
- EffectParameterKnob
- vertical
- me,f
- 38,46
- -1,46
-
-
-
- right
- me,f
- -1,46
- KnobLabel
- 1
-
-
-
-
+ background-color: transparent;
+ color: #191F24;
+ padding-left: 1px;
+ }
+ QLabel { qproperty-alignment: AlignCenter; }
+
+ KnobLabel
+ 1
+
+
+
+
-
- vertical
-
-
- horizontal
-
-
- 64
- knobs_no_center/knob_rotary_s%1.png
-
- [EffectRack1_EffectUnit_Effect],parameter
-
-
-
-
+
+ vertical
+
+
+ horizontal
+
+
+ 64
+ knobs/knob_rotary_s%1.png
+
+
+
+
+ [EffectRack1_EffectUnit_Effect],parameter
+
+
+
+
-
- horizontal
-
+
+ horizontal
+
0min,0min
-
- EffectSlot_parameter_inversion
- 2
-
- 0
- skin:/btn_link_type/btn_link_inversion_off.png
- skin:/btn_link_type/btn_link_inversion_off.png
-
-
- 1
- skin:/btn_link_type/btn_link_inversion_on.png
- skin:/btn_link_type/btn_link_inversion_on.png
-
-
- [EffectRack1_EffectUnit_Effect],parameter_link_inverse
- LeftButton
-
-
-
- EffectSlot_parameter_link_type
- 5
-
- 0
- skin:/btn_link_type/btn_link_type_none.png
- skin:/btn_link_type/btn_link_type_none.png
-
-
- 1
- skin:/btn_link_type/btn_link_type_linked.png
- skin:/btn_link_type/btn_link_type_linked.png
-
-
- 2
- skin:/btn_link_type/btn_link_type_left.png
- skin:/btn_link_type/btn_link_type_left.png
-
-
- 3
- skin:/btn_link_type/btn_link_type_right.png
- skin:/btn_link_type/btn_link_type_right.png
-
-
- 4
- skin:/btn_link_type/btn_link_type_left_right.png
- skin:/btn_link_type/btn_link_type_left_right.png
-
-
- [EffectRack1_EffectUnit_Effect],parameter_link_type
- LeftButton
-
-
+
+ EffectSlot_parameter_inversion
+ 2
+
+ 0
+ skin:/btn_link_type/btn_link_inversion_off.png
+ skin:/btn_link_type/btn_link_inversion_off.png
+
+
+ 1
+ skin:/btn_link_type/btn_link_inversion_on.png
+ skin:/btn_link_type/btn_link_inversion_on.png
+
+
+ [EffectRack1_EffectUnit_Effect],parameter_link_inverse
+ LeftButton
+
+
+
+ EffectSlot_parameter_link_type
+ 5
+
+ 0
+ skin:/btn_link_type/btn_link_type_none.png
+ skin:/btn_link_type/btn_link_type_none.png
+
+
+ 1
+ skin:/btn_link_type/btn_link_type_linked.png
+ skin:/btn_link_type/btn_link_type_linked.png
+
+
+ 2
+ skin:/btn_link_type/btn_link_type_left.png
+ skin:/btn_link_type/btn_link_type_left.png
+
+
+ 3
+ skin:/btn_link_type/btn_link_type_right.png
+ skin:/btn_link_type/btn_link_type_right.png
+
+
+ 4
+ skin:/btn_link_type/btn_link_type_left_right.png
+ skin:/btn_link_type/btn_link_type_left_right.png
+
+
+ [EffectRack1_EffectUnit_Effect],parameter_link_type
+ LeftButton
+
+
0min,0min
-
-
-
-
+
+
+
+
-
-
- [EffectRack1_EffectUnit_Effect],parameter_loaded
- visible
-
-
+
+
+ [EffectRack1_EffectUnit_Effect],parameter_loaded
+ visible
+
+
diff --git a/res/skins/Shade/mixer_panel.xml b/res/skins/Shade/mixer_panel.xml
index 71db10c361a..91855abdec2 100644
--- a/res/skins/Shade/mixer_panel.xml
+++ b/res/skins/Shade/mixer_panel.xml
@@ -323,6 +323,9 @@
**********************************************
-->
+ [EqualizerRack1_[Channel1]]
+ 1
+ 3
2
0
@@ -346,6 +349,9 @@
+ [EqualizerRack1_[Channel1]]
+ 1
+ 2
2
0
@@ -369,6 +375,9 @@
+ [EqualizerRack1_[Channel1]]
+ 1
+ 1
2
0
@@ -393,6 +402,9 @@
+ [EqualizerRack1_[Channel1]]
+ 1
+ 3
2
0
@@ -416,6 +428,9 @@
+ [EqualizerRack1_[Channel1]]
+ 1
+ 2
2
0
@@ -439,6 +454,9 @@
+ [EqualizerRack1_[Channel1]]
+ 1
+ 1
2
0
@@ -703,6 +721,9 @@
+ [EqualizerRack1_[Channel1]]
+ 1
+ 3
64
knobs/knob_rotary_s%1.png
32,76
@@ -715,6 +736,9 @@
+ [EqualizerRack1_[Channel1]]
+ 1
+ 2
64
knobs/knob_rotary_s%1.png
32,105
@@ -727,6 +751,9 @@
+ [EqualizerRack1_[Channel1]]
+ 1
+ 1
64
knobs/knob_rotary_s%1.png
32,134
@@ -749,6 +776,9 @@
+ [EqualizerRack1_[Channel2]]
+ 1
+ 3
64
knobs/knob_rotary_s%1.png
197,76
@@ -761,6 +791,9 @@
+ [EqualizerRack1_[Channel2]]
+ 1
+ 2
filterMid
64
knobs/knob_rotary_s%1.png
@@ -774,6 +807,9 @@
+ [EqualizerRack1_[Channel2]]
+ 1
+ 1
filterLow
64
knobs/knob_rotary_s%1.png
diff --git a/res/skins/Shade/style.qss b/res/skins/Shade/style.qss
index 20fa46b8cc9..8a347f52063 100644
--- a/res/skins/Shade/style.qss
+++ b/res/skins/Shade/style.qss
@@ -14,7 +14,7 @@
padding: 5px 0px;
}
#Mixxx, WWidget,
-WEffect,
+WEffectName,
WKey,
WLabel, QLabel,
WNumber, WNumberPos,
diff --git a/res/skins/Tango/buttons/btn_fx_selector_list.svg b/res/skins/Tango/buttons/btn_menu_arrow.svg
similarity index 100%
rename from res/skins/Tango/buttons/btn_fx_selector_list.svg
rename to res/skins/Tango/buttons/btn_menu_arrow.svg
diff --git a/res/skins/Tango/buttons/btn_fx_selector_list_hover.svg b/res/skins/Tango/buttons/btn_menu_arrow_hover.svg
similarity index 100%
rename from res/skins/Tango/buttons/btn_fx_selector_list_hover.svg
rename to res/skins/Tango/buttons/btn_menu_arrow_hover.svg
diff --git a/res/skins/Tango/decks/deck_left.xml b/res/skins/Tango/decks/deck_left.xml
index 91d4bed5a13..d76bd6f103f 100644
--- a/res/skins/Tango/decks/deck_left.xml
+++ b/res/skins/Tango/decks/deck_left.xml
@@ -111,21 +111,23 @@ Variables:
-
+
+ 0i,22f
vertical
- me,i
- Spacer1e1me,3f
-
- horizontal
- me,i
-
- Spacer1e3f,1me
- RoundFiller251me,22me
-
-
+
+ EffectChainselectorLeft
+ 40me,22f
+ [QuickEffectRack1_]
+
+
+ [Skin],show_eq_knobs
+ visible
+
+
+ Spacer1e0min,0me
[Master],show_mixer
diff --git a/res/skins/Tango/decks/deck_right.xml b/res/skins/Tango/decks/deck_right.xml
index 4e1bf836ffe..1557a454270 100644
--- a/res/skins/Tango/decks/deck_right.xml
+++ b/res/skins/Tango/decks/deck_right.xml
@@ -147,21 +147,22 @@ Variables:
-
+
+ 0i,22f
vertical
- me,i
- Spacer1e1me,3f
-
- horizontal
- me,i
-
- RoundFiller251me,22me
- Spacer1e3f,1me
-
-
+
+ 40me,22f
+ [QuickEffectRack1_]
+
+
+ [Skin],show_eq_knobs
+ visible
+
+
+ Spacer1e0min,0me
[Master],show_mixer
diff --git a/res/skins/Tango/eq_button.xml b/res/skins/Tango/eq_button.xml
new file mode 100644
index 00000000000..68d1d5f368b
--- /dev/null
+++ b/res/skins/Tango/eq_button.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+ 2
+
+
+
+
+ 0
+ buttons/btn_.svg
+ buttons/btn_.svg
+
+
+ 1
+ buttons/btn_.svg
+ buttons/btn_.svg
+
+
+ ,button_parameter
+ LeftButton
+
+
+
diff --git a/res/skins/Tango/fx/button.xml b/res/skins/Tango/fx/button.xml
index 6857f28d162..ec45beb420f 100644
--- a/res/skins/Tango/fx/button.xml
+++ b/res/skins/Tango/fx/button.xml
@@ -18,6 +18,9 @@ Variables:
2
+
+
+
0
skin:../Tango/buttons/btn_.svg
@@ -29,7 +32,7 @@ Variables:
skin:../Tango/buttons/btn_.svg
- ,
+ ,button_parameter
LeftButton
diff --git a/res/skins/Tango/fx/parameter_button.xml b/res/skins/Tango/fx/parameter_button.xml
index c9b276f13a0..79ef425ccc4 100644
--- a/res/skins/Tango/fx/parameter_button.xml
+++ b/res/skins/Tango/fx/parameter_button.xml
@@ -11,24 +11,23 @@ Variables:
parameter : the parameter
-->
- [_Effect]
+ [_Effect]
- stacked
+ vertical
FxParameterButton
- 52f,26f
+ 52f,32f
- FxParameterButtonOverlay
+ []
+ FxParameterPushButton
51f,18f
- button_parameter
-
- 51f,18f
+ min,me
FxParameterButtonName
@@ -36,22 +35,11 @@ Variables:
center
right
-
- ,button_parameter
- highlight
-
-
-
-
- FxParameterButtonUnderlay
- 51f,18f
- button_parameter
-
- ,button_parameter_loaded
+ ,button_parameter_loaded
visible
diff --git a/res/skins/Tango/fx/parameter_knob.xml b/res/skins/Tango/fx/parameter_knob.xml
index ac2ebcb1b07..c2950bf3734 100644
--- a/res/skins/Tango/fx/parameter_knob.xml
+++ b/res/skins/Tango/fx/parameter_knob.xml
@@ -41,6 +41,9 @@ Variables:
1.500
+
+
+
,parameter
diff --git a/res/skins/Tango/fx/parameter_row.xml b/res/skins/Tango/fx/parameter_row.xml
index 049fc8c2ddb..33a4e14f9a7 100644
--- a/res/skins/Tango/fx/parameter_row.xml
+++ b/res/skins/Tango/fx/parameter_row.xml
@@ -15,59 +15,52 @@ Variables passed through from fx_unit:
1
-
- 1
-
-
2
-
- 2
-
-
3
-
- 3
-
-
4
-
- 4
-
-
5
-
- 5
-
-
6
-
- 6
-
-
7
-
- 7
-
-
8
+
+
+ 1
+
+
+ 2
+
+
+ 3
+
+
+ 4
+
+
+ 5
+
+
+ 6
+
+
+ 7
+
8
-
diff --git a/res/skins/Tango/fx/unit_left.xml b/res/skins/Tango/fx/unit_left.xml
index f209399c0d1..0bdf26fba28 100644
--- a/res/skins/Tango/fx/unit_left.xml
+++ b/res/skins/Tango/fx/unit_left.xml
@@ -232,10 +232,16 @@ Variables:
[EffectRack1_EffectUnit],mix_mode
- 1min,0me
+
+
+ 30f,18f
+ EffectChainSelector
+
+
+ 1min,2me
- min,min
+ min,me
vertical
@@ -246,6 +252,7 @@ Variables:
super1
blue
+ 0min,2me
[Skin],show_superknobs
@@ -253,14 +260,6 @@ Variables:
-
- min,me
-
- [Skin],show_superknobs
- visible
-
-
-
AlignCenter
min,max
diff --git a/res/skins/Tango/fx/unit_left_mini.xml b/res/skins/Tango/fx/unit_left_mini.xml
index 87bdda3795d..6900d4274ca 100644
--- a/res/skins/Tango/fx/unit_left_mini.xml
+++ b/res/skins/Tango/fx/unit_left_mini.xml
@@ -224,7 +224,20 @@ Variables:
-
+
+ AlignCenter
+ max,min
+ horizontal
+
+
+ EffectChainPresetButtonLeft
+
+ 18f,18f
+
+
+
+
+
MixModeButton
EffectUnit_mix_mode
30f,18f
diff --git a/res/skins/Tango/fx/unit_right.xml b/res/skins/Tango/fx/unit_right.xml
index 9e187c72f35..96b94a87c43 100644
--- a/res/skins/Tango/fx/unit_right.xml
+++ b/res/skins/Tango/fx/unit_right.xml
@@ -66,20 +66,27 @@ Variables:
[EffectRack1_EffectUnit],mix_mode
+
+
+ 30f,18f
+ EffectChainSelector
+
+
1min,0me
- min,min
+ min,me
vertical
EffectUnit_super1
SuperWetDryKnob
- 30f,30f
+ 30f,26f
[]
super1
blue
+ 0min,2me
[Skin],show_superknobs
@@ -87,14 +94,6 @@ Variables:
-
- min,me
-
- [Skin],show_superknobs
- visible
-
-
-
AlignCenter
min,max
diff --git a/res/skins/Tango/fx/unit_right_mini.xml b/res/skins/Tango/fx/unit_right_mini.xml
index edbf6acea67..4513e5ca6c9 100644
--- a/res/skins/Tango/fx/unit_right_mini.xml
+++ b/res/skins/Tango/fx/unit_right_mini.xml
@@ -58,6 +58,19 @@ Variables:
[EffectRack1_EffectUnit],mix_mode
+
+ AlignCenter
+ max,min
+ horizontal
+
+
+ EffectChainPresetButtonRight
+
+ 18f,18f
+
+
+
+
3f,1min
diff --git a/res/skins/Tango/mixer/eq_knob_left.xml b/res/skins/Tango/mixer/eq_knob_left.xml
index f3f862b2fcd..43f31e69f3c 100644
--- a/res/skins/Tango/mixer/eq_knob_left.xml
+++ b/res/skins/Tango/mixer/eq_knob_left.xml
@@ -9,8 +9,9 @@ Variables:
parameter : 1, 2, 3 (low, mid, high)
-->
+ [EqualizerRack1_]
1
- [EqualizerRack1__Effect1]
+ [EqualizerRack1__Effect]
EQKnobContainerLeft
@@ -27,10 +28,9 @@ Variables:
min,min
horizontal
-
+
EQKillButton
12f,30f
- button_parameter
@@ -51,22 +51,24 @@ Variables:
2.000
+
+
+
- ,parameter
+ ,parameter
-
+
EQKilledUnderlay
30f,26f
- button_parameter
- ,loaded
+ ,loaded
visible
@@ -74,7 +76,7 @@ Variables:
0min,26min
- ,loaded
+ ,loaded
visible
diff --git a/res/skins/Tango/mixer/eq_knob_right.xml b/res/skins/Tango/mixer/eq_knob_right.xml
index d64e2376883..d1778661157 100644
--- a/res/skins/Tango/mixer/eq_knob_right.xml
+++ b/res/skins/Tango/mixer/eq_knob_right.xml
@@ -9,8 +9,9 @@ Variables:
parameter : 1, 2, 3 (low, mid, high)
-->
+ [EqualizerRack1_]
1
- [EqualizerRack1__Effect1]
+ [EqualizerRack1__Effect]
EQKnobContainerRight
@@ -35,15 +36,17 @@ Variables:
2.000
+
+
+
- ,parameter
+ ,parameter
-
+
EQKilledUnderlay
30f,26f
- button_parameter
@@ -53,10 +56,9 @@ Variables:
min,min
horizontal
-
+
EQKillButton
12f,30f
- button_parameter
@@ -67,7 +69,7 @@ Variables:
- ,loaded
+ ,loaded
visible
@@ -75,7 +77,7 @@ Variables:
0min,26min
- ,loaded
+ ,loaded
visible
diff --git a/res/skins/Tango/mixer/quick_fx_knob_left.xml b/res/skins/Tango/mixer/quick_fx_knob_left.xml
index 9a6fd4be6c8..dec6a06d7b1 100644
--- a/res/skins/Tango/mixer/quick_fx_knob_left.xml
+++ b/res/skins/Tango/mixer/quick_fx_knob_left.xml
@@ -40,7 +40,7 @@ Variables:
QuickEffectRack_enabled
QuickFXButton
12f,24f
- ,enabled
+ ,enabled
@@ -99,7 +99,7 @@ Variables:
QuickEffectRack_enabled
QuickFXButton
24f,12f
- ,enabled
+ ,enabled
@@ -126,7 +126,7 @@ Variables:
QuickEffectRack_enabled
QuickFXButton
24f,12f
- ,enabled
+ ,enabled
@@ -138,20 +138,7 @@ Variables:
-
- ,loaded
- visible
-
-
-
- 0min,30f
-
- ,loaded
-
- visible
-
-
diff --git a/res/skins/Tango/mixer/quick_fx_knob_right.xml b/res/skins/Tango/mixer/quick_fx_knob_right.xml
index cf86ed3eafd..ba60e0b4b0c 100644
--- a/res/skins/Tango/mixer/quick_fx_knob_right.xml
+++ b/res/skins/Tango/mixer/quick_fx_knob_right.xml
@@ -45,7 +45,7 @@ Variables:
QuickFxDisabledUnderlay
30f,26f
- ,enabled
+ ,enabled
@@ -66,7 +66,7 @@ Variables:
QuickEffectRack_enabled
QuickFXButton
12f,24f
- ,enabled
+ ,enabled
@@ -99,7 +99,7 @@ Variables:
QuickEffectRack_enabled
QuickFXButton
24f,12f
- ,enabled
+ ,enabled
@@ -126,7 +126,7 @@ Variables:
QuickEffectRack_enabled
QuickFXButton
24f,12f
- ,enabled
+ ,enabled
@@ -138,20 +138,7 @@ Variables:
-
- ,loaded
- visible
-
-
-
- 0min,30f
-
- ,loaded
-
- visible
-
-
diff --git a/res/skins/Tango/style.qss b/res/skins/Tango/style.qss
index 278abc22da4..526e4174472 100644
--- a/res/skins/Tango/style.qss
+++ b/res/skins/Tango/style.qss
@@ -27,9 +27,11 @@ QSpinBox,
WBeatSpinBox,
WOverview #PassthroughLabel,
WCueMenuPopup,
-WEffect,
+WEffectName,
WEffectSelector,
WEffectSelector QAbstractScrollArea,
+WEffectChainPresetSelector,
+WEffectChainPresetSelector QAbstractScrollArea,
#fadeModeCombobox,
#fadeModeCombobox QAbstractScrollArea,
WLibraryTextBrowser,
@@ -607,7 +609,7 @@ WWidgetGroup {
#DeckMini2,
#DeckMini3,
#DeckMini4 {
- background-color: #0f0f0f;
+ background-color: #1e1e1e;
}
#DeckContainer {
@@ -1708,11 +1710,13 @@ decks, samplers, mic, aux, fx */
}
WEffectSelector,
+ WEffectChainPresetSelector,
#fadeModeCombobox {
font-size: 13px/13px;
/* On Linux this is applied to both effect name and effect list. */
}
- WEffectSelector {
+ WEffectSelector,
+ WEffectChainPresetSelector {
/* Fixes the white bars on the top/bottom of the popup on Mac OS X */
margin: 0px;
/* If you use margin top/bottom 0, the combo box shrinks in width (go figure) and
@@ -1722,6 +1726,7 @@ decks, samplers, mic, aux, fx */
border: 0px solid transparent;
border-radius: 3px;
}
+ WEffectChainPresetSelector,
#fadeModeCombobox {
border: 1px solid #666;
margin: 0px 0px 2px 1px;
@@ -1729,10 +1734,16 @@ decks, samplers, mic, aux, fx */
border-radius: 2px;
height: 20px;
}
- WEffectSelector:hover {
+ WEffectChainPresetSelector {
+ background-color: #252525;
+ color: #888;
+ }
+ WEffectSelector:hover,
+ WEffectChainPresetSelector:hover {
background-color: #0f0f0f;
}
WEffectSelector::drop-down,
+ WEffectChainPresetSelector::drop-down,
#fadeModeCombobox::drop-down {
border: 0px;
margin: 0px;
@@ -1741,26 +1752,65 @@ decks, samplers, mic, aux, fx */
WEffectSelector::drop-down {
margin-right: -2px;
}
+ /* QuickEffect selector in left-hand decks has it's down arrow
+ on the left side, below the QuickEffect toggle */
+ #EffectChainselectorLeft::drop-down {
+ subcontrol-origin: margin;
+ subcontrol-position: left center;
+ }
+ WEffectChainPresetButton {
+ padding: 0px;
+ margin: 0px;
+ border-color: #0f0f0f;
+ border-style: solid;
+ border-width: 0px 1px 1px 1px;
+ border-radius: 2px;
+ background-color: #333;
+ }
+ WEffectChainPresetButton#EffectChainPresetButtonLeft {
+ border-width: 1px 0px 1px 1px;
+ }
+ WEffectChainPresetButton#EffectChainPresetButtonRight {
+ border-width: 1px 1px 1px 0px;
+ }
+ WEffectChainPresetButton:hover {
+ background-color: #151515;
+ }
+ WEffectChainPresetButton::menu-indicator {
+ subcontrol-position: center center;
+ subcontrol-origin: margin;
+ margin: 0px 2px 0px 0px;
+ padding: 0px;
+ border: 0px;
+ outline: none;
+ }
+
+ WEffectChainPresetButton::menu-indicator,
WEffectSelector::down-arrow,
+ WEffectChainPresetSelector::down-arrow,
#fadeModeCombobox::down-arrow {
/* When the skin is scaled, bg-color would be applied
to the (not scaled) button image only:
background-color: #101010;
width: 11px;
height: 20px; */
- image: url(skin:/../Tango/buttons/btn_fx_selector_list.svg) no-repeat center center;
+ image: url(skin:/../Tango/buttons/btn_arrow_down.svg) no-repeat center center;
}
+ WEffectChainPresetButton::menu-indicator:hover,
WEffectSelector::down-arrow:hover,
+ WEffectChainPresetSelector::down-arrow:hover,
#fadeModeCombobox::down-arrow:hover {
- image: url(skin:/../Tango/buttons/btn_fx_selector_list_hover.svg) no-repeat center center;
+ image: url(skin:/../Tango/buttons/btn_arrow_down_hover.svg) no-repeat center center;
}
WEffectSelector QAbstractScrollArea,
+ WEffectChainPresetSelector QAbstractScrollArea,
#fadeModeCombobox QAbstractScrollArea {
border-radius: 2px;
margin: 0px;
}
- WEffectSelector QAbstractScrollArea{
+ WEffectSelector QAbstractScrollArea,
+ WEffectChainPresetSelector QAbstractScrollArea {
min-width: 140px;
}
#fadeModeCombobox QAbstractScrollArea {
@@ -1768,6 +1818,7 @@ decks, samplers, mic, aux, fx */
}
/* selected item */
WEffectSelector::checked,
+ WEffectChainPresetSelector::checked,
#fadeModeCombobox::checked {
/* not applied
padding-left: 5px;
@@ -1778,6 +1829,7 @@ decks, samplers, mic, aux, fx */
}
/* tick mark frame */
WEffectSelector::indicator:checked,
+ WEffectChainPresetSelector::indicator:checked,
#fadeModeCombobox::indicator:checked {
/* This is sufficient to completely hide the tick mark,
but this alone would show an empty, shadowed box instead of tick mark: */
@@ -1796,6 +1848,7 @@ decks, samplers, mic, aux, fx */
image: url(skin:/../Tango/buttons/btn_lib_checkmark_white.svg) no-repeat center center;
}
WEffectSelector::indicator:!checked,
+ WEffectChainPresetSelector::indicator:!checked,
#fadeModeCombobox::indicator:!checked {
image: url(skin:/../Tango/buttons/btn_.svg) no-repeat center center;
}
@@ -1825,17 +1878,17 @@ decks, samplers, mic, aux, fx */
qproperty-layoutAlignment: 'AlignLeft | AlignVCenter';
margin-right: 1px;
}
- #FxParameterButtonOverlay[displayValue="0"]:hover {
+ #FxParameterPushButton[displayValue="0"]:hover {
border: 1px solid #888;
}
- #FxParameterButtonOverlay[displayValue="1"]:hover {
+ #FxParameterPushButton[displayValue="1"]:hover {
border: 1px solid #eeeeee;
}
- #FxParameterButtonUnderlay[displayValue="0"] {
+ #FxParameterPushButton[displayValue="0"] {
background-color: #4b4b4b;
}
- #FxParameterButtonUnderlay[displayValue="1"] {
+ #FxParameterPushButton[displayValue="1"] {
background-color: #006596;
}
#FxParameterButtonName {
@@ -2161,13 +2214,15 @@ WEffectSelector::indicator:unchecked,
}
#MainMenu QMenu::right-arrow,
WTrackMenu::right-arrow,
- WTrackMenu QMenu::right-arrow {
+ WTrackMenu QMenu::right-arrow,
+ WEffectChainPresetButton QMenu::right-arrow {
width: 0.35em;
height: 0.7em;
margin-right: 0.2em;
image: url(skin:/../Tango/buttons/btn_arrow_right.svg);
}
#MainMenu QMenu::right-arrow:selected,
+ WEffectChainPresetButton QMenu::right-arrow,
WTrackMenu::right-arrow:selected,
WTrackMenu QMenu::right-arrow:selected {
image: url(skin:/../Tango/buttons/btn_arrow_right_hover.svg);
@@ -2207,6 +2262,10 @@ WCueMenuPopup QLabel,
#SkinSettingsButton,
#SkinSettingsButtonMulti,
WEffectSelector, WEffectSelector QAbstractScrollArea,
+WEffectChainPresetButton QMenu,
+WEffectChainPresetButton QMenu::item,
+WEffectChainPresetButton QMenu QCheckBox,
+WEffectChainPresetSelector QAbstractScrollArea,
#fadeModeCombobox, #fadeModeCombobox QAbstractScrollArea,
#fadeModeCombobox QAbstractScrollArea::item {
background-color: #1a1a1a;
@@ -2223,6 +2282,8 @@ QLineEdit QMenu,
WCueMenuPopup,
WCoverArtMenu,
WEffectSelector QAbstractScrollArea,
+WEffectChainPresetButton QMenu,
+WEffectChainPresetSelector QAbstractScrollArea,
#fadeModeCombobox QAbstractScrollArea {
border: 1px solid #888;
border-radius: 2px;
@@ -2585,11 +2646,13 @@ WLibraryTextBrowser {
/* Scroll bars */
#LibraryContainer QScrollBar,
WEffectSelector QAbstractScrollArea QScrollBar,
+WEffectChainPresetSelector QAbstractScrollArea QScrollBar,
#fadeModeCombobox QAbstractScrollArea QScrollBar {
padding: 1px;
}
#LibraryContainer QScrollBar:horizontal,
WEffectSelector QAbstractScrollArea QScrollBar:horizontal,
+WEffectChainPresetSelector QAbstractScrollArea QScrollBar:horizontal,
#fadeModeCombobox QAbstractScrollArea QScrollBar:horizontal {
min-width: 12px;
height: 10px;
@@ -2598,6 +2661,7 @@ WEffectSelector QAbstractScrollArea QScrollBar:horizontal,
}
#LibraryContainer QScrollBar:vertical,
WEffectSelector QAbstractScrollArea QScrollBar:vertical,
+ WEffectChainPresetSelector QAbstractScrollArea QScrollBar:vertical,
#fadeModeCombobox QAbstractScrollArea QScrollBar:vertical {
min-height: 12px;
width: 10px;
@@ -2609,6 +2673,8 @@ WEffectSelector QAbstractScrollArea QScrollBar:horizontal,
#LibraryContainer QScrollBar::sub-page,
WEffectSelector QAbstractScrollArea QScrollBar::add-page,
WEffectSelector QAbstractScrollArea QScrollBar::sub-page,
+ WEffectChainPresetSelector QAbstractScrollArea QScrollBar::add-page,
+ WEffectChainPresetSelector QAbstractScrollArea QScrollBar::sub-page,
#fadeModeCombobox QAbstractScrollArea QScrollBar::add-page,
#fadeModeCombobox QAbstractScrollArea QScrollBar::sub-page {
min-width: 15px;
@@ -2617,6 +2683,7 @@ WEffectSelector QAbstractScrollArea QScrollBar:horizontal,
}
#LibraryContainer QScrollBar::handle:horizontal,
WEffectSelector QAbstractScrollArea QScrollBar::handle:horizontal,
+ WEffectChainPresetSelector QAbstractScrollArea QScrollBar::handle:horizontal,
#fadeModeCombobox QAbstractScrollArea QScrollBar::handle:horizontal {
min-width: 25px;
background: #595959;
@@ -2624,11 +2691,13 @@ WEffectSelector QAbstractScrollArea QScrollBar:horizontal,
}
#LibraryContainer QScrollBar::handle:horizontal:hover,
WEffectSelector QAbstractScrollArea QScrollBar::handle:horizontal:hover,
+ WEffectChainPresetSelector QAbstractScrollArea QScrollBar::handle:horizontal:hover,
#fadeModeCombobox QAbstractScrollArea QScrollBar::handle:horizontal:hover {
background: #888;
}
#LibraryContainer QScrollBar::handle:vertical,
WEffectSelector QAbstractScrollArea QScrollBar::handle:vertical,
+ WEffectChainPresetSelector QAbstractScrollArea QScrollBar::handle:vertical,
#fadeModeCombobox QAbstractScrollArea QScrollBar::handle:vertical {
min-height: 25px;
background: #595959;
@@ -2636,6 +2705,7 @@ WEffectSelector QAbstractScrollArea QScrollBar:horizontal,
}
#LibraryContainer QScrollBar::handle:vertical:hover,
WEffectSelector QAbstractScrollArea QScrollBar::handle:vertical:hover,
+ WEffectChainPresetSelector QAbstractScrollArea QScrollBar::handle:vertical:hover,
#fadeModeCombobox QAbstractScrollArea QScrollBar::handle:vertical:hover {
background: #888;
}
@@ -2644,6 +2714,8 @@ WEffectSelector QAbstractScrollArea QScrollBar:horizontal,
#LibraryContainer QScrollBar::add-line:vertical,
WEffectSelector QAbstractScrollArea QScrollBar::add-line:horizontal,
WEffectSelector QAbstractScrollArea QScrollBar::add-line:vertical,
+ WEffectChainPresetSelector QAbstractScrollArea QScrollBar::add-line:horizontal,
+ WEffectChainPresetSelector QAbstractScrollArea QScrollBar::add-line:vertical,
#fadeModeCombobox QAbstractScrollArea QScrollBar::add-line:horizontal,
#fadeModeCombobox QAbstractScrollArea QScrollBar::add-line:vertical {
width: 0px;
@@ -2653,6 +2725,8 @@ WEffectSelector QAbstractScrollArea QScrollBar:horizontal,
#LibraryContainer QScrollBar::sub-line:vertical,
WEffectSelector QAbstractScrollArea QScrollBar::sub-line:horizontal,
WEffectSelector QAbstractScrollArea QScrollBar::sub-line:vertical,
+ WEffectChainPresetSelector QAbstractScrollArea QScrollBar::sub-line:horizontal,
+ WEffectChainPresetSelector QAbstractScrollArea QScrollBar::sub-line:vertical,
#fadeModeCombobox QAbstractScrollArea QScrollBar::sub-line:horizontal,
#fadeModeCombobox QAbstractScrollArea QScrollBar::sub-line:vertical {
width: 0px;
@@ -2661,6 +2735,7 @@ WEffectSelector QAbstractScrollArea QScrollBar:horizontal,
/* Corner in between two scrollbars */
#LibraryContainer QAbstractScrollArea::corner,
WEffectSelector QAbstractScrollArea::corner,
+ WEffectChainPresetSelector QAbstractScrollArea::corner,
#fadeModeCombobox QAbstractScrollArea::corner {
background-color: #0f0f0f;
border: 0px;
@@ -2726,6 +2801,7 @@ Library features and their buttons:
#LibraryFeatureControls QPushButton:!enabled {
color: #888;
}
+ WEffectChainPresetSelector:hover,
#LibraryFeatureControls QPushButton:hover,
#fadeModeCombobox:hover {
border: 1px solid #888;
diff --git a/src/control/controleffectknob.cpp b/src/control/controleffectknob.cpp
index d2f14bf1595..0aaad17ceb8 100644
--- a/src/control/controleffectknob.cpp
+++ b/src/control/controleffectknob.cpp
@@ -1,6 +1,6 @@
#include "control/controleffectknob.h"
-#include "effects/effectmanifestparameter.h"
+#include "effects/backends/effectmanifestparameter.h"
#include "moc_controleffectknob.cpp"
#include "util/math.h"
@@ -8,19 +8,20 @@ ControlEffectKnob::ControlEffectKnob(const ConfigKey& key, double dMinValue, dou
: ControlPotmeter(key, dMinValue, dMaxValue) {
}
-void ControlEffectKnob::setBehaviour(EffectManifestParameter::ControlHint type,
- double dMinValue, double dMaxValue) {
+void ControlEffectKnob::setBehaviour(EffectManifestParameter::ValueScaler type,
+ double dMinValue,
+ double dMaxValue) {
if (m_pControl == nullptr) {
return;
}
- if (type == EffectManifestParameter::ControlHint::KNOB_LINEAR) {
- m_pControl->setBehavior(new ControlLinPotmeterBehavior(
- dMinValue, dMaxValue, false));
- } else if (type == EffectManifestParameter::ControlHint::KNOB_LINEAR_INVERSE) {
- m_pControl->setBehavior(new ControlLinInvPotmeterBehavior(
- dMinValue, dMaxValue, false));
- } else if (type == EffectManifestParameter::ControlHint::KNOB_LOGARITHMIC) {
+ if (type == EffectManifestParameter::ValueScaler::Linear) {
+ m_pControl->setBehavior(new ControlLinPotmeterBehavior(
+ dMinValue, dMaxValue, false));
+ } else if (type == EffectManifestParameter::ValueScaler::LinearInverse) {
+ m_pControl->setBehavior(new ControlLinInvPotmeterBehavior(
+ dMinValue, dMaxValue, false));
+ } else if (type == EffectManifestParameter::ValueScaler::Logarithmic) {
if (dMinValue == 0) {
if (dMaxValue == 1.0) {
// Volume like control
@@ -38,7 +39,7 @@ void ControlEffectKnob::setBehaviour(EffectManifestParameter::ControlHint type,
m_pControl->setBehavior(
new ControlLogPotmeterBehavior(dMinValue, dMaxValue, -40));
}
- } else if (type == EffectManifestParameter::ControlHint::KNOB_LOGARITHMIC_INVERSE) {
+ } else if (type == EffectManifestParameter::ValueScaler::LogarithmicInverse) {
m_pControl->setBehavior(
new ControlLogInvPotmeterBehavior(dMinValue, dMaxValue, -40));
}
diff --git a/src/control/controleffectknob.h b/src/control/controleffectknob.h
index 43e7cc3720f..149efc0fdd9 100644
--- a/src/control/controleffectknob.h
+++ b/src/control/controleffectknob.h
@@ -1,13 +1,14 @@
#pragma once
#include "control/controlpotmeter.h"
-#include "effects/effectmanifestparameter.h"
+#include "effects/backends/effectmanifestparameter.h"
class ControlEffectKnob : public ControlPotmeter {
Q_OBJECT
public:
ControlEffectKnob(const ConfigKey& key, double dMinValue = 0.0, double dMaxValue = 1.0);
- void setBehaviour(EffectManifestParameter::ControlHint type,
- double dMinValue, double dMaxValue);
+ void setBehaviour(EffectManifestParameter::ValueScaler type,
+ double dMinValue,
+ double dMaxValue);
};
diff --git a/src/controllers/controlpickermenu.cpp b/src/controllers/controlpickermenu.cpp
index 973264201d6..19f3d55fe37 100644
--- a/src/controllers/controlpickermenu.cpp
+++ b/src/controllers/controlpickermenu.cpp
@@ -1,8 +1,8 @@
#include "controllers/controlpickermenu.h"
-#include "effects/effectchainslot.h"
-#include "effects/effectparameterslot.h"
-#include "effects/effectrack.h"
+#include "effects/chains/equalizereffectchain.h"
+#include "effects/chains/standardeffectchain.h"
+#include "effects/defs.h"
#include "effects/effectslot.h"
#include "engine/controls/cuecontrol.h"
#include "engine/controls/loopingcontrol.h"
@@ -25,6 +25,7 @@ ControlPickerMenu::ControlPickerMenu(QWidget* pParent)
m_effectUnitStr = tr("Effect Unit %1");
m_effectStr = tr("Slot %1");
m_parameterStr = tr("Parameter %1");
+ m_buttonParameterStr = tr("Button Parameter %1");
m_libraryStr = tr("Library");
// Mixer Controls
@@ -107,7 +108,7 @@ ControlPickerMenu::ControlPickerMenu(QWidget* pParent)
// TODO: Although there is a mode with 4-band EQs, it's not feasible
// right now to add support for learning both it and regular 3-band eqs.
// Since 3-band is by far the most common, stick with that.
- constexpr int kMaxEqs = 3;
+ const int kMaxEqs = 3;
QList eqNames;
eqNames.append(tr("Low EQ"));
eqNames.append(tr("Mid EQ"));
@@ -115,8 +116,8 @@ ControlPickerMenu::ControlPickerMenu(QWidget* pParent)
for (int deck = 1; deck <= iNumDecks; ++deck) {
QMenu* deckMenu = addSubmenu(QString("Deck %1").arg(deck), eqMenu);
for (int effect = kMaxEqs - 1; effect >= 0; --effect) {
- const QString group = EqualizerRack::formatEffectSlotGroupString(
- iRackNumber, 0, QString("[Channel%1]").arg(deck));
+ const QString group = EqualizerEffectChain::formatEffectSlotGroup(
+ QString("[Channel%1]").arg(deck));
QMenu* bandMenu = addSubmenu(eqNames[effect], deckMenu);
QString control = "parameter%1";
addControl(group,
@@ -168,17 +169,25 @@ ControlPickerMenu::ControlPickerMenu(QWidget* pParent)
addDeckAndSamplerAndPreviewDeckControl("play", tr("Play"), tr("Play button"), transportMenu);
addDeckAndSamplerAndPreviewDeckControl("back", tr("Fast Rewind"), tr("Fast Rewind button"), transportMenu);
addDeckAndSamplerAndPreviewDeckControl("fwd", tr("Fast Forward"), tr("Fast Forward button"), transportMenu);
- addDeckAndSamplerAndPreviewDeckControl("playposition", tr("Strip Search"),
- tr("Strip-search through track"), transportMenu);
+ addDeckAndSamplerAndPreviewDeckControl("playposition",
+ tr("Strip Search"),
+ tr("Strip-search through track"),
+ transportMenu);
addDeckAndSamplerAndPreviewDeckControl("reverse", tr("Play Reverse"), tr("Play Reverse button"), transportMenu);
- addDeckAndSamplerAndPreviewDeckControl("reverseroll", tr("Reverse Roll (Censor)"),
- tr("Reverse roll (Censor) button"), transportMenu);
+ addDeckAndSamplerAndPreviewDeckControl("reverseroll",
+ tr("Reverse Roll (Censor)"),
+ tr("Reverse roll (Censor) button"),
+ transportMenu);
addDeckAndSamplerAndPreviewDeckControl("start", tr("Jump To Start"), tr("Jumps to start of track"), transportMenu);
- addDeckAndSamplerAndPreviewDeckControl("start_play", tr("Play From Start"),
- tr("Jump to start of track and play"), transportMenu);
+ addDeckAndSamplerAndPreviewDeckControl("start_play",
+ tr("Play From Start"),
+ tr("Jump to start of track and play"),
+ transportMenu);
addDeckAndSamplerAndPreviewDeckControl("stop", tr("Stop"), tr("Stop button"), transportMenu);
- addDeckAndSamplerAndPreviewDeckControl("start_stop", tr("Stop And Jump To Start"),
- tr("Stop playback and jump to start of track"), transportMenu);
+ addDeckAndSamplerAndPreviewDeckControl("start_stop",
+ tr("Stop And Jump To Start"),
+ tr("Stop playback and jump to start of track"),
+ transportMenu);
addDeckAndSamplerAndPreviewDeckControl("end", tr("Jump To End"), tr("Jump to end of track"), transportMenu);
transportMenu->addSeparator();
addDeckAndSamplerAndPreviewDeckControl("eject", tr("Eject"), tr("Eject track"), transportMenu);
@@ -198,10 +207,14 @@ ControlPickerMenu::ControlPickerMenu(QWidget* pParent)
addDeckAndSamplerControl("beats_adjust_slower", tr("Adjust Beatgrid Slower -.01"), tr("Decrease track's average BPM by 0.01"), bpmMenu);
addDeckAndSamplerControl("beats_translate_earlier", tr("Move Beatgrid Earlier"), tr("Adjust the beatgrid to the left"), bpmMenu);
addDeckAndSamplerControl("beats_translate_later", tr("Move Beatgrid Later"), tr("Adjust the beatgrid to the right"), bpmMenu);
- addDeckControl("beats_translate_curpos", tr("Adjust Beatgrid"),
- tr("Align beatgrid to current position"), bpmMenu);
- addDeckControl("beats_translate_match_alignment", tr("Adjust Beatgrid - Match Alignment"),
- tr("Adjust beatgrid to match another playing deck."), bpmMenu);
+ addDeckControl("beats_translate_curpos",
+ tr("Adjust Beatgrid"),
+ tr("Align beatgrid to current position"),
+ bpmMenu);
+ addDeckControl("beats_translate_match_alignment",
+ tr("Adjust Beatgrid - Match Alignment"),
+ tr("Adjust beatgrid to match another playing deck."),
+ bpmMenu);
bpmMenu->addSeparator();
addDeckAndSamplerControl("quantize", tr("Quantize Mode"), tr("Toggle quantize mode"), bpmMenu);
@@ -265,26 +278,45 @@ ControlPickerMenu::ControlPickerMenu(QWidget* pParent)
// Speed
QMenu* speedMenu = addSubmenu(tr("Speed"));
- addDeckAndSamplerControl("rate", tr("Playback Speed"),
- tr("Playback speed control (Vinyl \"Pitch\" slider)"), speedMenu, true);
+ addDeckAndSamplerControl("rate",
+ tr("Playback Speed"),
+ tr("Playback speed control (Vinyl \"Pitch\" slider)"),
+ speedMenu,
+ true);
speedMenu->addSeparator();
- addDeckAndSamplerControl("rate_perm_up", tr("Increase Speed"),
- tr("Adjust speed faster (coarse)"), speedMenu);
- addDeckAndSamplerControl("rate_perm_up_small", tr("Increase Speed (Fine)"),
- tr("Adjust speed faster (fine)"), speedMenu);
- addDeckAndSamplerControl("rate_perm_down", tr("Decrease Speed"),
- tr("Adjust speed slower (coarse)"), speedMenu);
- addDeckAndSamplerControl("rate_perm_down_small", tr("Increase Speed (Fine)"),
- tr("Adjust speed slower (fine)"), speedMenu);
+ addDeckAndSamplerControl("rate_perm_up",
+ tr("Increase Speed"),
+ tr("Adjust speed faster (coarse)"),
+ speedMenu);
+ addDeckAndSamplerControl("rate_perm_up_small",
+ tr("Increase Speed (Fine)"),
+ tr("Adjust speed faster (fine)"),
+ speedMenu);
+ addDeckAndSamplerControl("rate_perm_down",
+ tr("Decrease Speed"),
+ tr("Adjust speed slower (coarse)"),
+ speedMenu);
+ addDeckAndSamplerControl("rate_perm_down_small",
+ tr("Increase Speed (Fine)"),
+ tr("Adjust speed slower (fine)"),
+ speedMenu);
speedMenu->addSeparator();
- addDeckAndSamplerControl("rate_temp_up", tr("Temporarily Increase Speed"),
- tr("Temporarily increase speed (coarse)"), speedMenu);
- addDeckAndSamplerControl("rate_temp_up_small", tr("Temporarily Increase Speed (Fine)"),
- tr("Temporarily increase speed (fine)"), speedMenu);
- addDeckAndSamplerControl("rate_temp_down", tr("Temporarily Decrease Speed"),
- tr("Temporarily decrease speed (coarse)"), speedMenu);
- addDeckAndSamplerControl("rate_temp_down_small", tr("Temporarily Decrease Speed (Fine)"),
- tr("Temporarily decrease speed (fine)"), speedMenu);
+ addDeckAndSamplerControl("rate_temp_up",
+ tr("Temporarily Increase Speed"),
+ tr("Temporarily increase speed (coarse)"),
+ speedMenu);
+ addDeckAndSamplerControl("rate_temp_up_small",
+ tr("Temporarily Increase Speed (Fine)"),
+ tr("Temporarily increase speed (fine)"),
+ speedMenu);
+ addDeckAndSamplerControl("rate_temp_down",
+ tr("Temporarily Decrease Speed"),
+ tr("Temporarily decrease speed (coarse)"),
+ speedMenu);
+ addDeckAndSamplerControl("rate_temp_down_small",
+ tr("Temporarily Decrease Speed (Fine)"),
+ tr("Temporarily decrease speed (fine)"),
+ speedMenu);
// Pitch (Musical Key)
QMenu* pitchMenu = addSubmenu(tr("Pitch (Musical Key)"));
addDeckAndSamplerControl("pitch",
@@ -321,34 +353,48 @@ ControlPickerMenu::ControlPickerMenu(QWidget* pParent)
// Vinyl Control
QMenu* vinylControlMenu = addSubmenu(tr("Vinyl Control"));
- addDeckControl("vinylcontrol_enabled", tr("Toggle Vinyl Control"),
- tr("Toggle Vinyl Control (ON/OFF)"), vinylControlMenu);
- addDeckControl("vinylcontrol_mode", tr("Vinyl Control Mode"),
- tr("Toggle vinyl-control mode (ABS/REL/CONST)"), vinylControlMenu);
- addDeckControl("vinylcontrol_cueing", tr("Vinyl Control Cueing Mode"),
- tr("Toggle vinyl-control cueing mode (OFF/ONE/HOT)"), vinylControlMenu);
- addDeckControl("passthrough", tr("Vinyl Control Passthrough"),
- tr("Pass through external audio into the internal mixer"), vinylControlMenu);
- addControl(VINYL_PREF_KEY, "Toggle", tr("Vinyl Control Next Deck"),
- tr("Single deck mode - Switch vinyl control to next deck"), vinylControlMenu);
+ addDeckControl("vinylcontrol_enabled",
+ tr("Toggle Vinyl Control"),
+ tr("Toggle Vinyl Control (ON/OFF)"),
+ vinylControlMenu);
+ addDeckControl("vinylcontrol_mode",
+ tr("Vinyl Control Mode"),
+ tr("Toggle vinyl-control mode (ABS/REL/CONST)"),
+ vinylControlMenu);
+ addDeckControl("vinylcontrol_cueing",
+ tr("Vinyl Control Cueing Mode"),
+ tr("Toggle vinyl-control cueing mode (OFF/ONE/HOT)"),
+ vinylControlMenu);
+ addDeckControl("passthrough",
+ tr("Vinyl Control Passthrough"),
+ tr("Pass through external audio into the internal mixer"),
+ vinylControlMenu);
+ addControl(VINYL_PREF_KEY,
+ "Toggle",
+ tr("Vinyl Control Next Deck"),
+ tr("Single deck mode - Switch vinyl control to next deck"),
+ vinylControlMenu);
// Cues
QMenu* cueMenu = addSubmenu(tr("Cues"));
addDeckControl("cue_default", tr("Cue"), tr("Cue button"), cueMenu);
addDeckControl("cue_set", tr("Set Cue"), tr("Set cue point"), cueMenu);
addDeckControl("cue_goto", tr("Go-To Cue"), tr("Go to cue point"), cueMenu);
- addDeckAndSamplerAndPreviewDeckControl("cue_gotoandplay", tr("Go-To Cue And Play"),
- tr("Go to cue point and play"), cueMenu);
- addDeckControl("cue_gotoandstop", tr("Go-To Cue And Stop"),
- tr("Go to cue point and stop"), cueMenu);
- addDeckControl("cue_preview", tr("Preview Cue"),
- tr("Preview from cue point"), cueMenu);
- addDeckControl("cue_cdj", tr("Cue (CDJ Mode)"),
- tr("Cue button (CDJ mode)"), cueMenu);
- addDeckControl("play_stutter", tr("Stutter Cue"),
- tr("Stutter cue"), cueMenu);
- addDeckControl("cue_play", tr("CUP (Cue + Play)"),
- tr("Go to cue point and play after release"), cueMenu);
+ addDeckAndSamplerAndPreviewDeckControl("cue_gotoandplay",
+ tr("Go-To Cue And Play"),
+ tr("Go to cue point and play"),
+ cueMenu);
+ addDeckControl("cue_gotoandstop",
+ tr("Go-To Cue And Stop"),
+ tr("Go to cue point and stop"),
+ cueMenu);
+ addDeckControl("cue_preview", tr("Preview Cue"), tr("Preview from cue point"), cueMenu);
+ addDeckControl("cue_cdj", tr("Cue (CDJ Mode)"), tr("Cue button (CDJ mode)"), cueMenu);
+ addDeckControl("play_stutter", tr("Stutter Cue"), tr("Stutter cue"), cueMenu);
+ addDeckControl("cue_play",
+ tr("CUP (Cue + Play)"),
+ tr("Go to cue point and play after release"),
+ cueMenu);
// Hotcues
QMenu* hotcueMainMenu = addSubmenu(tr("Hotcues"));
@@ -402,33 +448,33 @@ ControlPickerMenu::ControlPickerMenu(QWidget* pParent)
}
QMenu* hotcueSubMenu = addSubmenu(tr("Hotcue %1").arg(QString::number(i)), parentMenu);
addDeckAndSamplerControl(QString("hotcue_%1_activate").arg(i),
- hotcueActivateTitle.arg(QString::number(i)),
- hotcueActivateDescription.arg(QString::number(i)),
- hotcueSubMenu);
+ hotcueActivateTitle.arg(QString::number(i)),
+ hotcueActivateDescription.arg(QString::number(i)),
+ hotcueSubMenu);
addDeckAndSamplerControl(QString("hotcue_%1_clear").arg(i),
- hotcueClearTitle.arg(QString::number(i)),
- hotcueClearDescription.arg(QString::number(i)),
- hotcueSubMenu);
+ hotcueClearTitle.arg(QString::number(i)),
+ hotcueClearDescription.arg(QString::number(i)),
+ hotcueSubMenu);
addDeckAndSamplerControl(QString("hotcue_%1_set").arg(i),
- hotcueSetTitle.arg(QString::number(i)),
- hotcueSetDescription.arg(QString::number(i)),
- hotcueSubMenu);
+ hotcueSetTitle.arg(QString::number(i)),
+ hotcueSetDescription.arg(QString::number(i)),
+ hotcueSubMenu);
addDeckAndSamplerControl(QString("hotcue_%1_goto").arg(i),
- hotcueGotoTitle.arg(QString::number(i)),
- hotcueGotoDescription.arg(QString::number(i)),
- hotcueSubMenu);
+ hotcueGotoTitle.arg(QString::number(i)),
+ hotcueGotoDescription.arg(QString::number(i)),
+ hotcueSubMenu);
addDeckAndSamplerControl(QString("hotcue_%1_gotoandstop").arg(i),
- hotcueGotoAndStopTitle.arg(QString::number(i)),
- hotcueGotoAndStopDescription.arg(QString::number(i)),
- hotcueSubMenu);
+ hotcueGotoAndStopTitle.arg(QString::number(i)),
+ hotcueGotoAndStopDescription.arg(QString::number(i)),
+ hotcueSubMenu);
addDeckAndSamplerControl(QString("hotcue_%1_gotoandplay").arg(i),
- hotcueGotoAndPlayTitle.arg(QString::number(i)),
- hotcueGotoAndPlayDescription.arg(QString::number(i)),
- hotcueSubMenu);
+ hotcueGotoAndPlayTitle.arg(QString::number(i)),
+ hotcueGotoAndPlayDescription.arg(QString::number(i)),
+ hotcueSubMenu);
addDeckAndSamplerControl(QString("hotcue_%1_activate_preview").arg(i),
- hotcuePreviewTitle.arg(QString::number(i)),
- hotcuePreviewDescription.arg(QString::number(i)),
- hotcueSubMenu);
+ hotcuePreviewTitle.arg(QString::number(i)),
+ hotcuePreviewDescription.arg(QString::number(i)),
+ hotcueSubMenu);
}
if (moreHotcues) {
hotcueMainMenu->addSeparator();
@@ -692,10 +738,14 @@ ControlPickerMenu::ControlPickerMenu(QWidget* pParent)
false,
m_libraryStr);
libraryMenu->addSeparator();
- addControl("[Library]", "GoToItem",
- tr("Go to the currently selected item"),
- tr("Choose the currently selected item and advance forward one pane if appropriate"),
- libraryMenu, false, m_libraryStr);
+ addControl("[Library]",
+ "GoToItem",
+ tr("Go to the currently selected item"),
+ tr("Choose the currently selected item and advance forward one "
+ "pane if appropriate"),
+ libraryMenu,
+ false,
+ m_libraryStr);
// Load track (these can be loaded into any channel)
addDeckAndSamplerControl("LoadSelectedTrack",
tr("Load Track"),
@@ -707,18 +757,27 @@ ControlPickerMenu::ControlPickerMenu(QWidget* pParent)
libraryMenu);
libraryMenu->addSeparator();
// Auto DJ
- addControl("[Library]", "AutoDjAddBottom",
- tr("Add to Auto DJ Queue (bottom)"),
- tr("Append the selected track to the Auto DJ Queue"),
- libraryMenu, false, m_libraryStr);
- addControl("[Library]", "AutoDjAddTop",
- tr("Add to Auto DJ Queue (top)"),
- tr("Prepend selected track to the Auto DJ Queue"),
- libraryMenu, false, m_libraryStr);
- addControl("[Library]", "AutoDjAddReplace",
- tr("Add to Auto DJ Queue (replace)"),
- tr("Replace Auto DJ Queue with selected tracks"),
- libraryMenu, false, m_libraryStr);
+ addControl("[Library]",
+ "AutoDjAddBottom",
+ tr("Add to Auto DJ Queue (bottom)"),
+ tr("Append the selected track to the Auto DJ Queue"),
+ libraryMenu,
+ false,
+ m_libraryStr);
+ addControl("[Library]",
+ "AutoDjAddTop",
+ tr("Add to Auto DJ Queue (top)"),
+ tr("Prepend selected track to the Auto DJ Queue"),
+ libraryMenu,
+ false,
+ m_libraryStr);
+ addControl("[Library]",
+ "AutoDjAddReplace",
+ tr("Add to Auto DJ Queue (replace)"),
+ tr("Replace Auto DJ Queue with selected tracks"),
+ libraryMenu,
+ false,
+ m_libraryStr);
libraryMenu->addSeparator();
addControl("[Library]",
"search_history_next",
@@ -751,10 +810,13 @@ ControlPickerMenu::ControlPickerMenu(QWidget* pParent)
m_libraryStr);
libraryMenu->addSeparator();
- addControl("[Recording]", "toggle_recording",
- tr("Record Mix"),
- tr("Toggle mix recording"),
- libraryMenu, false, m_libraryStr);
+ addControl("[Recording]",
+ "toggle_recording",
+ tr("Record Mix"),
+ tr("Toggle mix recording"),
+ libraryMenu,
+ false,
+ m_libraryStr);
// Effect Controls
QMenu* effectsMenu = addSubmenu(tr("Effects"));
@@ -762,317 +824,376 @@ ControlPickerMenu::ControlPickerMenu(QWidget* pParent)
// Quick Effect Rack COs
QMenu* quickEffectMenu = addSubmenu(tr("Quick Effects"), effectsMenu);
for (int i = 1; i <= iNumDecks; ++i) {
- addControl(QString("[QuickEffectRack1_[Channel%1]]").arg(i), "super1",
- tr("Deck %1 Quick Effect Super Knob").arg(i),
- tr("Quick Effect Super Knob (control linked effect parameters)"),
- quickEffectMenu, false, tr("Quick Effect"));
- addControl(QString("[QuickEffectRack1_[Channel%1]_Effect1]").arg(i), "enabled",
- tr("Deck %1 Quick Effect Enable Button").arg(i),
- tr("Quick Effect Enable Button"),
- quickEffectMenu, false, tr("Quick Effect"));
+ addControl(QString("[QuickEffectRack1_[Channel%1]]").arg(i),
+ "super1",
+ tr("Deck %1 Quick Effect Super Knob").arg(i),
+ tr("Quick Effect Super Knob (control linked effect "
+ "parameters)"),
+ quickEffectMenu,
+ false,
+ tr("Quick Effect"));
+ addControl(QString("[QuickEffectRack1_[Channel%1]_Effect1]").arg(i),
+ "enabled",
+ tr("Deck %1 Quick Effect Enable Button").arg(i),
+ tr("Quick Effect Enable Button"),
+ quickEffectMenu,
+ false,
+ tr("Quick Effect"));
}
effectsMenu->addSeparator();
- // When kNumEffectRacks is changed to >1 put effect unit actions into
- // separate "Effect Rack N" submenus.
- constexpr int kNumEffectRacks = 1;
- for (int iRackNumber = 1; iRackNumber <= kNumEffectRacks; ++iRackNumber) {
- const QString rackGroup = StandardEffectRack::formatGroupString(
- iRackNumber - 1);
- QString descriptionPrefix = m_effectRackStr.arg(iRackNumber);
-
- const int numEffectUnits = static_cast(ControlObject::get(
- ConfigKey(rackGroup, "num_effectunits")));
- for (int iEffectUnitNumber = 1; iEffectUnitNumber <= numEffectUnits;
- ++iEffectUnitNumber) {
- const QString effectUnitGroup =
- StandardEffectRack::formatEffectChainSlotGroupString(
- iRackNumber - 1, iEffectUnitNumber - 1);
-
- descriptionPrefix = QString("%1").arg(m_effectUnitStr.arg(iEffectUnitNumber));
-
- QMenu* effectUnitMenu = addSubmenu(m_effectUnitStr.arg(iEffectUnitNumber),
- effectsMenu);
- addControl(effectUnitGroup, "clear",
- tr("Clear Unit"),
- tr("Clear effect unit"),
- effectUnitMenu, false, descriptionPrefix);
- addControl(effectUnitGroup, "enabled",
- tr("Toggle Unit"),
- tr("Enable or disable effect processing"),
- effectUnitMenu, false, descriptionPrefix);
- addControl(effectUnitGroup, "mix",
- tr("Dry/Wet"),
- tr("Adjust the balance between the original (dry) and processed (wet) signal."),
- effectUnitMenu, true, descriptionPrefix);
- addControl(effectUnitGroup, "super1",
- tr("Super Knob"),
- tr("Super Knob (control effects' Meta Knobs)"),
- effectUnitMenu, true, descriptionPrefix);
+ for (int iEffectUnitNumber = 1; iEffectUnitNumber <= kNumStandardEffectUnits;
+ ++iEffectUnitNumber) {
+ const QString effectUnitGroup =
+ StandardEffectChain::formatEffectChainGroup(iEffectUnitNumber - 1);
+
+ const QString descriptionPrefix = QString("%1").arg(m_effectUnitStr.arg(iEffectUnitNumber));
+
+ QMenu* effectUnitMenu = addSubmenu(m_effectUnitStr.arg(iEffectUnitNumber),
+ effectsMenu);
+ addControl(effectUnitGroup,
+ "clear",
+ tr("Clear Unit"),
+ tr("Clear effect unit"),
+ effectUnitMenu,
+ false,
+ descriptionPrefix);
+ addControl(effectUnitGroup,
+ "enabled",
+ tr("Toggle Unit"),
+ tr("Enable or disable effect processing"),
+ effectUnitMenu,
+ false,
+ descriptionPrefix);
+ addControl(effectUnitGroup,
+ "mix",
+ tr("Dry/Wet"),
+ tr("Adjust the balance between the original (dry) and "
+ "processed (wet) signal."),
+ effectUnitMenu,
+ true,
+ descriptionPrefix);
+ addControl(effectUnitGroup,
+ "super1",
+ tr("Super Knob"),
+ tr("Super Knob (control effects' Meta Knobs)"),
+ effectUnitMenu,
+ true,
+ descriptionPrefix);
+ addControl(effectUnitGroup,
+ "mix_mode",
+ tr("Mix Mode Toggle"),
+ tr("Toggle effect unit between D/W and D+W modes"),
+ effectUnitMenu,
+ false,
+ descriptionPrefix);
+ addControl(effectUnitGroup,
+ "next_chain",
+ tr("Next Chain"),
+ tr("Next chain preset"),
+ effectUnitMenu,
+ false,
+ descriptionPrefix);
+ addControl(effectUnitGroup,
+ "prev_chain",
+ tr("Previous Chain"),
+ tr("Previous chain preset"),
+ effectUnitMenu,
+ false,
+ descriptionPrefix);
+ addControl(effectUnitGroup,
+ "chain_selector",
+ tr("Next/Previous Chain"),
+ tr("Next or previous chain preset"),
+ effectUnitMenu,
+ false,
+ descriptionPrefix);
+ addControl(effectUnitGroup,
+ "show_parameters",
+ tr("Show Effect Parameters"),
+ tr("Show Effect Parameters"),
+ effectUnitMenu,
+ false,
+ descriptionPrefix);
+
+ QString assignMenuTitle = tr("Effect Unit Assignment");
+ QString assignString = tr("Assign ");
+ QMenu* effectUnitGroups = addSubmenu(assignMenuTitle,
+ effectUnitMenu);
+
+ QString groupDescriptionPrefix = QString("%1").arg(
+ m_effectUnitStr.arg(iEffectUnitNumber));
+
+ addControl(effectUnitGroup, "group_[Master]_enable",
+ assignString + m_effectMasterOutputStr, // in ComboBox
+ assignString + m_effectMasterOutputStr, // description below
+ effectUnitGroups,
+ false,
+ groupDescriptionPrefix);
+ addControl(effectUnitGroup,
+ "group_[Headphone]_enable",
+ assignString + m_effectHeadphoneOutputStr,
+ assignString + m_effectHeadphoneOutputStr,
+ effectUnitGroups,
+ false,
+ groupDescriptionPrefix);
+
+ for (int iDeckNumber = 1; iDeckNumber <= iNumDecks; ++iDeckNumber) {
+ // PlayerManager::groupForDeck is 0-indexed.
+ QString playerGroup = PlayerManager::groupForDeck(iDeckNumber - 1);
+ // TODO(owen): Fix bad i18n here.
addControl(effectUnitGroup,
- "mix_mode",
- tr("Mix Mode Toggle"),
- tr("Toggle effect unit between D/W and D+W modes"),
- effectUnitMenu,
+ QString("group_%1_enable").arg(playerGroup),
+ assignString + m_deckStr.arg(iDeckNumber),
+ assignString + m_deckStr.arg(iDeckNumber),
+ effectUnitGroups,
false,
- descriptionPrefix);
- addControl(effectUnitGroup, "next_chain",
- tr("Next Chain"),
- tr("Next chain preset"),
- effectUnitMenu, false, descriptionPrefix);
- addControl(effectUnitGroup, "prev_chain",
- tr("Previous Chain"),
- tr("Previous chain preset"),
- effectUnitMenu, false, descriptionPrefix);
- addControl(effectUnitGroup, "chain_selector",
- tr("Next/Previous Chain"),
- tr("Next or previous chain preset"),
- effectUnitMenu, false, descriptionPrefix);
- addControl(effectUnitGroup, "show_parameters",
- tr("Show Effect Parameters"),
- tr("Show Effect Parameters"),
- effectUnitMenu, false, descriptionPrefix);
-
- QString assignMenuTitle = tr("Effect Unit Assignment");
- QString assignString = tr("Assign ");
- QMenu* effectUnitGroups = addSubmenu(assignMenuTitle,
- effectUnitMenu);
+ groupDescriptionPrefix);
+ }
- QString groupDescriptionPrefix = QString("%1").arg(
- m_effectUnitStr.arg(iEffectUnitNumber));
+ const int iNumSamplers = static_cast(ControlObject::get(
+ ConfigKey("[Master]", "num_samplers")));
+ for (int iSamplerNumber = 1; iSamplerNumber <= iNumSamplers;
+ ++iSamplerNumber) {
+ // PlayerManager::groupForSampler is 0-indexed.
+ QString playerGroup = PlayerManager::groupForSampler(iSamplerNumber - 1);
+ // TODO(owen): Fix bad i18n here.
+ addControl(effectUnitGroup,
+ QString("group_%1_enable").arg(playerGroup),
+ assignString + m_samplerStr.arg(iSamplerNumber),
+ assignString + m_samplerStr.arg(iSamplerNumber),
+ effectUnitGroups,
+ false,
+ groupDescriptionPrefix);
+ }
- addControl(effectUnitGroup, "group_[Master]_enable",
- assignString + m_effectMasterOutputStr, // in ComboBox
- assignString + m_effectMasterOutputStr, // description below
+ const int iNumMicrophones = static_cast(ControlObject::get(
+ ConfigKey("[Master]", "num_microphones")));
+ for (int iMicrophoneNumber = 1; iMicrophoneNumber <= iNumMicrophones;
+ ++iMicrophoneNumber) {
+ QString micGroup = PlayerManager::groupForMicrophone(iMicrophoneNumber - 1);
+ // TODO(owen): Fix bad i18n here.
+ addControl(effectUnitGroup,
+ QString("group_%1_enable").arg(micGroup),
+ assignString + m_microphoneStr.arg(iMicrophoneNumber),
+ assignString + m_microphoneStr.arg(iMicrophoneNumber),
effectUnitGroups,
false,
groupDescriptionPrefix);
+ }
+
+ const int iNumAuxiliaries = static_cast(ControlObject::get(
+ ConfigKey("[Master]", "num_auxiliaries")));
+ for (int iAuxiliaryNumber = 1; iAuxiliaryNumber <= iNumAuxiliaries;
+ ++iAuxiliaryNumber) {
+ QString auxGroup = PlayerManager::groupForAuxiliary(iAuxiliaryNumber - 1);
+ // TODO(owen): Fix bad i18n here.
addControl(effectUnitGroup,
- "group_[Headphone]_enable",
- assignString + m_effectHeadphoneOutputStr,
- assignString + m_effectHeadphoneOutputStr,
+ QString("group_%1_enable").arg(auxGroup),
+ assignString + m_auxStr.arg(iAuxiliaryNumber),
+ assignString + m_auxStr.arg(iAuxiliaryNumber),
effectUnitGroups,
false,
groupDescriptionPrefix);
+ }
- for (int iDeckNumber = 1; iDeckNumber <= iNumDecks; ++iDeckNumber) {
- // PlayerManager::groupForDeck is 0-indexed.
- QString playerGroup = PlayerManager::groupForDeck(iDeckNumber - 1);
- // TODO(owen): Fix bad i18n here.
- addControl(effectUnitGroup,
- QString("group_%1_enable").arg(playerGroup),
- assignString + m_deckStr.arg(iDeckNumber),
- assignString + m_deckStr.arg(iDeckNumber),
- effectUnitGroups,
- false,
- groupDescriptionPrefix);
- }
+ const int numEffectSlots = static_cast(ControlObject::get(
+ ConfigKey(effectUnitGroup, "num_effectslots")));
+ for (int iEffectSlotNumber = 1; iEffectSlotNumber <= numEffectSlots;
+ ++iEffectSlotNumber) {
+ const QString effectSlotGroup =
+ StandardEffectChain::formatEffectSlotGroup(
+ iEffectUnitNumber - 1, iEffectSlotNumber - 1);
- const int iNumSamplers = static_cast(ControlObject::get(
- ConfigKey("[Master]", "num_samplers")));
- for (int iSamplerNumber = 1; iSamplerNumber <= iNumSamplers;
- ++iSamplerNumber) {
- // PlayerManager::groupForSampler is 0-indexed.
- QString samplerGroup = PlayerManager::groupForSampler(iSamplerNumber - 1);
- // TODO(owen): Fix bad i18n here.
- addControl(effectUnitGroup,
- QString("group_%1_enable").arg(samplerGroup),
- assignString + m_samplerStr.arg(iSamplerNumber),
- assignString + m_samplerStr.arg(iSamplerNumber),
- effectUnitGroups,
- false,
- groupDescriptionPrefix);
- }
+ QMenu* effectSlotMenu = addSubmenu(m_effectStr.arg(iEffectSlotNumber),
+ effectUnitMenu);
- const int iNumMicrophones = static_cast(ControlObject::get(
- ConfigKey("[Master]", "num_microphones")));
- for (int iMicrophoneNumber = 1; iMicrophoneNumber <= iNumMicrophones;
- ++iMicrophoneNumber) {
- QString micGroup = PlayerManager::groupForMicrophone(iMicrophoneNumber - 1);
- // TODO(owen): Fix bad i18n here.
- addControl(effectUnitGroup,
- QString("group_%1_enable").arg(micGroup),
- assignString + m_microphoneStr.arg(iMicrophoneNumber),
- assignString + m_microphoneStr.arg(iMicrophoneNumber),
- effectUnitGroups,
- false,
- groupDescriptionPrefix);
- }
+ QString slotDescriptionPrefix =
+ QString("%1, %2").arg(descriptionPrefix,
+ m_effectStr.arg(iEffectSlotNumber));
+
+ addControl(effectSlotGroup,
+ "clear",
+ tr("Clear"),
+ tr("Clear the current effect"),
+ effectSlotMenu,
+ false,
+ slotDescriptionPrefix);
+ addControl(effectSlotGroup,
+ "meta",
+ tr("Meta Knob"),
+ tr("Effect Meta Knob (control linked effect parameters)"),
+ effectSlotMenu,
+ false,
+ slotDescriptionPrefix);
+ addControl(effectSlotGroup,
+ "enabled",
+ tr("Toggle"),
+ tr("Toggle the current effect"),
+ effectSlotMenu,
+ false,
+ slotDescriptionPrefix);
+ addControl(effectSlotGroup,
+ "next_effect",
+ tr("Next"),
+ tr("Switch to next effect"),
+ effectSlotMenu,
+ false,
+ slotDescriptionPrefix);
+ addControl(effectSlotGroup,
+ "prev_effect",
+ tr("Previous"),
+ tr("Switch to the previous effect"),
+ effectSlotMenu,
+ false,
+ slotDescriptionPrefix);
+ addControl(effectSlotGroup,
+ "effect_selector",
+ tr("Next or Previous"),
+ tr("Switch to either next or previous effect"),
+ effectSlotMenu,
+ false,
+ slotDescriptionPrefix);
+
+ // Effect parameter knobs
+ const int numParameterSlots = static_cast(ControlObject::get(
+ ConfigKey(effectSlotGroup, "num_parameterslots")));
+ for (int iParameterSlotNumber = 1; iParameterSlotNumber <= numParameterSlots;
+ ++iParameterSlotNumber) {
+ // The parameter slot group is the same as the effect slot
+ // group on a standard effect rack.
+ const QString parameterSlotGroup =
+ StandardEffectChain::formatEffectSlotGroup(
+ iEffectUnitNumber - 1, iEffectSlotNumber - 1);
+ const QString parameterSlotItemPrefix = EffectKnobParameterSlot::formatItemPrefix(
+ iParameterSlotNumber - 1);
+ QMenu* parameterSlotMenu = addSubmenu(
+ m_parameterStr.arg(iParameterSlotNumber),
+ effectSlotMenu);
+
+ QString parameterDescriptionPrefix =
+ QString("%1, %2").arg(slotDescriptionPrefix,
+ m_parameterStr.arg(iParameterSlotNumber));
- const int iNumAuxiliaries = static_cast(ControlObject::get(
- ConfigKey("[Master]", "num_auxiliaries")));
- for (int iAuxiliaryNumber = 1; iAuxiliaryNumber <= iNumAuxiliaries;
- ++iAuxiliaryNumber) {
- QString auxGroup = PlayerManager::groupForAuxiliary(iAuxiliaryNumber - 1);
- // TODO(owen): Fix bad i18n here.
- addControl(effectUnitGroup,
- QString("group_%1_enable").arg(auxGroup),
- assignString + m_auxStr.arg(iAuxiliaryNumber),
- assignString + m_auxStr.arg(iAuxiliaryNumber),
- effectUnitGroups,
+ // Likely to change soon.
+ addControl(parameterSlotGroup,
+ parameterSlotItemPrefix,
+ tr("Parameter Value"),
+ tr("Parameter Value"),
+ parameterSlotMenu,
+ true,
+ parameterDescriptionPrefix);
+ addControl(parameterSlotGroup,
+ parameterSlotItemPrefix + "_link_type",
+ tr("Meta Knob Mode"),
+ tr("Set how linked effect parameters change when "
+ "turning the Meta Knob."),
+ parameterSlotMenu,
false,
- groupDescriptionPrefix);
+ parameterDescriptionPrefix);
+ addControl(parameterSlotGroup,
+ parameterSlotItemPrefix + "_link_inverse",
+ tr("Meta Knob Mode Invert"),
+ tr("Invert how linked effect parameters change when "
+ "turning the Meta Knob."),
+ parameterSlotMenu,
+ false,
+ parameterDescriptionPrefix);
}
- const int numEffectSlots = static_cast(ControlObject::get(
- ConfigKey(effectUnitGroup, "num_effectslots")));
- for (int iEffectSlotNumber = 1; iEffectSlotNumber <= numEffectSlots;
- ++iEffectSlotNumber) {
- const QString effectSlotGroup =
- StandardEffectRack::formatEffectSlotGroupString(
- iRackNumber - 1, iEffectUnitNumber - 1,
- iEffectSlotNumber - 1);
-
- QMenu* effectSlotMenu = addSubmenu(m_effectStr.arg(iEffectSlotNumber),
- effectUnitMenu);
-
- QString slotDescriptionPrefix =
- QString("%1, %2").arg(descriptionPrefix,
- m_effectStr.arg(iEffectSlotNumber));
-
- addControl(effectSlotGroup, "clear",
- tr("Clear"), tr("Clear the current effect"),
- effectSlotMenu, false, slotDescriptionPrefix);
- addControl(effectSlotGroup, "meta",
- tr("Meta Knob"), tr("Effect Meta Knob (control linked effect parameters)"),
- effectSlotMenu, false, slotDescriptionPrefix);
- addControl(effectSlotGroup, "enabled",
- tr("Toggle"), tr("Toggle the current effect"),
- effectSlotMenu, false, slotDescriptionPrefix);
- addControl(effectSlotGroup, "next_effect",
- tr("Next"), tr("Switch to next effect"),
- effectSlotMenu, false, slotDescriptionPrefix);
- addControl(effectSlotGroup, "prev_effect",
- tr("Previous"), tr("Switch to the previous effect"),
- effectSlotMenu, false, slotDescriptionPrefix);
- addControl(effectSlotGroup, "effect_selector",
- tr("Next or Previous"),
- tr("Switch to either next or previous effect"),
- effectSlotMenu, false, slotDescriptionPrefix);
-
- // Effect parameter knobs
- const int numParameterSlots = static_cast(ControlObject::get(
- ConfigKey(effectSlotGroup, "num_parameterslots")));
- for (int iParameterSlotNumber = 1; iParameterSlotNumber <= numParameterSlots;
- ++iParameterSlotNumber) {
- // The parameter slot group is the same as the effect slot
- // group on a standard effect rack.
- const QString parameterSlotGroup =
- StandardEffectRack::formatEffectSlotGroupString(
- iRackNumber - 1, iEffectUnitNumber - 1,
- iEffectSlotNumber - 1);
- const QString parameterSlotItemPrefix = EffectParameterSlot::formatItemPrefix(
- iParameterSlotNumber - 1);
- QMenu* parameterSlotMenu = addSubmenu(
- m_parameterStr.arg(iParameterSlotNumber),
+ // Effect parameter buttons
+ const int numButtonParameterSlots = static_cast(ControlObject::get(
+ ConfigKey(effectSlotGroup, "num_button_parameterslots")));
+ for (int iParameterSlotNumber = 1; iParameterSlotNumber <= numButtonParameterSlots;
+ ++iParameterSlotNumber) {
+ // The parameter slot group is the same as the effect slot
+ // group on a standard effect rack.
+ const QString parameterSlotGroup =
+ StandardEffectChain::formatEffectSlotGroup(
+ iEffectUnitNumber - 1, iEffectSlotNumber - 1);
+ const QString parameterSlotItemPrefix =
+ EffectButtonParameterSlot::formatItemPrefix(
+ iParameterSlotNumber - 1);
+ QMenu* parameterSlotMenu = addSubmenu(
+ m_buttonParameterStr.arg(iParameterSlotNumber),
effectSlotMenu);
- QString parameterDescriptionPrefix =
- QString("%1, %2").arg(slotDescriptionPrefix,
- m_parameterStr.arg(iParameterSlotNumber));
-
- // Likely to change soon.
- addControl(parameterSlotGroup, parameterSlotItemPrefix,
- tr("Parameter Value"),
- tr("Parameter Value"),
- parameterSlotMenu, true,
- parameterDescriptionPrefix);
- addControl(parameterSlotGroup, parameterSlotItemPrefix + "_link_type",
- tr("Meta Knob Mode"),
- tr("Set how linked effect parameters change when turning the Meta Knob."),
- parameterSlotMenu, false,
- parameterDescriptionPrefix);
- addControl(parameterSlotGroup, parameterSlotItemPrefix + "_link_inverse",
- tr("Meta Knob Mode Invert"),
- tr("Invert how linked effect parameters change when turning the Meta Knob."),
- parameterSlotMenu, false,
- parameterDescriptionPrefix);
- }
-
- // Effect parameter buttons
- const int numButtonParameterSlots = static_cast(ControlObject::get(
- ConfigKey(effectSlotGroup, "num_button_parameterslots")));
- for (int iParameterSlotNumber = 1; iParameterSlotNumber <= numButtonParameterSlots;
- ++iParameterSlotNumber) {
- // The parameter slot group is the same as the effect slot
- // group on a standard effect rack.
- const QString parameterSlotGroup =
- StandardEffectRack::formatEffectSlotGroupString(
- iRackNumber - 1, iEffectUnitNumber - 1, iEffectSlotNumber - 1);
- const QString parameterSlotItemPrefix =
- EffectButtonParameterSlot::formatItemPrefix(
- iParameterSlotNumber - 1);
- QMenu* parameterSlotMenu = addSubmenu(
- m_parameterStr.arg(iParameterSlotNumber),
- effectSlotMenu);
-
- QString parameterDescriptionPrefix =
- QString("%1, %2").arg(slotDescriptionPrefix,
- m_parameterStr.arg(iParameterSlotNumber));
-
- // Likely to change soon.
- addControl(parameterSlotGroup,
- parameterSlotItemPrefix,
- tr("Button Parameter Value"),
- tr("Button Parameter Value"),
- parameterSlotMenu,
- true,
- parameterDescriptionPrefix);
- }
+ QString parameterDescriptionPrefix =
+ QString("%1, %2").arg(slotDescriptionPrefix,
+ m_buttonParameterStr.arg(iParameterSlotNumber));
+
+ // Likely to change soon.
+ addControl(parameterSlotGroup,
+ parameterSlotItemPrefix,
+ tr("Button Parameter Value"),
+ tr("Button Parameter Value"),
+ parameterSlotMenu,
+ true,
+ parameterDescriptionPrefix);
}
}
- // Clear Effect Rack
- addControl(rackGroup,
- "clear",
- tr("Clear Effect Rack"),
- tr("Clear effect rack"),
- effectsMenu,
- false,
- descriptionPrefix);
}
// Microphone Controls
QMenu* microphoneMenu = addSubmenu(tr("Microphone / Auxiliary"));
addMicrophoneAndAuxControl("talkover",
- tr("Microphone On/Off"),
- tr("Microphone on/off"), microphoneMenu,
- true, false);
- addControl("[Master]", "duckStrength",
- tr("Microphone Ducking Strength"),
- tr("Microphone Ducking Strength"),
- microphoneMenu, true);
- addControl("[Master]", "talkoverDucking",
- tr("Microphone Ducking Mode"),
- tr("Toggle microphone ducking mode (OFF, AUTO, MANUAL)"),
- microphoneMenu);
+ tr("Microphone On/Off"),
+ tr("Microphone on/off"),
+ microphoneMenu,
+ true,
+ false);
+ addControl("[Master]",
+ "duckStrength",
+ tr("Microphone Ducking Strength"),
+ tr("Microphone Ducking Strength"),
+ microphoneMenu,
+ true);
+ addControl("[Master]",
+ "talkoverDucking",
+ tr("Microphone Ducking Mode"),
+ tr("Toggle microphone ducking mode (OFF, AUTO, MANUAL)"),
+ microphoneMenu);
addMicrophoneAndAuxControl("passthrough",
- tr("Auxiliary On/Off"),
- tr("Auxiliary on/off"),
- microphoneMenu,
- false, true);
+ tr("Auxiliary On/Off"),
+ tr("Auxiliary on/off"),
+ microphoneMenu,
+ false,
+ true);
microphoneMenu->addSeparator();
addMicrophoneAndAuxControl("pregain",
- tr("Gain"),
- tr("Gain knob"), microphoneMenu,
- true, true, true);
+ tr("Gain"),
+ tr("Gain knob"),
+ microphoneMenu,
+ true,
+ true,
+ true);
addMicrophoneAndAuxControl("volume",
- tr("Volume Fader"),
- tr("Volume Fader"), microphoneMenu,
- true, true, true);
+ tr("Volume Fader"),
+ tr("Volume Fader"),
+ microphoneMenu,
+ true,
+ true,
+ true);
addMicrophoneAndAuxControl("volume_set_one",
- tr("Full Volume"),
- tr("Set to full volume"), microphoneMenu,
- true, true);
+ tr("Full Volume"),
+ tr("Set to full volume"),
+ microphoneMenu,
+ true,
+ true);
addMicrophoneAndAuxControl("volume_set_zero",
- tr("Zero Volume"),
- tr("Set to zero volume"), microphoneMenu,
- true, true);
+ tr("Zero Volume"),
+ tr("Set to zero volume"),
+ microphoneMenu,
+ true,
+ true);
addMicrophoneAndAuxControl("mute",
- tr("Mute"),
- tr("Mute button"), microphoneMenu,
- true, true);
+ tr("Mute"),
+ tr("Mute button"),
+ microphoneMenu,
+ true,
+ true);
addMicrophoneAndAuxControl("pfl",
tr("Headphone Listen"),
tr("Headphone listen button"),
@@ -1081,42 +1202,57 @@ ControlPickerMenu::ControlPickerMenu(QWidget* pParent)
true);
microphoneMenu->addSeparator();
addMicrophoneAndAuxControl("orientation",
- tr("Orientation"),
- tr("Mix orientation (e.g. left, right, center)"),
- microphoneMenu, true, true);
+ tr("Orientation"),
+ tr("Mix orientation (e.g. left, right, center)"),
+ microphoneMenu,
+ true,
+ true);
addMicrophoneAndAuxControl("orientation_left",
- tr("Orient Left"),
- tr("Set mix orientation to left"),
- microphoneMenu,
- true, true);
+ tr("Orient Left"),
+ tr("Set mix orientation to left"),
+ microphoneMenu,
+ true,
+ true);
addMicrophoneAndAuxControl("orientation_center",
- tr("Orient Center"),
- tr("Set mix orientation to center"), microphoneMenu,
- true, true);
+ tr("Orient Center"),
+ tr("Set mix orientation to center"),
+ microphoneMenu,
+ true,
+ true);
addMicrophoneAndAuxControl("orientation_right",
- tr("Orient Right"),
- tr("Set mix orientation to right"), microphoneMenu,
- true, true);
+ tr("Orient Right"),
+ tr("Set mix orientation to right"),
+ microphoneMenu,
+ true,
+ true);
// AutoDJ Controls
QMenu* autodjMenu = addSubmenu(tr("Auto DJ"));
- addControl("[AutoDJ]", "shuffle_playlist",
- tr("Auto DJ Shuffle"),
- tr("Shuffle the content of the Auto DJ queue"), autodjMenu);
- addControl("[AutoDJ]", "skip_next",
- tr("Auto DJ Skip Next"),
- tr("Skip the next track in the Auto DJ queue"), autodjMenu);
+ addControl("[AutoDJ]",
+ "shuffle_playlist",
+ tr("Auto DJ Shuffle"),
+ tr("Shuffle the content of the Auto DJ queue"),
+ autodjMenu);
+ addControl("[AutoDJ]",
+ "skip_next",
+ tr("Auto DJ Skip Next"),
+ tr("Skip the next track in the Auto DJ queue"),
+ autodjMenu);
addControl("[AutoDJ]",
"add_random_track",
tr("Auto DJ Add Random Track"),
tr("Add a random track to the Auto DJ queue"),
autodjMenu);
- addControl("[AutoDJ]", "fade_now",
- tr("Auto DJ Fade To Next"),
- tr("Trigger the transition to the next track"), autodjMenu);
- addControl("[AutoDJ]", "enabled",
- tr("Auto DJ Toggle"),
- tr("Toggle Auto DJ On/Off"), autodjMenu);
+ addControl("[AutoDJ]",
+ "fade_now",
+ tr("Auto DJ Fade To Next"),
+ tr("Trigger the transition to the next track"),
+ autodjMenu);
+ addControl("[AutoDJ]",
+ "enabled",
+ tr("Auto DJ Toggle"),
+ tr("Toggle Auto DJ On/Off"),
+ autodjMenu);
// Skin Controls
QMenu* guiMenu = addSubmenu(tr("User Interface"));
@@ -1212,10 +1348,14 @@ ControlPickerMenu::ControlPickerMenu(QWidget* pParent)
guiMenu->addSeparator();
// Controls to change a deck's star rating
- addDeckAndPreviewDeckControl("stars_up", tr("Star Rating Up"),
- tr("Increase the track rating by one star"), guiMenu);
- addDeckAndPreviewDeckControl("stars_down", tr("Star Rating Down"),
- tr("Decrease the track rating by one star"), guiMenu);
+ addDeckAndPreviewDeckControl("stars_up",
+ tr("Star Rating Up"),
+ tr("Increase the track rating by one star"),
+ guiMenu);
+ addDeckAndPreviewDeckControl("stars_down",
+ tr("Star Rating Down"),
+ tr("Decrease the track rating by one star"),
+ guiMenu);
// Misc. controls
addControl("[Shoutcast]",
@@ -1251,8 +1391,9 @@ void ControlPickerMenu::addSingleControl(const QString& group,
}
auto pAction = make_parented(actionTitle.isEmpty() ? title : actionTitle, pMenu);
- connect(pAction, &QAction::triggered,
- this, [this, controlIndex] { controlChosen(controlIndex); });
+ connect(pAction, &QAction::triggered, this, [this, controlIndex] {
+ controlChosen(controlIndex);
+ });
pMenu->addAction(pAction);
}
@@ -1303,14 +1444,24 @@ void ControlPickerMenu::addPlayerControl(const QString& control,
// PlayerManager::groupForDeck is 0-indexed.
QString prefix = m_deckStr.arg(i);
QString group = PlayerManager::groupForDeck(i - 1);
- addSingleControl(group, control, controlTitle, controlDescription,
- controlMenu, prefix, prefix);
+ addSingleControl(group,
+ control,
+ controlTitle,
+ controlDescription,
+ controlMenu,
+ prefix,
+ prefix);
if (resetControlMenu) {
QString resetTitle = QString("%1 (%2)").arg(controlTitle, m_resetStr);
QString resetDescription = QString("%1 (%2)").arg(controlDescription, m_resetStr);
- addSingleControl(group, resetControl, resetTitle, resetDescription,
- resetControlMenu, prefix, prefix);
+ addSingleControl(group,
+ resetControl,
+ resetTitle,
+ resetDescription,
+ resetControlMenu,
+ prefix,
+ prefix);
}
}
@@ -1323,14 +1474,24 @@ void ControlPickerMenu::addPlayerControl(const QString& control,
prefix = m_previewdeckStr.arg(i);
}
QString group = PlayerManager::groupForPreviewDeck(i - 1);
- addSingleControl(group, control, controlTitle, controlDescription,
- controlMenu, prefix, prefix);
+ addSingleControl(group,
+ control,
+ controlTitle,
+ controlDescription,
+ controlMenu,
+ prefix,
+ prefix);
if (resetControlMenu) {
QString resetTitle = QString("%1 (%2)").arg(controlTitle, m_resetStr);
QString resetDescription = QString("%1 (%2)").arg(controlDescription, m_resetStr);
- addSingleControl(group, resetControl, resetTitle, resetDescription,
- resetControlMenu, prefix, prefix);
+ addSingleControl(group,
+ resetControl,
+ resetTitle,
+ resetDescription,
+ resetControlMenu,
+ prefix,
+ prefix);
}
}
@@ -1393,14 +1554,24 @@ void ControlPickerMenu::addMicrophoneAndAuxControl(const QString& control,
for (int i = 1; i <= kNumMicrophones; ++i) {
QString prefix = m_microphoneStr.arg(i);
QString group = PlayerManager::groupForMicrophone(i - 1);
- addSingleControl(group, control, controlTitle, controlDescription,
- controlMenu, prefix, prefix);
+ addSingleControl(group,
+ control,
+ controlTitle,
+ controlDescription,
+ controlMenu,
+ prefix,
+ prefix);
if (resetControlMenu) {
QString resetTitle = QString("%1 (%2)").arg(controlTitle, m_resetStr);
QString resetDescription = QString("%1 (%2)").arg(controlDescription, m_resetStr);
- addSingleControl(group, resetControl, resetTitle, resetDescription,
- resetControlMenu, prefix, prefix);
+ addSingleControl(group,
+ resetControl,
+ resetTitle,
+ resetDescription,
+ resetControlMenu,
+ prefix,
+ prefix);
}
}
}
@@ -1411,14 +1582,24 @@ void ControlPickerMenu::addMicrophoneAndAuxControl(const QString& control,
for (int i = 1; i <= kNumAuxiliaries; ++i) {
QString prefix = m_auxStr.arg(i);
QString group = PlayerManager::groupForAuxiliary(i - 1);
- addSingleControl(group, control, controlTitle, controlDescription,
- controlMenu, prefix, prefix);
+ addSingleControl(group,
+ control,
+ controlTitle,
+ controlDescription,
+ controlMenu,
+ prefix,
+ prefix);
if (resetControlMenu) {
QString resetTitle = QString("%1 (%2)").arg(controlTitle, m_resetStr);
QString resetDescription = QString("%1 (%2)").arg(controlDescription, m_resetStr);
- addSingleControl(group, resetControl, resetTitle, resetDescription,
- resetControlMenu, prefix, prefix);
+ addSingleControl(group,
+ resetControl,
+ resetTitle,
+ resetDescription,
+ resetControlMenu,
+ prefix,
+ prefix);
}
}
}
diff --git a/src/controllers/controlpickermenu.h b/src/controllers/controlpickermenu.h
index 62b9430388b..4b7a0c247f7 100644
--- a/src/controllers/controlpickermenu.h
+++ b/src/controllers/controlpickermenu.h
@@ -28,7 +28,7 @@ class ControlPickerMenu : public QMenu {
void controlChosen(int controlIndex);
private:
- QMenu* addSubmenu(QString title, QMenu* pParent=NULL);
+ QMenu* addSubmenu(QString title, QMenu* pParent = NULL);
void addSingleControl(const QString& group,
const QString& control,
const QString& title,
@@ -103,6 +103,7 @@ class ControlPickerMenu : public QMenu {
QString m_effectUnitStr;
QString m_effectStr;
QString m_parameterStr;
+ QString m_buttonParameterStr;
QString m_libraryStr;
QList m_controlsAvailable;
diff --git a/src/coreservices.cpp b/src/coreservices.cpp
index 3abfef80452..3d46eec316c 100644
--- a/src/coreservices.cpp
+++ b/src/coreservices.cpp
@@ -12,11 +12,7 @@
#include "controllers/controllermanager.h"
#include "controllers/keyboard/keyboardeventfilter.h"
#include "database/mixxxdb.h"
-#include "effects/builtin/builtinbackend.h"
#include "effects/effectsmanager.h"
-#ifdef __LILV__
-#include "effects/lv2/lv2backend.h"
-#endif
#include "engine/enginemaster.h"
#include "library/coverartcache.h"
#include "library/library.h"
@@ -256,7 +252,7 @@ void CoreServices::initialize(QApplication* pApp) {
auto pChannelHandleFactory = std::make_shared();
emit initializationProgressUpdate(20, tr("effects"));
- m_pEffectsManager = std::make_shared(this, pConfig, pChannelHandleFactory);
+ m_pEffectsManager = std::make_shared(pConfig, pChannelHandleFactory);
m_pEngine = std::make_shared(
pConfig,
@@ -265,20 +261,6 @@ void CoreServices::initialize(QApplication* pApp) {
pChannelHandleFactory,
true);
- // Create effect backends. We do this after creating EngineMaster to allow
- // effect backends to refer to controls that are produced by the engine.
- BuiltInBackend* pBuiltInBackend = new BuiltInBackend(m_pEffectsManager.get());
- m_pEffectsManager->addEffectsBackend(pBuiltInBackend);
-#ifdef __LILV__
- m_pLV2Backend = new LV2Backend(m_pEffectsManager.get());
- // EffectsManager takes ownership
- m_pEffectsManager->addEffectsBackend(m_pLV2Backend);
-#else
- m_pLV2Backend = nullptr;
-#endif
-
- m_pEffectsManager->setup();
-
emit initializationProgressUpdate(30, tr("audio interface"));
// Although m_pSoundManager is created here, m_pSoundManager->setupDevices()
// needs to be called after m_pPlayerManager registers sound IO for each EngineChannel.
@@ -324,7 +306,7 @@ void CoreServices::initialize(QApplication* pApp) {
m_pPlayerManager->addSampler();
m_pPlayerManager->addPreviewDeck();
- m_pEffectsManager->loadEffectChains();
+ m_pEffectsManager->setup();
#ifdef __VINYLCONTROL__
m_pVCManager->init();
diff --git a/src/effects/builtin/autopaneffect.cpp b/src/effects/backends/builtin/autopaneffect.cpp
similarity index 72%
rename from src/effects/builtin/autopaneffect.cpp
rename to src/effects/backends/builtin/autopaneffect.cpp
index d425e5ca6e4..28b0734b439 100644
--- a/src/effects/builtin/autopaneffect.cpp
+++ b/src/effects/backends/builtin/autopaneffect.cpp
@@ -1,4 +1,4 @@
-#include "effects/builtin/autopaneffect.h"
+#include "effects/backends/builtin/autopaneffect.h"
#include
@@ -6,8 +6,7 @@
#include "util/math.h"
#include "util/sample.h"
-const float kPositionRampingThreshold = 0.002f;
-
+constexpr float kPositionRampingThreshold = 0.002f;
// static
QString AutoPanEffect::getId() {
@@ -23,7 +22,7 @@ EffectManifestPointer AutoPanEffect::getManifest() {
pManifest->setAuthor("The Mixxx Team");
pManifest->setVersion("1.0");
pManifest->setDescription(QObject::tr(
- "Bounce the sound left and right across the stereo field"));
+ "Bounce the sound left and right across the stereo field"));
// Period
EffectManifestParameterPointer period = pManifest->addParameter();
@@ -31,31 +30,26 @@ EffectManifestPointer AutoPanEffect::getManifest() {
period->setName(QObject::tr("Period"));
period->setShortName(QObject::tr("Period"));
period->setDescription(QObject::tr(
- "How fast the sound goes from one side to another\n"
- "1/4 - 4 beats rounded to 1/2 beat if tempo is detected\n"
- "1/4 - 4 seconds if no tempo is detected"));
- period->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR);
- period->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- period->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- period->setDefaultLinkType(EffectManifestParameter::LinkType::LINKED);
- period->setDefaultLinkInversion(EffectManifestParameter::LinkInversion::INVERTED);
- period->setMinimum(0.0);
- period->setMaximum(4.0);
- period->setDefault(2.0);
+ "How fast the sound goes from one side to another\n"
+ "1/4 - 4 beats rounded to 1/2 beat if tempo is detected\n"
+ "1/4 - 4 seconds if no tempo is detected"));
+ period->setValueScaler(EffectManifestParameter::ValueScaler::Linear);
+ period->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ period->setDefaultLinkType(EffectManifestParameter::LinkType::Linked);
+ period->setDefaultLinkInversion(EffectManifestParameter::LinkInversion::Inverted);
+ period->setRange(0.0, 2.0, 4.0);
EffectManifestParameterPointer smoothing = pManifest->addParameter();
smoothing->setId("smoothing");
smoothing->setName(QObject::tr("Smoothing"));
smoothing->setShortName(QObject::tr("Smooth"));
smoothing->setDescription(QObject::tr(
- "How smoothly the signal goes from one side to the other"));
- smoothing->setControlHint(EffectManifestParameter::ControlHint::KNOB_LOGARITHMIC);
- smoothing->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- smoothing->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- smoothing->setDefaultLinkType(EffectManifestParameter::LinkType::LINKED);
- smoothing->setMinimum(0.25);
- smoothing->setMaximum(0.50); // there are two steps per period so max is half
- smoothing->setDefault(0.50);
+ "How smoothly the signal goes from one side to the other"));
+ smoothing->setValueScaler(EffectManifestParameter::ValueScaler::Logarithmic);
+ smoothing->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ smoothing->setDefaultLinkType(EffectManifestParameter::LinkType::Linked);
+ smoothing->setRange(0.25, 0.50, 0.50); // There are two steps per period so max is half
+
// TODO(Ferran Pujol): when KnobComposedMaskedRing branch is merged to master,
// make the scaleStartParameter for this be 1.
@@ -65,35 +59,32 @@ EffectManifestPointer AutoPanEffect::getManifest() {
width->setName(QObject::tr("Width"));
width->setShortName(QObject::tr("Width"));
width->setDescription(QObject::tr(
- "How far the signal goes to each side"));
- width->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR);
- width->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- width->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- width->setDefaultLinkType(EffectManifestParameter::LinkType::LINKED);
- width->setMinimum(0.0);
- width->setMaximum(1.0); // 0.02 * sampleRate => 20ms
- width->setDefault(0.5);
+ "How far the signal goes to each side"));
+ width->setValueScaler(EffectManifestParameter::ValueScaler::Linear);
+ width->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ width->setDefaultLinkType(EffectManifestParameter::LinkType::Linked);
+ width->setRange(0.0, 0.5, 1.0); // 0.02 * sampleRate => 20ms
return pManifest;
}
-AutoPanEffect::AutoPanEffect(EngineEffect* pEffect)
- : m_pSmoothingParameter(pEffect->getParameterById("smoothing")),
- m_pPeriodParameter(pEffect->getParameterById("period")),
- m_pWidthParameter(pEffect->getParameterById("width")) {
+void AutoPanEffect::loadEngineEffectParameters(
+ const QMap& parameters) {
+ m_pSmoothingParameter = parameters.value("smoothing");
+ m_pPeriodParameter = parameters.value("period");
+ m_pWidthParameter = parameters.value("width");
}
AutoPanEffect::~AutoPanEffect() {
}
void AutoPanEffect::processChannel(
- const ChannelHandle& handle, AutoPanGroupState* pGroupState,
- const CSAMPLE* pInput, CSAMPLE* pOutput,
- const mixxx::EngineParameters& bufferParameters,
- const EffectEnableState enableState,
- const GroupFeatureState& groupFeatures) {
- Q_UNUSED(handle);
-
+ AutoPanGroupState* pGroupState,
+ const CSAMPLE* pInput,
+ CSAMPLE* pOutput,
+ const mixxx::EngineParameters& engineParameters,
+ const EffectEnableState enableState,
+ const GroupFeatureState& groupFeatures) {
if (enableState == EffectEnableState::Disabled) {
return;
}
@@ -105,14 +96,14 @@ void AutoPanEffect::processChannel(
if (groupFeatures.has_beat_length_sec) {
// period is a number of beats
double beats = std::max(roundToFraction(period, 2), 0.25);
- period = beats * groupFeatures.beat_length_sec * bufferParameters.sampleRate();
+ period = beats * groupFeatures.beat_length_sec * engineParameters.sampleRate();
// TODO(xxx) sync phase
//if (groupFeatures.has_beat_fraction) {
} else {
// period is a number of seconds
- period = std::max(period, 0.25) * bufferParameters.sampleRate();
+ period = std::max(period, 0.25) * engineParameters.sampleRate();
}
// When the period is changed, the position of the sound shouldn't
@@ -146,7 +137,7 @@ void AutoPanEffect::processChannel(
double sinusoid = 0;
// NOTE: Assuming engine is working in stereo.
- for (SINT i = 0; i + 1 < bufferParameters.samplesPerBuffer(); i += 2) {
+ for (SINT i = 0; i + 1 < engineParameters.samplesPerBuffer(); i += 2) {
const auto periodFraction = static_cast(pGroupState->time) /
static_cast(period);
@@ -182,7 +173,7 @@ void AutoPanEffect::processChannel(
-0.005 *
math_clamp(
((pGroupState->frac * 2.0) - 1.0f), -1.0, 1.0) *
- bufferParameters.sampleRate());
+ engineParameters.sampleRate());
double lawCoef = computeLawCoefficient(sinusoid);
pOutput[i] *= static_cast(pGroupState->frac * lawCoef);
diff --git a/src/effects/builtin/autopaneffect.h b/src/effects/backends/builtin/autopaneffect.h
similarity index 74%
rename from src/effects/builtin/autopaneffect.h
rename to src/effects/backends/builtin/autopaneffect.h
index 97c4e3da802..8244e6821b6 100644
--- a/src/effects/builtin/autopaneffect.h
+++ b/src/effects/backends/builtin/autopaneffect.h
@@ -2,7 +2,7 @@
#include
-#include "effects/effectprocessor.h"
+#include "effects/backends/effectprocessor.h"
#include "engine/effects/engineeffect.h"
#include "engine/effects/engineeffectparameter.h"
#include "engine/filters/enginefilterpansingle.h"
@@ -17,11 +17,12 @@
// somewhere else (I hear clicks when I change the period of flanger for example).
class RampedSample {
public:
-
inline RampedSample()
- : ramped(false),
- maxDifference(1.0f),
- initialized(false) {}
+ : ramped(false),
+ maxDifference(1.0f),
+ currentValue(0),
+ initialized(false) {
+ }
virtual ~RampedSample(){};
@@ -62,8 +63,8 @@ static constexpr int panMaxDelay = 3300; // allows a 30 Hz filter at 97346;
class AutoPanGroupState : public EffectState {
public:
- AutoPanGroupState(const mixxx::EngineParameters& bufferParameters)
- : EffectState(bufferParameters) {
+ AutoPanGroupState(const mixxx::EngineParameters& engineParameters)
+ : EffectState(engineParameters) {
time = 0;
delay = new EngineFilterPanSingle();
m_dPreviousPeriod = -1.0;
@@ -78,30 +79,33 @@ class AutoPanGroupState : public EffectState {
class AutoPanEffect : public EffectProcessorImpl {
public:
- AutoPanEffect(EngineEffect* pEffect);
+ AutoPanEffect() = default;
virtual ~AutoPanEffect();
static QString getId();
static EffectManifestPointer getManifest();
- void processChannel(const ChannelHandle& handle,
+ void loadEngineEffectParameters(
+ const QMap& parameters) override;
+
+ void processChannel(
AutoPanGroupState* pState,
- const CSAMPLE* pInput, CSAMPLE* pOutput,
- const mixxx::EngineParameters& bufferParameters,
+ const CSAMPLE* pInput,
+ CSAMPLE* pOutput,
+ const mixxx::EngineParameters& engineParameters,
const EffectEnableState enableState,
- const GroupFeatureState& groupFeatures);
+ const GroupFeatureState& groupFeatures) override;
double computeLawCoefficient(double position);
private:
-
QString debugString() const {
return getId();
}
- EngineEffectParameter* m_pSmoothingParameter;
- EngineEffectParameter* m_pPeriodParameter;
- EngineEffectParameter* m_pWidthParameter;
+ EngineEffectParameterPointer m_pSmoothingParameter;
+ EngineEffectParameterPointer m_pPeriodParameter;
+ EngineEffectParameterPointer m_pWidthParameter;
DISALLOW_COPY_AND_ASSIGN(AutoPanEffect);
};
diff --git a/src/effects/builtin/balanceeffect.cpp b/src/effects/backends/builtin/balanceeffect.cpp
similarity index 52%
rename from src/effects/builtin/balanceeffect.cpp
rename to src/effects/backends/builtin/balanceeffect.cpp
index 024f454ccd3..b281ccd6724 100644
--- a/src/effects/builtin/balanceeffect.cpp
+++ b/src/effects/backends/builtin/balanceeffect.cpp
@@ -21,69 +21,61 @@ EffectManifestPointer BalanceEffect::getManifest() {
pManifest->setAuthor("The Mixxx Team");
pManifest->setVersion("1.0");
pManifest->setDescription(QObject::tr(
- "Adjust the left/right balance and stereo width"));
+ "Adjust the left/right balance and stereo width"));
pManifest->setEffectRampsFromDry(true);
+ pManifest->setMetaknobDefault(0.5);
EffectManifestParameterPointer balance = pManifest->addParameter();
balance->setId("balance");
balance->setName(QObject::tr("Balance"));
balance->setShortName(QObject::tr("Balance"));
balance->setDescription(QObject::tr(
- "Adjust balance between left and right channels"));
- balance->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR);
- balance->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- balance->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- balance->setDefaultLinkType(EffectManifestParameter::LinkType::LINKED);
- balance->setMinimum(-1.0);
- balance->setMaximum(+1.0);
- balance->setDefault(0.0);
+ "Adjust balance between left and right channels"));
+ balance->setValueScaler(EffectManifestParameter::ValueScaler::Linear);
+ balance->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ balance->setDefaultLinkType(EffectManifestParameter::LinkType::Linked);
+ balance->setRange(-1.0, 0.0, +1.0);
EffectManifestParameterPointer midSide = pManifest->addParameter();
midSide->setId("midSide");
midSide->setName(QObject::tr("Mid/Side"));
midSide->setShortName(QObject::tr("Mid/Side"));
midSide->setDescription(QObject::tr(
- "Adjust stereo width by changing balance between middle and side of the signal.\n"
- "Fully left: mono\n"
- "Fully right: only side ambiance\n"
- "Center: does not change the original signal."));
- midSide->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR);
- midSide->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- midSide->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- midSide->setDefaultLinkType(EffectManifestParameter::LinkType::NONE);
- midSide->setMinimum(-1.0);
- midSide->setMaximum(+1.0);
- midSide->setDefault(0.0);
+ "Adjust stereo width by changing balance between middle and side of the signal.\n"
+ "Fully left: mono\n"
+ "Fully right: only side ambiance\n"
+ "Center: does not change the original signal."));
+ midSide->setValueScaler(EffectManifestParameter::ValueScaler::Linear);
+ midSide->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ midSide->setDefaultLinkType(EffectManifestParameter::LinkType::None);
+ midSide->setRange(-1.0, 0.0, +1.0);
EffectManifestParameterPointer midLowPass = pManifest->addParameter();
midLowPass->setId("bypassFreq");
midLowPass->setName(QObject::tr("Bypass Frequency"));
midLowPass->setShortName(QObject::tr("Bypass Fr."));
midLowPass->setDescription(QObject::tr(
- "Frequencies below this cutoff are not adjusted in the stereo field"));
- midLowPass->setControlHint(EffectManifestParameter::ControlHint::KNOB_LOGARITHMIC);
- midLowPass->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- midLowPass->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- midLowPass->setDefaultLinkType(EffectManifestParameter::LinkType::NONE);
+ "Frequencies below this cutoff are not adjusted in the stereo field"));
+ midLowPass->setValueScaler(EffectManifestParameter::ValueScaler::Logarithmic);
+ midLowPass->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ midLowPass->setDefaultLinkType(EffectManifestParameter::LinkType::None);
midLowPass->setNeutralPointOnScale(1);
- midLowPass->setDefault(kMinCornerHz);
- midLowPass->setMinimum(kMinCornerHz);
- midLowPass->setMaximum(kMaxCornerHz);
+ midLowPass->setRange(kMinCornerHz, kMinCornerHz, kMaxCornerHz);
return pManifest;
}
-BalanceGroupState::BalanceGroupState(const mixxx::EngineParameters& bufferParameters)
- : EffectState(bufferParameters),
+BalanceGroupState::BalanceGroupState(const mixxx::EngineParameters& engineParameters)
+ : EffectState(engineParameters),
m_pHighBuf(MAX_BUFFER_LEN),
- m_oldSampleRate(bufferParameters.sampleRate()),
+ m_oldSampleRate(engineParameters.sampleRate()),
m_freq(kMinCornerHz),
m_oldBalance(0),
m_oldMidSide(0) {
- m_low = std::make_unique(bufferParameters.sampleRate(),
- kMinCornerHz);
- m_high = std::make_unique(bufferParameters.sampleRate(),
- kMinCornerHz);
+ m_low = std::make_unique(engineParameters.sampleRate(),
+ kMinCornerHz);
+ m_high = std::make_unique(engineParameters.sampleRate(),
+ kMinCornerHz);
m_high->setStartFromDry(true);
}
@@ -95,22 +87,23 @@ void BalanceGroupState::setFilters(int sampleRate, double freq) {
m_high->setFrequencyCorners(sampleRate, freq);
}
-BalanceEffect::BalanceEffect(EngineEffect* pEffect)
- : m_pBalanceParameter(pEffect->getParameterById("balance")),
- m_pMidSideParameter(pEffect->getParameterById("midSide")),
- m_pBypassFreqParameter(pEffect->getParameterById("bypassFreq")) {
+void BalanceEffect::loadEngineEffectParameters(
+ const QMap& parameters) {
+ m_pBalanceParameter = parameters.value("balance");
+ m_pMidSideParameter = parameters.value("midSide");
+ m_pBypassFreqParameter = parameters.value("bypassFreq");
}
BalanceEffect::~BalanceEffect() {
}
-void BalanceEffect::processChannel(const ChannelHandle& handle,
- BalanceGroupState* pGroupState,
- const CSAMPLE* pInput, CSAMPLE* pOutput,
- const mixxx::EngineParameters& bufferParameters,
- const EffectEnableState enableState,
- const GroupFeatureState& groupFeatures) {
- Q_UNUSED(handle);
+void BalanceEffect::processChannel(
+ BalanceGroupState* pGroupState,
+ const CSAMPLE* pInput,
+ CSAMPLE* pOutput,
+ const mixxx::EngineParameters& engineParameters,
+ const EffectEnableState enableState,
+ const GroupFeatureState& groupFeatures) {
Q_UNUSED(groupFeatures);
CSAMPLE_GAIN balance = 0;
@@ -120,34 +113,43 @@ void BalanceEffect::processChannel(const ChannelHandle& handle,
midSide = static_cast(m_pMidSideParameter->value());
}
- CSAMPLE_GAIN balanceDelta = (balance - pGroupState->m_oldBalance)
- / CSAMPLE_GAIN(bufferParameters.framesPerBuffer());
- CSAMPLE_GAIN midSideDelta = (midSide - pGroupState->m_oldMidSide)
- / CSAMPLE_GAIN(bufferParameters.framesPerBuffer());
+ CSAMPLE_GAIN balanceDelta = (balance - pGroupState->m_oldBalance) /
+ CSAMPLE_GAIN(engineParameters.framesPerBuffer());
+ CSAMPLE_GAIN midSideDelta = (midSide - pGroupState->m_oldMidSide) /
+ CSAMPLE_GAIN(engineParameters.framesPerBuffer());
CSAMPLE_GAIN balanceStart = pGroupState->m_oldBalance + balanceDelta;
CSAMPLE_GAIN midSideStart = pGroupState->m_oldMidSide + midSideDelta;
double freq = pGroupState->m_freq;
- if (pGroupState->m_oldSampleRate != bufferParameters.sampleRate() ||
+ if (pGroupState->m_oldSampleRate != engineParameters.sampleRate() ||
(freq != m_pBypassFreqParameter->value())) {
freq = m_pBypassFreqParameter->value();
- pGroupState->m_oldSampleRate = bufferParameters.sampleRate();
- pGroupState->setFilters(bufferParameters.sampleRate(), pGroupState->m_freq);
+ pGroupState->m_oldSampleRate = engineParameters.sampleRate();
+ pGroupState->setFilters(engineParameters.sampleRate(), pGroupState->m_freq);
}
if (pGroupState->m_freq > kMinCornerHz) {
if (freq > kMinCornerHz && enableState != EffectEnableState::Disabling) {
- pGroupState->m_high->process(pInput, pGroupState->m_pHighBuf.data(), bufferParameters.samplesPerBuffer());
- pGroupState->m_low->process(pInput, pOutput, bufferParameters.samplesPerBuffer());
+ pGroupState->m_high->process(pInput,
+ pGroupState->m_pHighBuf.data(),
+ engineParameters.samplesPerBuffer());
+ pGroupState->m_low->process(pInput, pOutput, engineParameters.samplesPerBuffer());
} else {
- pGroupState->m_high->processAndPauseFilter(pInput, pGroupState->m_pHighBuf.data(), bufferParameters.samplesPerBuffer());
- pGroupState->m_low->processAndPauseFilter(pInput, pOutput, bufferParameters.samplesPerBuffer());
+ pGroupState->m_high->processAndPauseFilter(pInput,
+ pGroupState->m_pHighBuf.data(),
+ engineParameters.samplesPerBuffer());
+ pGroupState->m_low->processAndPauseFilter(
+ pInput, pOutput, engineParameters.samplesPerBuffer());
}
- for (SINT i = 0; i < bufferParameters.samplesPerBuffer() / 2; ++i) {
- CSAMPLE mid = (pGroupState->m_pHighBuf[i * 2] + pGroupState->m_pHighBuf[i * 2 + 1]) / 2.0f;
- CSAMPLE side = (pGroupState->m_pHighBuf[i * 2 + 1] - pGroupState->m_pHighBuf[i * 2]) / 2.0f;
+ for (SINT i = 0; i < engineParameters.samplesPerBuffer() / 2; ++i) {
+ CSAMPLE mid = (pGroupState->m_pHighBuf[i * 2] +
+ pGroupState->m_pHighBuf[i * 2 + 1]) /
+ 2.0f;
+ CSAMPLE side = (pGroupState->m_pHighBuf[i * 2 + 1] -
+ pGroupState->m_pHighBuf[i * 2]) /
+ 2.0f;
CSAMPLE_GAIN currentMidSide = midSideStart + midSideDelta * i;
if (currentMidSide > 0) {
mid *= (1 - currentMidSide);
@@ -167,22 +169,22 @@ void BalanceEffect::processChannel(const ChannelHandle& handle,
pGroupState->m_high->pauseFilter();
pGroupState->m_low->pauseFilter();
- for (SINT i = 0; i < bufferParameters.samplesPerBuffer() / 2; ++i) {
- CSAMPLE mid = (pInput[i * 2] + pInput[i * 2 + 1]) / 2.0f;
+ for (SINT i = 0; i < engineParameters.samplesPerBuffer() / 2; ++i) {
+ CSAMPLE mid = (pInput[i * 2] + pInput[i * 2 + 1]) / 2.0f;
CSAMPLE side = (pInput[i * 2 + 1] - pInput[i * 2]) / 2.0f;
CSAMPLE_GAIN currentMidSide = midSideStart + midSideDelta * i;
if (currentMidSide > 0) {
- mid *= (1 - currentMidSide);
+ mid *= (1 - currentMidSide);
} else {
- side *= (1 + currentMidSide);
+ side *= (1 + currentMidSide);
}
CSAMPLE_GAIN currentBalance = (balanceStart + balanceDelta * i);
if (currentBalance > 0) {
- pOutput[i * 2] = (mid - side) * (1 - currentBalance);
- pOutput[i * 2 + 1] = (mid + side);
+ pOutput[i * 2] = (mid - side) * (1 - currentBalance);
+ pOutput[i * 2 + 1] = (mid + side);
} else {
- pOutput[i * 2] = (mid - side);
- pOutput[i * 2 + 1] = (mid + side) * (1 + currentBalance);
+ pOutput[i * 2] = (mid - side);
+ pOutput[i * 2 + 1] = (mid + side) * (1 + currentBalance);
}
}
}
diff --git a/src/effects/builtin/balanceeffect.h b/src/effects/backends/builtin/balanceeffect.h
similarity index 56%
rename from src/effects/builtin/balanceeffect.h
rename to src/effects/backends/builtin/balanceeffect.h
index 4562c93a0ea..ebf372e06ff 100644
--- a/src/effects/builtin/balanceeffect.h
+++ b/src/effects/backends/builtin/balanceeffect.h
@@ -1,15 +1,15 @@
#pragma once
-#include "effects/effectprocessor.h"
+#include "effects/backends/effectprocessor.h"
#include "engine/effects/engineeffect.h"
#include "engine/effects/engineeffectparameter.h"
#include "engine/filters/enginefilterlinkwitzriley4.h"
-#include "util/samplebuffer.h"
#include "util/memory.h"
+#include "util/samplebuffer.h"
class BalanceGroupState : public EffectState {
public:
- BalanceGroupState(const mixxx::EngineParameters& bufferParameters);
+ BalanceGroupState(const mixxx::EngineParameters& engineParameters);
~BalanceGroupState();
void setFilters(int sampleRate, double freq);
@@ -28,28 +28,31 @@ class BalanceGroupState : public EffectState {
class BalanceEffect : public EffectProcessorImpl {
public:
- BalanceEffect(EngineEffect* pEffect);
+ BalanceEffect() = default;
virtual ~BalanceEffect();
static QString getId();
static EffectManifestPointer getManifest();
- void processChannel(const ChannelHandle& handle,
- BalanceGroupState* pState,
- const CSAMPLE* pInput, CSAMPLE* pOutput,
- const mixxx::EngineParameters& bufferParameters,
- const EffectEnableState enableState,
- const GroupFeatureState& groupFeatures);
+ void loadEngineEffectParameters(
+ const QMap& parameters) override;
- private:
+ void processChannel(
+ BalanceGroupState* pState,
+ const CSAMPLE* pInput,
+ CSAMPLE* pOutput,
+ const mixxx::EngineParameters& engineParameters,
+ const EffectEnableState enableState,
+ const GroupFeatureState& groupFeatures) override;
+ private:
QString debugString() const {
return getId();
}
- EngineEffectParameter* m_pBalanceParameter;
- EngineEffectParameter* m_pMidSideParameter;
- EngineEffectParameter* m_pBypassFreqParameter;
+ EngineEffectParameterPointer m_pBalanceParameter;
+ EngineEffectParameterPointer m_pMidSideParameter;
+ EngineEffectParameterPointer m_pBypassFreqParameter;
DISALLOW_COPY_AND_ASSIGN(BalanceEffect);
};
diff --git a/src/effects/backends/builtin/bessel4lvmixeqeffect.cpp b/src/effects/backends/builtin/bessel4lvmixeqeffect.cpp
new file mode 100644
index 00000000000..31fe55a00b1
--- /dev/null
+++ b/src/effects/backends/builtin/bessel4lvmixeqeffect.cpp
@@ -0,0 +1,92 @@
+#include "effects/backends/builtin/bessel4lvmixeqeffect.h"
+
+#include "effects/backends/builtin/equalizer_util.h"
+#include "util/math.h"
+
+// static
+QString Bessel4LVMixEQEffect::getId() {
+ return "org.mixxx.effects.bessel4lvmixeq";
+}
+
+// static
+EffectManifestPointer Bessel4LVMixEQEffect::getManifest() {
+ EffectManifestPointer pManifest(new EffectManifest());
+ pManifest->setId(getId());
+ pManifest->setName(QObject::tr("Bessel4 LV-Mix Isolator"));
+ pManifest->setShortName(QObject::tr("Bessel4 ISO"));
+ pManifest->setAuthor("The Mixxx Team");
+ pManifest->setVersion("1.0");
+ pManifest->setDescription(
+ QObject::tr("A Bessel 4th-order filter isolator with Lipshitz and "
+ "Vanderkooy mix (bit perfect unity, roll-off -24 "
+ "dB/octave).") +
+ " " + EqualizerUtil::adjustFrequencyShelvesTip());
+ pManifest->setIsMixingEQ(true);
+ pManifest->setEffectRampsFromDry(true);
+
+ EqualizerUtil::createCommonParameters(pManifest.data(), false);
+ return pManifest;
+}
+
+Bessel4LVMixEQEffect::Bessel4LVMixEQEffect() {
+ m_pLoFreqCorner = new ControlProxy("[Mixer Profile]", "LoEQFrequency");
+ m_pHiFreqCorner = new ControlProxy("[Mixer Profile]", "HiEQFrequency");
+}
+
+void Bessel4LVMixEQEffect::loadEngineEffectParameters(
+ const QMap& parameters) {
+ m_pPotLow = parameters.value("low");
+ m_pPotMid = parameters.value("mid");
+ m_pPotHigh = parameters.value("high");
+ m_pKillLow = parameters.value("killLow");
+ m_pKillMid = parameters.value("killMid");
+ m_pKillHigh = parameters.value("killHigh");
+}
+
+Bessel4LVMixEQEffect::~Bessel4LVMixEQEffect() {
+ delete m_pLoFreqCorner;
+ delete m_pHiFreqCorner;
+}
+
+void Bessel4LVMixEQEffect::processChannel(
+ Bessel4LVMixEQEffectGroupState* pState,
+ const CSAMPLE* pInput,
+ CSAMPLE* pOutput,
+ const mixxx::EngineParameters& engineParameters,
+ const EffectEnableState enableState,
+ const GroupFeatureState& groupFeatures) {
+ Q_UNUSED(groupFeatures);
+
+ if (enableState == EffectEnableState::Disabling) {
+ // Ramp to dry, when disabling, this will ramp from dry when enabling as well
+ pState->processChannelAndPause(pInput, pOutput, engineParameters.samplesPerBuffer());
+ } else {
+ double fLow;
+ double fMid;
+ double fHigh;
+ if (!m_pKillLow->toBool()) {
+ fLow = m_pPotLow->value();
+ } else {
+ fLow = 0;
+ }
+ if (!m_pKillMid->toBool()) {
+ fMid = m_pPotMid->value();
+ } else {
+ fMid = 0;
+ }
+ if (!m_pKillHigh->toBool()) {
+ fHigh = m_pPotHigh->value();
+ } else {
+ fHigh = 0;
+ }
+ pState->processChannel(pInput,
+ pOutput,
+ engineParameters.samplesPerBuffer(),
+ engineParameters.sampleRate(),
+ fLow,
+ fMid,
+ fHigh,
+ m_pLoFreqCorner->get(),
+ m_pHiFreqCorner->get());
+ }
+}
diff --git a/src/effects/backends/builtin/bessel4lvmixeqeffect.h b/src/effects/backends/builtin/bessel4lvmixeqeffect.h
new file mode 100644
index 00000000000..c5295f9eb2f
--- /dev/null
+++ b/src/effects/backends/builtin/bessel4lvmixeqeffect.h
@@ -0,0 +1,58 @@
+#pragma once
+#include
+
+#include "control/controlproxy.h"
+#include "effects/backends/builtin/lvmixeqbase.h"
+#include "effects/backends/effectprocessor.h"
+#include "engine/effects/engineeffect.h"
+#include "engine/effects/engineeffectparameter.h"
+#include "engine/filters/enginefilterbessel4.h"
+#include "engine/filters/enginefilterdelay.h"
+#include "util/class.h"
+#include "util/defs.h"
+#include "util/types.h"
+
+class Bessel4LVMixEQEffectGroupState : public LVMixEQEffectGroupState {
+ public:
+ Bessel4LVMixEQEffectGroupState(const mixxx::EngineParameters& engineParameters)
+ : LVMixEQEffectGroupState(engineParameters) {
+ }
+};
+
+class Bessel4LVMixEQEffect : public EffectProcessorImpl {
+ public:
+ Bessel4LVMixEQEffect();
+ virtual ~Bessel4LVMixEQEffect();
+
+ static QString getId();
+ static EffectManifestPointer getManifest();
+
+ void loadEngineEffectParameters(
+ const QMap& parameters) override;
+
+ void processChannel(
+ Bessel4LVMixEQEffectGroupState* pState,
+ const CSAMPLE* pInput,
+ CSAMPLE* pOutput,
+ const mixxx::EngineParameters& engineParameters,
+ const EffectEnableState enableState,
+ const GroupFeatureState& groupFeatureState) override;
+
+ private:
+ QString debugString() const {
+ return getId();
+ }
+
+ EngineEffectParameterPointer m_pPotLow;
+ EngineEffectParameterPointer m_pPotMid;
+ EngineEffectParameterPointer m_pPotHigh;
+
+ EngineEffectParameterPointer m_pKillLow;
+ EngineEffectParameterPointer m_pKillMid;
+ EngineEffectParameterPointer m_pKillHigh;
+
+ ControlProxy* m_pLoFreqCorner;
+ ControlProxy* m_pHiFreqCorner;
+
+ DISALLOW_COPY_AND_ASSIGN(Bessel4LVMixEQEffect);
+};
diff --git a/src/effects/builtin/bessel8lvmixeqeffect.cpp b/src/effects/backends/builtin/bessel8lvmixeqeffect.cpp
similarity index 50%
rename from src/effects/builtin/bessel8lvmixeqeffect.cpp
rename to src/effects/backends/builtin/bessel8lvmixeqeffect.cpp
index 898a28f798b..ff201f0bd60 100644
--- a/src/effects/builtin/bessel8lvmixeqeffect.cpp
+++ b/src/effects/backends/builtin/bessel8lvmixeqeffect.cpp
@@ -1,6 +1,6 @@
-#include "effects/builtin/bessel8lvmixeqeffect.h"
+#include "effects/backends/builtin/bessel8lvmixeqeffect.h"
-#include "effects/builtin/equalizer_util.h"
+#include "effects/backends/builtin/equalizer_util.h"
#include "util/math.h"
// static
@@ -16,8 +16,11 @@ EffectManifestPointer Bessel8LVMixEQEffect::getManifest() {
pManifest->setShortName(QObject::tr("Bessel8 ISO"));
pManifest->setAuthor("The Mixxx Team");
pManifest->setVersion("1.0");
- pManifest->setDescription(QObject::tr(
- "A Bessel 8th-order filter isolator with Lipshitz and Vanderkooy mix (bit perfect unity, roll-off -48 dB/octave).") + " " + EqualizerUtil::adjustFrequencyShelvesTip());
+ pManifest->setDescription(
+ QObject::tr("A Bessel 8th-order filter isolator with Lipshitz and "
+ "Vanderkooy mix (bit perfect unity, roll-off -48 "
+ "dB/octave).") +
+ " " + EqualizerUtil::adjustFrequencyShelvesTip());
pManifest->setIsMixingEQ(true);
pManifest->setEffectRampsFromDry(true);
@@ -25,34 +28,38 @@ EffectManifestPointer Bessel8LVMixEQEffect::getManifest() {
return pManifest;
}
-Bessel8LVMixEQEffect::Bessel8LVMixEQEffect(EngineEffect* pEffect)
- : m_pPotLow(pEffect->getParameterById("low")),
- m_pPotMid(pEffect->getParameterById("mid")),
- m_pPotHigh(pEffect->getParameterById("high")),
- m_pKillLow(pEffect->getParameterById("killLow")),
- m_pKillMid(pEffect->getParameterById("killMid")),
- m_pKillHigh(pEffect->getParameterById("killHigh")) {
+Bessel8LVMixEQEffect::Bessel8LVMixEQEffect() {
m_pLoFreqCorner = new ControlProxy("[Mixer Profile]", "LoEQFrequency");
m_pHiFreqCorner = new ControlProxy("[Mixer Profile]", "HiEQFrequency");
}
+void Bessel8LVMixEQEffect::loadEngineEffectParameters(
+ const QMap& parameters) {
+ m_pPotLow = parameters.value("low");
+ m_pPotMid = parameters.value("mid");
+ m_pPotHigh = parameters.value("high");
+ m_pKillLow = parameters.value("killLow");
+ m_pKillMid = parameters.value("killMid");
+ m_pKillHigh = parameters.value("killHigh");
+}
+
Bessel8LVMixEQEffect::~Bessel8LVMixEQEffect() {
delete m_pLoFreqCorner;
delete m_pHiFreqCorner;
}
-void Bessel8LVMixEQEffect::processChannel(const ChannelHandle& handle,
- Bessel8LVMixEQEffectGroupState* pState,
- const CSAMPLE* pInput, CSAMPLE* pOutput,
- const mixxx::EngineParameters& bufferParameters,
- const EffectEnableState enableState,
- const GroupFeatureState& groupFeatures) {
- Q_UNUSED(handle);
+void Bessel8LVMixEQEffect::processChannel(
+ Bessel8LVMixEQEffectGroupState* pState,
+ const CSAMPLE* pInput,
+ CSAMPLE* pOutput,
+ const mixxx::EngineParameters& engineParameters,
+ const EffectEnableState enableState,
+ const GroupFeatureState& groupFeatures) {
Q_UNUSED(groupFeatures);
if (enableState == EffectEnableState::Disabling) {
// Ramp to dry, when disabling, this will ramp from dry when enabling as well
- pState->processChannelAndPause(pInput, pOutput, bufferParameters.samplesPerBuffer());
+ pState->processChannelAndPause(pInput, pOutput, engineParameters.samplesPerBuffer());
} else {
double fLow;
double fMid;
@@ -72,10 +79,14 @@ void Bessel8LVMixEQEffect::processChannel(const ChannelHandle& handle,
} else {
fHigh = 0;
}
- pState->processChannel(
- pInput, pOutput,
- bufferParameters.samplesPerBuffer(), bufferParameters.sampleRate(),
- fLow, fMid, fHigh,
- m_pLoFreqCorner->get(), m_pHiFreqCorner->get());
+ pState->processChannel(pInput,
+ pOutput,
+ engineParameters.samplesPerBuffer(),
+ engineParameters.sampleRate(),
+ fLow,
+ fMid,
+ fHigh,
+ m_pLoFreqCorner->get(),
+ m_pHiFreqCorner->get());
}
}
diff --git a/src/effects/backends/builtin/bessel8lvmixeqeffect.h b/src/effects/backends/builtin/bessel8lvmixeqeffect.h
new file mode 100644
index 00000000000..097df8c96e6
--- /dev/null
+++ b/src/effects/backends/builtin/bessel8lvmixeqeffect.h
@@ -0,0 +1,60 @@
+#pragma once
+
+#include
+
+#include "control/controlproxy.h"
+#include "effects/backends/builtin/lvmixeqbase.h"
+#include "effects/backends/effectprocessor.h"
+#include "engine/effects/engineeffect.h"
+#include "engine/effects/engineeffectparameter.h"
+#include "engine/filters/enginefilterbessel8.h"
+#include "engine/filters/enginefilterdelay.h"
+#include "util/class.h"
+#include "util/defs.h"
+#include "util/sample.h"
+#include "util/types.h"
+
+class Bessel8LVMixEQEffectGroupState : public LVMixEQEffectGroupState {
+ public:
+ Bessel8LVMixEQEffectGroupState(const mixxx::EngineParameters& engineParameters)
+ : LVMixEQEffectGroupState(engineParameters) {
+ }
+};
+
+class Bessel8LVMixEQEffect : public EffectProcessorImpl {
+ public:
+ Bessel8LVMixEQEffect();
+ virtual ~Bessel8LVMixEQEffect();
+
+ static QString getId();
+ static EffectManifestPointer getManifest();
+
+ void loadEngineEffectParameters(
+ const QMap& parameters) override;
+
+ void processChannel(
+ Bessel8LVMixEQEffectGroupState* pState,
+ const CSAMPLE* pInput,
+ CSAMPLE* pOutput,
+ const mixxx::EngineParameters& engineParameters,
+ const EffectEnableState enableState,
+ const GroupFeatureState& groupFeatureState) override;
+
+ private:
+ QString debugString() const {
+ return getId();
+ }
+
+ EngineEffectParameterPointer m_pPotLow;
+ EngineEffectParameterPointer m_pPotMid;
+ EngineEffectParameterPointer m_pPotHigh;
+
+ EngineEffectParameterPointer m_pKillLow;
+ EngineEffectParameterPointer m_pKillMid;
+ EngineEffectParameterPointer m_pKillHigh;
+
+ ControlProxy* m_pLoFreqCorner;
+ ControlProxy* m_pHiFreqCorner;
+
+ DISALLOW_COPY_AND_ASSIGN(Bessel8LVMixEQEffect);
+};
diff --git a/src/effects/builtin/biquadfullkilleqeffect.cpp b/src/effects/backends/builtin/biquadfullkilleqeffect.cpp
similarity index 76%
rename from src/effects/builtin/biquadfullkilleqeffect.cpp
rename to src/effects/backends/builtin/biquadfullkilleqeffect.cpp
index 4c384556284..fa3bcb4b35a 100644
--- a/src/effects/builtin/biquadfullkilleqeffect.cpp
+++ b/src/effects/backends/builtin/biquadfullkilleqeffect.cpp
@@ -1,6 +1,6 @@
-#include "effects/builtin/biquadfullkilleqeffect.h"
+#include "effects/backends/builtin/biquadfullkilleqeffect.h"
-#include "effects/builtin/equalizer_util.h"
+#include "effects/backends/builtin/equalizer_util.h"
#include "util/math.h"
namespace {
@@ -23,7 +23,7 @@ double getCenterFrequency(double low, double high) {
return pow(10, scaleCenter);
}
-double knobValueToBiquadGainDb (double value, bool kill) {
+double knobValueToBiquadGainDb(double value, bool kill) {
if (kill) {
return kKillGain;
}
@@ -33,10 +33,9 @@ double knobValueToBiquadGainDb (double value, bool kill) {
double startDB = ratio2db(kBesselStartRatio);
value = 1 - (value / kBesselStartRatio);
return (kKillGain - startDB) * value + startDB;
-
}
-double knobValueToBesselRatio (double value, bool kill) {
+double knobValueToBesselRatio(double value, bool kill) {
if (kill) {
return 0.0;
}
@@ -45,7 +44,6 @@ double knobValueToBesselRatio (double value, bool kill) {
} // anonymous namespace
-
// static
QString BiquadFullKillEQEffect::getId() {
return "org.mixxx.effects.biquadfullkilleq";
@@ -59,8 +57,11 @@ EffectManifestPointer BiquadFullKillEQEffect::getManifest() {
pManifest->setShortName(QObject::tr("BQ EQ/ISO"));
pManifest->setAuthor("The Mixxx Team");
pManifest->setVersion("1.0");
- pManifest->setDescription(QObject::tr(
- "A 3-band Equalizer that combines an Equalizer and an Isolator circuit to offer gentle slopes and full kill.") + " " + EqualizerUtil::adjustFrequencyShelvesTip());
+ pManifest->setDescription(
+ QObject::tr(
+ "A 3-band Equalizer that combines an Equalizer and an "
+ "Isolator circuit to offer gentle slopes and full kill.") +
+ " " + EqualizerUtil::adjustFrequencyShelvesTip());
pManifest->setEffectRampsFromDry(true);
pManifest->setIsMixingEQ(true);
@@ -69,12 +70,12 @@ EffectManifestPointer BiquadFullKillEQEffect::getManifest() {
}
BiquadFullKillEQEffectGroupState::BiquadFullKillEQEffectGroupState(
- const mixxx::EngineParameters& bufferParameters)
- : EffectState(bufferParameters),
- m_pLowBuf(bufferParameters.samplesPerBuffer()),
- m_pBandBuf(bufferParameters.samplesPerBuffer()),
- m_pHighBuf(bufferParameters.samplesPerBuffer()),
- m_tempBuf(bufferParameters.samplesPerBuffer()),
+ const mixxx::EngineParameters& engineParameters)
+ : EffectState(engineParameters),
+ m_pLowBuf(engineParameters.samplesPerBuffer()),
+ m_pBandBuf(engineParameters.samplesPerBuffer()),
+ m_pHighBuf(engineParameters.samplesPerBuffer()),
+ m_tempBuf(engineParameters.samplesPerBuffer()),
m_oldLowBoost(0),
m_oldMidBoost(0),
m_oldHighBoost(0),
@@ -108,7 +109,7 @@ BiquadFullKillEQEffectGroupState::BiquadFullKillEQEffectGroupState(
LVMixEQEffectGroupStateConstants::kStartupHiFreq / 2,
kQHighKillShelve);
m_lvMixIso = std::make_unique<
- LVMixEQEffectGroupState>(bufferParameters);
+ LVMixEQEffectGroupState>(engineParameters);
setFilters(
mixxx::audio::SampleRate(
@@ -125,7 +126,6 @@ void BiquadFullKillEQEffectGroupState::setFilters(
double midCenter = getCenterFrequency(lowFreqCorner, highFreqCorner);
double highCenter = getCenterFrequency(highFreqCorner, kMaximumFrequency);
-
m_lowBoost->setFrequencyCorners(
sampleRate, lowCenter, kQBoost, m_oldLowBoost);
m_midBoost->setFrequencyCorners(
@@ -142,39 +142,42 @@ void BiquadFullKillEQEffectGroupState::setFilters(
m_lvMixIso->setFilters(sampleRate, lowFreqCorner, highFreqCorner);
}
-BiquadFullKillEQEffect::BiquadFullKillEQEffect(EngineEffect* pEffect)
- : m_pPotLow(pEffect->getParameterById("low")),
- m_pPotMid(pEffect->getParameterById("mid")),
- m_pPotHigh(pEffect->getParameterById("high")),
- m_pKillLow(pEffect->getParameterById("killLow")),
- m_pKillMid(pEffect->getParameterById("killMid")),
- m_pKillHigh(pEffect->getParameterById("killHigh")) {
+BiquadFullKillEQEffect::BiquadFullKillEQEffect() {
m_pLoFreqCorner = std::make_unique("[Mixer Profile]", "LoEQFrequency");
m_pHiFreqCorner = std::make_unique("[Mixer Profile]", "HiEQFrequency");
}
+void BiquadFullKillEQEffect::loadEngineEffectParameters(
+ const QMap& parameters) {
+ m_pPotLow = parameters.value("low");
+ m_pPotMid = parameters.value("mid");
+ m_pPotHigh = parameters.value("high");
+ m_pKillLow = parameters.value("killLow");
+ m_pKillMid = parameters.value("killMid");
+ m_pKillHigh = parameters.value("killHigh");
+}
+
// BiquadFullKillEQEffect::~BiquadFullKillEQEffect() {
// }
void BiquadFullKillEQEffect::processChannel(
- const ChannelHandle& handle,
BiquadFullKillEQEffectGroupState* pState,
const CSAMPLE* pInput,
CSAMPLE* pOutput,
- const mixxx::EngineParameters& bufferParameters,
+ const mixxx::EngineParameters& engineParameters,
const EffectEnableState enableState,
const GroupFeatureState& groupFeatures) {
- Q_UNUSED(handle);
Q_UNUSED(groupFeatures);
- if (pState->m_oldSampleRate != bufferParameters.sampleRate() ||
+ if (pState->m_oldSampleRate != engineParameters.sampleRate() ||
(pState->m_loFreqCorner != m_pLoFreqCorner->get()) ||
(pState->m_highFreqCorner != m_pHiFreqCorner->get())) {
pState->m_loFreqCorner = m_pLoFreqCorner->get();
pState->m_highFreqCorner = m_pHiFreqCorner->get();
- pState->m_oldSampleRate = bufferParameters.sampleRate();
- pState->setFilters(bufferParameters.sampleRate(),
- pState->m_loFreqCorner, pState->m_highFreqCorner);
+ pState->m_oldSampleRate = engineParameters.sampleRate();
+ pState->setFilters(engineParameters.sampleRate(),
+ pState->m_loFreqCorner,
+ pState->m_highFreqCorner);
}
// Ramp to dry, when disabling, this will ramp from dry when enabling as well
@@ -232,9 +235,7 @@ void BiquadFullKillEQEffect::processChannel(
inBuffer.append(pState->m_tempBuf.data());
outBuffer.append(pOutput);
- }
- else
- {
+ } else {
inBuffer.append(pInput);
outBuffer.append(pOutput);
@@ -261,41 +262,39 @@ void BiquadFullKillEQEffect::processChannel(
double lowCenter = getCenterFrequency(
kMinimumFrequency, pState->m_loFreqCorner);
pState->m_lowBoost->setFrequencyCorners(
- bufferParameters.sampleRate(), lowCenter, kQBoost, bqGainLow);
+ engineParameters.sampleRate(), lowCenter, kQBoost, bqGainLow);
pState->m_oldLowBoost = bqGainLow;
}
if (bqGainLow > 0.0) {
pState->m_lowBoost->process(
- inBuffer[bufIndex], outBuffer[bufIndex], bufferParameters.samplesPerBuffer());
+ inBuffer[bufIndex], outBuffer[bufIndex], engineParameters.samplesPerBuffer());
} else {
pState->m_lowBoost->processAndPauseFilter(
- inBuffer[bufIndex], outBuffer[bufIndex], bufferParameters.samplesPerBuffer());
+ inBuffer[bufIndex], outBuffer[bufIndex], engineParameters.samplesPerBuffer());
}
++bufIndex;
} else {
pState->m_lowBoost->pauseFilter();
}
-
if (bqGainLow < 0.0 || pState->m_oldLowKill < 0.0) {
if (bqGainLow != pState->m_oldLowKill) {
double lowCenter = getCenterFrequency(
kMinimumFrequency, pState->m_loFreqCorner);
pState->m_lowKill->setFrequencyCorners(
- bufferParameters.sampleRate(), lowCenter * 2, kQLowKillShelve, bqGainLow);
+ engineParameters.sampleRate(), lowCenter * 2, kQLowKillShelve, bqGainLow);
pState->m_oldLowKill = bqGainLow;
}
if (bqGainLow < 0.0) {
pState->m_lowKill->process(
- inBuffer[bufIndex], outBuffer[bufIndex], bufferParameters.samplesPerBuffer());
+ inBuffer[bufIndex], outBuffer[bufIndex], engineParameters.samplesPerBuffer());
} else {
pState->m_lowKill->processAndPauseFilter(
- inBuffer[bufIndex], outBuffer[bufIndex], bufferParameters.samplesPerBuffer());
+ inBuffer[bufIndex], outBuffer[bufIndex], engineParameters.samplesPerBuffer());
}
++bufIndex;
} else {
pState->m_lowKill->pauseFilter();
-
}
if (bqGainMid > 0.0 || pState->m_oldMidBoost > 0.0) {
@@ -303,15 +302,15 @@ void BiquadFullKillEQEffect::processChannel(
double midCenter = getCenterFrequency(
pState->m_loFreqCorner, pState->m_highFreqCorner);
pState->m_midBoost->setFrequencyCorners(
- bufferParameters.sampleRate(), midCenter, kQBoost, bqGainMid);
+ engineParameters.sampleRate(), midCenter, kQBoost, bqGainMid);
pState->m_oldMidBoost = bqGainMid;
}
if (bqGainMid > 0.0) {
pState->m_midBoost->process(
- inBuffer[bufIndex], outBuffer[bufIndex], bufferParameters.samplesPerBuffer());
+ inBuffer[bufIndex], outBuffer[bufIndex], engineParameters.samplesPerBuffer());
} else {
pState->m_midBoost->processAndPauseFilter(
- inBuffer[bufIndex], outBuffer[bufIndex], bufferParameters.samplesPerBuffer());
+ inBuffer[bufIndex], outBuffer[bufIndex], engineParameters.samplesPerBuffer());
}
++bufIndex;
} else {
@@ -323,15 +322,15 @@ void BiquadFullKillEQEffect::processChannel(
double midCenter = getCenterFrequency(
pState->m_loFreqCorner, pState->m_highFreqCorner);
pState->m_midKill->setFrequencyCorners(
- bufferParameters.sampleRate(), midCenter, kQKill, bqGainMid);
+ engineParameters.sampleRate(), midCenter, kQKill, bqGainMid);
pState->m_oldMidKill = bqGainMid;
}
if (bqGainMid < 0.0) {
pState->m_midKill->process(
- inBuffer[bufIndex], outBuffer[bufIndex], bufferParameters.samplesPerBuffer());
+ inBuffer[bufIndex], outBuffer[bufIndex], engineParameters.samplesPerBuffer());
} else {
pState->m_midKill->processAndPauseFilter(
- inBuffer[bufIndex], outBuffer[bufIndex], bufferParameters.samplesPerBuffer());
+ inBuffer[bufIndex], outBuffer[bufIndex], engineParameters.samplesPerBuffer());
}
++bufIndex;
} else {
@@ -343,15 +342,15 @@ void BiquadFullKillEQEffect::processChannel(
double highCenter = getCenterFrequency(
pState->m_highFreqCorner, kMaximumFrequency);
pState->m_highBoost->setFrequencyCorners(
- bufferParameters.sampleRate(), highCenter, kQBoost, bqGainHigh);
+ engineParameters.sampleRate(), highCenter, kQBoost, bqGainHigh);
pState->m_oldHighBoost = bqGainHigh;
}
if (bqGainHigh > 0.0) {
pState->m_highBoost->process(
- inBuffer[bufIndex], outBuffer[bufIndex], bufferParameters.samplesPerBuffer());
+ inBuffer[bufIndex], outBuffer[bufIndex], engineParameters.samplesPerBuffer());
} else {
pState->m_highBoost->processAndPauseFilter(
- inBuffer[bufIndex], outBuffer[bufIndex], bufferParameters.samplesPerBuffer());
+ inBuffer[bufIndex], outBuffer[bufIndex], engineParameters.samplesPerBuffer());
}
++bufIndex;
} else {
@@ -363,15 +362,15 @@ void BiquadFullKillEQEffect::processChannel(
double highCenter = getCenterFrequency(
pState->m_highFreqCorner, kMaximumFrequency);
pState->m_highKill->setFrequencyCorners(
- bufferParameters.sampleRate(), highCenter / 2, kQHighKillShelve, bqGainHigh);
+ engineParameters.sampleRate(), highCenter / 2, kQHighKillShelve, bqGainHigh);
pState->m_oldHighKill = bqGainHigh;
}
if (bqGainHigh < 0.0) {
pState->m_highKill->process(
- inBuffer[bufIndex], outBuffer[bufIndex], bufferParameters.samplesPerBuffer());
+ inBuffer[bufIndex], outBuffer[bufIndex], engineParameters.samplesPerBuffer());
} else {
pState->m_highKill->processAndPauseFilter(
- inBuffer[bufIndex], outBuffer[bufIndex], bufferParameters.samplesPerBuffer());
+ inBuffer[bufIndex], outBuffer[bufIndex], engineParameters.samplesPerBuffer());
}
++bufIndex;
} else {
@@ -379,7 +378,7 @@ void BiquadFullKillEQEffect::processChannel(
}
if (activeFilters == 0) {
- SampleUtil::copy(pOutput, pInput, bufferParameters.samplesPerBuffer());
+ SampleUtil::copy(pOutput, pInput, engineParameters.samplesPerBuffer());
}
if (enableState == EffectEnableState::Disabling) {
@@ -392,7 +391,8 @@ void BiquadFullKillEQEffect::processChannel(
}
if (enableState == EffectEnableState::Disabling) {
- pState->m_lvMixIso->processChannelAndPause(pOutput, pOutput, bufferParameters.samplesPerBuffer());
+ pState->m_lvMixIso->processChannelAndPause(
+ pOutput, pOutput, engineParameters.samplesPerBuffer());
} else {
double fLow = knobValueToBesselRatio(
m_pPotLow->value(), m_pKillLow->toBool());
@@ -400,10 +400,14 @@ void BiquadFullKillEQEffect::processChannel(
m_pPotMid->value(), m_pKillMid->toBool());
double fHigh = knobValueToBesselRatio(
m_pPotHigh->value(), m_pKillHigh->toBool());
- pState->m_lvMixIso->processChannel(
- pOutput, pOutput,
- bufferParameters.samplesPerBuffer(), bufferParameters.sampleRate(),
- fLow, fMid, fHigh,
- m_pLoFreqCorner->get(), m_pHiFreqCorner->get());
+ pState->m_lvMixIso->processChannel(pOutput,
+ pOutput,
+ engineParameters.samplesPerBuffer(),
+ engineParameters.sampleRate(),
+ fLow,
+ fMid,
+ fHigh,
+ m_pLoFreqCorner->get(),
+ m_pHiFreqCorner->get());
}
}
diff --git a/src/effects/builtin/biquadfullkilleqeffect.h b/src/effects/backends/builtin/biquadfullkilleqeffect.h
similarity index 71%
rename from src/effects/builtin/biquadfullkilleqeffect.h
rename to src/effects/backends/builtin/biquadfullkilleqeffect.h
index 3a2a4063a2a..065572d8510 100644
--- a/src/effects/builtin/biquadfullkilleqeffect.h
+++ b/src/effects/backends/builtin/biquadfullkilleqeffect.h
@@ -1,24 +1,23 @@
#pragma once
#include "control/controlproxy.h"
-#include "effects/effect.h"
-#include "effects/effectprocessor.h"
+#include "effects/backends/builtin/lvmixeqbase.h"
+#include "effects/backends/effectprocessor.h"
#include "engine/effects/engineeffect.h"
#include "engine/effects/engineeffectparameter.h"
-#include "engine/filters/enginefilterbiquad1.h"
#include "engine/filters/enginefilterbessel4.h"
-#include "effects/builtin/lvmixeqbase.h"
+#include "engine/filters/enginefilterbiquad1.h"
#include "engine/filters/enginefilterdelay.h"
#include "util/class.h"
#include "util/defs.h"
-#include "util/sample.h"
-#include "util/types.h"
#include "util/memory.h"
+#include "util/sample.h"
#include "util/samplebuffer.h"
+#include "util/types.h"
class BiquadFullKillEQEffectGroupState : public EffectState {
public:
- BiquadFullKillEQEffectGroupState(const mixxx::EngineParameters& bufferParameters);
+ BiquadFullKillEQEffectGroupState(const mixxx::EngineParameters& engineParameters);
void setFilters(
mixxx::audio::SampleRate sampleRate,
@@ -59,23 +58,26 @@ class BiquadFullKillEQEffectGroupState : public EffectState {
class BiquadFullKillEQEffect : public EffectProcessorImpl {
public:
- BiquadFullKillEQEffect(EngineEffect* pEffect);
+ BiquadFullKillEQEffect();
static QString getId();
static EffectManifestPointer getManifest();
- void setFilters(
- mixxx::audio::SampleRate sampleRate,
+ void loadEngineEffectParameters(
+ const QMap& parameters) override;
+
+ void processChannel(
+ BiquadFullKillEQEffectGroupState* pState,
+ const CSAMPLE* pInput,
+ CSAMPLE* pOutput,
+ const mixxx::EngineParameters& engineParameters,
+ const EffectEnableState enableState,
+ const GroupFeatureState& groupFeatureState) override;
+
+ void setFilters(mixxx::audio::SampleRate sampleRate,
double lowFreqCorner,
double highFreqCorner);
- void processChannel(const ChannelHandle& handle,
- BiquadFullKillEQEffectGroupState* pState,
- const CSAMPLE* pInput, CSAMPLE *pOutput,
- const mixxx::EngineParameters& bufferParameters,
- const EffectEnableState enableState,
- const GroupFeatureState& groupFeatureState) override;
-
private:
BiquadFullKillEQEffect(const BiquadFullKillEQEffect&) = delete;
void operator=(const BiquadFullKillEQEffect&) = delete;
@@ -84,13 +86,13 @@ class BiquadFullKillEQEffect : public EffectProcessorImpl m_pLoFreqCorner;
std::unique_ptr m_pHiFreqCorner;
diff --git a/src/effects/builtin/bitcrushereffect.cpp b/src/effects/backends/builtin/bitcrushereffect.cpp
similarity index 60%
rename from src/effects/builtin/bitcrushereffect.cpp
rename to src/effects/backends/builtin/bitcrushereffect.cpp
index 0f41fd054f3..b05c3f73f58 100644
--- a/src/effects/builtin/bitcrushereffect.cpp
+++ b/src/effects/backends/builtin/bitcrushereffect.cpp
@@ -1,4 +1,4 @@
-#include "effects/builtin/bitcrushereffect.h"
+#include "effects/backends/builtin/bitcrushereffect.h"
#include "util/sample.h"
@@ -16,63 +16,57 @@ EffectManifestPointer BitCrusherEffect::getManifest() {
pManifest->setAuthor("The Mixxx Team");
pManifest->setVersion("1.0");
pManifest->setDescription(QObject::tr(
- "Adds noise by the reducing the bit depth and sample rate"));
+ "Adds noise by the reducing the bit depth and sample rate"));
pManifest->setEffectRampsFromDry(true);
- pManifest->setMetaknobDefault(0.0);
EffectManifestParameterPointer depth = pManifest->addParameter();
depth->setId("bit_depth");
depth->setName(QObject::tr("Bit Depth"));
depth->setShortName(QObject::tr("Bit Depth"));
depth->setDescription(QObject::tr(
- "The bit depth of the samples"));
- depth->setControlHint(EffectManifestParameter::ControlHint::KNOB_LOGARITHMIC);
- depth->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- depth->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- depth->setDefaultLinkType(EffectManifestParameter::LinkType::LINKED);
- depth->setDefaultLinkInversion(EffectManifestParameter::LinkInversion::INVERTED);
+ "The bit depth of the samples"));
+ depth->setValueScaler(EffectManifestParameter::ValueScaler::Logarithmic);
+ depth->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ depth->setDefaultLinkType(EffectManifestParameter::LinkType::Linked);
+ depth->setDefaultLinkInversion(EffectManifestParameter::LinkInversion::Inverted);
depth->setNeutralPointOnScale(1.0);
- depth->setDefault(16);
// for values -1 0 +1
// we do not allow a 1 bit version because this causes a distortion because of the missing sign bit
- depth->setMinimum(2);
- depth->setMaximum(16);
+ depth->setRange(2, 16, 16);
EffectManifestParameterPointer frequency = pManifest->addParameter();
frequency->setId("downsample");
frequency->setName(QObject::tr("Downsampling"));
frequency->setShortName(QObject::tr("Down"));
frequency->setDescription(QObject::tr(
- "The sample rate to which the signal is downsampled"));
- frequency->setControlHint(EffectManifestParameter::ControlHint::KNOB_LOGARITHMIC);
- frequency->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- frequency->setUnitsHint(EffectManifestParameter::UnitsHint::SAMPLERATE);
- frequency->setDefaultLinkType(EffectManifestParameter::LinkType::LINKED);
- frequency->setDefaultLinkInversion(EffectManifestParameter::LinkInversion::INVERTED);
+ "The sample rate to which the signal is downsampled"));
+ frequency->setValueScaler(EffectManifestParameter::ValueScaler::Logarithmic);
+ frequency->setUnitsHint(EffectManifestParameter::UnitsHint::SampleRate);
+ frequency->setDefaultLinkType(EffectManifestParameter::LinkType::Linked);
+ frequency->setDefaultLinkInversion(EffectManifestParameter::LinkInversion::Inverted);
frequency->setNeutralPointOnScale(1.0);
- frequency->setDefault(1.0);
- frequency->setMinimum(0.02);
- frequency->setMaximum(1.0);
+ frequency->setRange(0.02, 1.0, 1.0);
return pManifest;
}
-BitCrusherEffect::BitCrusherEffect(EngineEffect* pEffect)
- : m_pBitDepthParameter(pEffect->getParameterById("bit_depth")),
- m_pDownsampleParameter(pEffect->getParameterById("downsample")) {
+void BitCrusherEffect::loadEngineEffectParameters(
+ const QMap& parameters) {
+ m_pBitDepthParameter = parameters.value("bit_depth");
+ m_pDownsampleParameter = parameters.value("downsample");
}
BitCrusherEffect::~BitCrusherEffect() {
//qDebug() << debugString() << "destroyed";
}
-void BitCrusherEffect::processChannel(const ChannelHandle& handle,
- BitCrusherGroupState* pState,
- const CSAMPLE* pInput, CSAMPLE* pOutput,
- const mixxx::EngineParameters& bufferParameters,
- const EffectEnableState enableState,
- const GroupFeatureState& groupFeatures) {
- Q_UNUSED(handle);
+void BitCrusherEffect::processChannel(
+ BitCrusherGroupState* pState,
+ const CSAMPLE* pInput,
+ CSAMPLE* pOutput,
+ const mixxx::EngineParameters& engineParameters,
+ const EffectEnableState enableState,
+ const GroupFeatureState& groupFeatures) {
Q_UNUSED(groupFeatures);
Q_UNUSED(enableState); // no need to ramp, it is just a bitcrusher ;-)
@@ -89,25 +83,32 @@ void BitCrusherEffect::processChannel(const ChannelHandle& handle,
const CSAMPLE gainCorrection = (17 - bit_depth) / 8;
for (SINT i = 0;
- i < bufferParameters.samplesPerBuffer();
- i += bufferParameters.channelCount()) {
+ i < engineParameters.samplesPerBuffer();
+ i += engineParameters.channelCount()) {
pState->accumulator += downsample;
if (pState->accumulator >= 1.0) {
pState->accumulator -= 1.0f;
if (bit_depth < 16) {
-
- pState->hold_l = floorf(SampleUtil::clampSample(pInput[i] * gainCorrection) * scale + 0.5f) / scale / gainCorrection;
- pState->hold_r = floorf(SampleUtil::clampSample(pInput[i+1] * gainCorrection) * scale + 0.5f) / scale / gainCorrection;
+ pState->hold_l = floorf(SampleUtil::clampSample(
+ pInput[i] * gainCorrection) *
+ scale +
+ 0.5f) /
+ scale / gainCorrection;
+ pState->hold_r = floorf(SampleUtil::clampSample(pInput[i + 1] *
+ gainCorrection) *
+ scale +
+ 0.5f) /
+ scale / gainCorrection;
} else {
// Mixxx float has 24 bit depth, Audio CDs are 16 bit
// here we do not change the depth
pState->hold_l = pInput[i];
- pState->hold_r = pInput[i+1];
+ pState->hold_r = pInput[i + 1];
}
}
pOutput[i] = pState->hold_l;
- pOutput[i+1] = pState->hold_r;
+ pOutput[i + 1] = pState->hold_r;
}
}
diff --git a/src/effects/builtin/bitcrushereffect.h b/src/effects/backends/builtin/bitcrushereffect.h
similarity index 53%
rename from src/effects/builtin/bitcrushereffect.h
rename to src/effects/backends/builtin/bitcrushereffect.h
index b7888032a65..3c6d991c5be 100644
--- a/src/effects/builtin/bitcrushereffect.h
+++ b/src/effects/backends/builtin/bitcrushereffect.h
@@ -2,8 +2,7 @@
#include
-#include "effects/effect.h"
-#include "effects/effectprocessor.h"
+#include "effects/backends/effectprocessor.h"
#include "engine/effects/engineeffect.h"
#include "engine/effects/engineeffectparameter.h"
#include "util/class.h"
@@ -11,8 +10,8 @@
struct BitCrusherGroupState : public EffectState {
// Default accumulator to 1 so we immediately pick an input value.
- BitCrusherGroupState(const mixxx::EngineParameters& bufferParameters)
- : EffectState(bufferParameters),
+ BitCrusherGroupState(const mixxx::EngineParameters& engineParameters)
+ : EffectState(engineParameters),
hold_l(0),
hold_r(0),
accumulator(1) {
@@ -24,27 +23,30 @@ struct BitCrusherGroupState : public EffectState {
class BitCrusherEffect : public EffectProcessorImpl {
public:
- BitCrusherEffect(EngineEffect* pEffect);
+ BitCrusherEffect() = default;
virtual ~BitCrusherEffect();
static QString getId();
static EffectManifestPointer getManifest();
- // See effectprocessor.h
- void processChannel(const ChannelHandle& handle,
- BitCrusherGroupState* pState,
- const CSAMPLE* pInput, CSAMPLE *pOutput,
- const mixxx::EngineParameters& bufferParameters,
- const EffectEnableState enableState,
- const GroupFeatureState& groupFeatureState);
+ void loadEngineEffectParameters(
+ const QMap& parameters) override;
+
+ void processChannel(
+ BitCrusherGroupState* pState,
+ const CSAMPLE* pInput,
+ CSAMPLE* pOutput,
+ const mixxx::EngineParameters& engineParameters,
+ const EffectEnableState enableState,
+ const GroupFeatureState& groupFeatureState) override;
private:
QString debugString() const {
return getId();
}
- EngineEffectParameter* m_pBitDepthParameter;
- EngineEffectParameter* m_pDownsampleParameter;
+ EngineEffectParameterPointer m_pBitDepthParameter;
+ EngineEffectParameterPointer m_pDownsampleParameter;
DISALLOW_COPY_AND_ASSIGN(BitCrusherEffect);
};
diff --git a/src/effects/backends/builtin/builtinbackend.cpp b/src/effects/backends/builtin/builtinbackend.cpp
new file mode 100644
index 00000000000..ac99e897505
--- /dev/null
+++ b/src/effects/backends/builtin/builtinbackend.cpp
@@ -0,0 +1,107 @@
+
+#include "effects/backends/builtin/builtinbackend.h"
+
+#include
+
+#include "effects/backends/builtin/balanceeffect.h"
+#include "effects/backends/builtin/bessel4lvmixeqeffect.h"
+#include "effects/backends/builtin/bessel8lvmixeqeffect.h"
+#include "effects/backends/builtin/biquadfullkilleqeffect.h"
+#include "effects/backends/builtin/bitcrushereffect.h"
+#include "effects/backends/builtin/filtereffect.h"
+#include "effects/backends/builtin/flangereffect.h"
+#include "effects/backends/builtin/graphiceqeffect.h"
+#include "effects/backends/builtin/linkwitzriley8eqeffect.h"
+#include "effects/backends/builtin/moogladder4filtereffect.h"
+#include "effects/backends/builtin/parametriceqeffect.h"
+#include "effects/backends/builtin/threebandbiquadeqeffect.h"
+#ifndef __MACAPPSTORE__
+#include "effects/backends/builtin/reverbeffect.h"
+#endif
+#include "effects/backends/builtin/autopaneffect.h"
+#include "effects/backends/builtin/echoeffect.h"
+#include "effects/backends/builtin/loudnesscontoureffect.h"
+#include "effects/backends/builtin/metronomeeffect.h"
+#include "effects/backends/builtin/phasereffect.h"
+#include "effects/backends/builtin/tremoloeffect.h"
+#include "effects/backends/builtin/whitenoiseeffect.h"
+
+BuiltInBackend::BuiltInBackend() {
+ // Keep this list in a reasonable order
+ // Mixing EQs
+ registerEffect();
+ registerEffect();
+ registerEffect();
+ registerEffect();
+ registerEffect();
+ // Compensations EQs
+ registerEffect();
+ registerEffect();
+ registerEffect();
+ // Fading Effects
+ registerEffect();
+ registerEffect();
+ registerEffect();
+ registerEffect();
+ registerEffect();
+ // Fancy effects
+ registerEffect();
+ registerEffect();
+ registerEffect();
+#ifndef __MACAPPSTORE__
+ registerEffect();
+#endif
+ registerEffect();
+ registerEffect();
+ registerEffect();
+}
+
+std::unique_ptr BuiltInBackend::createProcessor(
+ const EffectManifestPointer pManifest) const {
+ VERIFY_OR_DEBUG_ASSERT(m_registeredEffects.contains(pManifest->id())) {
+ return nullptr;
+ }
+ return m_registeredEffects[pManifest->id()].instantiator();
+}
+
+BuiltInBackend::~BuiltInBackend() {
+ m_registeredEffects.clear();
+ m_effectIds.clear();
+}
+
+void BuiltInBackend::registerEffectInner(
+ const QString& id,
+ EffectManifestPointer pManifest,
+ EffectProcessorInstantiator instantiator) {
+ VERIFY_OR_DEBUG_ASSERT(!m_registeredEffects.contains(id)) {
+ return;
+ }
+
+ pManifest->setBackendType(getType());
+
+ m_registeredEffects[id] = RegisteredEffect{pManifest, instantiator};
+ m_effectIds.append(id);
+}
+
+const QList BuiltInBackend::getEffectIds() const {
+ return m_effectIds;
+}
+
+EffectManifestPointer BuiltInBackend::getManifest(const QString& effectId) const {
+ VERIFY_OR_DEBUG_ASSERT(m_registeredEffects.contains(effectId)) {
+ return EffectManifestPointer();
+ }
+ return m_registeredEffects.value(effectId).pManifest;
+}
+
+const QList BuiltInBackend::getManifests() const {
+ QList list;
+ for (const auto& registeredEffect : m_registeredEffects) {
+ list.append(registeredEffect.pManifest);
+ }
+ return list;
+}
+
+bool BuiltInBackend::canInstantiateEffect(const QString& effectId) const {
+ return m_registeredEffects.contains(effectId);
+}
diff --git a/src/effects/backends/builtin/builtinbackend.h b/src/effects/backends/builtin/builtinbackend.h
new file mode 100644
index 00000000000..c79405a4667
--- /dev/null
+++ b/src/effects/backends/builtin/builtinbackend.h
@@ -0,0 +1,52 @@
+#pragma once
+
+#include "effects/backends/effectsbackend.h"
+#include "effects/defs.h"
+
+/// Refer to EffectsBackend for documentation
+class BuiltInBackend : public EffectsBackend {
+ public:
+ BuiltInBackend();
+ virtual ~BuiltInBackend();
+
+ EffectBackendType getType() const {
+ return EffectBackendType::BuiltIn;
+ };
+
+ const QList getEffectIds() const;
+ EffectManifestPointer getManifest(const QString& effectId) const;
+ const QList getManifests() const;
+ std::unique_ptr createProcessor(
+ const EffectManifestPointer pManifest) const;
+ bool canInstantiateEffect(const QString& effectId) const;
+
+ private:
+ QString debugString() const {
+ return "BuiltInBackend";
+ }
+
+ typedef std::unique_ptr (*EffectProcessorInstantiator)();
+
+ struct RegisteredEffect {
+ EffectManifestPointer pManifest;
+ EffectProcessorInstantiator instantiator;
+ };
+
+ void registerEffectInner(const QString& id,
+ EffectManifestPointer pManifest,
+ EffectProcessorInstantiator instantiator);
+
+ template
+ void registerEffect() {
+ registerEffectInner(
+ EffectProcessorImpl::getId(),
+ EffectProcessorImpl::getManifest(),
+ []() {
+ return static_cast>(
+ std::make_unique());
+ });
+ };
+
+ QMap m_registeredEffects;
+ QList m_effectIds;
+};
diff --git a/src/effects/builtin/echoeffect.cpp b/src/effects/backends/builtin/echoeffect.cpp
similarity index 63%
rename from src/effects/builtin/echoeffect.cpp
rename to src/effects/backends/builtin/echoeffect.cpp
index f7ffcc4a0d0..e76ad7def3f 100644
--- a/src/effects/builtin/echoeffect.cpp
+++ b/src/effects/backends/builtin/echoeffect.cpp
@@ -1,10 +1,10 @@
-#include "effects/builtin/echoeffect.h"
+#include "effects/backends/builtin/echoeffect.h"
#include
-#include "util/sample.h"
#include "util/math.h"
#include "util/rampingvalue.h"
+#include "util/sample.h"
constexpr int EchoGroupState::kMaxDelaySeconds;
@@ -38,110 +38,93 @@ EffectManifestPointer EchoEffect::getManifest() {
pManifest->setAuthor("The Mixxx Team");
pManifest->setVersion("1.0");
pManifest->setDescription(QObject::tr(
- "Stores the input signal in a temporary buffer and outputs it after a short time"));
- pManifest->setMetaknobDefault(db2ratio(-3.0));
+ "Stores the input signal in a temporary buffer and outputs it after a short time"));
EffectManifestParameterPointer delay = pManifest->addParameter();
delay->setId("delay_time");
delay->setName(QObject::tr("Time"));
delay->setShortName(QObject::tr("Time"));
delay->setDescription(QObject::tr(
- "Delay time\n"
- "1/8 - 2 beats if tempo is detected\n"
- "1/8 - 2 seconds if no tempo is detected"));
- delay->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR);
- delay->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- delay->setUnitsHint(EffectManifestParameter::UnitsHint::BEATS);
- delay->setMinimum(0.0);
- delay->setDefault(0.5);
- delay->setMaximum(2.0);
+ "Delay time\n"
+ "1/8 - 2 beats if tempo is detected\n"
+ "1/8 - 2 seconds if no tempo is detected"));
+ delay->setValueScaler(EffectManifestParameter::ValueScaler::Linear);
+ delay->setUnitsHint(EffectManifestParameter::UnitsHint::Beats);
+ delay->setRange(0.0, 0.5, 2.0);
EffectManifestParameterPointer feedback = pManifest->addParameter();
feedback->setId("feedback_amount");
feedback->setName(QObject::tr("Feedback"));
feedback->setShortName(QObject::tr("Feedback"));
feedback->setDescription(QObject::tr(
- "Amount the echo fades each time it loops"));
- feedback->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR);
- feedback->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- feedback->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- feedback->setMinimum(0.00);
- feedback->setDefault(db2ratio(-3.0));
- feedback->setMaximum(1.00);
+ "Amount the echo fades each time it loops"));
+ feedback->setValueScaler(EffectManifestParameter::ValueScaler::Linear);
+ feedback->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ feedback->setRange(0.00, db2ratio(-3.0), 1.00);
EffectManifestParameterPointer pingpong = pManifest->addParameter();
pingpong->setId("pingpong_amount");
pingpong->setName(QObject::tr("Ping Pong"));
pingpong->setShortName(QObject::tr("Ping Pong"));
- pingpong->setDescription(QObject::tr(
- "How much the echoed sound bounces between the left and right sides of the stereo field"));
- pingpong->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR);
- pingpong->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- pingpong->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- pingpong->setMinimum(0.0);
- pingpong->setDefault(0.0);
- pingpong->setMaximum(1.0);
+ pingpong->setDescription(
+ QObject::tr("How much the echoed sound bounces between the left "
+ "and right sides of the stereo field"));
+ pingpong->setValueScaler(EffectManifestParameter::ValueScaler::Linear);
+ pingpong->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ pingpong->setRange(0.0, 0.0, 1.0);
EffectManifestParameterPointer send = pManifest->addParameter();
send->setId("send_amount");
send->setName(QObject::tr("Send"));
send->setShortName(QObject::tr("Send"));
send->setDescription(QObject::tr(
- "How much of the signal to send into the delay buffer"));
- send->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR);
- send->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- send->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- send->setDefaultLinkType(EffectManifestParameter::LinkType::LINKED);
- send->setMinimum(0.0);
- send->setDefault(db2ratio(-3.0));
- send->setMaximum(1.0);
+ "How much of the signal to send into the delay buffer"));
+ send->setValueScaler(EffectManifestParameter::ValueScaler::Linear);
+ send->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ send->setDefaultLinkType(EffectManifestParameter::LinkType::Linked);
+ send->setRange(0.0, db2ratio(-3.0), 1.0);
EffectManifestParameterPointer quantize = pManifest->addParameter();
quantize->setId("quantize");
quantize->setName(QObject::tr("Quantize"));
quantize->setShortName(QObject::tr("Quantize"));
quantize->setDescription(QObject::tr(
- "Round the Time parameter to the nearest 1/4 beat."));
- quantize->setControlHint(EffectManifestParameter::ControlHint::TOGGLE_STEPPING);
- quantize->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- quantize->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- quantize->setDefault(1);
- quantize->setMinimum(0);
- quantize->setMaximum(1);
+ "Round the Time parameter to the nearest 1/4 beat."));
+ quantize->setValueScaler(EffectManifestParameter::ValueScaler::Toggle);
+ quantize->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ quantize->setRange(0, 1, 1);
EffectManifestParameterPointer triplet = pManifest->addParameter();
triplet->setId("triplet");
triplet->setName(QObject::tr("Triplets"));
triplet->setShortName(QObject::tr("Triplets"));
- triplet->setDescription(QObject::tr(
- "When the Quantize parameter is enabled, divide rounded 1/4 beats of Time parameter by 3."));
- triplet->setControlHint(EffectManifestParameter::ControlHint::TOGGLE_STEPPING);
- triplet->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- triplet->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- triplet->setDefault(0);
- triplet->setMinimum(0);
- triplet->setMaximum(1);
+ triplet->setDescription(
+ QObject::tr("When the Quantize parameter is enabled, divide "
+ "rounded 1/4 beats of Time parameter by 3."));
+ triplet->setValueScaler(EffectManifestParameter::ValueScaler::Toggle);
+ triplet->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ triplet->setRange(0, 0, 1);
return pManifest;
}
-EchoEffect::EchoEffect(EngineEffect* pEffect)
- : m_pDelayParameter(pEffect->getParameterById("delay_time")),
- m_pSendParameter(pEffect->getParameterById("send_amount")),
- m_pFeedbackParameter(pEffect->getParameterById("feedback_amount")),
- m_pPingPongParameter(pEffect->getParameterById("pingpong_amount")),
- m_pQuantizeParameter(pEffect->getParameterById("quantize")),
- m_pTripletParameter(pEffect->getParameterById("triplet")) {
- }
-
-void EchoEffect::processChannel(const ChannelHandle& handle, EchoGroupState* pGroupState,
- const CSAMPLE* pInput,
- CSAMPLE* pOutput,
- const mixxx::EngineParameters& bufferParameters,
- const EffectEnableState enableState,
- const GroupFeatureState& groupFeatures) {
- Q_UNUSED(handle);
+void EchoEffect::loadEngineEffectParameters(
+ const QMap& parameters) {
+ m_pDelayParameter = parameters.value("delay_time");
+ m_pSendParameter = parameters.value("send_amount");
+ m_pFeedbackParameter = parameters.value("feedback_amount");
+ m_pPingPongParameter = parameters.value("pingpong_amount");
+ m_pQuantizeParameter = parameters.value("quantize");
+ m_pTripletParameter = parameters.value("triplet");
+}
+void EchoEffect::processChannel(
+ EchoGroupState* pGroupState,
+ const CSAMPLE* pInput,
+ CSAMPLE* pOutput,
+ const mixxx::EngineParameters& engineParameters,
+ const EffectEnableState enableState,
+ const GroupFeatureState& groupFeatures) {
// The minimum of the parameter is zero so the exact center of the knob is 1 beat.
double period = m_pDelayParameter->value();
const auto send_current = static_cast(m_pSendParameter->value());
@@ -152,25 +135,25 @@ void EchoEffect::processChannel(const ChannelHandle& handle, EchoGroupState* pGr
if (groupFeatures.has_beat_length_sec) {
// period is a number of beats
if (m_pQuantizeParameter->toBool()) {
- period = std::max(roundToFraction(period, 4), 1/8.0);
+ period = std::max(roundToFraction(period, 4), 1 / 8.0);
if (m_pTripletParameter->toBool()) {
period /= 3.0;
}
- } else if (period < 1/8.0) {
- period = 1/8.0;
+ } else if (period < 1 / 8.0) {
+ period = 1 / 8.0;
}
delay_frames = static_cast(period * groupFeatures.beat_length_sec *
- bufferParameters.sampleRate());
+ engineParameters.sampleRate());
} else {
// period is a number of seconds
- period = std::max(period, 1/8.0);
- delay_frames = static_cast(period * bufferParameters.sampleRate());
+ period = std::max(period, 1 / 8.0);
+ delay_frames = static_cast(period * engineParameters.sampleRate());
}
VERIFY_OR_DEBUG_ASSERT(delay_frames > 0) {
delay_frames = 1;
}
- int delay_samples = delay_frames * bufferParameters.channelCount();
+ int delay_samples = delay_frames * engineParameters.channelCount();
VERIFY_OR_DEBUG_ASSERT(delay_samples <= pGroupState->delay_buf.size()) {
delay_samples = pGroupState->delay_buf.size();
}
@@ -184,17 +167,17 @@ void EchoEffect::processChannel(const ChannelHandle& handle, EchoGroupState* pGr
RampingValue send(send_current,
pGroupState->prev_send,
- bufferParameters.framesPerBuffer());
+ engineParameters.framesPerBuffer());
// Feedback the delay buffer and then add the new input.
RampingValue feedback(feedback_current,
pGroupState->prev_feedback,
- bufferParameters.framesPerBuffer());
+ engineParameters.framesPerBuffer());
//TODO: rewrite to remove assumption of stereo buffer
for (SINT i = 0;
- i < bufferParameters.samplesPerBuffer();
- i += bufferParameters.channelCount()) {
+ i < engineParameters.samplesPerBuffer();
+ i += engineParameters.channelCount()) {
CSAMPLE_GAIN send_ramped = send.getNext();
CSAMPLE_GAIN feedback_ramped = feedback.getNext();
@@ -202,17 +185,17 @@ void EchoEffect::processChannel(const ChannelHandle& handle, EchoGroupState* pGr
CSAMPLE bufferedSampleRight = pGroupState->delay_buf[read_position + 1];
if (read_position != prev_read_position) {
const CSAMPLE_GAIN frac = static_cast(i) /
- bufferParameters.samplesPerBuffer();
+ engineParameters.samplesPerBuffer();
bufferedSampleLeft *= frac;
bufferedSampleRight *= frac;
bufferedSampleLeft += pGroupState->delay_buf[prev_read_position] * (1 - frac);
bufferedSampleRight += pGroupState->delay_buf[prev_read_position + 1] * (1 - frac);
incrementRing(&prev_read_position,
- bufferParameters.channelCount(),
+ engineParameters.channelCount(),
pGroupState->delay_buf.size());
}
incrementRing(&read_position,
- bufferParameters.channelCount(),
+ engineParameters.channelCount(),
pGroupState->delay_buf.size());
// Actual delays distort and saturate, so clamp the buffer here.
@@ -244,7 +227,7 @@ void EchoEffect::processChannel(const ChannelHandle& handle, EchoGroupState* pGr
}
incrementRing(&pGroupState->write_position,
- bufferParameters.channelCount(),
+ engineParameters.channelCount(),
pGroupState->delay_buf.size());
++(pGroupState->ping_pong);
@@ -257,7 +240,7 @@ void EchoEffect::processChannel(const ChannelHandle& handle, EchoGroupState* pGr
// this effect must handle ramping to dry when disabling itself (instead
// of being handled by EngineEffect::process).
if (enableState == EffectEnableState::Disabling) {
- SampleUtil::applyRampingGain(pOutput, 1.0, 0.0, bufferParameters.samplesPerBuffer());
+ SampleUtil::applyRampingGain(pOutput, 1.0, 0.0, engineParameters.samplesPerBuffer());
pGroupState->delay_buf.clear();
pGroupState->prev_send = 0;
} else {
diff --git a/src/effects/backends/builtin/echoeffect.h b/src/effects/backends/builtin/echoeffect.h
new file mode 100644
index 00000000000..b9697f1e920
--- /dev/null
+++ b/src/effects/backends/builtin/echoeffect.h
@@ -0,0 +1,80 @@
+#pragma once
+
+#include
+
+#include "effects/backends/effectprocessor.h"
+#include "engine/effects/engineeffect.h"
+#include "engine/effects/engineeffectparameter.h"
+#include "engine/engine.h"
+#include "util/class.h"
+#include "util/defs.h"
+#include "util/sample.h"
+#include "util/samplebuffer.h"
+
+class EchoGroupState : public EffectState {
+ public:
+ // 3 seconds max. This supports the full range of 2 beats for tempos down to
+ // 40 BPM.
+ static constexpr int kMaxDelaySeconds = 3;
+
+ EchoGroupState(const mixxx::EngineParameters& engineParameters)
+ : EffectState(engineParameters) {
+ audioParametersChanged(engineParameters);
+ clear();
+ }
+
+ void audioParametersChanged(const mixxx::EngineParameters& engineParameters) {
+ delay_buf = mixxx::SampleBuffer(kMaxDelaySeconds *
+ engineParameters.sampleRate() *
+ engineParameters.channelCount());
+ };
+
+ void clear() {
+ delay_buf.clear();
+ prev_send = 0.0f;
+ prev_feedback = 0.0f;
+ prev_delay_samples = 0;
+ write_position = 0;
+ ping_pong = 0;
+ };
+
+ mixxx::SampleBuffer delay_buf;
+ CSAMPLE_GAIN prev_send;
+ CSAMPLE_GAIN prev_feedback;
+ int prev_delay_samples;
+ int write_position;
+ int ping_pong;
+};
+
+class EchoEffect : public EffectProcessorImpl {
+ public:
+ EchoEffect() = default;
+
+ static QString getId();
+ static EffectManifestPointer getManifest();
+
+ void loadEngineEffectParameters(
+ const QMap& parameters) override;
+
+ void processChannel(
+ EchoGroupState* pState,
+ const CSAMPLE* pInput,
+ CSAMPLE* pOutput,
+ const mixxx::EngineParameters& engineParameters,
+ const EffectEnableState enableState,
+ const GroupFeatureState& groupFeatures) override;
+
+ private:
+ QString debugString() const {
+ return getId();
+ }
+
+ EngineEffectParameterPointer m_pDelayParameter;
+ EngineEffectParameterPointer m_pSendParameter;
+ EngineEffectParameterPointer m_pFeedbackParameter;
+ EngineEffectParameterPointer m_pPingPongParameter;
+ EngineEffectParameterPointer m_pQuantizeParameter;
+ EngineEffectParameterPointer m_pTripletParameter;
+
+ DISALLOW_COPY_AND_ASSIGN(EchoEffect);
+};
diff --git a/src/effects/builtin/equalizer_util.h b/src/effects/backends/builtin/equalizer_util.h
similarity index 52%
rename from src/effects/builtin/equalizer_util.h
rename to src/effects/backends/builtin/equalizer_util.h
index 96700ce5965..fe4d252ebf3 100644
--- a/src/effects/builtin/equalizer_util.h
+++ b/src/effects/backends/builtin/equalizer_util.h
@@ -2,17 +2,17 @@
#include
-#include "effects/effectmanifest.h"
+#include "effects/backends/effectmanifest.h"
class EqualizerUtil {
public:
// Creates common EQ parameters like low/mid/high gain and kill buttons.
static void createCommonParameters(EffectManifest* pManifest, bool linear) {
- EffectManifestParameter::ControlHint controlHint =
- EffectManifestParameter::ControlHint::KNOB_LOGARITHMIC;
+ EffectManifestParameter::ValueScaler valueScaler =
+ EffectManifestParameter::ValueScaler::Logarithmic;
double maximum = 4.0;
if (linear) {
- controlHint = EffectManifestParameter::ControlHint::KNOB_LINEAR;
+ valueScaler = EffectManifestParameter::ValueScaler::Linear;
maximum = 2.0;
}
@@ -20,74 +20,56 @@ class EqualizerUtil {
low->setId("low");
low->setName(QObject::tr("Low"));
low->setDescription(QObject::tr("Gain for Low Filter"));
- low->setControlHint(controlHint);
- low->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- low->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
+ low->setValueScaler(valueScaler);
+ low->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
low->setNeutralPointOnScale(0.5);
- low->setDefault(1.0);
- low->setMinimum(0);
- low->setMaximum(maximum);
+ low->setRange(0, 1.0, maximum);
EffectManifestParameterPointer killLow = pManifest->addParameter();
killLow->setId("killLow");
killLow->setName(QObject::tr("Kill Low"));
killLow->setDescription(QObject::tr("Kill the Low Filter"));
- killLow->setControlHint(EffectManifestParameter::ControlHint::TOGGLE_STEPPING);
- killLow->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- killLow->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- killLow->setDefault(0);
- killLow->setMinimum(0);
- killLow->setMaximum(1);
+ killLow->setValueScaler(EffectManifestParameter::ValueScaler::Toggle);
+ killLow->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ killLow->setRange(0, 0, 1);
EffectManifestParameterPointer mid = pManifest->addParameter();
mid->setId("mid");
mid->setName(QObject::tr("Mid"));
mid->setDescription(QObject::tr("Gain for Mid Filter"));
- mid->setControlHint(controlHint);
- mid->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- mid->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
+ mid->setValueScaler(valueScaler);
+ mid->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
mid->setNeutralPointOnScale(0.5);
- mid->setDefault(1.0);
- mid->setMinimum(0);
- mid->setMaximum(maximum);
+ mid->setRange(0, 1.0, maximum);
EffectManifestParameterPointer killMid = pManifest->addParameter();
killMid->setId("killMid");
killMid->setName(QObject::tr("Kill Mid"));
killMid->setDescription(QObject::tr("Kill the Mid Filter"));
- killMid->setControlHint(EffectManifestParameter::ControlHint::TOGGLE_STEPPING);
- killMid->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- killMid->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- killMid->setDefault(0);
- killMid->setMinimum(0);
- killMid->setMaximum(1);
+ killMid->setValueScaler(EffectManifestParameter::ValueScaler::Toggle);
+ killMid->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ killMid->setRange(0, 0, 1);
EffectManifestParameterPointer high = pManifest->addParameter();
high->setId("high");
high->setName(QObject::tr("High"));
high->setDescription(QObject::tr("Gain for High Filter"));
- high->setControlHint(controlHint);
- high->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- high->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
+ high->setValueScaler(valueScaler);
+ high->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
high->setNeutralPointOnScale(0.5);
- high->setDefault(1.0);
- high->setMinimum(0);
- high->setMaximum(maximum);
+ high->setRange(0, 1.0, maximum);
EffectManifestParameterPointer killHigh = pManifest->addParameter();
killHigh->setId("killHigh");
killHigh->setName(QObject::tr("Kill High"));
killHigh->setDescription(QObject::tr("Kill the High Filter"));
- killHigh->setControlHint(EffectManifestParameter::ControlHint::TOGGLE_STEPPING);
- killHigh->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- killHigh->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- killHigh->setDefault(0);
- killHigh->setMinimum(0);
- killHigh->setMaximum(1);
+ killHigh->setValueScaler(EffectManifestParameter::ValueScaler::Toggle);
+ killHigh->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ killHigh->setRange(0, 0, 1);
}
static QString adjustFrequencyShelvesTip() {
return QObject::tr(
- "To adjust frequency shelves, go to Preferences -> Equalizers.");
+ "To adjust frequency shelves, go to Preferences -> Equalizers.");
}
};
diff --git a/src/effects/builtin/filtereffect.cpp b/src/effects/backends/builtin/filtereffect.cpp
similarity index 60%
rename from src/effects/builtin/filtereffect.cpp
rename to src/effects/backends/builtin/filtereffect.cpp
index 831b48e6140..99633d3d635 100644
--- a/src/effects/builtin/filtereffect.cpp
+++ b/src/effects/backends/builtin/filtereffect.cpp
@@ -1,4 +1,5 @@
-#include "effects/builtin/filtereffect.h"
+#include "effects/backends/builtin/filtereffect.h"
+
#include "util/math.h"
namespace {
@@ -20,62 +21,54 @@ EffectManifestPointer FilterEffect::getManifest() {
pManifest->setAuthor("The Mixxx Team");
pManifest->setVersion("1.0");
pManifest->setDescription(QObject::tr(
- "Allows only high or low frequencies to play."));
+ "Allows only high or low frequencies to play."));
pManifest->setEffectRampsFromDry(true);
+ pManifest->setMetaknobDefault(0.5);
EffectManifestParameterPointer lpf = pManifest->addParameter();
lpf->setId("lpf");
lpf->setName(QObject::tr("Low Pass Filter Cutoff"));
lpf->setShortName(QObject::tr("LPF"));
lpf->setDescription(QObject::tr(
- "Corner frequency ratio of the low pass filter"));
- lpf->setControlHint(EffectManifestParameter::ControlHint::KNOB_LOGARITHMIC);
- lpf->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- lpf->setUnitsHint(EffectManifestParameter::UnitsHint::HERTZ);
- lpf->setDefaultLinkType(EffectManifestParameter::LinkType::LINKED_LEFT);
+ "Corner frequency ratio of the low pass filter"));
+ lpf->setValueScaler(EffectManifestParameter::ValueScaler::Logarithmic);
+ lpf->setUnitsHint(EffectManifestParameter::UnitsHint::Hertz);
+ lpf->setDefaultLinkType(EffectManifestParameter::LinkType::LinkedLeft);
lpf->setNeutralPointOnScale(1);
- lpf->setDefault(kMaxCorner);
- lpf->setMinimum(kMinCorner);
- lpf->setMaximum(kMaxCorner);
+ lpf->setRange(kMinCorner, kMaxCorner, kMaxCorner);
EffectManifestParameterPointer q = pManifest->addParameter();
q->setId("q");
q->setName(QObject::tr("Resonance"));
q->setShortName(QObject::tr("Q"));
q->setDescription(QObject::tr(
- "Resonance of the filters\n"
- "Default: flat top")); // What does this mean?
- q->setControlHint(EffectManifestParameter::ControlHint::KNOB_LOGARITHMIC);
- q->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- q->setUnitsHint(EffectManifestParameter::UnitsHint::SAMPLERATE);
- q->setDefault(0.707106781); // 0.707106781 = Butterworth
- q->setMinimum(0.4);
- q->setMaximum(4.0);
+ "Resonance of the filters\n"
+ "Default: flat top")); // What does this mean?
+ q->setValueScaler(EffectManifestParameter::ValueScaler::Logarithmic);
+ q->setUnitsHint(EffectManifestParameter::UnitsHint::SampleRate);
+ q->setRange(0.4, 0.707106781, 4.0); // 0.707106781 = Butterworth
EffectManifestParameterPointer hpf = pManifest->addParameter();
hpf->setId("hpf");
hpf->setName(QObject::tr("High Pass Filter Cutoff"));
hpf->setShortName(QObject::tr("HPF"));
hpf->setDescription(QObject::tr(
- "Corner frequency ratio of the high pass filter"));
- hpf->setControlHint(EffectManifestParameter::ControlHint::KNOB_LOGARITHMIC);
- hpf->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- hpf->setUnitsHint(EffectManifestParameter::UnitsHint::HERTZ);
- hpf->setDefaultLinkType(EffectManifestParameter::LinkType::LINKED_RIGHT);
+ "Corner frequency ratio of the high pass filter"));
+ hpf->setValueScaler(EffectManifestParameter::ValueScaler::Logarithmic);
+ hpf->setUnitsHint(EffectManifestParameter::UnitsHint::Hertz);
+ hpf->setDefaultLinkType(EffectManifestParameter::LinkType::LinkedRight);
hpf->setNeutralPointOnScale(0.0);
- hpf->setDefault(kMinCorner);
- hpf->setMinimum(kMinCorner);
- hpf->setMaximum(kMaxCorner);
+ hpf->setRange(kMinCorner, kMinCorner, kMaxCorner);
return pManifest;
}
-FilterGroupState::FilterGroupState(const mixxx::EngineParameters& bufferParameters)
- : EffectState(bufferParameters),
- m_loFreq(kMaxCorner / bufferParameters.sampleRate()),
+FilterGroupState::FilterGroupState(const mixxx::EngineParameters& engineParameters)
+ : EffectState(engineParameters),
+ m_loFreq(kMaxCorner / engineParameters.sampleRate()),
m_q(0.707106781),
- m_hiFreq(kMinCorner / bufferParameters.sampleRate()) {
- m_buffer = mixxx::SampleBuffer(bufferParameters.samplesPerBuffer());
+ m_hiFreq(kMinCorner / engineParameters.sampleRate()) {
+ m_buffer = mixxx::SampleBuffer(engineParameters.samplesPerBuffer());
m_pLowFilter = new EngineFilterBiquad1Low(1, m_loFreq, m_q, true);
m_pHighFilter = new EngineFilterBiquad1High(1, m_hiFreq, m_q, true);
}
@@ -85,39 +78,40 @@ FilterGroupState::~FilterGroupState() {
delete m_pHighFilter;
}
-FilterEffect::FilterEffect(EngineEffect* pEffect)
- : m_pLPF(pEffect->getParameterById("lpf")),
- m_pQ(pEffect->getParameterById("q")),
- m_pHPF(pEffect->getParameterById("hpf")) {
+void FilterEffect::loadEngineEffectParameters(
+ const QMap& parameters) {
+ m_pLPF = parameters.value("lpf");
+ m_pQ = parameters.value("q");
+ m_pHPF = parameters.value("hpf");
}
FilterEffect::~FilterEffect() {
//qDebug() << debugString() << "destroyed";
}
-void FilterEffect::processChannel(const ChannelHandle& handle,
- FilterGroupState* pState,
- const CSAMPLE* pInput, CSAMPLE* pOutput,
- const mixxx::EngineParameters& bufferParameters,
- const EffectEnableState enableState,
- const GroupFeatureState& groupFeatures) {
- Q_UNUSED(handle);
+void FilterEffect::processChannel(
+ FilterGroupState* pState,
+ const CSAMPLE* pInput,
+ CSAMPLE* pOutput,
+ const mixxx::EngineParameters& engineParameters,
+ const EffectEnableState enableState,
+ const GroupFeatureState& groupFeatures) {
Q_UNUSED(groupFeatures);
double hpf;
double lpf;
double q = m_pQ->value();
- const double minCornerNormalized = kMinCorner / bufferParameters.sampleRate();
- const double maxCornerNormalized = kMaxCorner / bufferParameters.sampleRate();
+ const double minCornerNormalized = kMinCorner / engineParameters.sampleRate();
+ const double maxCornerNormalized = kMaxCorner / engineParameters.sampleRate();
if (enableState == EffectEnableState::Disabling) {
// Ramp to dry, when disabling, this will ramp from dry when enabling as well
hpf = minCornerNormalized;
lpf = maxCornerNormalized;
} else {
- hpf = m_pHPF->value() / bufferParameters.sampleRate();
- lpf = m_pLPF->value() / bufferParameters.sampleRate();
+ hpf = m_pHPF->value() / engineParameters.sampleRate();
+ lpf = m_pLPF->value() / engineParameters.sampleRate();
}
if ((pState->m_loFreq != lpf) ||
@@ -152,11 +146,12 @@ void FilterEffect::processChannel(const ChannelHandle& handle,
if (hpf > minCornerNormalized) {
// hpf enabled, fade-in is handled in the filter when starting from pause
- pState->m_pHighFilter->process(pInput, pHpfOutput, bufferParameters.samplesPerBuffer());
+ pState->m_pHighFilter->process(pInput, pHpfOutput, engineParameters.samplesPerBuffer());
} else if (pState->m_hiFreq > minCornerNormalized) {
- // hpf disabling
- pState->m_pHighFilter->processAndPauseFilter(pInput,
- pHpfOutput, bufferParameters.samplesPerBuffer());
+ // hpf disabling
+ pState->m_pHighFilter->processAndPauseFilter(pInput,
+ pHpfOutput,
+ engineParameters.samplesPerBuffer());
} else {
// paused LP uses input directly
pLpfInput = pInput;
@@ -164,16 +159,17 @@ void FilterEffect::processChannel(const ChannelHandle& handle,
if (lpf < maxCornerNormalized) {
// lpf enabled, fade-in is handled in the filter when starting from pause
- pState->m_pLowFilter->process(pLpfInput, pOutput, bufferParameters.samplesPerBuffer());
+ pState->m_pLowFilter->process(pLpfInput, pOutput, engineParameters.samplesPerBuffer());
} else if (pState->m_loFreq < maxCornerNormalized) {
// hpf disabling
pState->m_pLowFilter->processAndPauseFilter(pLpfInput,
- pOutput, bufferParameters.samplesPerBuffer());
+ pOutput,
+ engineParameters.samplesPerBuffer());
} else if (pLpfInput == pInput) {
// Both disabled
if (pOutput != pInput) {
// We need to copy pInput pOutput
- SampleUtil::copy(pOutput, pInput, bufferParameters.samplesPerBuffer());
+ SampleUtil::copy(pOutput, pInput, engineParameters.samplesPerBuffer());
}
}
diff --git a/src/effects/builtin/filtereffect.h b/src/effects/backends/builtin/filtereffect.h
similarity index 57%
rename from src/effects/builtin/filtereffect.h
rename to src/effects/backends/builtin/filtereffect.h
index a7ba64c5570..60ffc19caaf 100644
--- a/src/effects/builtin/filtereffect.h
+++ b/src/effects/backends/builtin/filtereffect.h
@@ -1,7 +1,6 @@
#pragma once
-#include "effects/effect.h"
-#include "effects/effectprocessor.h"
+#include "effects/backends/effectprocessor.h"
#include "engine/effects/engineeffect.h"
#include "engine/effects/engineeffectparameter.h"
#include "engine/filters/enginefilterbiquad1.h"
@@ -12,7 +11,7 @@
#include "util/types.h"
struct FilterGroupState : public EffectState {
- FilterGroupState(const mixxx::EngineParameters& bufferParameters);
+ FilterGroupState(const mixxx::EngineParameters& engineParameters);
~FilterGroupState();
void setFilters(int sampleRate, double lowFreq, double highFreq);
@@ -24,32 +23,35 @@ struct FilterGroupState : public EffectState {
double m_loFreq;
double m_q;
double m_hiFreq;
-
};
class FilterEffect : public EffectProcessorImpl {
public:
- FilterEffect(EngineEffect* pEffect);
+ FilterEffect() = default;
virtual ~FilterEffect();
static QString getId();
static EffectManifestPointer getManifest();
- void processChannel(const ChannelHandle& handle,
- FilterGroupState* pState,
- const CSAMPLE* pInput, CSAMPLE *pOutput,
- const mixxx::EngineParameters& bufferParameters,
- const EffectEnableState enableState,
- const GroupFeatureState& groupFeatures);
+ void loadEngineEffectParameters(
+ const QMap& parameters) override;
+
+ void processChannel(
+ FilterGroupState* pState,
+ const CSAMPLE* pInput,
+ CSAMPLE* pOutput,
+ const mixxx::EngineParameters& engineParameters,
+ const EffectEnableState enableState,
+ const GroupFeatureState& groupFeatures) override;
private:
QString debugString() const {
return getId();
}
- EngineEffectParameter* m_pLPF;
- EngineEffectParameter* m_pQ;
- EngineEffectParameter* m_pHPF;
+ EngineEffectParameterPointer m_pLPF;
+ EngineEffectParameterPointer m_pQ;
+ EngineEffectParameterPointer m_pHPF;
DISALLOW_COPY_AND_ASSIGN(FilterEffect);
};
diff --git a/src/effects/builtin/flangereffect.cpp b/src/effects/backends/builtin/flangereffect.cpp
similarity index 58%
rename from src/effects/builtin/flangereffect.cpp
rename to src/effects/backends/builtin/flangereffect.cpp
index 542bd58a1a7..347bc65abf4 100644
--- a/src/effects/builtin/flangereffect.cpp
+++ b/src/effects/backends/builtin/flangereffect.cpp
@@ -1,10 +1,10 @@
-#include "effects/builtin/flangereffect.h"
+#include "effects/backends/builtin/flangereffect.h"
#include
#include "util/math.h"
-namespace{
+namespace {
// Gain correction was verified with replay gain and default parameters
constexpr CSAMPLE kGainCorrection = 1.41253754f; // 3 dB
@@ -28,63 +28,51 @@ EffectManifestPointer FlangerEffect::getManifest() {
pManifest->setShortName(QObject::tr("Flanger"));
pManifest->setAuthor("The Mixxx Team");
pManifest->setVersion("1.0");
- pManifest->setDescription(QObject::tr(
- "Mixes the input with a delayed, pitch modulated copy of itself to create comb filtering"));
- pManifest->setMetaknobDefault(1.0);
+ pManifest->setDescription(
+ QObject::tr("Mixes the input with a delayed, pitch modulated copy "
+ "of itself to create comb filtering"));
EffectManifestParameterPointer speed = pManifest->addParameter();
speed->setId("speed");
speed->setName(QObject::tr("Speed"));
speed->setShortName(QObject::tr("Speed"));
speed->setDescription(QObject::tr(
- "Speed of the LFO (low frequency oscillator)\n"
- "32 - 1/4 beats rounded to 1/2 beat per LFO cycle if tempo is detected\n"
- "1/32 - 4 Hz if no tempo is detected"));
- speed->setControlHint(EffectManifestParameter::ControlHint::KNOB_LOGARITHMIC_INVERSE);
- speed->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- speed->setMinimum(kMinLfoBeats);
- speed->setMaximum(kMaxLfoBeats);
- speed->setDefault(8);
+ "Speed of the LFO (low frequency oscillator)\n"
+ "32 - 1/4 beats rounded to 1/2 beat per LFO cycle if tempo is detected\n"
+ "1/32 - 4 Hz if no tempo is detected"));
+ speed->setValueScaler(EffectManifestParameter::ValueScaler::LogarithmicInverse);
+ speed->setRange(kMinLfoBeats, 8, kMaxLfoBeats);
EffectManifestParameterPointer width = pManifest->addParameter();
width->setId("width");
width->setName(QObject::tr("Width"));
width->setShortName(QObject::tr("Width"));
width->setDescription(QObject::tr(
- "Delay amplitude of the LFO (low frequency oscillator)"));
- width->setControlHint(EffectManifestParameter::ControlHint::KNOB_LOGARITHMIC);
- width->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- width->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- width->setDefault(kMaxLfoWidthMs / 2);
- width->setMinimum(0.0);
- width->setMaximum(kMaxLfoWidthMs);
+ "Delay amplitude of the LFO (low frequency oscillator)"));
+ width->setValueScaler(EffectManifestParameter::ValueScaler::Logarithmic);
+ width->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ width->setRange(0.0, kMaxLfoWidthMs / 2, kMaxLfoWidthMs);
EffectManifestParameterPointer manual = pManifest->addParameter();
manual->setId("manual");
manual->setName(QObject::tr("Manual"));
manual->setShortName(QObject::tr("Manual"));
manual->setDescription(QObject::tr(
- "Delay offset of the LFO (low frequency oscillator).\n"
- "With width at zero, this allows for manually sweeping over the entire delay range."));
- manual->setControlHint(EffectManifestParameter::ControlHint::KNOB_LOGARITHMIC);
- manual->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- manual->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- manual->setDefault(kCenterDelayMs);
- manual->setMinimum(kMinDelayMs);
- manual->setMaximum(kMaxDelayMs);
+ "Delay offset of the LFO (low frequency oscillator).\n"
+ "With width at zero, this allows for manually sweeping over the entire delay range."));
+ manual->setValueScaler(EffectManifestParameter::ValueScaler::Logarithmic);
+ manual->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ manual->setRange(kMinDelayMs, kCenterDelayMs, kMaxDelayMs);
EffectManifestParameterPointer regen = pManifest->addParameter();
regen->setId("regen");
regen->setName(QObject::tr("Regeneration"));
regen->setShortName(QObject::tr("Regen"));
regen->setDescription(QObject::tr(
- "How much of the delay output is feed back into the input"));
- regen->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR);
- regen->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- regen->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- regen->setDefault(0.25);
- regen->setMinimum(0.0);
- regen->setMaximum(1.0);
+ "How much of the delay output is feed back into the input"));
+ regen->setValueScaler(EffectManifestParameter::ValueScaler::Linear);
+ regen->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ regen->setRange(0.0, 0.25, 1.0);
EffectManifestParameterPointer mix = pManifest->addParameter();
mix->setId("mix");
@@ -92,13 +80,10 @@ EffectManifestPointer FlangerEffect::getManifest() {
mix->setShortName(QObject::tr("Mix"));
mix->setDescription(QObject::tr(
"Intensity of the effect"));
- mix->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR);
- mix->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- mix->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- mix->setDefaultLinkType(EffectManifestParameter::LinkType::LINKED);
- mix->setDefault(1.0);
- mix->setMinimum(0.0);
- mix->setMaximum(1.0);
+ mix->setValueScaler(EffectManifestParameter::ValueScaler::Linear);
+ mix->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ mix->setDefaultLinkType(EffectManifestParameter::LinkType::Linked);
+ mix->setRange(0.0, 1.0, 1.0);
EffectManifestParameterPointer triplet = pManifest->addParameter();
triplet->setId("triplet");
@@ -106,37 +91,34 @@ EffectManifestPointer FlangerEffect::getManifest() {
triplet->setShortName(QObject::tr("Triplets"));
triplet->setDescription(QObject::tr(
"Divide rounded 1/2 beats of the Period parameter by 3."));
- triplet->setControlHint(EffectManifestParameter::ControlHint::TOGGLE_STEPPING);
- triplet->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- triplet->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- triplet->setDefault(0);
- triplet->setMinimum(0);
- triplet->setMaximum(1);
+ triplet->setValueScaler(EffectManifestParameter::ValueScaler::Toggle);
+ triplet->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ triplet->setRange(0, 0, 1);
return pManifest;
}
-FlangerEffect::FlangerEffect(EngineEffect* pEffect)
- : m_pSpeedParameter(pEffect->getParameterById("speed")),
- m_pWidthParameter(pEffect->getParameterById("width")),
- m_pManualParameter(pEffect->getParameterById("manual")),
- m_pRegenParameter(pEffect->getParameterById("regen")),
- m_pMixParameter(pEffect->getParameterById("mix")),
- m_pTripletParameter(pEffect->getParameterById("triplet")) {
+void FlangerEffect::loadEngineEffectParameters(
+ const QMap& parameters) {
+ m_pSpeedParameter = parameters.value("speed");
+ m_pWidthParameter = parameters.value("width");
+ m_pManualParameter = parameters.value("manual");
+ m_pRegenParameter = parameters.value("regen");
+ m_pMixParameter = parameters.value("mix");
+ m_pTripletParameter = parameters.value("triplet");
}
FlangerEffect::~FlangerEffect() {
//qDebug() << debugString() << "destroyed";
}
-void FlangerEffect::processChannel(const ChannelHandle& handle,
- FlangerGroupState* pState,
- const CSAMPLE* pInput, CSAMPLE* pOutput,
- const mixxx::EngineParameters& bufferParameters,
- const EffectEnableState enableState,
- const GroupFeatureState& groupFeatures) {
- Q_UNUSED(handle);
-
+void FlangerEffect::processChannel(
+ FlangerGroupState* pState,
+ const CSAMPLE* pInput,
+ CSAMPLE* pOutput,
+ const mixxx::EngineParameters& engineParameters,
+ const EffectEnableState enableState,
+ const GroupFeatureState& groupFeatures) {
double lfoPeriodParameter = m_pSpeedParameter->value();
double lfoPeriodFrames;
if (groupFeatures.has_beat_length_sec) {
@@ -145,12 +127,12 @@ void FlangerEffect::processChannel(const ChannelHandle& handle,
if (m_pTripletParameter->toBool()) {
lfoPeriodParameter /= 3.0;
}
- lfoPeriodFrames = lfoPeriodParameter * groupFeatures.beat_length_sec
- * bufferParameters.sampleRate();
+ lfoPeriodFrames = lfoPeriodParameter * groupFeatures.beat_length_sec *
+ engineParameters.sampleRate();
} else {
// lfoPeriodParameter is a number of seconds
- lfoPeriodFrames = std::max(lfoPeriodParameter, kMinLfoBeats)
- * bufferParameters.sampleRate();
+ lfoPeriodFrames = std::max(lfoPeriodParameter, kMinLfoBeats) *
+ engineParameters.sampleRate();
}
// When the period is changed, the position of the sound shouldn't
@@ -161,19 +143,18 @@ void FlangerEffect::processChannel(const ChannelHandle& handle,
}
pState->previousPeriodFrames = lfoPeriodFrames;
-
// lfoPeriodSamples is used to calculate the delay for each channel
// independently in the loop below, so do not multiply lfoPeriodSamples by
// the number of channels.
const auto mix = static_cast(m_pMixParameter->value());
RampingValue mixRamped(
- pState->prev_mix, mix, bufferParameters.framesPerBuffer());
+ pState->prev_mix, mix, engineParameters.framesPerBuffer());
pState->prev_mix = mix;
const auto regen = static_cast(m_pRegenParameter->value());
RampingValue regenRamped(
- pState->prev_regen, regen, bufferParameters.framesPerBuffer());
+ pState->prev_regen, regen, engineParameters.framesPerBuffer());
pState->prev_regen = regen;
// With and Manual is limited by amount of amplitude that remains from width
@@ -185,19 +166,19 @@ void FlangerEffect::processChannel(const ChannelHandle& handle,
manual = math_clamp(manual, minManual, maxManual);
RampingValue widthRamped(
- pState->prev_width, width, bufferParameters.framesPerBuffer());
+ pState->prev_width, width, engineParameters.framesPerBuffer());
pState->prev_width = static_cast(width);
RampingValue manualRamped(
- pState->prev_manual, manual, bufferParameters.framesPerBuffer());
+ pState->prev_manual, manual, engineParameters.framesPerBuffer());
pState->prev_manual = static_cast(manual);
CSAMPLE* delayLeft = pState->delayLeft;
CSAMPLE* delayRight = pState->delayRight;
for (SINT i = 0;
- i < bufferParameters.samplesPerBuffer();
- i += bufferParameters.channelCount()) {
+ i < engineParameters.samplesPerBuffer();
+ i += engineParameters.channelCount()) {
CSAMPLE_GAIN mix_ramped = mixRamped.getNext();
CSAMPLE_GAIN regen_ramped = regenRamped.getNext();
double width_ramped = widthRamped.getNext();
@@ -210,12 +191,16 @@ void FlangerEffect::processChannel(const ChannelHandle& handle,
auto periodFraction = pState->lfoFrames / static_cast(lfoPeriodFrames);
double delayMs = manual_ramped + width_ramped / 2 * sin(M_PI * 2.0f * periodFraction);
- double delayFrames = delayMs * bufferParameters.sampleRate() / 1000;
-
- SINT framePrev = (pState->delayPos - static_cast(floor(delayFrames))
- + kBufferLenth) % kBufferLenth;
- SINT frameNext = (pState->delayPos - static_cast(ceil(delayFrames))
- + kBufferLenth) % kBufferLenth;
+ double delayFrames = delayMs * engineParameters.sampleRate() / 1000;
+
+ SINT framePrev =
+ (pState->delayPos - static_cast(floor(delayFrames)) +
+ kBufferLenth) %
+ kBufferLenth;
+ SINT frameNext =
+ (pState->delayPos - static_cast(ceil(delayFrames)) +
+ kBufferLenth) %
+ kBufferLenth;
CSAMPLE prevLeft = delayLeft[framePrev];
CSAMPLE nextLeft = delayLeft[frameNext];
@@ -228,7 +213,8 @@ void FlangerEffect::processChannel(const ChannelHandle& handle,
CSAMPLE delayedSampleRight = prevRight + frac * (nextRight - prevRight);
delayLeft[pState->delayPos] = tanh_approx(pInput[i] + regen_ramped * delayedSampleLeft);
- delayRight[pState->delayPos] = tanh_approx(pInput[i + 1] + regen_ramped * delayedSampleRight);
+ delayRight[pState->delayPos] =
+ tanh_approx(pInput[i + 1] + regen_ramped * delayedSampleRight);
pState->delayPos = (pState->delayPos + 1) % kBufferLenth;
diff --git a/src/effects/builtin/flangereffect.h b/src/effects/backends/builtin/flangereffect.h
similarity index 62%
rename from src/effects/builtin/flangereffect.h
rename to src/effects/backends/builtin/flangereffect.h
index a942f90bc68..59420861701 100644
--- a/src/effects/builtin/flangereffect.h
+++ b/src/effects/backends/builtin/flangereffect.h
@@ -2,14 +2,14 @@
#include
-#include "effects/effectprocessor.h"
+#include "effects/backends/effectprocessor.h"
#include "engine/effects/engineeffect.h"
#include "engine/effects/engineeffectparameter.h"
#include "util/class.h"
#include "util/defs.h"
+#include "util/rampingvalue.h"
#include "util/sample.h"
#include "util/types.h"
-#include "util/rampingvalue.h"
namespace {
constexpr double kMaxDelayMs = 13.0;
@@ -17,14 +17,14 @@ constexpr double kMinDelayMs = 0.22;
constexpr double kCenterDelayMs = (kMaxDelayMs - kMinDelayMs) / 2 + kMinDelayMs;
constexpr double kMaxLfoWidthMs = kMaxDelayMs - kMinDelayMs;
// using + 1.0 instead of ceil() for Mac OS
-constexpr SINT kBufferLenth = static_cast(kMaxDelayMs + 1.0) * 96; // for 96 kHz
-constexpr double kMinLfoBeats = 1/4.0;
+constexpr SINT kBufferLenth = static_cast(kMaxDelayMs + 1.0) * 96; // for 96 kHz
+constexpr double kMinLfoBeats = 1 / 4.0;
constexpr double kMaxLfoBeats = 32.0;
} // anonymous namespace
struct FlangerGroupState : public EffectState {
- FlangerGroupState(const mixxx::EngineParameters& bufferParameters)
- : EffectState(bufferParameters),
+ FlangerGroupState(const mixxx::EngineParameters& engineParameters)
+ : EffectState(engineParameters),
delayPos(0),
lfoFrames(0),
previousPeriodFrames(-1),
@@ -48,31 +48,34 @@ struct FlangerGroupState : public EffectState {
class FlangerEffect : public EffectProcessorImpl {
public:
- FlangerEffect(EngineEffect* pEffect);
+ FlangerEffect() = default;
virtual ~FlangerEffect();
static QString getId();
static EffectManifestPointer getManifest();
- // See effectprocessor.h
- void processChannel(const ChannelHandle& handle,
- FlangerGroupState* pState,
- const CSAMPLE* pInput, CSAMPLE* pOutput,
- const mixxx::EngineParameters& bufferParameters,
- const EffectEnableState enableState,
- const GroupFeatureState& groupFeatures);
+ void loadEngineEffectParameters(
+ const QMap& parameters) override;
+
+ void processChannel(
+ FlangerGroupState* pState,
+ const CSAMPLE* pInput,
+ CSAMPLE* pOutput,
+ const mixxx::EngineParameters& engineParameters,
+ const EffectEnableState enableState,
+ const GroupFeatureState& groupFeatures) override;
private:
QString debugString() const {
return getId();
}
- EngineEffectParameter* m_pSpeedParameter;
- EngineEffectParameter* m_pWidthParameter;
- EngineEffectParameter* m_pManualParameter;
- EngineEffectParameter* m_pRegenParameter;
- EngineEffectParameter* m_pMixParameter;
- EngineEffectParameter* m_pTripletParameter;
+ EngineEffectParameterPointer m_pSpeedParameter;
+ EngineEffectParameterPointer m_pWidthParameter;
+ EngineEffectParameterPointer m_pManualParameter;
+ EngineEffectParameterPointer m_pRegenParameter;
+ EngineEffectParameterPointer m_pMixParameter;
+ EngineEffectParameterPointer m_pTripletParameter;
DISALLOW_COPY_AND_ASSIGN(FlangerEffect);
};
diff --git a/src/effects/builtin/graphiceqeffect.cpp b/src/effects/backends/builtin/graphiceqeffect.cpp
similarity index 56%
rename from src/effects/builtin/graphiceqeffect.cpp
rename to src/effects/backends/builtin/graphiceqeffect.cpp
index dbeeb8d63cc..64c9576c753 100644
--- a/src/effects/builtin/graphiceqeffect.cpp
+++ b/src/effects/backends/builtin/graphiceqeffect.cpp
@@ -1,4 +1,5 @@
-#include "effects/builtin/graphiceqeffect.h"
+#include "effects/backends/builtin/graphiceqeffect.h"
+
#include "util/math.h"
#define Q 1.2247449
@@ -17,27 +18,23 @@ EffectManifestPointer GraphicEQEffect::getManifest() {
pManifest->setAuthor("The Mixxx Team");
pManifest->setVersion("1.0");
pManifest->setDescription(QObject::tr(
- "An 8-band graphic equalizer based on biquad filters"));
+ "An 8-band graphic equalizer based on biquad filters"));
pManifest->setEffectRampsFromDry(true);
pManifest->setIsMasterEQ(true);
// Display rounded center frequencies for each filter
- float centerFrequencies[8] = {45, 100, 220, 500, 1100, 2500,
- 5500, 12000};
+ float centerFrequencies[8] = {45, 100, 220, 500, 1100, 2500, 5500, 12000};
EffectManifestParameterPointer low = pManifest->addParameter();
low->setId(QString("low"));
low->setName(QString("%1 Hz").arg(centerFrequencies[0]));
low->setShortName(QString("%1 Hz").arg(centerFrequencies[0]));
low->setDescription(QObject::tr(
- "Gain for Low Filter"));
- low->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR);
- low->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- low->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
+ "Gain for Low Filter"));
+ low->setValueScaler(EffectManifestParameter::ValueScaler::Linear);
+ low->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
low->setNeutralPointOnScale(0.5);
- low->setDefault(0);
- low->setMinimum(-12);
- low->setMaximum(12);
+ low->setRange(-12, 0, 12);
QString paramName;
for (int i = 0; i < 6; i++) {
@@ -52,42 +49,37 @@ EffectManifestPointer GraphicEQEffect::getManifest() {
mid->setName(paramName);
mid->setShortName(paramName);
mid->setDescription(QObject::tr(
- "Gain for Band Filter %1").arg(i + 1));
- mid->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR);
- mid->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- mid->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
+ "Gain for Band Filter %1")
+ .arg(i + 1));
+ mid->setValueScaler(EffectManifestParameter::ValueScaler::Linear);
+ mid->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
mid->setNeutralPointOnScale(0.5);
- mid->setDefault(0);
- mid->setMinimum(-12);
- mid->setMaximum(12);
+ mid->setRange(-12, 0, 12);
}
EffectManifestParameterPointer high = pManifest->addParameter();
high->setId(QString("high"));
high->setName(QString("%1 kHz").arg(centerFrequencies[7] / 1000));
high->setDescription(QObject::tr(
- "Gain for High Filter"));
- high->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR);
- high->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- high->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- high->setDefault(0);
- high->setMinimum(-12);
- high->setMaximum(12);
+ "Gain for High Filter"));
+ high->setValueScaler(EffectManifestParameter::ValueScaler::Linear);
+ high->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ high->setRange(-12, 0, 12);
return pManifest;
}
GraphicEQEffectGroupState::GraphicEQEffectGroupState(
- const mixxx::EngineParameters& bufferParameters)
- : EffectState(bufferParameters) {
+ const mixxx::EngineParameters& engineParameters)
+ : EffectState(engineParameters) {
m_oldLow = 0;
for (int i = 0; i < 6; i++) {
m_oldMid.append(1.0);
}
m_oldHigh = 0;
- m_pBufs.append(SampleUtil::alloc(bufferParameters.samplesPerBuffer()));
- m_pBufs.append(SampleUtil::alloc(bufferParameters.samplesPerBuffer()));
+ m_pBufs.append(SampleUtil::alloc(engineParameters.samplesPerBuffer()));
+ m_pBufs.append(SampleUtil::alloc(engineParameters.samplesPerBuffer()));
// Initialize the default center frequencies
m_centerFrequencies[0] = 81;
@@ -104,8 +96,8 @@ GraphicEQEffectGroupState::GraphicEQEffectGroupState(
m_high = new EngineFilterBiquad1HighShelving(44100, m_centerFrequencies[7], Q);
for (int i = 1; i < 7; i++) {
m_bands.append(new EngineFilterBiquad1Peaking(44100,
- m_centerFrequencies[i],
- Q));
+ m_centerFrequencies[i],
+ Q));
}
}
@@ -117,48 +109,45 @@ GraphicEQEffectGroupState::~GraphicEQEffectGroupState() {
delete m_low;
delete m_high;
- foreach(CSAMPLE* buf, m_pBufs) {
+ foreach (CSAMPLE* buf, m_pBufs) {
SampleUtil::free(buf);
}
}
void GraphicEQEffectGroupState::setFilters(int sampleRate) {
- m_low->setFrequencyCorners(sampleRate, m_centerFrequencies[0], Q,
- m_oldLow);
- m_high->setFrequencyCorners(sampleRate, m_centerFrequencies[7], Q,
- m_oldHigh);
+ m_low->setFrequencyCorners(sampleRate, m_centerFrequencies[0], Q, m_oldLow);
+ m_high->setFrequencyCorners(sampleRate, m_centerFrequencies[7], Q, m_oldHigh);
for (int i = 0; i < 6; i++) {
- m_bands[i]->setFrequencyCorners(sampleRate, m_centerFrequencies[i + 1],
- Q, m_oldMid[i]);
+ m_bands[i]->setFrequencyCorners(sampleRate, m_centerFrequencies[i + 1], Q, m_oldMid[i]);
}
}
-GraphicEQEffect::GraphicEQEffect(EngineEffect* pEffect)
- : m_oldSampleRate(44100) {
- m_pPotLow = pEffect->getParameterById("low");
+void GraphicEQEffect::loadEngineEffectParameters(
+ const QMap& parameters) {
+ m_pPotLow = parameters.value("low");
for (int i = 0; i < 6; i++) {
- m_pPotMid.append(pEffect->getParameterById(QString("mid%1").arg(i)));
+ m_pPotMid.append(parameters.value(QString("mid%1").arg(i)));
}
- m_pPotHigh = pEffect->getParameterById("high");
+ m_pPotHigh = parameters.value("high");
}
GraphicEQEffect::~GraphicEQEffect() {
}
-void GraphicEQEffect::processChannel(const ChannelHandle& handle,
- GraphicEQEffectGroupState* pState,
- const CSAMPLE* pInput, CSAMPLE* pOutput,
- const mixxx::EngineParameters& bufferParameters,
- const EffectEnableState enableState,
- const GroupFeatureState& groupFeatures) {
- Q_UNUSED(handle);
+void GraphicEQEffect::processChannel(
+ GraphicEQEffectGroupState* pState,
+ const CSAMPLE* pInput,
+ CSAMPLE* pOutput,
+ const mixxx::EngineParameters& engineParameters,
+ const EffectEnableState enableState,
+ const GroupFeatureState& groupFeatures) {
Q_UNUSED(groupFeatures);
// If the sample rate has changed, initialize the filters using the new
// sample rate
- if (m_oldSampleRate != bufferParameters.sampleRate()) {
- m_oldSampleRate = bufferParameters.sampleRate();
- pState->setFilters(bufferParameters.sampleRate());
+ if (m_oldSampleRate != engineParameters.sampleRate()) {
+ m_oldSampleRate = engineParameters.sampleRate();
+ pState->setFilters(engineParameters.sampleRate());
}
float fLow;
@@ -166,9 +155,10 @@ void GraphicEQEffect::processChannel(const ChannelHandle& handle,
float fHigh;
if (enableState == EffectEnableState::Disabling) {
- // Ramp to dry, when disabling, this will ramp from dry when enabling as well
+ // Ramp to dry, when disabling, this will ramp from dry when enabling as well
fLow = 1.0;
- fHigh = 1.0;;
+ fHigh = 1.0;
+ ;
for (int i = 0; i < 6; i++) {
fMid[i] = 1.0;
}
@@ -180,38 +170,43 @@ void GraphicEQEffect::processChannel(const ChannelHandle& handle,
}
}
-
if (fLow != pState->m_oldLow) {
- pState->m_low->setFrequencyCorners(bufferParameters.sampleRate(),
- pState->m_centerFrequencies[0], Q,
- fLow);
+ pState->m_low->setFrequencyCorners(engineParameters.sampleRate(),
+ pState->m_centerFrequencies[0],
+ Q,
+ fLow);
}
if (fHigh != pState->m_oldHigh) {
- pState->m_high->setFrequencyCorners(bufferParameters.sampleRate(),
- pState->m_centerFrequencies[7], Q,
- fHigh);
+ pState->m_high->setFrequencyCorners(engineParameters.sampleRate(),
+ pState->m_centerFrequencies[7],
+ Q,
+ fHigh);
}
for (int i = 0; i < 6; i++) {
if (fMid[i] != pState->m_oldMid[i]) {
- pState->m_bands[i]->setFrequencyCorners(bufferParameters.sampleRate(),
- pState->m_centerFrequencies[i + 1],
- Q, fMid[i]);
+ pState->m_bands[i]->setFrequencyCorners(engineParameters.sampleRate(),
+ pState->m_centerFrequencies[i + 1],
+ Q,
+ fMid[i]);
}
}
int bufIndex = 0;
if (fLow != 0) {
- pState->m_low->process(pInput, pState->m_pBufs[1 - bufIndex], bufferParameters.samplesPerBuffer());
+ pState->m_low->process(pInput,
+ pState->m_pBufs[1 - bufIndex],
+ engineParameters.samplesPerBuffer());
bufIndex = 1 - bufIndex;
} else {
pState->m_low->pauseFilter();
- SampleUtil::copy(pState->m_pBufs[bufIndex], pInput, bufferParameters.samplesPerBuffer());
+ SampleUtil::copy(pState->m_pBufs[bufIndex], pInput, engineParameters.samplesPerBuffer());
}
for (int i = 0; i < 6; i++) {
if (fMid[i] != 0) {
pState->m_bands[i]->process(pState->m_pBufs[bufIndex],
- pState->m_pBufs[1 - bufIndex], bufferParameters.samplesPerBuffer());
+ pState->m_pBufs[1 - bufIndex],
+ engineParameters.samplesPerBuffer());
bufIndex = 1 - bufIndex;
} else {
pState->m_bands[i]->pauseFilter();
@@ -220,9 +215,10 @@ void GraphicEQEffect::processChannel(const ChannelHandle& handle,
if (fHigh != 0) {
pState->m_high->process(pState->m_pBufs[bufIndex],
- pOutput, bufferParameters.samplesPerBuffer());
+ pOutput,
+ engineParameters.samplesPerBuffer());
} else {
- SampleUtil::copy(pOutput, pState->m_pBufs[bufIndex], bufferParameters.samplesPerBuffer());
+ SampleUtil::copy(pOutput, pState->m_pBufs[bufIndex], engineParameters.samplesPerBuffer());
pState->m_high->pauseFilter();
}
diff --git a/src/effects/builtin/graphiceqeffect.h b/src/effects/backends/builtin/graphiceqeffect.h
similarity index 59%
rename from src/effects/builtin/graphiceqeffect.h
rename to src/effects/backends/builtin/graphiceqeffect.h
index b4a3c40a745..42178c65ba2 100644
--- a/src/effects/builtin/graphiceqeffect.h
+++ b/src/effects/backends/builtin/graphiceqeffect.h
@@ -3,8 +3,7 @@
#include
#include "control/controlproxy.h"
-#include "effects/effect.h"
-#include "effects/effectprocessor.h"
+#include "effects/backends/effectprocessor.h"
#include "engine/effects/engineeffect.h"
#include "engine/effects/engineeffectparameter.h"
#include "engine/filters/enginefilterbiquad1.h"
@@ -15,7 +14,7 @@
class GraphicEQEffectGroupState : public EffectState {
public:
- GraphicEQEffectGroupState(const mixxx::EngineParameters& bufferParameters);
+ GraphicEQEffectGroupState(const mixxx::EngineParameters& engineParameters);
virtual ~GraphicEQEffectGroupState();
void setFilters(int sampleRate);
@@ -32,27 +31,32 @@ class GraphicEQEffectGroupState : public EffectState {
class GraphicEQEffect : public EffectProcessorImpl {
public:
- GraphicEQEffect(EngineEffect* pEffect);
+ GraphicEQEffect() = default;
virtual ~GraphicEQEffect();
static QString getId();
static EffectManifestPointer getManifest();
- void processChannel(const ChannelHandle& handle,
- GraphicEQEffectGroupState* pState,
- const CSAMPLE* pInput, CSAMPLE *pOutput,
- const mixxx::EngineParameters& bufferParameters,
- const EffectEnableState enableState,
- const GroupFeatureState& groupFeatureState);
+ void loadEngineEffectParameters(
+ const QMap& parameters) override;
+
+ void processChannel(
+ GraphicEQEffectGroupState* pState,
+ const CSAMPLE* pInput,
+ CSAMPLE* pOutput,
+ const mixxx::EngineParameters& engineParameters,
+ const EffectEnableState enableState,
+ const GroupFeatureState& groupFeatureState) override;
private:
QString debugString() const {
return getId();
}
- EngineEffectParameter* m_pPotLow;
- QList m_pPotMid;
- EngineEffectParameter* m_pPotHigh;
+ EngineEffectParameterPointer m_pPotLow;
+ QList m_pPotMid;
+ EngineEffectParameterPointer m_pPotHigh;
+
mixxx::audio::SampleRate m_oldSampleRate;
DISALLOW_COPY_AND_ASSIGN(GraphicEQEffect);
diff --git a/src/effects/builtin/linkwitzriley8eqeffect.cpp b/src/effects/backends/builtin/linkwitzriley8eqeffect.cpp
similarity index 62%
rename from src/effects/builtin/linkwitzriley8eqeffect.cpp
rename to src/effects/backends/builtin/linkwitzriley8eqeffect.cpp
index 62e271032dc..03c020a441c 100644
--- a/src/effects/builtin/linkwitzriley8eqeffect.cpp
+++ b/src/effects/backends/builtin/linkwitzriley8eqeffect.cpp
@@ -1,6 +1,6 @@
-#include "effects/builtin/linkwitzriley8eqeffect.h"
+#include "effects/backends/builtin/linkwitzriley8eqeffect.h"
-#include "effects/builtin/equalizer_util.h"
+#include "effects/backends/builtin/equalizer_util.h"
#include "util/math.h"
static constexpr unsigned int kStartupSamplerate = 44100;
@@ -20,8 +20,11 @@ EffectManifestPointer LinkwitzRiley8EQEffect::getManifest() {
pManifest->setShortName(QObject::tr("LR8 ISO"));
pManifest->setAuthor("The Mixxx Team");
pManifest->setVersion("1.0");
- pManifest->setDescription(QObject::tr(
- "A Linkwitz-Riley 8th-order filter isolator (optimized crossover, constant phase shift, roll-off -48 dB/octave).") + " " + EqualizerUtil::adjustFrequencyShelvesTip());
+ pManifest->setDescription(
+ QObject::tr("A Linkwitz-Riley 8th-order filter isolator (optimized "
+ "crossover, constant phase shift, roll-off -48 "
+ "dB/octave).") +
+ " " + EqualizerUtil::adjustFrequencyShelvesTip());
pManifest->setIsMixingEQ(true);
EqualizerUtil::createCommonParameters(pManifest.data(), false);
@@ -29,15 +32,14 @@ EffectManifestPointer LinkwitzRiley8EQEffect::getManifest() {
}
LinkwitzRiley8EQEffectGroupState::LinkwitzRiley8EQEffectGroupState(
- const mixxx::EngineParameters& bufferParameters)
- : EffectState(bufferParameters),
+ const mixxx::EngineParameters& engineParameters)
+ : EffectState(engineParameters),
old_low(1.0),
old_mid(1.0),
old_high(1.0),
m_oldSampleRate(kStartupSamplerate),
m_loFreq(kStartupLoFreq),
m_hiFreq(kStartupHiFreq) {
-
m_pLowBuf = SampleUtil::alloc(MAX_BUFFER_LEN);
m_pMidBuf = SampleUtil::alloc(MAX_BUFFER_LEN);
m_pHighBuf = SampleUtil::alloc(MAX_BUFFER_LEN);
@@ -58,37 +60,40 @@ LinkwitzRiley8EQEffectGroupState::~LinkwitzRiley8EQEffectGroupState() {
SampleUtil::free(m_pHighBuf);
}
-void LinkwitzRiley8EQEffectGroupState::setFilters(int sampleRate, int lowFreq,
- int highFreq) {
+void LinkwitzRiley8EQEffectGroupState::setFilters(int sampleRate, int lowFreq, int highFreq) {
m_low1->setFrequencyCorners(sampleRate, lowFreq);
m_high1->setFrequencyCorners(sampleRate, lowFreq);
m_low2->setFrequencyCorners(sampleRate, highFreq);
m_high2->setFrequencyCorners(sampleRate, highFreq);
}
-LinkwitzRiley8EQEffect::LinkwitzRiley8EQEffect(EngineEffect* pEffect)
- : m_pPotLow(pEffect->getParameterById("low")),
- m_pPotMid(pEffect->getParameterById("mid")),
- m_pPotHigh(pEffect->getParameterById("high")),
- m_pKillLow(pEffect->getParameterById("killLow")),
- m_pKillMid(pEffect->getParameterById("killMid")),
- m_pKillHigh(pEffect->getParameterById("killHigh")) {
+LinkwitzRiley8EQEffect::LinkwitzRiley8EQEffect() {
m_pLoFreqCorner = new ControlProxy("[Mixer Profile]", "LoEQFrequency");
m_pHiFreqCorner = new ControlProxy("[Mixer Profile]", "HiEQFrequency");
}
+void LinkwitzRiley8EQEffect::loadEngineEffectParameters(
+ const QMap& parameters) {
+ m_pPotLow = parameters.value("low");
+ m_pPotMid = parameters.value("mid");
+ m_pPotHigh = parameters.value("high");
+ m_pKillLow = parameters.value("killLow");
+ m_pKillMid = parameters.value("killMid");
+ m_pKillHigh = parameters.value("killHigh");
+}
+
LinkwitzRiley8EQEffect::~LinkwitzRiley8EQEffect() {
delete m_pLoFreqCorner;
delete m_pHiFreqCorner;
}
-void LinkwitzRiley8EQEffect::processChannel(const ChannelHandle& handle,
- LinkwitzRiley8EQEffectGroupState* pState,
- const CSAMPLE* pInput, CSAMPLE* pOutput,
- const mixxx::EngineParameters& bufferParameters,
- const EffectEnableState enableState,
- const GroupFeatureState& groupFeatures) {
- Q_UNUSED(handle);
+void LinkwitzRiley8EQEffect::processChannel(
+ LinkwitzRiley8EQEffectGroupState* pState,
+ const CSAMPLE* pInput,
+ CSAMPLE* pOutput,
+ const mixxx::EngineParameters& engineParameters,
+ const EffectEnableState enableState,
+ const GroupFeatureState& groupFeatures) {
Q_UNUSED(groupFeatures);
float fLow = 0.f, fMid = 0.f, fHigh = 0.f;
@@ -102,37 +107,48 @@ void LinkwitzRiley8EQEffect::processChannel(const ChannelHandle& handle,
fHigh = static_cast(m_pPotHigh->value());
}
- if (pState->m_oldSampleRate != bufferParameters.sampleRate() ||
+ if (pState->m_oldSampleRate != engineParameters.sampleRate() ||
(pState->m_loFreq != static_cast(m_pLoFreqCorner->get())) ||
(pState->m_hiFreq != static_cast(m_pHiFreqCorner->get()))) {
pState->m_loFreq = static_cast(m_pLoFreqCorner->get());
pState->m_hiFreq = static_cast(m_pHiFreqCorner->get());
- pState->m_oldSampleRate = bufferParameters.sampleRate();
- pState->setFilters(bufferParameters.sampleRate(), pState->m_loFreq, pState->m_hiFreq);
+ pState->m_oldSampleRate = engineParameters.sampleRate();
+ pState->setFilters(engineParameters.sampleRate(), pState->m_loFreq, pState->m_hiFreq);
}
- pState->m_high2->process(pInput, pState->m_pHighBuf, bufferParameters.samplesPerBuffer()); // HighPass first run
- pState->m_low2->process(pInput, pState->m_pLowBuf, bufferParameters.samplesPerBuffer()); // LowPass first run for low and bandpass
+ pState->m_high2->process(pInput,
+ pState->m_pHighBuf,
+ engineParameters.samplesPerBuffer()); // HighPass first run
+ pState->m_low2->process(pInput,
+ pState->m_pLowBuf,
+ engineParameters
+ .samplesPerBuffer()); // LowPass first run for low and bandpass
if (fMid != pState->old_mid || fHigh != pState->old_high) {
SampleUtil::applyRampingGain(pState->m_pHighBuf,
static_cast(pState->old_high),
fHigh,
- bufferParameters.samplesPerBuffer());
+ engineParameters.samplesPerBuffer());
SampleUtil::addWithRampingGain(pState->m_pHighBuf,
pState->m_pLowBuf,
static_cast(pState->old_mid),
fMid,
- bufferParameters.samplesPerBuffer());
+ engineParameters.samplesPerBuffer());
} else {
- SampleUtil::applyGain(pState->m_pHighBuf, fHigh, bufferParameters.samplesPerBuffer());
+ SampleUtil::applyGain(pState->m_pHighBuf, fHigh, engineParameters.samplesPerBuffer());
SampleUtil::addWithGain(pState->m_pHighBuf,
- pState->m_pLowBuf, fMid,
- bufferParameters.samplesPerBuffer());
+ pState->m_pLowBuf,
+ fMid,
+ engineParameters.samplesPerBuffer());
}
- pState->m_high1->process(pState->m_pHighBuf, pState->m_pMidBuf, bufferParameters.samplesPerBuffer()); // HighPass + BandPass second run
- pState->m_low1->process(pState->m_pLowBuf, pState->m_pLowBuf, bufferParameters.samplesPerBuffer()); // LowPass second run
+ pState->m_high1->process(pState->m_pHighBuf,
+ pState->m_pMidBuf,
+ engineParameters
+ .samplesPerBuffer()); // HighPass + BandPass second run
+ pState->m_low1->process(pState->m_pLowBuf,
+ pState->m_pLowBuf,
+ engineParameters.samplesPerBuffer()); // LowPass second run
if (fLow != pState->old_low) {
SampleUtil::copy2WithRampingGain(pOutput,
@@ -142,12 +158,14 @@ void LinkwitzRiley8EQEffect::processChannel(const ChannelHandle& handle,
pState->m_pMidBuf,
1,
1,
- bufferParameters.samplesPerBuffer());
+ engineParameters.samplesPerBuffer());
} else {
SampleUtil::copy2WithGain(pOutput,
- pState->m_pLowBuf, fLow,
- pState->m_pMidBuf, 1,
- bufferParameters.samplesPerBuffer());
+ pState->m_pLowBuf,
+ fLow,
+ pState->m_pMidBuf,
+ 1,
+ engineParameters.samplesPerBuffer());
}
if (enableState == EffectEnableState::Disabling) {
diff --git a/src/effects/builtin/linkwitzriley8eqeffect.h b/src/effects/backends/builtin/linkwitzriley8eqeffect.h
similarity index 63%
rename from src/effects/builtin/linkwitzriley8eqeffect.h
rename to src/effects/backends/builtin/linkwitzriley8eqeffect.h
index 0bf85b3354a..15ed871dc02 100644
--- a/src/effects/builtin/linkwitzriley8eqeffect.h
+++ b/src/effects/backends/builtin/linkwitzriley8eqeffect.h
@@ -3,8 +3,7 @@
#include
#include "control/controlproxy.h"
-#include "effects/effect.h"
-#include "effects/effectprocessor.h"
+#include "effects/backends/effectprocessor.h"
#include "engine/effects/engineeffect.h"
#include "engine/effects/engineeffectparameter.h"
#include "engine/filters/enginefilterlinkwitzriley8.h"
@@ -15,7 +14,7 @@
class LinkwitzRiley8EQEffectGroupState : public EffectState {
public:
- LinkwitzRiley8EQEffectGroupState(const mixxx::EngineParameters& bufferParameters);
+ LinkwitzRiley8EQEffectGroupState(const mixxx::EngineParameters& engineParameters);
virtual ~LinkwitzRiley8EQEffectGroupState();
void setFilters(int sampleRate, int lowFreq, int highFreq);
@@ -40,32 +39,35 @@ class LinkwitzRiley8EQEffectGroupState : public EffectState {
class LinkwitzRiley8EQEffect : public EffectProcessorImpl {
public:
- LinkwitzRiley8EQEffect(EngineEffect* pEffect);
+ LinkwitzRiley8EQEffect();
virtual ~LinkwitzRiley8EQEffect();
static QString getId();
static EffectManifestPointer getManifest();
- // See effectprocessor.h
- void processChannel(const ChannelHandle& handle,
- LinkwitzRiley8EQEffectGroupState* pState,
- const CSAMPLE* pInput, CSAMPLE *pOutput,
- const mixxx::EngineParameters& bufferParameters,
- const EffectEnableState enableState,
- const GroupFeatureState& groupFeatureState);
+ void loadEngineEffectParameters(
+ const QMap& parameters) override;
+
+ void processChannel(
+ LinkwitzRiley8EQEffectGroupState* pState,
+ const CSAMPLE* pInput,
+ CSAMPLE* pOutput,
+ const mixxx::EngineParameters& engineParameters,
+ const EffectEnableState enableState,
+ const GroupFeatureState& groupFeatureState) override;
private:
QString debugString() const {
return getId();
}
- EngineEffectParameter* m_pPotLow;
- EngineEffectParameter* m_pPotMid;
- EngineEffectParameter* m_pPotHigh;
+ EngineEffectParameterPointer m_pPotLow;
+ EngineEffectParameterPointer m_pPotMid;
+ EngineEffectParameterPointer m_pPotHigh;
- EngineEffectParameter* m_pKillLow;
- EngineEffectParameter* m_pKillMid;
- EngineEffectParameter* m_pKillHigh;
+ EngineEffectParameterPointer m_pKillLow;
+ EngineEffectParameterPointer m_pKillMid;
+ EngineEffectParameterPointer m_pKillHigh;
ControlProxy* m_pLoFreqCorner;
ControlProxy* m_pHiFreqCorner;
diff --git a/src/effects/builtin/loudnesscontoureffect.cpp b/src/effects/backends/builtin/loudnesscontoureffect.cpp
similarity index 64%
rename from src/effects/builtin/loudnesscontoureffect.cpp
rename to src/effects/backends/builtin/loudnesscontoureffect.cpp
index 1bd78f1f4b0..17fa5167ab4 100644
--- a/src/effects/builtin/loudnesscontoureffect.cpp
+++ b/src/effects/backends/builtin/loudnesscontoureffect.cpp
@@ -1,4 +1,5 @@
-#include "effects/builtin/loudnesscontoureffect.h"
+#include "effects/backends/builtin/loudnesscontoureffect.h"
+
#include "util/math.h"
namespace {
@@ -13,7 +14,6 @@ static constexpr double kHiShelveQ = 0.7;
} // anonymous namespace
-
// static
QString LoudnessContourEffect::getId() {
return "org.mixxx.effects.loudnesscontour";
@@ -28,57 +28,52 @@ EffectManifestPointer LoudnessContourEffect::getManifest() {
pManifest->setAuthor("The Mixxx Team");
pManifest->setVersion("1.0");
pManifest->setDescription(QObject::tr(
- "Amplifies low and high frequencies at low volumes to compensate for reduced sensitivity of the human ear."));
+ "Amplifies low and high frequencies at low volumes to compensate "
+ "for reduced sensitivity of the human ear."));
pManifest->setEffectRampsFromDry(true);
- pManifest->setMetaknobDefault(-kMaxLoGain / 2);
+ pManifest->setMetaknobDefault(1.0);
EffectManifestParameterPointer loudness = pManifest->addParameter();
loudness->setId("loudness");
loudness->setName(QObject::tr("Loudness"));
loudness->setShortName(QObject::tr("Loudness"));
loudness->setDescription(QObject::tr(
- "Set the gain of the applied loudness contour"));
- loudness->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR);
- loudness->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- loudness->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- loudness->setDefaultLinkType(EffectManifestParameter::LinkType::LINKED);
+ "Set the gain of the applied loudness contour"));
+ loudness->setValueScaler(EffectManifestParameter::ValueScaler::Linear);
+ loudness->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ loudness->setDefaultLinkType(EffectManifestParameter::LinkType::Linked);
loudness->setNeutralPointOnScale(1);
- loudness->setDefault(-kMaxLoGain / 2);
- loudness->setMinimum(-kMaxLoGain);
- loudness->setMaximum(0);
+ loudness->setRange(-kMaxLoGain, -kMaxLoGain / 2, 0);
EffectManifestParameterPointer useGain = pManifest->addParameter();
useGain->setId("useGain");
useGain->setName(QObject::tr("Use Gain"));
useGain->setShortName(QObject::tr("Use Gain"));
useGain->setDescription(QObject::tr(
- "Follow Gain Knob"));
- useGain->setControlHint(EffectManifestParameter::ControlHint::TOGGLE_STEPPING);
- useGain->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- useGain->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- useGain->setDefault(0);
- useGain->setMinimum(0);
- useGain->setMaximum(1);
+ "Follow Gain Knob"));
+ useGain->setValueScaler(EffectManifestParameter::ValueScaler::Toggle);
+ useGain->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ useGain->setRange(0, 0, 1);
return pManifest;
}
LoudnessContourEffectGroupState::LoudnessContourEffectGroupState(
- const mixxx::EngineParameters& bufferParameters)
- : EffectState(bufferParameters),
+ const mixxx::EngineParameters& engineParameters)
+ : EffectState(engineParameters),
m_oldGainKnob(1.0),
m_oldLoudness(0.0),
m_oldGain(1.0f),
m_oldFilterGainDb(0),
m_oldUseGain(false),
- m_oldSampleRate(bufferParameters.sampleRate()) {
- m_pBuf = SampleUtil::alloc(bufferParameters.samplesPerBuffer());
+ m_oldSampleRate(engineParameters.sampleRate()) {
+ m_pBuf = SampleUtil::alloc(engineParameters.samplesPerBuffer());
// Initialize the filters with default parameters
m_low = std::make_unique(
- bufferParameters.sampleRate() , kLoPeakFreq , kHiShelveQ);
+ engineParameters.sampleRate(), kLoPeakFreq, kHiShelveQ);
m_high = std::make_unique(
- bufferParameters.sampleRate() , kHiShelveFreq ,kHiShelveQ);
+ engineParameters.sampleRate(), kHiShelveFreq, kHiShelveQ);
}
LoudnessContourEffectGroupState::~LoudnessContourEffectGroupState() {
@@ -90,34 +85,30 @@ void LoudnessContourEffectGroupState::setFilters(int sampleRate, double gain) {
sampleRate, kLoPeakFreq, kLoPleakQ, gain);
m_high->setFrequencyCorners(
sampleRate, kHiShelveFreq, kHiShelveQ, gain / kHiShelveGainDiv);
-
}
-LoudnessContourEffect::LoudnessContourEffect(
- EngineEffect* pEffect)
- : m_pLoudness(pEffect->getParameterById("loudness")),
- m_pUseGain(pEffect->getParameterById("useGain")) {
+void LoudnessContourEffect::loadEngineEffectParameters(
+ const QMap& parameters) {
+ m_pLoudness = parameters.value("loudness");
+ m_pUseGain = parameters.value("useGain");
}
LoudnessContourEffect::~LoudnessContourEffect() {
}
void LoudnessContourEffect::processChannel(
- const ChannelHandle& handle,
LoudnessContourEffectGroupState* pState,
const CSAMPLE* pInput,
CSAMPLE* pOutput,
- const mixxx::EngineParameters& bufferParameters,
+ const mixxx::EngineParameters& engineParameters,
const EffectEnableState enableState,
const GroupFeatureState& groupFeatures) {
- Q_UNUSED(handle);
Q_UNUSED(groupFeatures);
double filterGainDb = pState->m_oldFilterGainDb;
auto gain = static_cast(pState->m_oldGain);
if (enableState != EffectEnableState::Disabling) {
-
bool useGain = m_pUseGain->toBool() && groupFeatures.has_gain;
double loudness = m_pLoudness->value();
double gainKnob = groupFeatures.gain;
@@ -127,40 +118,40 @@ void LoudnessContourEffect::processChannel(
if (useGain != pState->m_oldUseGain ||
gainKnob != pState->m_oldGainKnob ||
loudness != pState->m_oldLoudness ||
- bufferParameters.sampleRate() != pState->m_oldSampleRate) {
-
+ engineParameters.sampleRate() != pState->m_oldSampleRate) {
pState->m_oldUseGain = useGain;
- pState->m_oldGainKnob = gainKnob;
+ pState->m_oldGainKnob = gainKnob;
pState->m_oldLoudness = loudness;
- pState->m_oldSampleRate = bufferParameters.sampleRate();
+ pState->m_oldSampleRate = engineParameters.sampleRate();
if (useGain) {
gainKnob = math_clamp(gainKnob, 0.03, 1.0); // Limit at 0 .. -30 dB
double gainKnobDb = ratio2db(gainKnob);
filterGainDb = loudness * gainKnobDb / kMaxLoGain;
gain = 1; // No need for adjust gain because master gain follows
- }
- else {
+ } else {
filterGainDb = -loudness;
// compensate filter boost to avoid clipping
gain = static_cast(db2ratio(-filterGainDb));
}
- pState->setFilters(bufferParameters.sampleRate(), filterGainDb);
+ pState->setFilters(engineParameters.sampleRate(), filterGainDb);
}
}
if (filterGainDb == 0) {
pState->m_low->pauseFilter();
pState->m_high->pauseFilter();
- SampleUtil::copy(pOutput, pInput, bufferParameters.samplesPerBuffer());
+ SampleUtil::copy(pOutput, pInput, engineParameters.samplesPerBuffer());
} else {
- pState->m_low->process(pInput, pOutput, bufferParameters.samplesPerBuffer());
- pState->m_high->process(pOutput, pState->m_pBuf, bufferParameters.samplesPerBuffer());
- SampleUtil::copyWithRampingGain(
- pOutput, pState->m_pBuf, pState->m_oldGain, gain,
- bufferParameters.samplesPerBuffer());
+ pState->m_low->process(pInput, pOutput, engineParameters.samplesPerBuffer());
+ pState->m_high->process(pOutput, pState->m_pBuf, engineParameters.samplesPerBuffer());
+ SampleUtil::copyWithRampingGain(pOutput,
+ pState->m_pBuf,
+ pState->m_oldGain,
+ gain,
+ engineParameters.samplesPerBuffer());
}
- pState->m_oldFilterGainDb = filterGainDb ;
+ pState->m_oldFilterGainDb = filterGainDb;
pState->m_oldGain = gain;
}
diff --git a/src/effects/builtin/loudnesscontoureffect.h b/src/effects/backends/builtin/loudnesscontoureffect.h
similarity index 67%
rename from src/effects/builtin/loudnesscontoureffect.h
rename to src/effects/backends/builtin/loudnesscontoureffect.h
index d2149cf2767..01eef8f304a 100644
--- a/src/effects/builtin/loudnesscontoureffect.h
+++ b/src/effects/backends/builtin/loudnesscontoureffect.h
@@ -1,20 +1,19 @@
#pragma once
#include "control/controlproxy.h"
-#include "effects/effect.h"
-#include "effects/effectprocessor.h"
+#include "effects/backends/effectprocessor.h"
#include "engine/effects/engineeffect.h"
#include "engine/effects/engineeffectparameter.h"
#include "engine/filters/enginefilterbiquad1.h"
#include "util/class.h"
#include "util/defs.h"
+#include "util/memory.h"
#include "util/sample.h"
#include "util/types.h"
-#include "util/memory.h"
class LoudnessContourEffectGroupState final : public EffectState {
public:
- LoudnessContourEffectGroupState(const mixxx::EngineParameters& bufferParameters);
+ LoudnessContourEffectGroupState(const mixxx::EngineParameters& engineParameters);
~LoudnessContourEffectGroupState();
void setFilters(int sampleRate, double gain);
@@ -33,20 +32,24 @@ class LoudnessContourEffectGroupState final : public EffectState {
class LoudnessContourEffect
: public EffectProcessorImpl {
public:
- LoudnessContourEffect(EngineEffect* pEffect);
+ LoudnessContourEffect() = default;
~LoudnessContourEffect() override;
static QString getId();
static EffectManifestPointer getManifest();
- void setFilters(int sampleRate);
+ void loadEngineEffectParameters(
+ const QMap& parameters) override;
- void processChannel(const ChannelHandle& handle,
- LoudnessContourEffectGroupState* pState,
- const CSAMPLE* pInput, CSAMPLE *pOutput,
- const mixxx::EngineParameters& bufferParameters,
- const EffectEnableState enableState,
- const GroupFeatureState& groupFeatureState) override;
+ void processChannel(
+ LoudnessContourEffectGroupState* pState,
+ const CSAMPLE* pInput,
+ CSAMPLE* pOutput,
+ const mixxx::EngineParameters& engineParameters,
+ const EffectEnableState enableState,
+ const GroupFeatureState& groupFeatureState) override;
+
+ void setFilters(int sampleRate);
private:
LoudnessContourEffect(const LoudnessContourEffect&) = delete;
@@ -56,6 +59,6 @@ class LoudnessContourEffect
return getId();
}
- EngineEffectParameter* m_pLoudness;
- EngineEffectParameter* m_pUseGain;
+ EngineEffectParameterPointer m_pLoudness;
+ EngineEffectParameterPointer m_pUseGain;
};
diff --git a/src/effects/builtin/lvmixeqbase.h b/src/effects/backends/builtin/lvmixeqbase.h
similarity index 86%
rename from src/effects/builtin/lvmixeqbase.h
rename to src/effects/backends/builtin/lvmixeqbase.h
index 02f74a03e1c..e24e20e5832 100644
--- a/src/effects/builtin/lvmixeqbase.h
+++ b/src/effects/backends/builtin/lvmixeqbase.h
@@ -1,6 +1,6 @@
#pragma once
-#include "effects/effectprocessor.h"
+#include "effects/backends/effectprocessor.h"
#include "engine/filters/enginefilterdelay.h"
#include "util/defs.h"
#include "util/math.h"
@@ -20,26 +20,26 @@ class LVMixEQEffectGroupStateConstants {
template
class LVMixEQEffectGroupState : public EffectState {
public:
- explicit LVMixEQEffectGroupState(const mixxx::EngineParameters& bufferParameters)
- : EffectState(bufferParameters),
+ explicit LVMixEQEffectGroupState(const mixxx::EngineParameters& engineParameters)
+ : EffectState(engineParameters),
m_oldLow(1.0),
m_oldMid(1.0),
m_oldHigh(1.0),
m_rampHoldOff(LVMixEQEffectGroupStateConstants::kRampDone),
- m_oldSampleRate(bufferParameters.sampleRate()),
+ m_oldSampleRate(engineParameters.sampleRate()),
m_loFreq(LVMixEQEffectGroupStateConstants::kStartupLoFreq),
m_hiFreq(LVMixEQEffectGroupStateConstants::kStartupHiFreq) {
- m_pLowBuf = SampleUtil::alloc(bufferParameters.samplesPerBuffer());
- m_pBandBuf = SampleUtil::alloc(bufferParameters.samplesPerBuffer());
- m_pHighBuf = SampleUtil::alloc(bufferParameters.samplesPerBuffer());
+ m_pLowBuf = SampleUtil::alloc(engineParameters.samplesPerBuffer());
+ m_pBandBuf = SampleUtil::alloc(engineParameters.samplesPerBuffer());
+ m_pHighBuf = SampleUtil::alloc(engineParameters.samplesPerBuffer());
- m_low1 = new LPF(bufferParameters.sampleRate(),
+ m_low1 = new LPF(engineParameters.sampleRate(),
LVMixEQEffectGroupStateConstants::kStartupLoFreq);
- m_low2 = new LPF(bufferParameters.sampleRate(),
+ m_low2 = new LPF(engineParameters.sampleRate(),
LVMixEQEffectGroupStateConstants::kStartupHiFreq);
m_delay2 = new EngineFilterDelay();
m_delay3 = new EngineFilterDelay();
- setFilters(bufferParameters.sampleRate(),
+ setFilters(engineParameters.sampleRate(),
LVMixEQEffectGroupStateConstants::kStartupLoFreq,
LVMixEQEffectGroupStateConstants::kStartupHiFreq);
}
@@ -122,9 +122,12 @@ class LVMixEQEffectGroupState : public EffectState {
fMid == m_oldMid &&
fHigh == m_oldHigh) {
SampleUtil::copy3WithGain(pOutput,
- m_pLowBuf, fLow,
- m_pBandBuf, fMid,
- m_pHighBuf, fHigh,
+ m_pLowBuf,
+ fLow,
+ m_pBandBuf,
+ fMid,
+ m_pHighBuf,
+ fHigh,
numSamples);
} else {
SINT copySamples = 0;
@@ -153,17 +156,26 @@ class LVMixEQEffectGroupState : public EffectState {
rampingSamples = numSamples - copySamples;
SampleUtil::copy3WithGain(pOutput,
- m_pLowBuf, m_oldLow,
- m_pBandBuf, m_oldMid,
- m_pHighBuf, m_oldHigh,
+ m_pLowBuf,
+ m_oldLow,
+ m_pBandBuf,
+ m_oldMid,
+ m_pHighBuf,
+ m_oldHigh,
copySamples);
}
if (rampingSamples) {
SampleUtil::copy3WithRampingGain(&pOutput[copySamples],
- &m_pLowBuf[copySamples], m_oldLow, fLow,
- &m_pBandBuf[copySamples], m_oldMid, fMid,
- &m_pHighBuf[copySamples], m_oldHigh, fHigh,
+ &m_pLowBuf[copySamples],
+ m_oldLow,
+ fLow,
+ &m_pBandBuf[copySamples],
+ m_oldMid,
+ fMid,
+ &m_pHighBuf[copySamples],
+ m_oldHigh,
+ fHigh,
rampingSamples);
m_oldLow = fLow;
@@ -194,9 +206,15 @@ class LVMixEQEffectGroupState : public EffectState {
}
SampleUtil::copy3WithRampingGain(pOutput,
- m_pLowBuf, m_oldLow, 0.0,
- m_pBandBuf, m_oldMid, 0.0,
- m_pHighBuf, m_oldHigh, 1.0,
+ m_pLowBuf,
+ m_oldLow,
+ 0.0,
+ m_pBandBuf,
+ m_oldMid,
+ 0.0,
+ m_pHighBuf,
+ m_oldHigh,
+ 1.0,
numSamples);
}
diff --git a/src/effects/builtin/metronomeclick.h b/src/effects/backends/builtin/metronomeclick.h
similarity index 100%
rename from src/effects/builtin/metronomeclick.h
rename to src/effects/backends/builtin/metronomeclick.h
diff --git a/src/effects/builtin/metronomeeffect.cpp b/src/effects/backends/builtin/metronomeeffect.cpp
similarity index 67%
rename from src/effects/builtin/metronomeeffect.cpp
rename to src/effects/backends/builtin/metronomeeffect.cpp
index 3423b472b6c..e94e9e26cde 100644
--- a/src/effects/builtin/metronomeeffect.cpp
+++ b/src/effects/backends/builtin/metronomeeffect.cpp
@@ -7,7 +7,6 @@
#include "util/math.h"
#include "util/sample.h"
-
// static
QString MetronomeEffect::getId() {
return "org.mixxx.effects.metronome";
@@ -29,45 +28,39 @@ EffectManifestPointer MetronomeEffect::getManifest() {
period->setId("bpm");
period->setName(QObject::tr("BPM"));
period->setDescription(QObject::tr("Set the beats per minute value of the click sound"));
- period->setControlHint(EffectManifestParameter::ControlHint::KNOB_LOGARITHMIC);
- period->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- period->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- period->setMinimum(40);
- period->setDefault(120);
- period->setMaximum(208);
-
+ period->setValueScaler(EffectManifestParameter::ValueScaler::Logarithmic);
+ period->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ period->setRange(40, 120, 208);
// Period unit
EffectManifestParameterPointer periodUnit = pManifest->addParameter();
periodUnit->setId("sync");
periodUnit->setName(QObject::tr("Sync"));
- periodUnit->setDescription(QObject::tr("Synchronizes the BPM with the track if it can be retrieved"));
- periodUnit->setControlHint(EffectManifestParameter::ControlHint::TOGGLE_STEPPING);
- periodUnit->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- periodUnit->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- periodUnit->setDefault(1);
- periodUnit->setMinimum(0);
- periodUnit->setMaximum(1);
+ periodUnit->setDescription(QObject::tr(
+ "Synchronizes the BPM with the track if it can be retrieved"));
+ periodUnit->setValueScaler(EffectManifestParameter::ValueScaler::Toggle);
+ periodUnit->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ periodUnit->setRange(0, 1, 1);
return pManifest;
}
-MetronomeEffect::MetronomeEffect(EngineEffect* pEffect)
- : m_pBpmParameter(pEffect->getParameterById("bpm")),
- m_pSyncParameter(pEffect->getParameterById("sync")) {
+void MetronomeEffect::loadEngineEffectParameters(
+ const QMap& parameters) {
+ m_pBpmParameter = parameters.value("bpm");
+ m_pSyncParameter = parameters.value("sync");
}
MetronomeEffect::~MetronomeEffect() {
}
void MetronomeEffect::processChannel(
- const ChannelHandle& handle,
MetronomeGroupState* pGroupState,
- const CSAMPLE* pInput, CSAMPLE* pOutput,
- const mixxx::EngineParameters& bufferParameters,
+ const CSAMPLE* pInput,
+ CSAMPLE* pOutput,
+ const mixxx::EngineParameters& engineParameters,
const EffectEnableState enableState,
const GroupFeatureState& groupFeatures) {
- Q_UNUSED(handle);
Q_UNUSED(pInput);
MetronomeGroupState* gs = pGroupState;
@@ -79,10 +72,10 @@ void MetronomeEffect::processChannel(
SINT clickSize = kClickSize44100;
const CSAMPLE* click = kClick44100;
- if (bufferParameters.sampleRate() >= 96000) {
+ if (engineParameters.sampleRate() >= 96000) {
clickSize = kClickSize96000;
click = kClick96000;
- } else if (bufferParameters.sampleRate() >= 48000) {
+ } else if (engineParameters.sampleRate() >= 48000) {
clickSize = kClickSize48000;
click = kClick48000;
}
@@ -90,7 +83,7 @@ void MetronomeEffect::processChannel(
SINT maxFrames;
if (m_pSyncParameter->toBool() && groupFeatures.has_beat_length_sec) {
maxFrames = static_cast(
- bufferParameters.sampleRate() * groupFeatures.beat_length_sec);
+ engineParameters.sampleRate() * groupFeatures.beat_length_sec);
if (groupFeatures.has_beat_fraction) {
const auto currentFrame = static_cast(
maxFrames * groupFeatures.beat_fraction);
@@ -104,37 +97,35 @@ void MetronomeEffect::processChannel(
}
} else {
maxFrames = static_cast(
- bufferParameters.sampleRate() * 60 / m_pBpmParameter->value());
+ engineParameters.sampleRate() * 60 / m_pBpmParameter->value());
}
- SampleUtil::copy(pOutput, pInput, bufferParameters.samplesPerBuffer());
+ SampleUtil::copy(pOutput, pInput, engineParameters.samplesPerBuffer());
if (gs->m_framesSinceClickStart < clickSize) {
// still in click region, write remaining click frames.
const SINT copyFrames =
- math_min(bufferParameters.framesPerBuffer(),
+ math_min(engineParameters.framesPerBuffer(),
clickSize - gs->m_framesSinceClickStart);
- SampleUtil::addMonoToStereo(pOutput, &click[gs->m_framesSinceClickStart],
- copyFrames);
+ SampleUtil::addMonoToStereo(pOutput, &click[gs->m_framesSinceClickStart], copyFrames);
}
- gs->m_framesSinceClickStart += bufferParameters.framesPerBuffer();
+ gs->m_framesSinceClickStart += engineParameters.framesPerBuffer();
if (gs->m_framesSinceClickStart > maxFrames) {
// overflow, all overflowed frames are the start of a new click sound
gs->m_framesSinceClickStart -= maxFrames;
- while (gs->m_framesSinceClickStart > bufferParameters.framesPerBuffer()) {
+ while (gs->m_framesSinceClickStart > engineParameters.framesPerBuffer()) {
// loop into a valid region, this happens if the maxFrames was lowered
- gs->m_framesSinceClickStart -= bufferParameters.framesPerBuffer();
+ gs->m_framesSinceClickStart -= engineParameters.framesPerBuffer();
}
// gs->m_framesSinceClickStart matches now already at the first frame
// of next pOutput.
const unsigned int outputOffset =
- bufferParameters.framesPerBuffer() - gs->m_framesSinceClickStart;
+ engineParameters.framesPerBuffer() - gs->m_framesSinceClickStart;
const unsigned int copyFrames =
math_min(gs->m_framesSinceClickStart, clickSize);
- SampleUtil::addMonoToStereo(&pOutput[outputOffset * 2], click,
- copyFrames);
+ SampleUtil::addMonoToStereo(&pOutput[outputOffset * 2], click, copyFrames);
}
}
diff --git a/src/effects/backends/builtin/metronomeeffect.h b/src/effects/backends/builtin/metronomeeffect.h
new file mode 100644
index 00000000000..1a95fe03dbb
--- /dev/null
+++ b/src/effects/backends/builtin/metronomeeffect.h
@@ -0,0 +1,50 @@
+#pragma once
+
+#include
+
+#include "effects/backends/effectprocessor.h"
+#include "engine/effects/engineeffect.h"
+#include "engine/effects/engineeffectparameter.h"
+#include "engine/filters/enginefilterpansingle.h"
+#include "util/class.h"
+#include "util/defs.h"
+#include "util/sample.h"
+#include "util/types.h"
+
+class MetronomeGroupState final : public EffectState {
+ public:
+ MetronomeGroupState(const mixxx::EngineParameters& engineParameters)
+ : EffectState(engineParameters),
+ m_framesSinceClickStart(0) {
+ }
+ ~MetronomeGroupState() {
+ }
+
+ SINT m_framesSinceClickStart;
+};
+
+class MetronomeEffect : public EffectProcessorImpl {
+ public:
+ MetronomeEffect() = default;
+ virtual ~MetronomeEffect();
+
+ static QString getId();
+ static EffectManifestPointer getManifest();
+
+ void loadEngineEffectParameters(
+ const QMap& parameters) override;
+
+ void processChannel(
+ MetronomeGroupState* pState,
+ const CSAMPLE* pInput,
+ CSAMPLE* pOutput,
+ const mixxx::EngineParameters& engineParameters,
+ const EffectEnableState enableState,
+ const GroupFeatureState& groupFeatures) override;
+
+ private:
+ EngineEffectParameterPointer m_pBpmParameter;
+ EngineEffectParameterPointer m_pSyncParameter;
+
+ DISALLOW_COPY_AND_ASSIGN(MetronomeEffect);
+};
diff --git a/src/effects/builtin/moogladder4filtereffect.cpp b/src/effects/backends/builtin/moogladder4filtereffect.cpp
similarity index 59%
rename from src/effects/builtin/moogladder4filtereffect.cpp
rename to src/effects/backends/builtin/moogladder4filtereffect.cpp
index fd5691dd213..d907538c4a7 100644
--- a/src/effects/builtin/moogladder4filtereffect.cpp
+++ b/src/effects/backends/builtin/moogladder4filtereffect.cpp
@@ -1,4 +1,5 @@
-#include "effects/builtin/moogladder4filtereffect.h"
+#include "effects/backends/builtin/moogladder4filtereffect.h"
+
#include "util/math.h"
static constexpr double kMinCorner = 0.0003; // 13 Hz @ 44100
@@ -17,65 +18,60 @@ EffectManifestPointer MoogLadder4FilterEffect::getManifest() {
pManifest->setShortName(QObject::tr("Moog Filter"));
pManifest->setAuthor("The Mixxx Team");
pManifest->setVersion("1.0");
- pManifest->setDescription(QObject::tr(
- "A 4-pole Moog ladder filter, based on Antti Houvilainen's non linear digital implementation"));
+ pManifest->setDescription(
+ QObject::tr("A 4-pole Moog ladder filter, based on Antti "
+ "Houvilainen's non linear digital implementation"));
pManifest->setEffectRampsFromDry(true);
+ pManifest->setMetaknobDefault(0.5);
EffectManifestParameterPointer lpf = pManifest->addParameter();
lpf->setId("lpf");
lpf->setName(QObject::tr("LPF"));
lpf->setDescription(QObject::tr("Corner frequency ratio of the low pass filter"));
- lpf->setControlHint(EffectManifestParameter::ControlHint::KNOB_LOGARITHMIC);
- lpf->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- lpf->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- lpf->setDefaultLinkType(EffectManifestParameter::LinkType::LINKED_LEFT);
+ lpf->setValueScaler(EffectManifestParameter::ValueScaler::Logarithmic);
+ lpf->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ lpf->setDefaultLinkType(EffectManifestParameter::LinkType::LinkedLeft);
lpf->setNeutralPointOnScale(1);
- lpf->setDefault(kMaxCorner);
- lpf->setMinimum(kMinCorner);
- lpf->setMaximum(kMaxCorner);
+ lpf->setRange(kMinCorner, kMaxCorner, kMaxCorner);
EffectManifestParameterPointer q = pManifest->addParameter();
q->setId("resonance");
q->setName(QObject::tr("Resonance"));
q->setShortName(QObject::tr("Res"));
q->setDescription(QObject::tr("Resonance of the filters. 4 = self oscillating"));
- q->setControlHint(EffectManifestParameter::ControlHint::KNOB_LOGARITHMIC);
- q->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- q->setUnitsHint(EffectManifestParameter::UnitsHint::SAMPLERATE);
- q->setMinimum(0.0);
- q->setMaximum(4.0);
- q->setDefault(1.0);
+ q->setValueScaler(EffectManifestParameter::ValueScaler::Logarithmic);
+ q->setUnitsHint(EffectManifestParameter::UnitsHint::SampleRate);
+ q->setRange(0.0, 1.0, 4.0);
EffectManifestParameterPointer hpf = pManifest->addParameter();
hpf->setId("hpf");
hpf->setName(QObject::tr("HPF"));
hpf->setDescription(QObject::tr("Corner frequency ratio of the high pass filter"));
- hpf->setControlHint(EffectManifestParameter::ControlHint::KNOB_LOGARITHMIC);
- hpf->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- hpf->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- hpf->setDefaultLinkType(EffectManifestParameter::LinkType::LINKED_RIGHT);
+ hpf->setValueScaler(EffectManifestParameter::ValueScaler::Logarithmic);
+ hpf->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ hpf->setDefaultLinkType(EffectManifestParameter::LinkType::LinkedRight);
hpf->setNeutralPointOnScale(0.0);
- hpf->setDefault(kMinCorner);
- hpf->setMinimum(kMinCorner);
- hpf->setMaximum(kMaxCorner);
+ hpf->setRange(kMinCorner, kMinCorner, kMaxCorner);
return pManifest;
}
MoogLadder4FilterGroupState::MoogLadder4FilterGroupState(
- const mixxx::EngineParameters& bufferParameters)
- : EffectState(bufferParameters),
+ const mixxx::EngineParameters& engineParameters)
+ : EffectState(engineParameters),
m_loFreq(kMaxCorner),
m_resonance(0),
m_hiFreq(kMinCorner),
- m_samplerate(bufferParameters.sampleRate()) {
- m_pBuf = SampleUtil::alloc(bufferParameters.samplesPerBuffer());
+ m_samplerate(engineParameters.sampleRate()) {
+ m_pBuf = SampleUtil::alloc(engineParameters.samplesPerBuffer());
m_pLowFilter = new EngineFilterMoogLadder4Low(
- bufferParameters.sampleRate(),
- m_loFreq * bufferParameters.sampleRate(), m_resonance);
+ engineParameters.sampleRate(),
+ m_loFreq * engineParameters.sampleRate(),
+ m_resonance);
m_pHighFilter = new EngineFilterMoogLadder4High(
- bufferParameters.sampleRate(),
- m_hiFreq * bufferParameters.sampleRate(), m_resonance);
+ engineParameters.sampleRate(),
+ m_hiFreq * engineParameters.sampleRate(),
+ m_resonance);
}
MoogLadder4FilterGroupState::~MoogLadder4FilterGroupState() {
@@ -84,10 +80,11 @@ MoogLadder4FilterGroupState::~MoogLadder4FilterGroupState() {
delete m_pHighFilter;
}
-MoogLadder4FilterEffect::MoogLadder4FilterEffect(EngineEffect* pEffect)
- : m_pLPF(pEffect->getParameterById("lpf")),
- m_pResonance(pEffect->getParameterById("resonance")),
- m_pHPF(pEffect->getParameterById("hpf")) {
+void MoogLadder4FilterEffect::loadEngineEffectParameters(
+ const QMap& parameters) {
+ m_pLPF = parameters.value("lpf");
+ m_pResonance = parameters.value("resonance");
+ m_pHPF = parameters.value("hpf");
}
MoogLadder4FilterEffect::~MoogLadder4FilterEffect() {
@@ -95,13 +92,12 @@ MoogLadder4FilterEffect::~MoogLadder4FilterEffect() {
}
void MoogLadder4FilterEffect::processChannel(
- const ChannelHandle& handle,
MoogLadder4FilterGroupState* pState,
- const CSAMPLE* pInput, CSAMPLE* pOutput,
- const mixxx::EngineParameters& bufferParameters,
+ const CSAMPLE* pInput,
+ CSAMPLE* pOutput,
+ const mixxx::EngineParameters& engineParameters,
const EffectEnableState enableState,
const GroupFeatureState& groupFeatures) {
- Q_UNUSED(handle);
Q_UNUSED(groupFeatures);
double resonance = m_pResonance->value();
@@ -118,17 +114,17 @@ void MoogLadder4FilterEffect::processChannel(
if (pState->m_loFreq != lpf ||
pState->m_resonance != resonance ||
- pState->m_samplerate != bufferParameters.sampleRate()) {
- pState->m_pLowFilter->setParameter(bufferParameters.sampleRate(),
- static_cast(lpf * bufferParameters.sampleRate()),
+ pState->m_samplerate != engineParameters.sampleRate()) {
+ pState->m_pLowFilter->setParameter(engineParameters.sampleRate(),
+ static_cast(lpf * engineParameters.sampleRate()),
static_cast(resonance));
}
if (pState->m_hiFreq != hpf ||
pState->m_resonance != resonance ||
- pState->m_samplerate != bufferParameters.sampleRate()) {
- pState->m_pHighFilter->setParameter(bufferParameters.sampleRate(),
- static_cast(hpf * bufferParameters.sampleRate()),
+ pState->m_samplerate != engineParameters.sampleRate()) {
+ pState->m_pHighFilter->setParameter(engineParameters.sampleRate(),
+ static_cast(hpf * engineParameters.sampleRate()),
static_cast(resonance));
}
@@ -142,11 +138,12 @@ void MoogLadder4FilterEffect::processChannel(
if (hpf > kMinCorner) {
// hpf enabled, fade-in is handled in the filter when starting from pause
- pState->m_pHighFilter->process(pInput, pHpfOutput, bufferParameters.samplesPerBuffer());
+ pState->m_pHighFilter->process(pInput, pHpfOutput, engineParameters.samplesPerBuffer());
} else if (pState->m_hiFreq > kMinCorner) {
// hpf disabling
pState->m_pHighFilter->processAndPauseFilter(pInput,
- pHpfOutput, bufferParameters.samplesPerBuffer());
+ pHpfOutput,
+ engineParameters.samplesPerBuffer());
} else {
// paused LP uses input directly
pLpfInput = pInput;
@@ -154,21 +151,22 @@ void MoogLadder4FilterEffect::processChannel(
if (lpf < kMaxCorner) {
// lpf enabled, fade-in is handled in the filter when starting from pause
- pState->m_pLowFilter->process(pLpfInput, pOutput, bufferParameters.samplesPerBuffer());
+ pState->m_pLowFilter->process(pLpfInput, pOutput, engineParameters.samplesPerBuffer());
} else if (pState->m_loFreq < kMaxCorner) {
// hpf disabling
pState->m_pLowFilter->processAndPauseFilter(pLpfInput,
- pOutput, bufferParameters.samplesPerBuffer());
+ pOutput,
+ engineParameters.samplesPerBuffer());
} else if (pLpfInput == pInput) {
// Both disabled
if (pOutput != pInput) {
// We need to copy pInput pOutput
- SampleUtil::copy(pOutput, pInput, bufferParameters.samplesPerBuffer());
+ SampleUtil::copy(pOutput, pInput, engineParameters.samplesPerBuffer());
}
}
pState->m_loFreq = lpf;
pState->m_resonance = resonance;
pState->m_hiFreq = hpf;
- pState->m_samplerate = bufferParameters.sampleRate();
+ pState->m_samplerate = engineParameters.sampleRate();
}
diff --git a/src/effects/builtin/moogladder4filtereffect.h b/src/effects/backends/builtin/moogladder4filtereffect.h
similarity index 57%
rename from src/effects/builtin/moogladder4filtereffect.h
rename to src/effects/backends/builtin/moogladder4filtereffect.h
index 8f269b4905a..8814a536173 100644
--- a/src/effects/builtin/moogladder4filtereffect.h
+++ b/src/effects/backends/builtin/moogladder4filtereffect.h
@@ -1,7 +1,5 @@
#pragma once
-
-#include "effects/effect.h"
-#include "effects/effectprocessor.h"
+#include "effects/backends/effectprocessor.h"
#include "engine/effects/engineeffect.h"
#include "engine/effects/engineeffectparameter.h"
#include "engine/filters/enginefiltermoogladder4.h"
@@ -12,7 +10,7 @@
class MoogLadder4FilterGroupState : public EffectState {
public:
- MoogLadder4FilterGroupState(const mixxx::EngineParameters& bufferParameters);
+ MoogLadder4FilterGroupState(const mixxx::EngineParameters& engineParameters);
~MoogLadder4FilterGroupState();
void setFilters(int sampleRate, double lowFreq, double highFreq);
@@ -28,28 +26,31 @@ class MoogLadder4FilterGroupState : public EffectState {
class MoogLadder4FilterEffect : public EffectProcessorImpl {
public:
- MoogLadder4FilterEffect(EngineEffect* pEffect);
+ MoogLadder4FilterEffect() = default;
virtual ~MoogLadder4FilterEffect();
static QString getId();
static EffectManifestPointer getManifest();
- // See effectprocessor.h
- void processChannel(const ChannelHandle& handle,
- MoogLadder4FilterGroupState* pState,
- const CSAMPLE* pInput, CSAMPLE *pOutput,
- const mixxx::EngineParameters& bufferParameters,
- const EffectEnableState enableState,
- const GroupFeatureState& groupFeatures);
+ void loadEngineEffectParameters(
+ const QMap& parameters) override;
+
+ void processChannel(
+ MoogLadder4FilterGroupState* pState,
+ const CSAMPLE* pInput,
+ CSAMPLE* pOutput,
+ const mixxx::EngineParameters& engineParameters,
+ const EffectEnableState enableState,
+ const GroupFeatureState& groupFeatures) override;
private:
QString debugString() const {
return getId();
}
- EngineEffectParameter* m_pLPF;
- EngineEffectParameter* m_pResonance;
- EngineEffectParameter* m_pHPF;
+ EngineEffectParameterPointer m_pLPF;
+ EngineEffectParameterPointer m_pResonance;
+ EngineEffectParameterPointer m_pHPF;
DISALLOW_COPY_AND_ASSIGN(MoogLadder4FilterEffect);
};
diff --git a/src/effects/builtin/parametriceqeffect.cpp b/src/effects/backends/builtin/parametriceqeffect.cpp
similarity index 53%
rename from src/effects/builtin/parametriceqeffect.cpp
rename to src/effects/backends/builtin/parametriceqeffect.cpp
index 11927b58853..212f1a65d12 100644
--- a/src/effects/builtin/parametriceqeffect.cpp
+++ b/src/effects/backends/builtin/parametriceqeffect.cpp
@@ -1,4 +1,5 @@
-#include "effects/builtin/parametriceqeffect.h"
+#include "effects/backends/builtin/parametriceqeffect.h"
+
#include "util/math.h"
namespace {
@@ -21,8 +22,8 @@ EffectManifestPointer ParametricEQEffect::getManifest() {
pManifest->setAuthor("The Mixxx Team");
pManifest->setVersion("1.0");
pManifest->setDescription(QObject::tr(
- "An gentle 2-band parametric equalizer based on biquad filters.\n"
- "It is designed as a complement to the steep mixing equalizers."));
+ "An gentle 2-band parametric equalizer based on biquad filters.\n"
+ "It is designed as a complement to the steep mixing equalizers."));
pManifest->setEffectRampsFromDry(true);
pManifest->setIsMasterEQ(true);
@@ -31,95 +32,78 @@ EffectManifestPointer ParametricEQEffect::getManifest() {
gain1->setName(QObject::tr("Gain 1"));
gain1->setShortName(QObject::tr("Gain 1"));
gain1->setDescription(QObject::tr(
- "Gain for Filter 1"));
- gain1->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR);
- gain1->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- gain1->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
+ "Gain for Filter 1"));
+ gain1->setValueScaler(EffectManifestParameter::ValueScaler::Linear);
+ gain1->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
gain1->setNeutralPointOnScale(0.5);
- gain1->setDefault(0);
- gain1->setMinimum(-18);
- gain1->setMaximum(18); // dB
+ gain1->setRange(-18, 0, 18); // dB
EffectManifestParameterPointer q1 = pManifest->addParameter();
q1->setId("q1");
q1->setName(QObject::tr("Q 1"));
q1->setShortName(QObject::tr("Q 1"));
q1->setDescription(QObject::tr(
- "Controls the bandwidth of Filter 1.\n"
- "A lower Q affects a wider band of frequencies,\n"
- "a higher Q affects a narrower band of frequencies."));
- q1->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR);
- q1->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- q1->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
+ "Controls the bandwidth of Filter 1.\n"
+ "A lower Q affects a wider band of frequencies,\n"
+ "a higher Q affects a narrower band of frequencies."));
+ q1->setValueScaler(EffectManifestParameter::ValueScaler::Linear);
+ q1->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
q1->setNeutralPointOnScale(0.5);
- q1->setDefault(1.75);
- q1->setMinimum(0.5);
- q1->setMaximum(3.0);
+ q1->setRange(0.5, 1.75, 3.0);
EffectManifestParameterPointer center1 = pManifest->addParameter();
center1->setId("center1");
center1->setName(QObject::tr("Center 1"));
center1->setShortName(QObject::tr("Center 1"));
center1->setDescription(QObject::tr(
- "Center frequency for Filter 1, from 100 Hz to 14 kHz"));
- center1->setControlHint(EffectManifestParameter::ControlHint::KNOB_LOGARITHMIC);
- center1->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- center1->setUnitsHint(EffectManifestParameter::UnitsHint::HERTZ);
+ "Center frequency for Filter 1, from 100 Hz to 14 kHz"));
+ center1->setValueScaler(EffectManifestParameter::ValueScaler::Logarithmic);
+ center1->setUnitsHint(EffectManifestParameter::UnitsHint::Hertz);
center1->setNeutralPointOnScale(0.5);
- center1->setDefault(kDefaultCenter1);
- center1->setMinimum(100);
- center1->setMaximum(14000);
+ center1->setRange(100, kDefaultCenter1, 14000);
EffectManifestParameterPointer gain2 = pManifest->addParameter();
gain2->setId("gain2");
gain2->setName(QObject::tr("Gain 2"));
gain2->setShortName(QObject::tr("Gain 2"));
gain2->setDescription(QObject::tr(
- "Gain for Filter 2"));
- gain2->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR);
- gain2->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- gain2->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
+ "Gain for Filter 2"));
+ gain2->setValueScaler(EffectManifestParameter::ValueScaler::Linear);
+ gain2->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
gain2->setNeutralPointOnScale(0.5);
- gain2->setDefault(0);
- gain2->setMinimum(-18);
- gain2->setMaximum(18); // dB
+ gain2->setRange(-18, 0, 18); // dB
EffectManifestParameterPointer q2 = pManifest->addParameter();
q2->setId("q2");
q2->setName(QObject::tr("Q 2"));
q2->setShortName(QObject::tr("Q 2"));
q2->setDescription(QObject::tr(
- "Controls the bandwidth of Filter 2.\n"
- "A lower Q affects a wider band of frequencies,\n"
- "a higher Q affects a narrower band of frequencies."));
- q2->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR);
- q2->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- q2->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
+ "Controls the bandwidth of Filter 2.\n"
+ "A lower Q affects a wider band of frequencies,\n"
+ "a higher Q affects a narrower band of frequencies."));
+ q2->setValueScaler(EffectManifestParameter::ValueScaler::Linear);
+ q2->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
q2->setNeutralPointOnScale(0.5);
- q2->setDefault(1.75);
- q2->setMinimum(0.5);
- q2->setMaximum(3.0);
+ q2->setRange(0.5, 1.75, 3.0);
EffectManifestParameterPointer center2 = pManifest->addParameter();
center2->setId("center2");
center2->setName(QObject::tr("Center 2"));
center2->setShortName(QObject::tr("Center 2"));
center2->setDescription(QObject::tr(
- "Center frequency for Filter 2, from 100 Hz to 14 kHz"));
- center2->setControlHint(EffectManifestParameter::ControlHint::KNOB_LOGARITHMIC);
- center2->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- center2->setUnitsHint(EffectManifestParameter::UnitsHint::HERTZ);
+ "Center frequency for Filter 2, from 100 Hz to 14 kHz"));
+ center2->setValueScaler(EffectManifestParameter::ValueScaler::Logarithmic);
+ center2->setUnitsHint(EffectManifestParameter::UnitsHint::Hertz);
center2->setNeutralPointOnScale(0.5);
- center2->setDefault(kDefaultCenter2);
- center2->setMinimum(100);
- center2->setMaximum(14000);
+ center2->setRange(100, kDefaultCenter2, 14000);
return pManifest;
}
ParametricEQEffectGroupState::ParametricEQEffectGroupState(
- const mixxx::EngineParameters& bufferParameters)
- : EffectState(bufferParameters) {
+ const mixxx::EngineParameters& engineParameters)
+ : EffectState(engineParameters),
+ m_oldSampleRate(44100) {
for (int i = 0; i < kBandCount; i++) {
m_oldGain.append(1.0);
m_oldQ.append(1.75);
@@ -131,7 +115,7 @@ ParametricEQEffectGroupState::ParametricEQEffectGroupState(
// Initialize the filters with default parameters
for (int i = 0; i < kBandCount; i++) {
m_bands.push_back(std::make_unique(
- bufferParameters.sampleRate(), m_oldCenter[i], m_oldQ[i]));
+ engineParameters.sampleRate(), m_oldCenter[i], m_oldQ[i]));
}
}
@@ -142,33 +126,33 @@ void ParametricEQEffectGroupState::setFilters(int sampleRate) {
}
}
-ParametricEQEffect::ParametricEQEffect(EngineEffect* pEffect)
- : m_oldSampleRate(44100) {
- m_pPotGain.append(pEffect->getParameterById("gain1"));
- m_pPotQ.append(pEffect->getParameterById("q1"));
- m_pPotCenter.append(pEffect->getParameterById("center1"));
- m_pPotGain.append(pEffect->getParameterById("gain2"));
- m_pPotQ.append(pEffect->getParameterById("q2"));
- m_pPotCenter.append(pEffect->getParameterById("center2"));
+void ParametricEQEffect::loadEngineEffectParameters(
+ const QMap& parameters) {
+ m_pPotGain.append(parameters.value("gain1"));
+ m_pPotQ.append(parameters.value("q1"));
+ m_pPotCenter.append(parameters.value("center1"));
+ m_pPotGain.append(parameters.value("gain2"));
+ m_pPotQ.append(parameters.value("q2"));
+ m_pPotCenter.append(parameters.value("center2"));
}
ParametricEQEffect::~ParametricEQEffect() {
}
-void ParametricEQEffect::processChannel(const ChannelHandle& handle,
- ParametricEQEffectGroupState* pState,
- const CSAMPLE* pInput, CSAMPLE* pOutput,
- const mixxx::EngineParameters& bufferParameters,
- const EffectEnableState enableState,
- const GroupFeatureState& groupFeatures) {
- Q_UNUSED(handle);
+void ParametricEQEffect::processChannel(
+ ParametricEQEffectGroupState* pState,
+ const CSAMPLE* pInput,
+ CSAMPLE* pOutput,
+ const mixxx::EngineParameters& engineParameters,
+ const EffectEnableState enableState,
+ const GroupFeatureState& groupFeatures) {
Q_UNUSED(groupFeatures);
// If the sample rate has changed, initialize the filters using the new
// sample rate
- if (m_oldSampleRate != bufferParameters.sampleRate()) {
- m_oldSampleRate = bufferParameters.sampleRate();
- pState->setFilters(bufferParameters.sampleRate());
+ if (pState->m_oldSampleRate != engineParameters.sampleRate()) {
+ pState->m_oldSampleRate = engineParameters.sampleRate();
+ pState->setFilters(engineParameters.sampleRate());
}
CSAMPLE_GAIN fGain[2];
@@ -188,24 +172,24 @@ void ParametricEQEffect::processChannel(const ChannelHandle& handle,
fQ[i] != pState->m_oldQ[i] ||
fCenter[i] != pState->m_oldCenter[i]) {
pState->m_bands[i]->setFrequencyCorners(
- bufferParameters.sampleRate(), fCenter[i], fQ[i], fGain[i]);
+ engineParameters.sampleRate(), fCenter[i], fQ[i], fGain[i]);
}
}
if (fGain[0] != 0) {
- pState->m_bands[0]->process(pInput, pOutput, bufferParameters.samplesPerBuffer());
+ pState->m_bands[0]->process(pInput, pOutput, engineParameters.samplesPerBuffer());
if (fGain[1] != 0) {
- pState->m_bands[1]->process(pOutput, pOutput, bufferParameters.samplesPerBuffer());
+ pState->m_bands[1]->process(pOutput, pOutput, engineParameters.samplesPerBuffer());
} else {
pState->m_bands[1]->pauseFilter();
}
} else {
pState->m_bands[0]->pauseFilter();
if (fGain[1] != 0) {
- pState->m_bands[1]->process(pInput, pOutput, bufferParameters.samplesPerBuffer());
+ pState->m_bands[1]->process(pInput, pOutput, engineParameters.samplesPerBuffer());
} else {
pState->m_bands[1]->pauseFilter();
- SampleUtil::copy(pOutput, pInput, bufferParameters.samplesPerBuffer());
+ SampleUtil::copy(pOutput, pInput, engineParameters.samplesPerBuffer());
}
}
diff --git a/src/effects/builtin/parametriceqeffect.h b/src/effects/backends/builtin/parametriceqeffect.h
similarity index 53%
rename from src/effects/builtin/parametriceqeffect.h
rename to src/effects/backends/builtin/parametriceqeffect.h
index b41a4511870..eae3ecff4e3 100644
--- a/src/effects/builtin/parametriceqeffect.h
+++ b/src/effects/backends/builtin/parametriceqeffect.h
@@ -1,64 +1,73 @@
#pragma once
-#include
#include
+#include
+#include "audio/types.h"
#include "control/controlproxy.h"
-#include "effects/effect.h"
-#include "effects/effectprocessor.h"
+#include "effects/backends/effectprocessor.h"
#include "engine/effects/engineeffect.h"
#include "engine/effects/engineeffectparameter.h"
#include "engine/filters/enginefilterbiquad1.h"
#include "util/class.h"
#include "util/defs.h"
+#include "util/memory.h"
#include "util/sample.h"
#include "util/types.h"
-#include "util/memory.h"
// The ParametricEQEffect models the mid bands from a SSL Black EQ (242)
// with a gentle parameter range, as requested here:
-// https://www.mixxx.org/forums/viewtopic.php?f=3&t=9239&p=33312&hilit=SSL#p33312
+// https://mixxx.discourse.group/t/sending-output-via-a-software-equalizer/16718/10#p33312
// The main use case is to tweak the room or recording sound, which is hard to achieve
// with the sharp and wide curves of the mixing EQs.
class ParametricEQEffectGroupState final : public EffectState {
public:
- ParametricEQEffectGroupState(const mixxx::EngineParameters& bufferParameters);
+ ParametricEQEffectGroupState(const mixxx::EngineParameters& engineParameters);
void setFilters(int sampleRate);
+ // These containers are only appended in the constructor which is called on
+ // the main thread, so there is no risk of allocation in the audio thread.
std::vector > m_bands;
QList m_oldGain;
QList m_oldCenter;
QList m_oldQ;
+ mixxx::audio::SampleRate m_oldSampleRate;
+
QList m_pBufs;
};
class ParametricEQEffect : public EffectProcessorImpl {
public:
- ParametricEQEffect(EngineEffect* pEffect);
+ ParametricEQEffect() = default;
virtual ~ParametricEQEffect();
static QString getId();
static EffectManifestPointer getManifest();
- // See effectprocessor.h
- void processChannel(const ChannelHandle& handle,
- ParametricEQEffectGroupState* pState,
- const CSAMPLE* pInput, CSAMPLE *pOutput,
- const mixxx::EngineParameters& bufferParameters,
- const EffectEnableState enableState,
- const GroupFeatureState& groupFeatureState);
+ void loadEngineEffectParameters(
+ const QMap& parameters) override;
+
+ void processChannel(
+ ParametricEQEffectGroupState* pState,
+ const CSAMPLE* pInput,
+ CSAMPLE* pOutput,
+ const mixxx::EngineParameters& engineParameters,
+ const EffectEnableState enableState,
+ const GroupFeatureState& groupFeatureState) override;
private:
QString debugString() const {
return getId();
}
- QList m_pPotGain;
- QList m_pPotQ;
- QList m_pPotCenter;
+ // These QLists are only appended on the main thread in loadEngineEffectParameters,
+ // so there is no risk of allocation in the audio thread.
+ QList m_pPotGain;
+ QList m_pPotQ;
+ QList m_pPotCenter;
mixxx::audio::SampleRate m_oldSampleRate;
diff --git a/src/effects/builtin/phasereffect.cpp b/src/effects/backends/builtin/phasereffect.cpp
similarity index 58%
rename from src/effects/builtin/phasereffect.cpp
rename to src/effects/backends/builtin/phasereffect.cpp
index defd40a6a26..a2d90786dca 100644
--- a/src/effects/builtin/phasereffect.cpp
+++ b/src/effects/backends/builtin/phasereffect.cpp
@@ -1,4 +1,4 @@
-#include "effects/builtin/phasereffect.h"
+#include "effects/backends/builtin/phasereffect.h"
#include
@@ -21,8 +21,8 @@ EffectManifestPointer PhaserEffect::getManifest() {
pManifest->setAuthor("The Mixxx Team");
pManifest->setVersion("1.0");
pManifest->setDescription(QObject::tr(
- "Mixes the input signal with a copy passed through a series of "
- "all-pass filters to create comb filtering"));
+ "Mixes the input signal with a copy passed through a series of "
+ "all-pass filters to create comb filtering"));
pManifest->setEffectRampsFromDry(true);
EffectManifestParameterPointer period = pManifest->addParameter();
@@ -30,120 +30,100 @@ EffectManifestPointer PhaserEffect::getManifest() {
period->setName(QObject::tr("Period"));
period->setShortName(QObject::tr("Period"));
period->setDescription(QObject::tr(
- "Period of the LFO (low frequency oscillator)\n"
- "1/4 - 4 beats rounded to 1/2 beat if tempo is detected\n"
- "1/4 - 4 seconds if no tempo is detected"));
- period->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR);
- period->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- period->setUnitsHint(EffectManifestParameter::UnitsHint::BEATS);
- period->setMinimum(0.0);
- period->setMaximum(4.0);
- period->setDefault(1.0);
+ "Period of the LFO (low frequency oscillator)\n"
+ "1/4 - 4 beats rounded to 1/2 beat if tempo is detected\n"
+ "1/4 - 4 seconds if no tempo is detected"));
+ period->setValueScaler(EffectManifestParameter::ValueScaler::Linear);
+ period->setUnitsHint(EffectManifestParameter::UnitsHint::Beats);
+ period->setRange(0.0, 1.0, 4.0);
EffectManifestParameterPointer fb = pManifest->addParameter();
fb->setId("feedback");
fb->setName(QObject::tr("Feedback"));
fb->setShortName(QObject::tr("Feedback"));
fb->setDescription(QObject::tr(
- "Controls how much of the output signal is looped"));
- fb->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR);
- fb->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- fb->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- fb->setMinimum(-1.0);
- fb->setMaximum(1.0);
- fb->setDefault(0.0);
+ "Controls how much of the output signal is looped"));
+ fb->setValueScaler(EffectManifestParameter::ValueScaler::Linear);
+ fb->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ fb->setRange(-1.0, 0.0, 1.0);
EffectManifestParameterPointer range = pManifest->addParameter();
range->setId("range");
range->setName(QObject::tr("Range"));
range->setShortName(QObject::tr("Range"));
range->setDescription(QObject::tr(
- "Controls the frequency range across which the notches sweep."));
- range->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR);
- range->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- range->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- range->setMinimum(0.05);
- range->setMaximum(1.0);
- range->setDefault(1.0);
+ "Controls the frequency range across which the notches sweep."));
+ range->setValueScaler(EffectManifestParameter::ValueScaler::Linear);
+ range->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ range->setRange(0.05, 1.0, 1.0);
EffectManifestParameterPointer stages = pManifest->addParameter();
stages->setId("stages");
stages->setName(QObject::tr("Stages"));
stages->setShortName(QObject::tr("Stages"));
stages->setDescription(QObject::tr(
- "Number of stages")); // stages of what?
- stages->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR);
- stages->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- stages->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- stages->setMinimum(1.0);
- stages->setMaximum(6.0);
- stages->setDefault(3.5);
+ "Number of stages")); // stages of what?
+ stages->setValueScaler(EffectManifestParameter::ValueScaler::Linear);
+ stages->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ stages->setRange(1.0, 3.5, 6.0);
EffectManifestParameterPointer depth = pManifest->addParameter();
depth->setId("depth");
depth->setName(QObject::tr("Depth"));
depth->setShortName(QObject::tr("Depth"));
depth->setDescription(QObject::tr(
- "Intensity of the effect"));
- depth->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR);
- depth->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- depth->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- depth->setDefaultLinkType(EffectManifestParameter::LinkType::LINKED);
- depth->setMinimum(0.5);
- depth->setMaximum(1.0);
- depth->setDefault(0.5);
+ "Intensity of the effect"));
+ depth->setValueScaler(EffectManifestParameter::ValueScaler::Linear);
+ depth->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ depth->setDefaultLinkType(EffectManifestParameter::LinkType::Linked);
+ depth->setRange(0.5, 0.5, 1.0);
EffectManifestParameterPointer triplet = pManifest->addParameter();
triplet->setId("triplet");
triplet->setName(QObject::tr("Triplets"));
triplet->setShortName(QObject::tr("Triplets"));
triplet->setDescription(QObject::tr(
- "Divide rounded 1/2 beats of the Period parameter by 3."));
- triplet->setControlHint(EffectManifestParameter::ControlHint::TOGGLE_STEPPING);
- triplet->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- triplet->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- triplet->setDefault(0);
- triplet->setMinimum(0);
- triplet->setMaximum(1);
+ "Divide rounded 1/2 beats of the Period parameter by 3."));
+ triplet->setValueScaler(EffectManifestParameter::ValueScaler::Toggle);
+ triplet->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ triplet->setRange(0, 0, 1);
EffectManifestParameterPointer stereo = pManifest->addParameter();
stereo->setId("stereo");
stereo->setName(QObject::tr("Stereo"));
stereo->setShortName(QObject::tr("Stereo"));
stereo->setDescription(QObject::tr(
- "Sets the LFOs (low frequency oscillators) for the left and right channels out of phase with each others"));
- stereo->setControlHint(EffectManifestParameter::ControlHint::TOGGLE_STEPPING);
- stereo->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- stereo->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- stereo->setMinimum(0);
- stereo->setMaximum(1);
- stereo->setDefault(0);
+ "Sets the LFOs (low frequency oscillators) for the left and right "
+ "channels out of phase with each others"));
+ stereo->setValueScaler(EffectManifestParameter::ValueScaler::Toggle);
+ stereo->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ stereo->setRange(0, 0, 1);
return pManifest;
}
-PhaserEffect::PhaserEffect(EngineEffect* pEffect)
- : m_pStagesParameter(pEffect->getParameterById("stages")),
- m_pLFOPeriodParameter(pEffect->getParameterById("lfo_period")),
- m_pDepthParameter(pEffect->getParameterById("depth")),
- m_pFeedbackParameter(pEffect->getParameterById("feedback")),
- m_pRangeParameter(pEffect->getParameterById("range")),
- m_pTripletParameter(pEffect->getParameterById("triplet")),
- m_pStereoParameter(pEffect->getParameterById("stereo")) {
+void PhaserEffect::loadEngineEffectParameters(
+ const QMap& parameters) {
+ m_pStagesParameter = parameters.value("stages");
+ m_pLFOPeriodParameter = parameters.value("lfo_period");
+ m_pDepthParameter = parameters.value("depth");
+ m_pFeedbackParameter = parameters.value("feedback");
+ m_pRangeParameter = parameters.value("range");
+ m_pTripletParameter = parameters.value("triplet");
+ m_pStereoParameter = parameters.value("stereo");
}
PhaserEffect::~PhaserEffect() {
//qDebug() << debugString() << "destroyed";
}
-void PhaserEffect::processChannel(const ChannelHandle& handle,
- PhaserGroupState* pState,
- const CSAMPLE* pInput, CSAMPLE* pOutput,
- const mixxx::EngineParameters& bufferParameters,
- const EffectEnableState enableState,
- const GroupFeatureState& groupFeatures) {
- Q_UNUSED(handle);
-
+void PhaserEffect::processChannel(
+ PhaserGroupState* pState,
+ const CSAMPLE* pInput,
+ CSAMPLE* pOutput,
+ const mixxx::EngineParameters& engineParameters,
+ const EffectEnableState enableState,
+ const GroupFeatureState& groupFeatures) {
if (enableState == EffectEnableState::Enabling) {
pState->clear();
}
@@ -157,14 +137,15 @@ void PhaserEffect::processChannel(const ChannelHandle& handle,
double periodSamples;
if (groupFeatures.has_beat_length_sec) {
// periodParameter is a number of beats
- periodParameter = std::max(roundToFraction(periodParameter, 2.0), 1/4.0);
+ periodParameter = std::max(roundToFraction(periodParameter, 2.0), 1 / 4.0);
if (m_pTripletParameter->toBool()) {
periodParameter /= 3.0;
}
- periodSamples = periodParameter * groupFeatures.beat_length_sec * bufferParameters.sampleRate();
+ periodSamples = periodParameter * groupFeatures.beat_length_sec *
+ engineParameters.sampleRate();
} else {
// periodParameter is a number of seconds
- periodSamples = std::max(periodParameter, 1/4.0) * bufferParameters.sampleRate();
+ periodSamples = std::max(periodParameter, 1 / 4.0) * engineParameters.sampleRate();
}
// freqSkip is used to calculate the phase independently for each channel,
// so do not multiply periodSamples by the number of channels.
@@ -186,16 +167,15 @@ void PhaserEffect::processChannel(const ChannelHandle& handle,
CSAMPLE left = 0, right = 0;
CSAMPLE_GAIN oldDepth = pState->oldDepth;
- const CSAMPLE_GAIN depthDelta = (depth - oldDepth)
- / bufferParameters.framesPerBuffer();
+ const CSAMPLE_GAIN depthDelta = (depth - oldDepth) / engineParameters.framesPerBuffer();
const CSAMPLE_GAIN depthStart = oldDepth + depthDelta;
const auto stereoCheck = static_cast(m_pStereoParameter->value());
int counter = 0;
for (SINT i = 0;
- i < bufferParameters.samplesPerBuffer();
- i += bufferParameters.channelCount()) {
+ i < engineParameters.samplesPerBuffer();
+ i += engineParameters.channelCount()) {
left = pInput[i] + std::tanh(left * feedback);
right = pInput[i + 1] + std::tanh(right * feedback);
@@ -226,7 +206,7 @@ void PhaserEffect::processChannel(const ChannelHandle& handle,
left = processSample(left, oldInLeft, oldOutLeft, filterCoefLeft, stages);
right = processSample(right, oldInRight, oldOutRight, filterCoefRight, stages);
- const CSAMPLE_GAIN depth = depthStart + depthDelta * (i / bufferParameters.channelCount());
+ const CSAMPLE_GAIN depth = depthStart + depthDelta * (i / engineParameters.channelCount());
// Computing output combining the original and processed sample
pOutput[i] = pInput[i] * (1.0f - 0.5f * depth) + left * depth * 0.5f;
diff --git a/src/effects/builtin/phasereffect.h b/src/effects/backends/builtin/phasereffect.h
similarity index 55%
rename from src/effects/builtin/phasereffect.h
rename to src/effects/backends/builtin/phasereffect.h
index bc71a0f7865..1e6312f840d 100644
--- a/src/effects/builtin/phasereffect.h
+++ b/src/effects/backends/builtin/phasereffect.h
@@ -1,6 +1,6 @@
#pragma once
-#include "effects/effectprocessor.h"
+#include "effects/backends/effectprocessor.h"
#include "engine/effects/engineeffect.h"
#include "engine/effects/engineeffectparameter.h"
#include "util/class.h"
@@ -12,8 +12,8 @@
class PhaserGroupState final : public EffectState {
public:
- PhaserGroupState(const mixxx::EngineParameters& bufferParameters)
- : EffectState(bufferParameters) {
+ PhaserGroupState(const mixxx::EngineParameters& engineParameters)
+ : EffectState(engineParameters) {
clear();
}
@@ -34,42 +34,46 @@ class PhaserGroupState final : public EffectState {
CSAMPLE leftPhase;
CSAMPLE rightPhase;
CSAMPLE_GAIN oldDepth;
-
};
class PhaserEffect : public EffectProcessorImpl {
-
public:
- PhaserEffect(EngineEffect* pEffect);
+ PhaserEffect() = default;
virtual ~PhaserEffect();
static QString getId();
static EffectManifestPointer getManifest();
- // See effectprocessor.h
- void processChannel(const ChannelHandle& handle,
- PhaserGroupState* pState,
- const CSAMPLE* pInput, CSAMPLE* pOutput,
- const mixxx::EngineParameters& bufferParameters,
- const EffectEnableState enableState,
- const GroupFeatureState& groupFeatures);
+ void loadEngineEffectParameters(
+ const QMap& parameters) override;
+
+ void processChannel(
+ PhaserGroupState* pState,
+ const CSAMPLE* pInput,
+ CSAMPLE* pOutput,
+ const mixxx::EngineParameters& engineParameters,
+ const EffectEnableState enableState,
+ const GroupFeatureState& groupFeatures) override;
private:
QString debugString() const {
return getId();
}
- EngineEffectParameter* m_pStagesParameter;
- EngineEffectParameter* m_pLFOPeriodParameter;
- EngineEffectParameter* m_pDepthParameter;
- EngineEffectParameter* m_pFeedbackParameter;
- EngineEffectParameter* m_pRangeParameter;
- EngineEffectParameter* m_pTripletParameter;
- EngineEffectParameter* m_pStereoParameter;
+ EngineEffectParameterPointer m_pStagesParameter;
+ EngineEffectParameterPointer m_pLFOPeriodParameter;
+ EngineEffectParameterPointer m_pDepthParameter;
+ EngineEffectParameterPointer m_pFeedbackParameter;
+ EngineEffectParameterPointer m_pRangeParameter;
+ EngineEffectParameterPointer m_pTripletParameter;
+ EngineEffectParameterPointer m_pStereoParameter;
//Passing the sample through a series of allpass filters
- inline CSAMPLE processSample(CSAMPLE input, CSAMPLE* oldIn, CSAMPLE* oldOut,
- CSAMPLE mainCoef, int stages) {
+ inline CSAMPLE processSample(CSAMPLE input,
+ CSAMPLE* oldIn,
+ CSAMPLE* oldOut,
+ CSAMPLE mainCoef,
+ int stages) {
for (int j = 0; j < stages; j++) {
oldOut[j] = (mainCoef * input) + (mainCoef * oldOut[j]) - oldIn[j];
oldIn[j] = input;
diff --git a/src/effects/backends/builtin/reverbeffect.cpp b/src/effects/backends/builtin/reverbeffect.cpp
new file mode 100644
index 00000000000..eb6cf0081cd
--- /dev/null
+++ b/src/effects/backends/builtin/reverbeffect.cpp
@@ -0,0 +1,125 @@
+#include "effects/backends/builtin/reverbeffect.h"
+
+#include
+
+#include "util/sample.h"
+
+// static
+QString ReverbEffect::getId() {
+ return "org.mixxx.effects.reverb";
+}
+
+// static
+EffectManifestPointer ReverbEffect::getManifest() {
+ EffectManifestPointer pManifest(new EffectManifest());
+ pManifest->setAddDryToWet(true);
+ pManifest->setEffectRampsFromDry(true);
+
+ pManifest->setId(getId());
+ pManifest->setName(QObject::tr("Reverb"));
+ pManifest->setAuthor("The Mixxx Team, CAPS Plugins");
+ pManifest->setVersion("1.0");
+ pManifest->setDescription(QObject::tr(
+ "Emulates the sound of the signal bouncing off the walls of a room"));
+
+ EffectManifestParameterPointer decay = pManifest->addParameter();
+ decay->setId("decay");
+ decay->setName(QObject::tr("Decay"));
+ decay->setShortName(QObject::tr("Decay"));
+ decay->setDescription(QObject::tr(
+ "Lower decay values cause reverberations to fade out more quickly."));
+ decay->setValueScaler(EffectManifestParameter::ValueScaler::Linear);
+ decay->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ decay->setRange(0, 0.5, 1);
+
+ EffectManifestParameterPointer bandwidth = pManifest->addParameter();
+ bandwidth->setId("bandwidth");
+ bandwidth->setName(QObject::tr("Bandwidth"));
+ bandwidth->setShortName(QObject::tr("BW"));
+ bandwidth->setDescription(QObject::tr(
+ "Bandwidth of the low pass filter at the input.\n"
+ "Higher values result in less attenuation of high frequencies."));
+ bandwidth->setValueScaler(EffectManifestParameter::ValueScaler::Linear);
+ bandwidth->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ bandwidth->setRange(0, 1, 1);
+
+ EffectManifestParameterPointer damping = pManifest->addParameter();
+ damping->setId("damping");
+ damping->setName(QObject::tr("Damping"));
+ damping->setShortName(QObject::tr("Damping"));
+ damping->setDescription(
+ QObject::tr("Higher damping values cause high frequencies to decay "
+ "more quickly than low frequencies."));
+ damping->setValueScaler(EffectManifestParameter::ValueScaler::Linear);
+ damping->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ damping->setRange(0, 0, 1);
+
+ EffectManifestParameterPointer send = pManifest->addParameter();
+ send->setId("send_amount");
+ send->setName(QObject::tr("Send"));
+ send->setShortName(QObject::tr("Send"));
+ send->setDescription(QObject::tr(
+ "How much of the signal to send in to the effect"));
+ send->setValueScaler(EffectManifestParameter::ValueScaler::Linear);
+ send->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ send->setDefaultLinkType(EffectManifestParameter::LinkType::Linked);
+ send->setDefaultLinkInversion(EffectManifestParameter::LinkInversion::NotInverted);
+ send->setRange(0, 0, 1);
+
+ return pManifest;
+}
+
+void ReverbEffect::loadEngineEffectParameters(
+ const QMap& parameters) {
+ m_pDecayParameter = parameters.value("decay");
+ m_pBandWidthParameter = parameters.value("bandwidth");
+ m_pDampingParameter = parameters.value("damping");
+ m_pSendParameter = parameters.value("send_amount");
+}
+
+ReverbEffect::~ReverbEffect() {
+ //qDebug() << debugString() << "destroyed";
+}
+
+void ReverbEffect::processChannel(
+ ReverbGroupState* pState,
+ const CSAMPLE* pInput,
+ CSAMPLE* pOutput,
+ const mixxx::EngineParameters& engineParameters,
+ const EffectEnableState enableState,
+ const GroupFeatureState& groupFeatures) {
+ Q_UNUSED(groupFeatures);
+
+ const auto decay = static_cast(m_pDecayParameter->value());
+ const auto bandwidth = static_cast(m_pBandWidthParameter->value());
+ const auto damping = static_cast(m_pDampingParameter->value());
+ const auto sendCurrent = static_cast(m_pSendParameter->value());
+
+ // Reinitialize the effect when turning it on to prevent replaying the old buffer
+ // from the last time the effect was enabled.
+ // Also, update the sample rate if it has changed.
+ if (enableState == EffectEnableState::Enabling ||
+ pState->sampleRate != engineParameters.sampleRate()) {
+ pState->reverb.init(engineParameters.sampleRate());
+ pState->sampleRate = engineParameters.sampleRate();
+ }
+
+ pState->reverb.processBuffer(pInput,
+ pOutput,
+ engineParameters.samplesPerBuffer(),
+ bandwidth,
+ decay,
+ damping,
+ sendCurrent,
+ pState->sendPrevious);
+
+ // The ramping of the send parameter handles ramping when enabling, so
+ // this effect must handle ramping to dry when disabling itself (instead
+ // of being handled by EngineEffect::process).
+ if (enableState == EffectEnableState::Disabling) {
+ SampleUtil::applyRampingGain(pOutput, 1.0, 0.0, engineParameters.samplesPerBuffer());
+ pState->sendPrevious = 0;
+ } else {
+ pState->sendPrevious = sendCurrent;
+ }
+}
diff --git a/src/effects/backends/builtin/reverbeffect.h b/src/effects/backends/builtin/reverbeffect.h
new file mode 100644
index 00000000000..d3bd1d7ceae
--- /dev/null
+++ b/src/effects/backends/builtin/reverbeffect.h
@@ -0,0 +1,66 @@
+// Ported from CAPS Reverb.
+// This effect is GPL code.
+
+#pragma once
+
+#include
+
+#include
+
+#include "effects/backends/effectprocessor.h"
+#include "engine/effects/engineeffect.h"
+#include "engine/effects/engineeffectparameter.h"
+#include "util/class.h"
+#include "util/defs.h"
+#include "util/sample.h"
+#include "util/types.h"
+
+class ReverbGroupState : public EffectState {
+ public:
+ ReverbGroupState(const mixxx::EngineParameters& engineParameters)
+ : EffectState(engineParameters),
+ sampleRate(engineParameters.sampleRate()),
+ sendPrevious(0) {
+ }
+
+ void engineParametersChanged(const mixxx::EngineParameters& engineParameters) {
+ sampleRate = engineParameters.sampleRate();
+ sendPrevious = 0;
+ }
+
+ float sampleRate;
+ float sendPrevious;
+ MixxxPlateX2 reverb{};
+};
+
+class ReverbEffect : public EffectProcessorImpl {
+ public:
+ ReverbEffect() = default;
+ virtual ~ReverbEffect();
+
+ static QString getId();
+ static EffectManifestPointer getManifest();
+
+ void loadEngineEffectParameters(
+ const QMap& parameters) override;
+
+ void processChannel(
+ ReverbGroupState* pState,
+ const CSAMPLE* pInput,
+ CSAMPLE* pOutput,
+ const mixxx::EngineParameters& engineParameters,
+ const EffectEnableState enableState,
+ const GroupFeatureState& groupFeatures) override;
+
+ private:
+ QString debugString() const {
+ return getId();
+ }
+
+ EngineEffectParameterPointer m_pDecayParameter;
+ EngineEffectParameterPointer m_pBandWidthParameter;
+ EngineEffectParameterPointer m_pDampingParameter;
+ EngineEffectParameterPointer m_pSendParameter;
+
+ DISALLOW_COPY_AND_ASSIGN(ReverbEffect);
+};
diff --git a/src/effects/builtin/threebandbiquadeqeffect.cpp b/src/effects/backends/builtin/threebandbiquadeqeffect.cpp
similarity index 75%
rename from src/effects/builtin/threebandbiquadeqeffect.cpp
rename to src/effects/backends/builtin/threebandbiquadeqeffect.cpp
index a2ceee06411..26bec1c134f 100644
--- a/src/effects/builtin/threebandbiquadeqeffect.cpp
+++ b/src/effects/backends/builtin/threebandbiquadeqeffect.cpp
@@ -1,6 +1,6 @@
-#include "effects/builtin/threebandbiquadeqeffect.h"
+#include "effects/backends/builtin/threebandbiquadeqeffect.h"
-#include "effects/builtin/equalizer_util.h"
+#include "effects/backends/builtin/equalizer_util.h"
#include "util/math.h"
namespace {
@@ -19,7 +19,6 @@ static constexpr double kQKillShelve = 0.4;
static constexpr double kBoostGain = 12;
static constexpr double kKillGain = -26;
-
double getCenterFrequency(double low, double high) {
double scaleLow = log10(low);
double scaleHigh = log10(high);
@@ -28,7 +27,7 @@ double getCenterFrequency(double low, double high) {
return pow(10, scaleCenter);
}
-double knobValueToBiquadGainDb (double value, bool kill) {
+double knobValueToBiquadGainDb(double value, bool kill) {
if (kill) {
return kKillGain;
}
@@ -44,7 +43,6 @@ double knobValueToBiquadGainDb (double value, bool kill) {
} // anonymous namespace
-
// static
QString ThreeBandBiquadEQEffect::getId() {
return "org.mixxx.effects.threebandbiquadeq";
@@ -58,9 +56,10 @@ EffectManifestPointer ThreeBandBiquadEQEffect::getManifest() {
pManifest->setShortName(QObject::tr("BQ EQ"));
pManifest->setAuthor("The Mixxx Team");
pManifest->setVersion("1.0");
- pManifest->setDescription(QObject::tr(
- "A 3-band Equalizer with two biquad bell filters, a shelving high pass and kill switches.") +
- " " + EqualizerUtil::adjustFrequencyShelvesTip());
+ pManifest->setDescription(
+ QObject::tr("A 3-band Equalizer with two biquad bell filters, a "
+ "shelving high pass and kill switches.") +
+ " " + EqualizerUtil::adjustFrequencyShelvesTip());
pManifest->setEffectRampsFromDry(true);
pManifest->setIsMixingEQ(true);
@@ -69,9 +68,9 @@ EffectManifestPointer ThreeBandBiquadEQEffect::getManifest() {
}
ThreeBandBiquadEQEffectGroupState::ThreeBandBiquadEQEffectGroupState(
- const mixxx::EngineParameters& bufferParameters)
- : EffectState(bufferParameters),
- m_tempBuf(bufferParameters.samplesPerBuffer()),
+ const mixxx::EngineParameters& engineParameters)
+ : EffectState(engineParameters),
+ m_tempBuf(engineParameters.samplesPerBuffer()),
m_oldLowBoost(0),
m_oldMidBoost(0),
m_oldHighBoost(0),
@@ -80,22 +79,21 @@ ThreeBandBiquadEQEffectGroupState::ThreeBandBiquadEQEffectGroupState(
m_oldHighCut(0),
m_loFreqCorner(0),
m_highFreqCorner(0),
- m_oldSampleRate(bufferParameters.sampleRate()) {
-
+ m_oldSampleRate(engineParameters.sampleRate()) {
// Initialize the filters with default parameters
m_lowBoost = std::make_unique(
- bufferParameters.sampleRate() , kStartupLoFreq, kQBoost);
+ engineParameters.sampleRate(), kStartupLoFreq, kQBoost);
m_midBoost = std::make_unique(
- bufferParameters.sampleRate() , kStartupMidFreq, kQBoost);
+ engineParameters.sampleRate(), kStartupMidFreq, kQBoost);
m_highBoost = std::make_unique(
- bufferParameters.sampleRate() , kStartupHiFreq, kQBoost);
+ engineParameters.sampleRate(), kStartupHiFreq, kQBoost);
m_lowCut = std::make_unique(
- bufferParameters.sampleRate() , kStartupLoFreq, kQKill);
+ engineParameters.sampleRate(), kStartupLoFreq, kQKill);
m_midCut = std::make_unique(
- bufferParameters.sampleRate() , kStartupMidFreq, kQKill);
+ engineParameters.sampleRate(), kStartupMidFreq, kQKill);
m_highCut = std::make_unique(
- bufferParameters.sampleRate() , kStartupHiFreq / 2, kQKillShelve);
+ engineParameters.sampleRate(), kStartupHiFreq / 2, kQKillShelve);
}
ThreeBandBiquadEQEffectGroupState::~ThreeBandBiquadEQEffectGroupState() {
@@ -103,12 +101,10 @@ ThreeBandBiquadEQEffectGroupState::~ThreeBandBiquadEQEffectGroupState() {
void ThreeBandBiquadEQEffectGroupState::setFilters(
int sampleRate, double lowFreqCorner, double highFreqCorner) {
-
double lowCenter = getCenterFrequency(kMinimumFrequency, lowFreqCorner);
double midCenter = getCenterFrequency(lowFreqCorner, highFreqCorner);
double highCenter = getCenterFrequency(highFreqCorner, kMaximumFrequency);
-
m_lowBoost->setFrequencyCorners(
sampleRate, lowCenter, kQBoost, m_oldLowBoost);
m_midBoost->setFrequencyCorners(
@@ -121,44 +117,46 @@ void ThreeBandBiquadEQEffectGroupState::setFilters(
sampleRate, midCenter, kQKill, m_oldMidCut);
m_highCut->setFrequencyCorners(
sampleRate, highCenter / 2, kQKillShelve, m_oldHighCut);
-
}
-ThreeBandBiquadEQEffect::ThreeBandBiquadEQEffect(EngineEffect* pEffect)
- : m_pPotLow(pEffect->getParameterById("low")),
- m_pPotMid(pEffect->getParameterById("mid")),
- m_pPotHigh(pEffect->getParameterById("high")),
- m_pKillLow(pEffect->getParameterById("killLow")),
- m_pKillMid(pEffect->getParameterById("killMid")),
- m_pKillHigh(pEffect->getParameterById("killHigh")) {
+ThreeBandBiquadEQEffect::ThreeBandBiquadEQEffect() {
m_pLoFreqCorner = std::make_unique("[Mixer Profile]", "LoEQFrequency");
m_pHiFreqCorner = std::make_unique("[Mixer Profile]", "HiEQFrequency");
}
+void ThreeBandBiquadEQEffect::loadEngineEffectParameters(
+ const QMap& parameters) {
+ m_pPotLow = parameters.value("low");
+ m_pPotMid = parameters.value("mid");
+ m_pPotHigh = parameters.value("high");
+ m_pKillLow = parameters.value("killLow");
+ m_pKillMid = parameters.value("killMid");
+ m_pKillHigh = parameters.value("killHigh");
+}
+
ThreeBandBiquadEQEffect::~ThreeBandBiquadEQEffect() {
}
void ThreeBandBiquadEQEffect::processChannel(
- const ChannelHandle& handle,
ThreeBandBiquadEQEffectGroupState* pState,
const CSAMPLE* pInput,
CSAMPLE* pOutput,
- const mixxx::EngineParameters& bufferParameters,
+ const mixxx::EngineParameters& engineParameters,
const EffectEnableState enableState,
const GroupFeatureState& groupFeatures) {
- Q_UNUSED(handle);
Q_UNUSED(groupFeatures);
- if (pState->m_oldSampleRate != bufferParameters.sampleRate() ||
+ if (pState->m_oldSampleRate != engineParameters.sampleRate() ||
(pState->m_loFreqCorner != m_pLoFreqCorner->get()) ||
(pState->m_highFreqCorner != m_pHiFreqCorner->get())) {
pState->m_loFreqCorner = m_pLoFreqCorner->get();
pState->m_highFreqCorner = m_pHiFreqCorner->get();
- pState->m_oldSampleRate = bufferParameters.sampleRate();
- pState->setFilters(bufferParameters.sampleRate(), pState->m_loFreqCorner, pState->m_highFreqCorner);
+ pState->m_oldSampleRate = engineParameters.sampleRate();
+ pState->setFilters(engineParameters.sampleRate(),
+ pState->m_loFreqCorner,
+ pState->m_highFreqCorner);
}
-
// Ramp to dry, when disabling, this will ramp from dry when enabling as well
double bqGainLow = 0;
double bqGainMid = 0;
@@ -214,9 +212,7 @@ void ThreeBandBiquadEQEffect::processChannel(
inBuffer.append(pState->m_tempBuf.data());
outBuffer.append(pOutput);
- }
- else
- {
+ } else {
inBuffer.append(pInput);
outBuffer.append(pOutput);
@@ -243,15 +239,15 @@ void ThreeBandBiquadEQEffect::processChannel(
double lowCenter = getCenterFrequency(
kMinimumFrequency, pState->m_loFreqCorner);
pState->m_lowBoost->setFrequencyCorners(
- bufferParameters.sampleRate(), lowCenter, kQBoost, bqGainLow);
+ engineParameters.sampleRate(), lowCenter, kQBoost, bqGainLow);
pState->m_oldLowBoost = bqGainLow;
}
if (bqGainLow > 0.0) {
pState->m_lowBoost->process(
- inBuffer[bufIndex], outBuffer[bufIndex], bufferParameters.samplesPerBuffer());
+ inBuffer[bufIndex], outBuffer[bufIndex], engineParameters.samplesPerBuffer());
} else {
pState->m_lowBoost->processAndPauseFilter(
- inBuffer[bufIndex], outBuffer[bufIndex], bufferParameters.samplesPerBuffer());
+ inBuffer[bufIndex], outBuffer[bufIndex], engineParameters.samplesPerBuffer());
}
++bufIndex;
} else {
@@ -263,15 +259,15 @@ void ThreeBandBiquadEQEffect::processChannel(
double lowCenter = getCenterFrequency(
kMinimumFrequency, pState->m_loFreqCorner);
pState->m_lowCut->setFrequencyCorners(
- bufferParameters.sampleRate(), lowCenter, kQKill, bqGainLow);
+ engineParameters.sampleRate(), lowCenter, kQKill, bqGainLow);
pState->m_oldLowCut = bqGainLow;
}
if (bqGainLow < 0.0) {
pState->m_lowCut->process(
- inBuffer[bufIndex], outBuffer[bufIndex], bufferParameters.samplesPerBuffer());
+ inBuffer[bufIndex], outBuffer[bufIndex], engineParameters.samplesPerBuffer());
} else {
pState->m_lowCut->processAndPauseFilter(
- inBuffer[bufIndex], outBuffer[bufIndex], bufferParameters.samplesPerBuffer());
+ inBuffer[bufIndex], outBuffer[bufIndex], engineParameters.samplesPerBuffer());
}
++bufIndex;
} else {
@@ -283,36 +279,35 @@ void ThreeBandBiquadEQEffect::processChannel(
double midCenter = getCenterFrequency(
pState->m_loFreqCorner, pState->m_highFreqCorner);
pState->m_midBoost->setFrequencyCorners(
- bufferParameters.sampleRate(), midCenter, kQBoost, bqGainMid);
+ engineParameters.sampleRate(), midCenter, kQBoost, bqGainMid);
pState->m_oldMidBoost = bqGainMid;
}
if (bqGainMid > 0.0) {
pState->m_midBoost->process(
- inBuffer[bufIndex], outBuffer[bufIndex], bufferParameters.samplesPerBuffer());
+ inBuffer[bufIndex], outBuffer[bufIndex], engineParameters.samplesPerBuffer());
} else {
pState->m_midBoost->processAndPauseFilter(
- inBuffer[bufIndex], outBuffer[bufIndex], bufferParameters.samplesPerBuffer());
+ inBuffer[bufIndex], outBuffer[bufIndex], engineParameters.samplesPerBuffer());
}
++bufIndex;
} else {
pState->m_midBoost->pauseFilter();
}
-
if (bqGainMid < 0.0 || pState->m_oldMidCut < 0.0) {
if (bqGainMid != pState->m_oldMidCut) {
double midCenter = getCenterFrequency(
pState->m_loFreqCorner, pState->m_highFreqCorner);
pState->m_midCut->setFrequencyCorners(
- bufferParameters.sampleRate(), midCenter, kQKill, bqGainMid);
+ engineParameters.sampleRate(), midCenter, kQKill, bqGainMid);
pState->m_oldMidCut = bqGainMid;
}
if (bqGainMid < 0.0) {
pState->m_midCut->process(
- inBuffer[bufIndex], outBuffer[bufIndex], bufferParameters.samplesPerBuffer());
+ inBuffer[bufIndex], outBuffer[bufIndex], engineParameters.samplesPerBuffer());
} else {
pState->m_midCut->processAndPauseFilter(
- inBuffer[bufIndex], outBuffer[bufIndex], bufferParameters.samplesPerBuffer());
+ inBuffer[bufIndex], outBuffer[bufIndex], engineParameters.samplesPerBuffer());
}
++bufIndex;
} else {
@@ -324,15 +319,15 @@ void ThreeBandBiquadEQEffect::processChannel(
double highCenter = getCenterFrequency(
pState->m_highFreqCorner, kMaximumFrequency);
pState->m_highBoost->setFrequencyCorners(
- bufferParameters.sampleRate(), highCenter, kQBoost, bqGainHigh);
+ engineParameters.sampleRate(), highCenter, kQBoost, bqGainHigh);
pState->m_oldHighBoost = bqGainHigh;
}
if (bqGainHigh > 0.0) {
pState->m_highBoost->process(
- inBuffer[bufIndex], outBuffer[bufIndex], bufferParameters.samplesPerBuffer());
+ inBuffer[bufIndex], outBuffer[bufIndex], engineParameters.samplesPerBuffer());
} else {
pState->m_highBoost->processAndPauseFilter(
- inBuffer[bufIndex], outBuffer[bufIndex], bufferParameters.samplesPerBuffer());
+ inBuffer[bufIndex], outBuffer[bufIndex], engineParameters.samplesPerBuffer());
}
++bufIndex;
} else {
@@ -344,15 +339,15 @@ void ThreeBandBiquadEQEffect::processChannel(
double highCenter = getCenterFrequency(
pState->m_highFreqCorner, kMaximumFrequency);
pState->m_highCut->setFrequencyCorners(
- bufferParameters.sampleRate(), highCenter / 2, kQKillShelve, bqGainHigh);
+ engineParameters.sampleRate(), highCenter / 2, kQKillShelve, bqGainHigh);
pState->m_oldHighCut = bqGainHigh;
}
if (bqGainHigh < 0.0) {
pState->m_highCut->process(
- inBuffer[bufIndex], outBuffer[bufIndex], bufferParameters.samplesPerBuffer());
+ inBuffer[bufIndex], outBuffer[bufIndex], engineParameters.samplesPerBuffer());
} else {
pState->m_highCut->processAndPauseFilter(
- inBuffer[bufIndex], outBuffer[bufIndex], bufferParameters.samplesPerBuffer());
+ inBuffer[bufIndex], outBuffer[bufIndex], engineParameters.samplesPerBuffer());
}
++bufIndex;
} else {
@@ -360,7 +355,7 @@ void ThreeBandBiquadEQEffect::processChannel(
}
if (activeFilters == 0) {
- SampleUtil::copy(pOutput, pInput, bufferParameters.samplesPerBuffer());
+ SampleUtil::copy(pOutput, pInput, engineParameters.samplesPerBuffer());
}
if (enableState == EffectEnableState::Disabling) {
diff --git a/src/effects/builtin/threebandbiquadeqeffect.h b/src/effects/backends/builtin/threebandbiquadeqeffect.h
similarity index 70%
rename from src/effects/builtin/threebandbiquadeqeffect.h
rename to src/effects/backends/builtin/threebandbiquadeqeffect.h
index 308a3131d2c..5d69d40593d 100644
--- a/src/effects/builtin/threebandbiquadeqeffect.h
+++ b/src/effects/backends/builtin/threebandbiquadeqeffect.h
@@ -1,21 +1,20 @@
#pragma once
#include "control/controlproxy.h"
-#include "effects/effect.h"
-#include "effects/effectprocessor.h"
+#include "effects/backends/effectprocessor.h"
#include "engine/effects/engineeffect.h"
#include "engine/effects/engineeffectparameter.h"
#include "engine/filters/enginefilterbiquad1.h"
#include "util/class.h"
#include "util/defs.h"
-#include "util/sample.h"
-#include "util/types.h"
#include "util/memory.h"
+#include "util/sample.h"
#include "util/samplebuffer.h"
+#include "util/types.h"
class ThreeBandBiquadEQEffectGroupState final : public EffectState {
public:
- ThreeBandBiquadEQEffectGroupState(const mixxx::EngineParameters& bufferParameters);
+ ThreeBandBiquadEQEffectGroupState(const mixxx::EngineParameters& engineParameters);
~ThreeBandBiquadEQEffectGroupState();
void setFilters(
@@ -43,21 +42,24 @@ class ThreeBandBiquadEQEffectGroupState final : public EffectState {
class ThreeBandBiquadEQEffect : public EffectProcessorImpl {
public:
- ThreeBandBiquadEQEffect(EngineEffect* pEffect);
+ ThreeBandBiquadEQEffect();
~ThreeBandBiquadEQEffect() override;
static QString getId();
static EffectManifestPointer getManifest();
- void setFilters(int sampleRate, double lowFreqCorner, double highFreqCorner);
+ void loadEngineEffectParameters(
+ const QMap& parameters) override;
+
+ void processChannel(
+ ThreeBandBiquadEQEffectGroupState* pState,
+ const CSAMPLE* pInput,
+ CSAMPLE* pOutput,
+ const mixxx::EngineParameters& engineParameters,
+ const EffectEnableState enableState,
+ const GroupFeatureState& groupFeatureState) override;
- // See effectprocessor.h
- void processChannel(const ChannelHandle& handle,
- ThreeBandBiquadEQEffectGroupState* pState,
- const CSAMPLE* pInput, CSAMPLE *pOutput,
- const mixxx::EngineParameters& bufferParameters,
- const EffectEnableState enableState,
- const GroupFeatureState& groupFeatureState) override;
+ void setFilters(int sampleRate, double lowFreqCorner, double highFreqCorner);
private:
ThreeBandBiquadEQEffect(const ThreeBandBiquadEQEffect&) = delete;
@@ -67,13 +69,13 @@ class ThreeBandBiquadEQEffect : public EffectProcessorImpl m_pLoFreqCorner;
std::unique_ptr m_pHiFreqCorner;
diff --git a/src/effects/builtin/tremoloeffect.cpp b/src/effects/backends/builtin/tremoloeffect.cpp
similarity index 51%
rename from src/effects/builtin/tremoloeffect.cpp
rename to src/effects/backends/builtin/tremoloeffect.cpp
index 7d116e0b25b..61ae0f641a1 100644
--- a/src/effects/builtin/tremoloeffect.cpp
+++ b/src/effects/backends/builtin/tremoloeffect.cpp
@@ -1,4 +1,4 @@
-#include "effects/builtin/tremoloeffect.h"
+#include "effects/backends/builtin/tremoloeffect.h"
namespace {
// Used to avoid gain discontinuities when changing parameters too fast
@@ -19,134 +19,112 @@ EffectManifestPointer TremoloEffect::getManifest() {
pManifest->setAuthor("The Mixxx Team");
pManifest->setVersion("1.0");
pManifest->setDescription(QObject::tr(
- "Cycles the volume up and down"));
- pManifest->setMetaknobDefault(1.0);
+ "Cycles the volume up and down"));
EffectManifestParameterPointer depth = pManifest->addParameter();
depth->setId("depth");
depth->setName(QObject::tr("Depth"));
depth->setShortName(QObject::tr("Depth"));
depth->setDescription(QObject::tr(
- "How much the effect changes the volume"));
- depth->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR);
- depth->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- depth->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- depth->setDefaultLinkType(EffectManifestParameter::LinkType::LINKED);
- depth->setDefault(1);
- depth->setMinimum(0);
- depth->setMaximum(1);
+ "How much the effect changes the volume"));
+ depth->setValueScaler(EffectManifestParameter::ValueScaler::Linear);
+ depth->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ depth->setDefaultLinkType(EffectManifestParameter::LinkType::Linked);
+ depth->setRange(0, 1, 1);
EffectManifestParameterPointer rate = pManifest->addParameter();
rate->setId("rate");
rate->setName(QObject::tr("Rate"));
rate->setShortName(QObject::tr("Rate"));
rate->setDescription(QObject::tr(
- "Rate of the volume changes\n"
- "4 beats - 1/8 beat if tempo is detected\n"
- "1/4 Hz - 8 Hz if no tempo is detected"));
- rate->setControlHint(
- EffectManifestParameter::ControlHint::KNOB_LOGARITHMIC);
- rate->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- rate->setUnitsHint(EffectManifestParameter::UnitsHint::BEATS);
- rate->setDefault(1);
- rate->setMinimum(1.0/4);
- rate->setMaximum(8);
+ "Rate of the volume changes\n"
+ "4 beats - 1/8 beat if tempo is detected\n"
+ "1/4 Hz - 8 Hz if no tempo is detected"));
+ rate->setValueScaler(
+ EffectManifestParameter::ValueScaler::Logarithmic);
+ rate->setUnitsHint(EffectManifestParameter::UnitsHint::Beats);
+ rate->setRange(1.0 / 4, 1, 8);
EffectManifestParameterPointer width = pManifest->addParameter();
width->setId("width");
width->setName(QObject::tr("Width"));
width->setShortName(QObject::tr("Width"));
width->setDescription(QObject::tr(
- "Width of the volume peak\n"
- "10% - 90% of the effect period"));
- width->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR);
- width->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- width->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- width->setMinimum(0.1);
- width->setDefault(0.5);
- width->setMaximum(0.9);
+ "Width of the volume peak\n"
+ "10% - 90% of the effect period"));
+ width->setValueScaler(EffectManifestParameter::ValueScaler::Linear);
+ width->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ width->setRange(0.1, 0.5, 0.9);
EffectManifestParameterPointer waveform = pManifest->addParameter();
waveform->setId("waveform");
waveform->setName(QObject::tr("Waveform"));
waveform->setShortName(QObject::tr("Waveform"));
waveform->setDescription(QObject::tr(
- "Shape of the volume modulation wave\n"
- "Fully left: Square wave\n"
- "Fully right: Sine wave"));
- waveform->setControlHint(
- EffectManifestParameter::ControlHint::KNOB_LOGARITHMIC);
- waveform->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- waveform->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- waveform->setMinimum(0.005);
- waveform->setDefault(0.5);
- waveform->setMaximum(1);
+ "Shape of the volume modulation wave\n"
+ "Fully left: Square wave\n"
+ "Fully right: Sine wave"));
+ waveform->setValueScaler(
+ EffectManifestParameter::ValueScaler::Logarithmic);
+ waveform->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ waveform->setRange(0.005, 0.5, 1);
EffectManifestParameterPointer phase = pManifest->addParameter();
phase->setId("phase");
phase->setName(QObject::tr("Phase"));
phase->setShortName(QObject::tr("Phase"));
phase->setDescription(QObject::tr(
- "Shifts the position of the volume peak within the period\n"
- "Fully left: beginning of the effect period\n"
- "Fully right: end of the effect period"));
- phase->setControlHint(
- EffectManifestParameter::ControlHint::KNOB_LINEAR);
- phase->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- phase->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- phase->setDefault(0);
- phase->setMinimum(0);
- phase->setMaximum(1);
+ "Shifts the position of the volume peak within the period\n"
+ "Fully left: beginning of the effect period\n"
+ "Fully right: end of the effect period"));
+ phase->setValueScaler(
+ EffectManifestParameter::ValueScaler::Linear);
+ phase->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ phase->setRange(0, 0, 1);
EffectManifestParameterPointer quantize = pManifest->addParameter();
quantize->setId("quantize");
quantize->setName(QObject::tr("Quantize"));
quantize->setShortName(QObject::tr("Quantize"));
quantize->setDescription(QObject::tr(
- "Round the Rate parameter to the nearest whole division of a beat."));
- quantize->setControlHint(
- EffectManifestParameter::ControlHint::TOGGLE_STEPPING);
- quantize->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- quantize->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- quantize->setDefault(1);
- quantize->setMinimum(0);
- quantize->setMaximum(1);
+ "Round the Rate parameter to the nearest whole division of a beat."));
+ quantize->setValueScaler(
+ EffectManifestParameter::ValueScaler::Toggle);
+ quantize->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ quantize->setRange(0, 1, 1);
EffectManifestParameterPointer triplet = pManifest->addParameter();
triplet->setId("triplet");
triplet->setName(QObject::tr("Triplets"));
triplet->setShortName(QObject::tr("Triplet"));
triplet->setDescription(QObject::tr(
- "When the Quantize parameter is enabled, divide the effect period by 3."));
- triplet->setControlHint(
- EffectManifestParameter::ControlHint::TOGGLE_STEPPING);
- triplet->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- triplet->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- triplet->setDefault(0);
- triplet->setMinimum(0);
- triplet->setMaximum(1);
+ "When the Quantize parameter is enabled, divide the effect period by 3."));
+ triplet->setValueScaler(
+ EffectManifestParameter::ValueScaler::Toggle);
+ triplet->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ triplet->setRange(0, 0, 1);
return pManifest;
}
-TremoloEffect::TremoloEffect(EngineEffect* pEffect)
- : m_pDepthParameter(pEffect->getParameterById("depth")),
- m_pRateParameter(pEffect->getParameterById("rate")),
- m_pWidthParameter(pEffect->getParameterById("width")),
- m_pWaveformParameter(pEffect->getParameterById("waveform")),
- m_pPhaseParameter(pEffect->getParameterById("phase")),
- m_pQuantizeParameter(pEffect->getParameterById("quantize")),
- m_pTripletParameter(pEffect->getParameterById("triplet")) {
+void TremoloEffect::loadEngineEffectParameters(
+ const QMap& parameters) {
+ m_pDepthParameter = parameters.value("depth");
+ m_pRateParameter = parameters.value("rate");
+ m_pWidthParameter = parameters.value("width");
+ m_pWaveformParameter = parameters.value("waveform");
+ m_pPhaseParameter = parameters.value("phase");
+ m_pQuantizeParameter = parameters.value("quantize");
+ m_pTripletParameter = parameters.value("triplet");
}
-void TremoloEffect::processChannel(const ChannelHandle& handle,
- TremoloState* pState,
- const CSAMPLE* pInput, CSAMPLE* pOutput,
- const mixxx::EngineParameters& bufferParameters,
- const EffectEnableState enableState,
- const GroupFeatureState& groupFeatures) {
- Q_UNUSED(handle);
-
+void TremoloEffect::processChannel(
+ TremoloState* pState,
+ const CSAMPLE* pInput,
+ CSAMPLE* pOutput,
+ const mixxx::EngineParameters& engineParameters,
+ const EffectEnableState enableState,
+ const GroupFeatureState& groupFeatures) {
const double width = m_pWidthParameter->value();
const double smooth = m_pWaveformParameter->value();
const double depth = m_pDepthParameter->value();
@@ -156,17 +134,13 @@ void TremoloEffect::processChannel(const ChannelHandle& handle,
const GroupFeatureState& gf = groupFeatures;
- bool quantizeEnabling = !pState->quantizeEnabled
- && m_pQuantizeParameter->toBool();
- bool tripletDisabling = pState->tripletEnabled
- && !m_pTripletParameter->toBool();
+ bool quantizeEnabling = !pState->quantizeEnabled && m_pQuantizeParameter->toBool();
+ bool tripletDisabling = pState->tripletEnabled && !m_pTripletParameter->toBool();
- if (enableState == EffectEnableState::Enabling
- || quantizeEnabling
- || tripletDisabling) {
+ if (enableState == EffectEnableState::Enabling || quantizeEnabling || tripletDisabling) {
if (gf.has_beat_length_sec && gf.has_beat_fraction) {
currentFrame = static_cast(gf.beat_fraction *
- gf.beat_length_sec * bufferParameters.sampleRate());
+ gf.beat_length_sec * engineParameters.sampleRate());
} else {
currentFrame = 0;
}
@@ -185,10 +159,10 @@ void TremoloEffect::processChannel(const ChannelHandle& handle,
}
}
const auto framePerBeat = static_cast(
- gf.beat_length_sec * bufferParameters.sampleRate());
+ gf.beat_length_sec * engineParameters.sampleRate());
framePerPeriod = static_cast(framePerBeat / rate);
} else {
- framePerPeriod = static_cast(bufferParameters.sampleRate() / rate);
+ framePerPeriod = static_cast(engineParameters.sampleRate() / rate);
}
const auto phaseOffsetFrame = static_cast(
@@ -196,8 +170,8 @@ void TremoloEffect::processChannel(const ChannelHandle& handle,
currentFrame = currentFrame % framePerPeriod;
for (SINT i = 0;
- i < bufferParameters.samplesPerBuffer();
- i += bufferParameters.channelCount()) {
+ i < engineParameters.samplesPerBuffer();
+ i += engineParameters.channelCount()) {
unsigned int positionFrame = (currentFrame - phaseOffsetFrame);
positionFrame = positionFrame % framePerPeriod;
@@ -216,9 +190,10 @@ void TremoloEffect::processChannel(const ChannelHandle& handle,
// This function gives the gain to apply for position in [0 1]
// Plot the function to get a grasp :
// From a sine to a square wave depending on the smooth parameter
- double gainTarget = 1.0 - (depth / 2.0)
- + (atan(sin(2.0 * M_PI * position) / smooth) / (2 * atan(1 / smooth)))
- * depth;
+ double gainTarget = 1.0 - (depth / 2.0) +
+ (atan(sin(2.0 * M_PI * position) / smooth) /
+ (2 * atan(1 / smooth))) *
+ depth;
if (gainTarget > gain + kMaxGainIncrement) {
gain += kMaxGainIncrement;
@@ -228,7 +203,7 @@ void TremoloEffect::processChannel(const ChannelHandle& handle,
gain = gainTarget;
}
- for (int channel = 0; channel < bufferParameters.channelCount(); channel++) {
+ for (int channel = 0; channel < engineParameters.channelCount(); channel++) {
pOutput[i + channel] = static_cast(gain) * pInput[i + channel];
}
diff --git a/src/effects/backends/builtin/tremoloeffect.h b/src/effects/backends/builtin/tremoloeffect.h
new file mode 100644
index 00000000000..4daa0adb1d8
--- /dev/null
+++ b/src/effects/backends/builtin/tremoloeffect.h
@@ -0,0 +1,52 @@
+#pragma once
+#include "effects/backends/effectprocessor.h"
+#include "engine/effects/engineeffect.h"
+#include "engine/effects/engineeffectparameter.h"
+#include "util/class.h"
+#include "util/defs.h"
+#include "util/sample.h"
+#include "util/types.h"
+
+class TremoloState : public EffectState {
+ public:
+ TremoloState(const mixxx::EngineParameters& engineParameters)
+ : EffectState(engineParameters){};
+ double gain;
+ unsigned int currentFrame;
+ bool quantizeEnabled = false;
+ bool tripletEnabled = false;
+};
+
+class TremoloEffect : public EffectProcessorImpl {
+ public:
+ TremoloEffect() = default;
+
+ static QString getId();
+ static EffectManifestPointer getManifest();
+
+ void loadEngineEffectParameters(
+ const QMap& parameters) override;
+
+ void processChannel(
+ TremoloState* pState,
+ const CSAMPLE* pInput,
+ CSAMPLE* pOutput,
+ const mixxx::EngineParameters& engineParameters,
+ const EffectEnableState enableState,
+ const GroupFeatureState& groupFeatures) override;
+
+ private:
+ QString debugString() const {
+ return getId();
+ }
+
+ EngineEffectParameterPointer m_pDepthParameter;
+ EngineEffectParameterPointer m_pRateParameter;
+ EngineEffectParameterPointer m_pWidthParameter;
+ EngineEffectParameterPointer m_pWaveformParameter;
+ EngineEffectParameterPointer m_pPhaseParameter;
+ EngineEffectParameterPointer m_pQuantizeParameter;
+ EngineEffectParameterPointer m_pTripletParameter;
+
+ DISALLOW_COPY_AND_ASSIGN(TremoloEffect);
+};
diff --git a/src/effects/builtin/whitenoiseeffect.cpp b/src/effects/backends/builtin/whitenoiseeffect.cpp
similarity index 55%
rename from src/effects/builtin/whitenoiseeffect.cpp
rename to src/effects/backends/builtin/whitenoiseeffect.cpp
index 0a9409142b4..bd9f33b1619 100644
--- a/src/effects/builtin/whitenoiseeffect.cpp
+++ b/src/effects/backends/builtin/whitenoiseeffect.cpp
@@ -1,4 +1,4 @@
-#include "effects/builtin/whitenoiseeffect.h"
+#include "effects/backends/builtin/whitenoiseeffect.h"
#include "util/rampingvalue.h"
@@ -22,48 +22,41 @@ EffectManifestPointer WhiteNoiseEffect::getManifest() {
pManifest->setEffectRampsFromDry(true);
// This is dry/wet parameter
- EffectManifestParameterPointer intensity = pManifest->addParameter();
- intensity->setId(dryWetParameterId);
- intensity->setName(QObject::tr("Dry/Wet"));
- intensity->setDescription(QObject::tr("Crossfade the noise with the dry signal"));
- intensity->setControlHint(EffectManifestParameter::ControlHint::KNOB_LOGARITHMIC);
- intensity->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN);
- intensity->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN);
- intensity->setDefaultLinkType(EffectManifestParameter::LinkType::LINKED);
- intensity->setMinimum(0);
- intensity->setDefault(0);
- intensity->setMaximum(1);
+ EffectManifestParameterPointer drywet = pManifest->addParameter();
+ drywet->setId(dryWetParameterId);
+ drywet->setName(QObject::tr("Dry/Wet"));
+ drywet->setDescription(QObject::tr("Crossfade the noise with the dry signal"));
+ drywet->setValueScaler(EffectManifestParameter::ValueScaler::Logarithmic);
+ drywet->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
+ drywet->setDefaultLinkType(EffectManifestParameter::LinkType::Linked);
+ drywet->setRange(0, 1, 1);
return pManifest;
}
-WhiteNoiseEffect::WhiteNoiseEffect(EngineEffect* pEffect)
- : m_pDryWetParameter(pEffect->getParameterById(dryWetParameterId)) {
-}
-
-WhiteNoiseEffect::~WhiteNoiseEffect() {
+void WhiteNoiseEffect::loadEngineEffectParameters(
+ const QMap& parameters) {
+ m_pDryWetParameter = parameters.value(dryWetParameterId);
}
void WhiteNoiseEffect::processChannel(
- const ChannelHandle& handle,
- WhiteNoiseGroupState* pGroupState,
+ WhiteNoiseGroupState* pState,
const CSAMPLE* pInput,
CSAMPLE* pOutput,
- const mixxx::EngineParameters& bufferParameters,
+ const mixxx::EngineParameters& engineParameters,
const EffectEnableState enableState,
const GroupFeatureState& groupFeatures) {
- Q_UNUSED(handle);
Q_UNUSED(groupFeatures);
- WhiteNoiseGroupState& gs = *pGroupState;
+ WhiteNoiseGroupState& gs = *pState;
CSAMPLE drywet = static_cast(m_pDryWetParameter->value());
RampingValue drywet_ramping_value(
- drywet, gs.previous_drywet, bufferParameters.framesPerBuffer());
+ drywet, gs.previous_drywet, engineParameters.framesPerBuffer());
std::uniform_real_distribution<> r_distributor(0.0, 1.0);
- for (unsigned int i = 0; i < bufferParameters.samplesPerBuffer(); i++) {
+ for (unsigned int i = 0; i < engineParameters.samplesPerBuffer(); i++) {
CSAMPLE_GAIN drywet_ramped = drywet_ramping_value.getNext();
float noise = static_cast(
diff --git a/src/effects/builtin/whitenoiseeffect.h b/src/effects/backends/builtin/whitenoiseeffect.h
similarity index 65%
rename from src/effects/builtin/whitenoiseeffect.h
rename to src/effects/backends/builtin/whitenoiseeffect.h
index 437f7ffa42f..fdbef8757e4 100644
--- a/src/effects/builtin/whitenoiseeffect.h
+++ b/src/effects/backends/builtin/whitenoiseeffect.h
@@ -2,7 +2,7 @@
#include
-#include "effects/effectprocessor.h"
+#include "effects/backends/effectprocessor.h"
#include "engine/effects/engineeffect.h"
#include "engine/effects/engineeffectparameter.h"
#include "engine/filters/enginefilterpansingle.h"
@@ -14,8 +14,8 @@
class WhiteNoiseGroupState final : public EffectState {
public:
- WhiteNoiseGroupState(const mixxx::EngineParameters& bufferParameters)
- : EffectState(bufferParameters),
+ WhiteNoiseGroupState(const mixxx::EngineParameters& engineParameters)
+ : EffectState(engineParameters),
previous_drywet(0.0),
gen(rs()) {
}
@@ -29,23 +29,24 @@ class WhiteNoiseGroupState final : public EffectState {
class WhiteNoiseEffect : public EffectProcessorImpl {
public:
- WhiteNoiseEffect(EngineEffect* pEffect);
- virtual ~WhiteNoiseEffect();
+ WhiteNoiseEffect() = default;
static QString getId();
static EffectManifestPointer getManifest();
- // See effectprocessor.h
- void processChannel(const ChannelHandle& handle,
+ void processChannel(
WhiteNoiseGroupState* pState,
const CSAMPLE* pInput,
CSAMPLE* pOutput,
- const mixxx::EngineParameters& bufferParameters,
+ const mixxx::EngineParameters& engineParameters,
const EffectEnableState enableState,
- const GroupFeatureState& groupFeatures);
+ const GroupFeatureState& groupFeatures) override;
+
+ void loadEngineEffectParameters(
+ const QMap& parameters) override;
private:
- EngineEffectParameter* m_pDryWetParameter;
+ EngineEffectParameterPointer m_pDryWetParameter;
DISALLOW_COPY_AND_ASSIGN(WhiteNoiseEffect);
};
diff --git a/src/effects/backends/effectmanifest.cpp b/src/effects/backends/effectmanifest.cpp
new file mode 100644
index 00000000000..993a2205a87
--- /dev/null
+++ b/src/effects/backends/effectmanifest.cpp
@@ -0,0 +1,29 @@
+#include "effects/backends/effectmanifest.h"
+
+QDebug operator<<(QDebug dbg, const EffectManifest& manifest) {
+ return dbg.maybeSpace() << QString("EffectManifest(%1)").arg(manifest.id());
+}
+
+bool EffectManifest::hasMetaKnobLinking() const {
+ for (const auto& pParameterManifest : m_parameters) {
+ if (pParameterManifest->defaultLinkType() !=
+ EffectManifestParameter::LinkType::None) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool EffectManifest::sortLexigraphically(
+ EffectManifestPointer pManifest1, EffectManifestPointer pManifest2) {
+ // Sort built-in effects first before external plugins
+ int backendNameComparision = static_cast(pManifest1->backendType()) -
+ static_cast(pManifest2->backendType());
+ if (backendNameComparision != 0) {
+ return backendNameComparision < 0;
+ }
+
+ int displayNameComparision = QString::localeAwareCompare(
+ pManifest1->displayName(), pManifest2->displayName());
+ return displayNameComparision < 0;
+}
diff --git a/src/effects/effectmanifest.h b/src/effects/backends/effectmanifest.h
similarity index 58%
rename from src/effects/effectmanifest.h
rename to src/effects/backends/effectmanifest.h
index a09a57351b3..d74f2b5c1b6 100644
--- a/src/effects/effectmanifest.h
+++ b/src/effects/backends/effectmanifest.h
@@ -1,36 +1,47 @@
#pragma once
#include
+#include
#include
#include
-#include
-#include "effects/effectmanifestparameter.h"
+#include "effects/backends/effectmanifestparameter.h"
+#include "effects/backends/effectsbackend.h"
#include "effects/defs.h"
-// An EffectManifest is a full description of the metadata associated with an
-// effect (e.g. name, author, version, description, etc.) and the parameters of
-// the effect that are intended to be exposed to the rest of Mixxx for user or
-// script control.
-//
-// EffectManifest is composed purely of simple data types, and when an
-// EffectManifest is const, it should be completely immutable. EffectManifest is
-// meant to be used in most cases as a reference, and in Qt collections, so it
-// is important that the implicit copy and assign constructors work, and that
-// the no-argument constructor be non-explicit. All methods are left virtual to
-// allow a backend to replace the entire functionality with its own (for
-// example, a database-backed manifest)
-class EffectManifest final {
+/// An EffectManifest is a description of the metadata associated with an effect
+/// (ID, display name, author, description) and all the parameters of the effect.
+/// The pair of the ID string and EffectBackendType uniquely identifies an
+/// effect. EffectManifests are used by EffectBackends to create EffectProcessors
+/// which implement the DSP logic of the effect. The name string of effect
+/// parameters in the manifest is used to link EngineEffectParameters
+/// with member variables used in the DSP logic of the EffectProcessorImpl.
+///
+/// EffectManifest is composed purely of simple data types, and when an
+/// EffectManifest is const, it should be completely immutable. EffectManifest is
+/// meant to be used in most cases as a reference, and in Qt collections, so it
+/// is important that the implicit copy and assign constructors work, and that
+/// the no-argument constructor be non-explicit.
+class EffectManifest {
public:
EffectManifest()
- : m_backendType(EffectBackendType::Unknown),
- m_isMixingEQ(false),
- m_isMasterEQ(false),
- m_effectRampsFromDry(false),
- m_bAddDryToWet(false),
- m_metaknobDefault(0.5) {
+ : m_backendType(EffectBackendType::Unknown),
+ m_isMixingEQ(false),
+ m_isMasterEQ(false),
+ m_effectRampsFromDry(false),
+ m_bAddDryToWet(false),
+ m_metaknobDefault(0.0) {
}
+ /// Hack to store unique IDs in QComboBox models
+ const QString uniqueId() const {
+ return m_id + " " + EffectsBackend::backendTypeToString(m_backendType);
+ }
+
+ /// WARNING! Effects must not be identified solely by ID string or name.
+ /// ID strings and names are only unique among EffectManifests from one
+ /// EffectsBackend. Use EffectManifest::operator== to compare both ID string
+ /// and EffectBackendType.
const QString& id() const {
return m_id;
}
@@ -101,6 +112,8 @@ class EffectManifest final {
m_isMasterEQ = value;
}
+ bool hasMetaKnobLinking() const;
+
void setDescription(const QString& description) {
m_description = description;
}
@@ -112,6 +125,7 @@ class EffectManifest final {
EffectManifestParameterPointer addParameter() {
EffectManifestParameterPointer effectManifestParameterPointer(
new EffectManifestParameter());
+ effectManifestParameterPointer->setIndex(m_parameters.size());
m_parameters.append(effectManifestParameterPointer);
return effectManifestParameterPointer;
}
@@ -141,39 +155,20 @@ class EffectManifest final {
m_metaknobDefault = metaknobDefault;
}
- QString backendName() {
- switch (m_backendType) {
- case EffectBackendType::BuiltIn:
- return QString("Built-in");
- case EffectBackendType::LV2:
- return QString("LV2");
- default:
- return QString("Unknown");
- }
+ bool operator==(const EffectManifest& other) const {
+ return other.id() == m_id && other.backendType() == m_backendType;
}
- // Use this when showing the string in the GUI
- QString translatedBackendName() {
- switch (m_backendType) {
- case EffectBackendType::BuiltIn:
- //: Used for effects that are built into Mixxx
- return QObject::tr("Built-in");
- case EffectBackendType::LV2:
- return QString("LV2");
- default:
- return QString();
- }
- }
- static EffectBackendType backendTypeFromString(const QString& name) {
- if (name == "Built-in") {
- return EffectBackendType::BuiltIn;
- } else if (name == "LV2") {
- return EffectBackendType::LV2;
- } else {
- return EffectBackendType::Unknown;
+ bool operator<(const EffectManifest& other) const {
+ if (other.backendType() != m_backendType) {
+ return other.backendType() < m_backendType;
}
+ return other.id() < m_id;
}
+ static bool sortLexigraphically(
+ EffectManifestPointer pManifest1, EffectManifestPointer pManifest2);
+
private:
QString debugString() const {
return QString("EffectManifest(%1)").arg(m_id);
@@ -186,7 +181,7 @@ class EffectManifest final {
QString m_author;
QString m_version;
QString m_description;
- // This helps us at DlgPrefEQ's basic selection of Equalizers
+ /// This helps us at DlgPrefEQ's basic selection of Equalizers
bool m_isMixingEQ;
bool m_isMasterEQ;
QList m_parameters;
diff --git a/src/effects/effectmanifestparameter.cpp b/src/effects/backends/effectmanifestparameter.cpp
similarity index 75%
rename from src/effects/effectmanifestparameter.cpp
rename to src/effects/backends/effectmanifestparameter.cpp
index 0094635c148..9e3ba418a57 100644
--- a/src/effects/effectmanifestparameter.cpp
+++ b/src/effects/backends/effectmanifestparameter.cpp
@@ -1,4 +1,4 @@
-#include "effects/effectmanifestparameter.h"
+#include "effects/backends/effectmanifestparameter.h"
QDebug operator<<(QDebug dbg, const EffectManifestParameter& parameter) {
return dbg.maybeSpace() << QString("EffectManifestParameter(%1)").arg(parameter.id());
diff --git a/src/effects/backends/effectmanifestparameter.h b/src/effects/backends/effectmanifestparameter.h
new file mode 100644
index 00000000000..a744058acfc
--- /dev/null
+++ b/src/effects/backends/effectmanifestparameter.h
@@ -0,0 +1,282 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+
+#include "effects/defs.h"
+#include "util/assert.h"
+
+class EffectManifestParameter;
+typedef QSharedPointer EffectManifestParameterPointer;
+
+class EffectManifestParameter {
+ public:
+ enum class ParameterType : int {
+ Knob,
+ Button,
+ NumTypes,
+ };
+
+ enum class ValueScaler : int {
+ Unknown = 0,
+ Linear,
+ LinearInverse,
+ Logarithmic,
+ LogarithmicInverse,
+ /// A step rotary, steps given by m_steps are arranged with equal
+ /// distance on scale
+ Integral,
+ /// For button and enum controls, not accessible from many controllers,
+ /// no linking to meta knob
+ Toggle,
+ };
+
+ enum class UnitsHint : int {
+ Unknown = 0,
+ Time,
+ Hertz,
+ /// Fraction of the Sample Rate
+ SampleRate,
+ /// Multiples of a Beat
+ Beats,
+ };
+
+ enum class LinkType : int {
+ /// Not controlled by the meta knob
+ None = 0,
+ /// Controlled by the meta knob as it is
+ Linked,
+ /// Controlled by the left side of the meta knob
+ LinkedLeft,
+ /// Controlled by the right side of the meta knob
+ LinkedRight,
+ /// Controlled by both sides of the meta knob
+ LinkedLeftRight,
+ NumLinkTypes,
+ };
+
+ static QString LinkTypeToString(LinkType type) {
+ switch (type) {
+ case LinkType::Linked:
+ return QLatin1String("LINKED");
+ case LinkType::LinkedLeft:
+ return QLatin1String("LINKED_LEFT");
+ case LinkType::LinkedRight:
+ return QLatin1String("LINKED_RIGHT");
+ case LinkType::LinkedLeftRight:
+ return QLatin1String("LINKED_LEFT_RIGHT");
+ default:
+ return QLatin1String("NONE");
+ }
+ }
+
+ static LinkType LinkTypeFromString(const QString& string) {
+ if (string == QLatin1String("LINKED")) {
+ return LinkType::Linked;
+ } else if (string == QLatin1String("LINKED_LEFT")) {
+ return LinkType::LinkedLeft;
+ } else if (string == QLatin1String("LINKED_RIGHT")) {
+ return LinkType::LinkedRight;
+ } else if (string == QLatin1String("LINKED_LEFT_RIGHT")) {
+ return LinkType::LinkedLeftRight;
+ } else {
+ return LinkType::None;
+ }
+ }
+
+ enum class LinkInversion : int {
+ NotInverted = 0,
+ Inverted = 1
+ };
+
+ EffectManifestParameter()
+ : m_valueScaler(ValueScaler::Unknown),
+ m_unitsHint(UnitsHint::Unknown),
+ m_defaultLinkType(LinkType::None),
+ m_defaultLinkInversion(LinkInversion::NotInverted),
+ m_neutralPointOnScale(0.0),
+ m_default(0),
+ m_minimum(0),
+ m_maximum(1.0) {
+ }
+
+ ~EffectManifestParameter() {
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Parameter Information
+ ////////////////////////////////////////////////////////////////////////////////
+
+ const QString& id() const {
+ return m_id;
+ }
+ void setId(const QString& id) {
+ m_id = id;
+ }
+
+ const QString& name() const {
+ return m_name;
+ }
+ void setName(const QString& name) {
+ m_name = name;
+ }
+
+ const QString& shortName() const {
+ return m_shortName;
+ }
+ void setShortName(const QString& shortName) {
+ m_shortName = shortName;
+ }
+
+ const QString& description() const {
+ return m_description;
+ }
+ void setDescription(const QString& description) {
+ m_description = description;
+ }
+
+ int index() const {
+ return m_iIndex;
+ }
+ void setIndex(int index) {
+ m_iIndex = index;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Usage hints
+ ////////////////////////////////////////////////////////////////////////////////
+
+ const ParameterType& parameterType() const {
+ return m_parameterType;
+ }
+
+ ValueScaler valueScaler() const {
+ return m_valueScaler;
+ }
+ void setValueScaler(ValueScaler valueScaler) {
+ m_valueScaler = valueScaler;
+ if (valueScaler == ValueScaler::Toggle) {
+ setParameterType(ParameterType::Button);
+ } else {
+ setParameterType(ParameterType::Knob);
+ }
+ }
+
+ UnitsHint unitsHint() const {
+ return m_unitsHint;
+ }
+ void setUnitsHint(UnitsHint unitsHint) {
+ m_unitsHint = unitsHint;
+ }
+
+ LinkType defaultLinkType() const {
+ return m_defaultLinkType;
+ }
+ void setDefaultLinkType(const LinkType linkType) {
+ m_defaultLinkType = linkType;
+ }
+
+ LinkInversion defaultLinkInversion() const {
+ return m_defaultLinkInversion;
+ }
+ void setDefaultLinkInversion(const LinkInversion linkInversion) {
+ m_defaultLinkInversion = linkInversion;
+ }
+
+ /// Neutral Point On Scale is the parameter in the range 0 .. 1 on the knob that
+ /// is adopted as neutral when controlled by the meta knob.
+ /// This is allows to link the meta knob in a way that two effects are
+ /// cranked in simultaneous, or in case of a split filter like meta knob,
+ /// both effects are neutral at meta knob center.
+ /// A EQ Gain has usually a neutral point of 0.5 (0 dB) while a delay knob
+ /// has a neutral point of 0.0 (no delay)
+ /// A EQ Gain knob cannot be used on a split meta knob.
+ double neutralPointOnScale() const {
+ return m_neutralPointOnScale;
+ }
+ void setNeutralPointOnScale(double neutralPoint) {
+ m_neutralPointOnScale = neutralPoint;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Value Settings
+ ////////////////////////////////////////////////////////////////////////////////
+
+ const double& getDefault() const {
+ return m_default;
+ }
+
+ const double& getMinimum() const {
+ return m_minimum;
+ }
+
+ const double& getMaximum() const {
+ return m_maximum;
+ }
+
+ /// Minimum, default, and maximum are set together in one function so their
+ /// validity only needs to be checked once.
+ void setRange(const double& minimum, const double& defaultValue, const double& maximum) {
+ VERIFY_OR_DEBUG_ASSERT(minimum <= defaultValue && defaultValue <= maximum) {
+ qWarning() << "EffectManifestParameter" << m_name
+ << "tried to set invalid parameter range:"
+ << "minimum" << minimum
+ << "default" << defaultValue
+ << "maximum" << maximum;
+ return;
+ }
+ m_minimum = minimum;
+ m_default = defaultValue;
+ m_maximum = maximum;
+ }
+
+ void appendStep(const QPair