From 3c18e436cddc123347a9dedbb8e71346a26ecd05 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Thu, 17 Sep 2009 23:21:26 +0200 Subject: [PATCH] ZynAddSubFX: resynced with their Git repo ZynAddSubFX has gained some new developer power so development has been going on well for quite a while now in their Git repo. It's time for the first big resync so future changes can be integrated easily. --- plugins/zynaddsubfx/CMakeLists.txt | 83 +- plugins/zynaddsubfx/LocalZynAddSubFx.cpp | 4 +- plugins/zynaddsubfx/ZynAddSubFx.cpp | 3 +- plugins/zynaddsubfx/src/AUTHORS.txt | 13 +- plugins/zynaddsubfx/src/ChangeLog | 33 +- .../zynaddsubfx/src/Controls/CMakeLists.txt | 8 + plugins/zynaddsubfx/src/Controls/Control.cpp | 40 + plugins/zynaddsubfx/src/Controls/Control.h | 58 + plugins/zynaddsubfx/src/Controls/DelayCtl.cpp | 50 + plugins/zynaddsubfx/src/Controls/DelayCtl.h | 43 + plugins/zynaddsubfx/src/DSP/AnalogFilter.C | 358 ----- plugins/zynaddsubfx/src/DSP/AnalogFilter.cpp | 407 +++++ plugins/zynaddsubfx/src/DSP/AnalogFilter.h | 29 +- plugins/zynaddsubfx/src/DSP/CMakeLists.txt | 13 + .../src/DSP/{FFTwrapper.C => FFTwrapper.cpp} | 49 +- plugins/zynaddsubfx/src/DSP/FFTwrapper.h | 47 +- .../src/DSP/{Filter.C => Filter.cpp} | 54 +- plugins/zynaddsubfx/src/DSP/Filter.h | 13 +- plugins/zynaddsubfx/src/DSP/Filter_.h | 23 +- plugins/zynaddsubfx/src/DSP/FormantFilter.C | 163 -- plugins/zynaddsubfx/src/DSP/FormantFilter.cpp | 176 +++ plugins/zynaddsubfx/src/DSP/FormantFilter.h | 25 +- .../src/DSP/{SVFilter.C => SVFilter.cpp} | 120 +- plugins/zynaddsubfx/src/DSP/SVFilter.h | 23 +- .../src/Effects/{Alienwah.C => Alienwah.cpp} | 233 +-- plugins/zynaddsubfx/src/Effects/Alienwah.h | 89 +- .../zynaddsubfx/src/Effects/CMakeLists.txt | 19 + plugins/zynaddsubfx/src/Effects/Chorus.C | 275 ---- plugins/zynaddsubfx/src/Effects/Chorus.cpp | 316 ++++ plugins/zynaddsubfx/src/Effects/Chorus.h | 157 +- plugins/zynaddsubfx/src/Effects/Distorsion.C | 376 ----- .../zynaddsubfx/src/Effects/Distorsion.cpp | 427 ++++++ plugins/zynaddsubfx/src/Effects/Distorsion.h | 71 +- .../zynaddsubfx/src/Effects/DynamicFilter.C | 312 ---- .../zynaddsubfx/src/Effects/DynamicFilter.cpp | 344 +++++ .../zynaddsubfx/src/Effects/DynamicFilter.h | 73 +- plugins/zynaddsubfx/src/Effects/EQ.C | 193 --- plugins/zynaddsubfx/src/Effects/EQ.cpp | 214 +++ plugins/zynaddsubfx/src/Effects/EQ.h | 51 +- plugins/zynaddsubfx/src/Effects/Echo.C | 224 --- plugins/zynaddsubfx/src/Effects/Echo.cpp | 257 ++++ plugins/zynaddsubfx/src/Effects/Echo.h | 194 +-- .../src/Effects/{Effect.C => Effect.cpp} | 12 +- plugins/zynaddsubfx/src/Effects/Effect.h | 121 +- .../Effects/{EffectLFO.C => EffectLFO.cpp} | 60 +- plugins/zynaddsubfx/src/Effects/EffectLFO.h | 18 +- plugins/zynaddsubfx/src/Effects/EffectMgr.C | 295 ---- plugins/zynaddsubfx/src/Effects/EffectMgr.cpp | 332 +++++ plugins/zynaddsubfx/src/Effects/EffectMgr.h | 105 +- plugins/zynaddsubfx/src/Effects/Phaser.C | 250 ---- plugins/zynaddsubfx/src/Effects/Phaser.cpp | 283 ++++ plugins/zynaddsubfx/src/Effects/Phaser.h | 147 +- plugins/zynaddsubfx/src/Effects/Reverb.C | 430 ------ plugins/zynaddsubfx/src/Effects/Reverb.cpp | 471 ++++++ plugins/zynaddsubfx/src/Effects/Reverb.h | 253 ++-- plugins/zynaddsubfx/src/FAQ.txt | 6 +- plugins/zynaddsubfx/src/HISTORY.txt | 13 + plugins/zynaddsubfx/src/Input/ALSAMidiIn.C | 111 -- plugins/zynaddsubfx/src/Input/ALSAMidiIn.cpp | 110 ++ plugins/zynaddsubfx/src/Input/ALSAMidiIn.h | 28 +- plugins/zynaddsubfx/src/Input/CMakeLists.txt | 19 + plugins/zynaddsubfx/src/Input/MidiIn.C | 73 - plugins/zynaddsubfx/src/Input/MidiIn.cpp | 95 ++ plugins/zynaddsubfx/src/Input/MidiIn.h | 28 +- .../Input/{NULLMidiIn.C => NULLMidiIn.cpp} | 20 +- plugins/zynaddsubfx/src/Input/NULLMidiIn.h | 26 +- .../src/Input/{OSSMidiIn.C => OSSMidiIn.cpp} | 103 +- plugins/zynaddsubfx/src/Input/OSSMidiIn.h | 31 +- plugins/zynaddsubfx/src/Input/WINMidiIn.C | 83 -- plugins/zynaddsubfx/src/Input/WINMidiIn.cpp | 87 ++ plugins/zynaddsubfx/src/Input/WINMidiIn.h | 4 +- .../zynaddsubfx/src/Misc/{Bank.C => Bank.cpp} | 526 +++---- plugins/zynaddsubfx/src/Misc/Bank.h | 124 +- plugins/zynaddsubfx/src/Misc/CMakeLists.txt | 18 + plugins/zynaddsubfx/src/Misc/Config.C | 331 ----- plugins/zynaddsubfx/src/Misc/Config.cpp | 341 +++++ plugins/zynaddsubfx/src/Misc/Config.h | 78 +- plugins/zynaddsubfx/src/Misc/Control.h | 100 ++ plugins/zynaddsubfx/src/Misc/Dump.C | 99 -- plugins/zynaddsubfx/src/Misc/Dump.cpp | 107 ++ plugins/zynaddsubfx/src/Misc/Dump.h | 54 +- plugins/zynaddsubfx/src/Misc/LASHClient.cpp | 104 ++ plugins/zynaddsubfx/src/Misc/LASHClient.h | 66 + plugins/zynaddsubfx/src/Misc/Master.C | 738 --------- plugins/zynaddsubfx/src/Misc/Master.cpp | 778 ++++++++++ plugins/zynaddsubfx/src/Misc/Master.h | 205 +-- plugins/zynaddsubfx/src/Misc/Microtonal.C | 514 ------- plugins/zynaddsubfx/src/Misc/Microtonal.cpp | 597 ++++++++ plugins/zynaddsubfx/src/Misc/Microtonal.h | 160 +- plugins/zynaddsubfx/src/Misc/Part.C | 1077 -------------- plugins/zynaddsubfx/src/Misc/Part.cpp | 1138 ++++++++++++++ plugins/zynaddsubfx/src/Misc/Part.h | 239 +-- plugins/zynaddsubfx/src/Misc/Stereo.cpp | 37 + plugins/zynaddsubfx/src/Misc/Stereo.h | 67 + .../zynaddsubfx/src/Misc/{Util.C => Util.cpp} | 66 +- plugins/zynaddsubfx/src/Misc/Util.h | 8 +- .../src/Misc/{XMLwrapper.C => XMLwrapper.cpp} | 422 +++--- plugins/zynaddsubfx/src/Misc/XMLwrapper.h | 388 +++-- plugins/zynaddsubfx/src/Output/CMakeLists.txt | 33 + .../zynaddsubfx/src/Output/DSSIaudiooutput.C | 279 ---- .../src/Output/DSSIaudiooutput.cpp | 288 ++++ .../zynaddsubfx/src/Output/DSSIaudiooutput.h | 10 +- ...RTaudiooutput.C => JACK_RTaudiooutput.cpp} | 160 +- .../zynaddsubfx/src/Output/JACKaudiooutput.C | 163 -- .../src/Output/JACKaudiooutput.cpp | 163 ++ .../zynaddsubfx/src/Output/JACKaudiooutput.h | 4 +- .../{OSSaudiooutput.C => OSSaudiooutput.cpp} | 47 +- .../zynaddsubfx/src/Output/OSSaudiooutput.h | 38 +- .../{PAaudiooutput.C => PAaudiooutput.cpp} | 27 +- .../zynaddsubfx/src/Output/PAaudiooutput.h | 4 +- .../src/Output/{Recorder.C => Recorder.cpp} | 98 +- plugins/zynaddsubfx/src/Output/Recorder.h | 53 +- .../{VSTaudiooutput.C => VSTaudiooutput.cpp} | 40 +- .../zynaddsubfx/src/Output/VSTaudiooutput.h | 43 +- .../zynaddsubfx/src/Output/WAVaudiooutput.C | 85 -- .../zynaddsubfx/src/Output/WAVaudiooutput.cpp | 99 ++ .../zynaddsubfx/src/Output/WAVaudiooutput.h | 33 +- .../zynaddsubfx/src/Params/ADnoteParameters.C | 637 -------- .../src/Params/ADnoteParameters.cpp | 648 ++++++++ .../zynaddsubfx/src/Params/ADnoteParameters.h | 407 ++--- plugins/zynaddsubfx/src/Params/CMakeLists.txt | 18 + .../Params/{Controller.C => Controller.cpp} | 208 ++- plugins/zynaddsubfx/src/Params/Controller.h | 266 ++-- .../{EnvelopeParams.C => EnvelopeParams.cpp} | 200 ++- .../zynaddsubfx/src/Params/EnvelopeParams.h | 84 +- plugins/zynaddsubfx/src/Params/FilterParams.C | 344 ----- .../zynaddsubfx/src/Params/FilterParams.cpp | 366 +++++ plugins/zynaddsubfx/src/Params/FilterParams.h | 125 +- .../src/Params/{LFOParams.C => LFOParams.cpp} | 38 +- plugins/zynaddsubfx/src/Params/LFOParams.h | 67 +- .../src/Params/PADnoteParameters.C | 762 ---------- .../src/Params/PADnoteParameters.cpp | 806 ++++++++++ .../src/Params/PADnoteParameters.h | 239 +-- .../src/Params/{Presets.C => Presets.cpp} | 101 +- plugins/zynaddsubfx/src/Params/Presets.h | 54 +- .../{PresetsStore.C => PresetsStore.cpp} | 160 +- plugins/zynaddsubfx/src/Params/PresetsStore.h | 61 +- .../src/Params/SUBnoteParameters.C | 238 --- .../src/Params/SUBnoteParameters.cpp | 243 +++ .../src/Params/SUBnoteParameters.h | 127 +- plugins/zynaddsubfx/src/README.txt | 38 +- plugins/zynaddsubfx/src/Samples/AuSample.cpp | 28 + plugins/zynaddsubfx/src/Samples/AuSample.h | 36 + .../zynaddsubfx/src/Samples/CMakeLists.txt | 13 + plugins/zynaddsubfx/src/Samples/FqSample.cpp | 33 + plugins/zynaddsubfx/src/Samples/FqSample.h | 37 + plugins/zynaddsubfx/src/Samples/Sample.cpp | 119 ++ plugins/zynaddsubfx/src/Samples/Sample.h | 70 + plugins/zynaddsubfx/src/Seq/CMakeLists.txt | 11 + .../src/Seq/{MIDIEvents.C => MIDIEvents.cpp} | 39 +- plugins/zynaddsubfx/src/Seq/MIDIEvents.h | 46 +- .../src/Seq/{MIDIFile.C => MIDIFile.cpp} | 293 ++-- plugins/zynaddsubfx/src/Seq/MIDIFile.h | 113 +- .../src/Seq/{Sequencer.C => Sequencer.cpp} | 116 +- plugins/zynaddsubfx/src/Seq/Sequencer.h | 93 +- plugins/zynaddsubfx/src/Synth/ADnote.C | 1271 ---------------- plugins/zynaddsubfx/src/Synth/ADnote.cpp | 1321 +++++++++++++++++ plugins/zynaddsubfx/src/Synth/ADnote.cxx | 136 ++ plugins/zynaddsubfx/src/Synth/ADnote.h | 318 ++-- plugins/zynaddsubfx/src/Synth/CMakeLists.txt | 18 + .../src/Synth/{Envelope.C => Envelope.cpp} | 137 +- plugins/zynaddsubfx/src/Synth/Envelope.h | 26 +- .../zynaddsubfx/src/Synth/{LFO.C => LFO.cpp} | 136 +- plugins/zynaddsubfx/src/Synth/LFO.h | 28 +- plugins/zynaddsubfx/src/Synth/OscilGen.C | 1182 --------------- plugins/zynaddsubfx/src/Synth/OscilGen.cpp | 1292 ++++++++++++++++ plugins/zynaddsubfx/src/Synth/OscilGen.h | 250 ++-- plugins/zynaddsubfx/src/Synth/PADnote.C | 516 ------- plugins/zynaddsubfx/src/Synth/PADnote.cpp | 527 +++++++ plugins/zynaddsubfx/src/Synth/PADnote.h | 158 +- .../src/Synth/{Resonance.C => Resonance.cpp} | 160 +- plugins/zynaddsubfx/src/Synth/Resonance.h | 49 +- plugins/zynaddsubfx/src/Synth/SUBnote.C | 641 -------- plugins/zynaddsubfx/src/Synth/SUBnote.cpp | 678 +++++++++ plugins/zynaddsubfx/src/Synth/SUBnote.h | 147 +- plugins/zynaddsubfx/src/UI/ConfigUI.cc | 1 + plugins/zynaddsubfx/src/UI/ConfigUI.fl | 4 + plugins/zynaddsubfx/src/UI/MasterUI.cc | 34 +- plugins/zynaddsubfx/src/UI/MasterUI.fl | 52 +- plugins/zynaddsubfx/src/UI/MasterUI.h | 4 +- plugins/zynaddsubfx/src/UI/PartUI.cc | 77 +- plugins/zynaddsubfx/src/UI/PartUI.fl | 50 +- plugins/zynaddsubfx/src/UI/PartUI.h | 12 + plugins/zynaddsubfx/src/UI/VirKeyboard.cc | 10 +- plugins/zynaddsubfx/src/UI/VirKeyboard.fl | 19 +- plugins/zynaddsubfx/src/bugs.txt | 1 + plugins/zynaddsubfx/src/globals.h | 41 +- 187 files changed, 19449 insertions(+), 16454 deletions(-) create mode 100644 plugins/zynaddsubfx/src/Controls/CMakeLists.txt create mode 100644 plugins/zynaddsubfx/src/Controls/Control.cpp create mode 100644 plugins/zynaddsubfx/src/Controls/Control.h create mode 100644 plugins/zynaddsubfx/src/Controls/DelayCtl.cpp create mode 100644 plugins/zynaddsubfx/src/Controls/DelayCtl.h delete mode 100644 plugins/zynaddsubfx/src/DSP/AnalogFilter.C create mode 100644 plugins/zynaddsubfx/src/DSP/AnalogFilter.cpp create mode 100644 plugins/zynaddsubfx/src/DSP/CMakeLists.txt rename plugins/zynaddsubfx/src/DSP/{FFTwrapper.C => FFTwrapper.cpp} (69%) rename plugins/zynaddsubfx/src/DSP/{Filter.C => Filter.cpp} (61%) delete mode 100644 plugins/zynaddsubfx/src/DSP/FormantFilter.C create mode 100644 plugins/zynaddsubfx/src/DSP/FormantFilter.cpp rename plugins/zynaddsubfx/src/DSP/{SVFilter.C => SVFilter.cpp} (54%) rename plugins/zynaddsubfx/src/Effects/{Alienwah.C => Alienwah.cpp} (52%) create mode 100644 plugins/zynaddsubfx/src/Effects/CMakeLists.txt delete mode 100644 plugins/zynaddsubfx/src/Effects/Chorus.C create mode 100644 plugins/zynaddsubfx/src/Effects/Chorus.cpp delete mode 100644 plugins/zynaddsubfx/src/Effects/Distorsion.C create mode 100644 plugins/zynaddsubfx/src/Effects/Distorsion.cpp delete mode 100644 plugins/zynaddsubfx/src/Effects/DynamicFilter.C create mode 100644 plugins/zynaddsubfx/src/Effects/DynamicFilter.cpp delete mode 100644 plugins/zynaddsubfx/src/Effects/EQ.C create mode 100644 plugins/zynaddsubfx/src/Effects/EQ.cpp delete mode 100644 plugins/zynaddsubfx/src/Effects/Echo.C create mode 100644 plugins/zynaddsubfx/src/Effects/Echo.cpp rename plugins/zynaddsubfx/src/Effects/{Effect.C => Effect.cpp} (83%) rename plugins/zynaddsubfx/src/Effects/{EffectLFO.C => EffectLFO.cpp} (70%) delete mode 100644 plugins/zynaddsubfx/src/Effects/EffectMgr.C create mode 100644 plugins/zynaddsubfx/src/Effects/EffectMgr.cpp delete mode 100644 plugins/zynaddsubfx/src/Effects/Phaser.C create mode 100644 plugins/zynaddsubfx/src/Effects/Phaser.cpp delete mode 100644 plugins/zynaddsubfx/src/Effects/Reverb.C create mode 100644 plugins/zynaddsubfx/src/Effects/Reverb.cpp delete mode 100644 plugins/zynaddsubfx/src/Input/ALSAMidiIn.C create mode 100644 plugins/zynaddsubfx/src/Input/ALSAMidiIn.cpp create mode 100644 plugins/zynaddsubfx/src/Input/CMakeLists.txt delete mode 100644 plugins/zynaddsubfx/src/Input/MidiIn.C create mode 100644 plugins/zynaddsubfx/src/Input/MidiIn.cpp rename plugins/zynaddsubfx/src/Input/{NULLMidiIn.C => NULLMidiIn.cpp} (85%) rename plugins/zynaddsubfx/src/Input/{OSSMidiIn.C => OSSMidiIn.cpp} (50%) delete mode 100644 plugins/zynaddsubfx/src/Input/WINMidiIn.C create mode 100644 plugins/zynaddsubfx/src/Input/WINMidiIn.cpp rename plugins/zynaddsubfx/src/Misc/{Bank.C => Bank.cpp} (50%) create mode 100644 plugins/zynaddsubfx/src/Misc/CMakeLists.txt delete mode 100644 plugins/zynaddsubfx/src/Misc/Config.C create mode 100644 plugins/zynaddsubfx/src/Misc/Config.cpp create mode 100644 plugins/zynaddsubfx/src/Misc/Control.h delete mode 100644 plugins/zynaddsubfx/src/Misc/Dump.C create mode 100644 plugins/zynaddsubfx/src/Misc/Dump.cpp create mode 100644 plugins/zynaddsubfx/src/Misc/LASHClient.cpp create mode 100644 plugins/zynaddsubfx/src/Misc/LASHClient.h delete mode 100644 plugins/zynaddsubfx/src/Misc/Master.C create mode 100644 plugins/zynaddsubfx/src/Misc/Master.cpp delete mode 100644 plugins/zynaddsubfx/src/Misc/Microtonal.C create mode 100644 plugins/zynaddsubfx/src/Misc/Microtonal.cpp delete mode 100644 plugins/zynaddsubfx/src/Misc/Part.C create mode 100644 plugins/zynaddsubfx/src/Misc/Part.cpp create mode 100644 plugins/zynaddsubfx/src/Misc/Stereo.cpp create mode 100644 plugins/zynaddsubfx/src/Misc/Stereo.h rename plugins/zynaddsubfx/src/Misc/{Util.C => Util.cpp} (68%) rename plugins/zynaddsubfx/src/Misc/{XMLwrapper.C => XMLwrapper.cpp} (55%) create mode 100644 plugins/zynaddsubfx/src/Output/CMakeLists.txt delete mode 100644 plugins/zynaddsubfx/src/Output/DSSIaudiooutput.C create mode 100644 plugins/zynaddsubfx/src/Output/DSSIaudiooutput.cpp rename plugins/zynaddsubfx/src/Output/{JACK_RTaudiooutput.C => JACK_RTaudiooutput.cpp} (53%) delete mode 100644 plugins/zynaddsubfx/src/Output/JACKaudiooutput.C create mode 100644 plugins/zynaddsubfx/src/Output/JACKaudiooutput.cpp rename plugins/zynaddsubfx/src/Output/{OSSaudiooutput.C => OSSaudiooutput.cpp} (78%) rename plugins/zynaddsubfx/src/Output/{PAaudiooutput.C => PAaudiooutput.cpp} (74%) rename plugins/zynaddsubfx/src/Output/{Recorder.C => Recorder.cpp} (54%) rename plugins/zynaddsubfx/src/Output/{VSTaudiooutput.C => VSTaudiooutput.cpp} (70%) delete mode 100644 plugins/zynaddsubfx/src/Output/WAVaudiooutput.C create mode 100644 plugins/zynaddsubfx/src/Output/WAVaudiooutput.cpp delete mode 100644 plugins/zynaddsubfx/src/Params/ADnoteParameters.C create mode 100644 plugins/zynaddsubfx/src/Params/ADnoteParameters.cpp create mode 100644 plugins/zynaddsubfx/src/Params/CMakeLists.txt rename plugins/zynaddsubfx/src/Params/{Controller.C => Controller.cpp} (64%) rename plugins/zynaddsubfx/src/Params/{EnvelopeParams.C => EnvelopeParams.cpp} (58%) delete mode 100644 plugins/zynaddsubfx/src/Params/FilterParams.C create mode 100644 plugins/zynaddsubfx/src/Params/FilterParams.cpp rename plugins/zynaddsubfx/src/Params/{LFOParams.C => LFOParams.cpp} (85%) delete mode 100644 plugins/zynaddsubfx/src/Params/PADnoteParameters.C create mode 100644 plugins/zynaddsubfx/src/Params/PADnoteParameters.cpp rename plugins/zynaddsubfx/src/Params/{Presets.C => Presets.cpp} (62%) rename plugins/zynaddsubfx/src/Params/{PresetsStore.C => PresetsStore.cpp} (54%) delete mode 100644 plugins/zynaddsubfx/src/Params/SUBnoteParameters.C create mode 100644 plugins/zynaddsubfx/src/Params/SUBnoteParameters.cpp create mode 100644 plugins/zynaddsubfx/src/Samples/AuSample.cpp create mode 100644 plugins/zynaddsubfx/src/Samples/AuSample.h create mode 100644 plugins/zynaddsubfx/src/Samples/CMakeLists.txt create mode 100644 plugins/zynaddsubfx/src/Samples/FqSample.cpp create mode 100644 plugins/zynaddsubfx/src/Samples/FqSample.h create mode 100644 plugins/zynaddsubfx/src/Samples/Sample.cpp create mode 100644 plugins/zynaddsubfx/src/Samples/Sample.h create mode 100644 plugins/zynaddsubfx/src/Seq/CMakeLists.txt rename plugins/zynaddsubfx/src/Seq/{MIDIEvents.C => MIDIEvents.cpp} (78%) rename plugins/zynaddsubfx/src/Seq/{MIDIFile.C => MIDIFile.cpp} (66%) rename plugins/zynaddsubfx/src/Seq/{Sequencer.C => Sequencer.cpp} (65%) delete mode 100644 plugins/zynaddsubfx/src/Synth/ADnote.C create mode 100644 plugins/zynaddsubfx/src/Synth/ADnote.cpp create mode 100644 plugins/zynaddsubfx/src/Synth/ADnote.cxx create mode 100644 plugins/zynaddsubfx/src/Synth/CMakeLists.txt rename plugins/zynaddsubfx/src/Synth/{Envelope.C => Envelope.cpp} (56%) rename plugins/zynaddsubfx/src/Synth/{LFO.C => LFO.cpp} (51%) delete mode 100644 plugins/zynaddsubfx/src/Synth/OscilGen.C create mode 100644 plugins/zynaddsubfx/src/Synth/OscilGen.cpp delete mode 100644 plugins/zynaddsubfx/src/Synth/PADnote.C create mode 100644 plugins/zynaddsubfx/src/Synth/PADnote.cpp rename plugins/zynaddsubfx/src/Synth/{Resonance.C => Resonance.cpp} (60%) delete mode 100644 plugins/zynaddsubfx/src/Synth/SUBnote.C create mode 100644 plugins/zynaddsubfx/src/Synth/SUBnote.cpp create mode 100644 plugins/zynaddsubfx/src/bugs.txt diff --git a/plugins/zynaddsubfx/CMakeLists.txt b/plugins/zynaddsubfx/CMakeLists.txt index e83c7fd64..d583a8539 100644 --- a/plugins/zynaddsubfx/CMakeLists.txt +++ b/plugins/zynaddsubfx/CMakeLists.txt @@ -2,55 +2,6 @@ IF(LMMS_HAVE_FFTW3F) INCLUDE(BuildPlugin) -SET(ZYN_SRC_CORE - ${CMAKE_CURRENT_SOURCE_DIR}/src/DSP/AnalogFilter.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/DSP/Filter.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/DSP/SVFilter.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/DSP/FFTwrapper.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/DSP/FormantFilter.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Input/NULLMidiIn.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Input/MidiIn.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Output/Recorder.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Output/WAVaudiooutput.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Effects/EffectMgr.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Effects/Effect.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Effects/Phaser.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Effects/Echo.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Effects/EffectLFO.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Effects/Chorus.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Effects/DynamicFilter.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Effects/Reverb.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Effects/EQ.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Effects/Distorsion.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Effects/Alienwah.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Params/LFOParams.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Params/EnvelopeParams.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Params/SUBnoteParameters.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Params/ADnoteParameters.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Params/Presets.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Params/FilterParams.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Params/PADnoteParameters.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Params/Controller.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Params/PresetsStore.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Seq/MIDIFile.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Seq/MIDIEvents.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Seq/Sequencer.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Synth/PADnote.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Synth/SUBnote.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Synth/LFO.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Synth/Resonance.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Synth/ADnote.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Synth/Envelope.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Synth/OscilGen.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Misc/Dump.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Misc/Bank.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Misc/Config.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Misc/XMLwrapper.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Misc/Util.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Misc/Master.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Misc/Microtonal.C - ${CMAKE_CURRENT_SOURCE_DIR}/src/Misc/Part.C) - SET(ZYN_SRC_GUI ${CMAKE_CURRENT_SOURCE_DIR}/src/UI/MasterUI.cc ${CMAKE_CURRENT_SOURCE_DIR}/src/UI/VirKeyboard.cc @@ -72,6 +23,7 @@ SET(ZYN_SRC_GUI ${CMAKE_CURRENT_SOURCE_DIR}/src/UI/BankUI.cc ) + SET(MXML_SRC ${CMAKE_CURRENT_SOURCE_DIR}/mxml/mxml-attr.c ${CMAKE_CURRENT_SOURCE_DIR}/mxml/mxml-entity.c @@ -108,10 +60,37 @@ IF(LMMS_BUILD_WIN32) ADD_DEFINITIONS(-DPTW32_STATIC_LIB) ENDIF(LMMS_BUILD_WIN32) -INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/fltk/ ${CMAKE_CURRENT_SOURCE_DIR} ${FFTW3F_INCLUDE_DIRS}) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/fltk/ ${CMAKE_CURRENT_SOURCE_DIR}/mxml ${CMAKE_CURRENT_SOURCE_DIR} ${FFTW3F_INCLUDE_DIRS}) -ADD_LIBRARY(ZynAddSubFxCore SHARED LocalZynAddSubFx.cpp ${ZYN_SRC_CORE} ${MXML_SRC}) -TARGET_LINK_LIBRARIES(ZynAddSubFxCore ${FFTW3F_LIBRARIES} -lz -lpthread) +set(ZASF_CORE_LIBS + zynaddsubfx_input + zynaddsubfx_output + zynaddsubfx_misc + zynaddsubfx_synth + zynaddsubfx_seq + zynaddsubfx_effect + zynaddsubfx_params + zynaddsubfx_dsp + zynaddsubfx_samples + zynaddsubfx_controls + ) + +macro(unit_test NAME CXX_FILE FILES) +endmacro(unit_test) + +add_subdirectory(src/Misc) +add_subdirectory(src/Input) +add_subdirectory(src/Controls) +add_subdirectory(src/Synth) +add_subdirectory(src/Output) +add_subdirectory(src/Seq) +add_subdirectory(src/Effects) +add_subdirectory(src/Params) +add_subdirectory(src/DSP) +add_subdirectory(src/Samples) + +ADD_LIBRARY(ZynAddSubFxCore SHARED LocalZynAddSubFx.cpp ${MXML_SRC}) +TARGET_LINK_LIBRARIES(ZynAddSubFxCore ${FFTW3F_LIBRARIES} ${ZASF_CORE_LIBS} -lz -lpthread) IF(LMMS_BUILD_WIN32) TARGET_LINK_LIBRARIES(ZynAddSubFxCore -lwsock32) INSTALL(TARGETS ZynAddSubFxCore DESTINATION ${PLUGIN_DIR}) diff --git a/plugins/zynaddsubfx/LocalZynAddSubFx.cpp b/plugins/zynaddsubfx/LocalZynAddSubFx.cpp index bce9655c6..719da4fb0 100644 --- a/plugins/zynaddsubfx/LocalZynAddSubFx.cpp +++ b/plugins/zynaddsubfx/LocalZynAddSubFx.cpp @@ -26,7 +26,7 @@ #include "LocalZynAddSubFx.h" -#include "src/Input/MidiIn.h" +#include "src/Input/NULLMidiIn.h" #include "src/Misc/Master.h" #include "src/Misc/Dump.h" @@ -169,7 +169,7 @@ void LocalZynAddSubFx::setPresetDir( const std::string & _dir ) void LocalZynAddSubFx::processMidiEvent( const midiEvent & _e ) { // all functions are called while m_master->mutex is held - static MidiIn midiIn; + static NULLMidiIn midiIn; switch( _e.m_type ) { diff --git a/plugins/zynaddsubfx/ZynAddSubFx.cpp b/plugins/zynaddsubfx/ZynAddSubFx.cpp index 4e8475bad..774f58047 100644 --- a/plugins/zynaddsubfx/ZynAddSubFx.cpp +++ b/plugins/zynaddsubfx/ZynAddSubFx.cpp @@ -191,8 +191,7 @@ void ZynAddSubFxInstrument::loadResource( const ResourceItem * _item ) { m_remotePlugin->lock(); m_remotePlugin->sendMessage( - RemotePlugin::message( IdLoadPresetFromFile ). - addString( QSTR_TO_STDSTR( mapper.fileName() ) ) ); + RemotePlugin::message( IdLoadPresetFromFile ).addString( fn ) ); m_remotePlugin->waitForMessage( IdLoadPresetFromFile ); m_remotePlugin->unlock(); } diff --git a/plugins/zynaddsubfx/src/AUTHORS.txt b/plugins/zynaddsubfx/src/AUTHORS.txt index a1ffa13d1..83014b3d1 100644 --- a/plugins/zynaddsubfx/src/AUTHORS.txt +++ b/plugins/zynaddsubfx/src/AUTHORS.txt @@ -1,13 +1,16 @@ Main author: - Nasca Octavian Paul + Nasca Octavian Paul Developers: - Mark McCurry + Mark McCurry + Harald Hvaal Contributors: - Gerald Folcher (legato, mono notes memory) - Lars Luthman (zombie fix,jack midi, LASH support) - Daniel Clemente (with a workaround of X11 repeated key bug) + Gerald Folcher (legato, mono notes memory) + Lars Luthman (zombie fix,jack midi, LASH support) + Daniel Clemente (with a workaround of X11 repeated key bug) Emmanuel Saracco (fix for JACK output) Achim Settelmeier (QUERTZ keyboard layout for virtual keyboard) + Jérémie Andréi (AZERTY keyboard layout, Array index fix) + Alexis Ballier (const char* <-> string mismatch, NULLMidi prototype fix) diff --git a/plugins/zynaddsubfx/src/ChangeLog b/plugins/zynaddsubfx/src/ChangeLog index 3416596ab..f1922e210 100644 --- a/plugins/zynaddsubfx/src/ChangeLog +++ b/plugins/zynaddsubfx/src/ChangeLog @@ -840,7 +840,7 @@ hovers over them - Created tooltips for the effects knobs - Standardized the code, so it could compile with pedantic without - errors [it looks like some errors may have ben missed] + errors [it looks like some errors may have been missed] 22 Feb 2009 (Mark McCurry) - Fix improper deallocation in PresetsStore @@ -861,3 +861,34 @@ - Almost all changes contained in Effects until further discussion on the style, so consistancy can be reached +28 May 2009 (Mark McCurry) + - Added some more Doxygen comments + - Added Audio Samples classes + - Added Stereo template + - Added Control class + - Added DelayCtl class + +20 Iun 2009 (Paul Nasca) + - Bugfix: WAV export of PADsynth + +10 Iul 2009 (Paul Nasca) + - Update copyright info + +11 Jul 2009 (Mark McCurry) + - Added Proportinal Portamento + - Replaced Docbook with AsciiDoc + +18 Jul 2009 (Mark McCurry) + - Enabled volume controller by default + +20 Jul 2009 (Mark McCurry) + - Incorperated AZERTY layout by sourceforge user jimee + +02 Sep 2009 (Mark McCurry) + - Incorperated const char* <-> string mismatch by Alexis Ballier + +04 Sep 2009 (Mark McCurry) + - Incorperated NULLMidiIn function prototype fix by Alexis Ballier + +07 Sep 2009 (Mark McCurry) + - Fixed glitch in XMLwrapper, which would prevent file loading diff --git a/plugins/zynaddsubfx/src/Controls/CMakeLists.txt b/plugins/zynaddsubfx/src/Controls/CMakeLists.txt new file mode 100644 index 000000000..07ee3eaf4 --- /dev/null +++ b/plugins/zynaddsubfx/src/Controls/CMakeLists.txt @@ -0,0 +1,8 @@ +set(zynaddsubfx_controls_SRCS + Control.cpp + DelayCtl.cpp +) + +add_library(zynaddsubfx_controls STATIC + ${zynaddsubfx_controls_SRCS} + ) diff --git a/plugins/zynaddsubfx/src/Controls/Control.cpp b/plugins/zynaddsubfx/src/Controls/Control.cpp new file mode 100644 index 000000000..36792fc63 --- /dev/null +++ b/plugins/zynaddsubfx/src/Controls/Control.cpp @@ -0,0 +1,40 @@ +/* + ZynAddSubFX - a software synthesizer + + Control.C - Control base class + Copyright (C) 2009-2009 Mark McCurry + Author: Mark McCurry + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ +#include "Control.h" + +Control::Control(char ndefaultval) + :defaultval(ndefaultval),lockqueue(-1),locked(false) +{} + +void Control::lock() +{ + locked=true; + lockqueue=-1; +} + +void Control::ulock() +{ + if (locked&&lockqueue>=0) + setmVal(lockqueue); + locked=false; +} + diff --git a/plugins/zynaddsubfx/src/Controls/Control.h b/plugins/zynaddsubfx/src/Controls/Control.h new file mode 100644 index 000000000..2b6eaea77 --- /dev/null +++ b/plugins/zynaddsubfx/src/Controls/Control.h @@ -0,0 +1,58 @@ +/* + ZynAddSubFX - a software synthesizer + + Control.h - Control base class + Copyright (C) 2009-2009 Mark McCurry + Author: Mark McCurry + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ +#ifndef CONTROL_H +#define CONTROL_H +#include +/**A control for a parameter within the program*/ +class Control +{ +public: + Control(char ndefaultval);/**\todo create proper initialization list*/ + ~Control() {}; + /**Return the string, which represents the internal value + * @return a string representation of the current value*/ + virtual std::string getString()const=0; + /**Set the Control to the given value + * @param nval A number 0-127*/ + virtual void setmVal(char nval)=0; + /**Return the midi value (aka the char) + * @return the current value*/ + virtual char getmVal()const=0; + /** Will lock the Control until it is ulocked + * + * Locking a Control will Stop it from having + * its internal data altered*/ + void lock(); + /** Will unlock the Control + * + * This will also update the Control + * if something attempted to update it while it was locked*/ + void ulock(); +private: + char defaultval;/** + +DelayCtl::DelayCtl() + :Control(64),value(64/127.0*1.5) {} /**\todo finishme*/ + +std::string DelayCtl::getString() const +{ + std::ostringstream buf; + buf< -#include -#include "AnalogFilter.h" - -AnalogFilter::AnalogFilter(unsigned char Ftype,REALTYPE Ffreq, REALTYPE Fq,unsigned char Fstages){ - stages=Fstages; - for (int i=0;i<3;i++){ - oldc[i]=0.0;oldd[i]=0.0; - c[i]=0.0;d[i]=0.0; - }; - type=Ftype; - freq=Ffreq; - q=Fq; - gain=1.0; - if (stages>=MAX_FILTER_STAGES) stages=MAX_FILTER_STAGES; - cleanup(); - firsttime=0; - abovenq=0;oldabovenq=0; - setfreq_and_q(Ffreq,Fq); - firsttime=1; - d[0]=0;//this is not used - outgain=1.0; -}; - -AnalogFilter::~AnalogFilter(){ -}; - -void AnalogFilter::cleanup(){ - for (int i=0;ifreq; - if (freq>(SAMPLE_RATE/2-500.0)) { - freq=SAMPLE_RATE/2-500.0; - zerocoefs=1; - }; - if (freq<0.1) freq=0.1; - //do not allow bogus Q - if (q<0.0) q=0.0; - REALTYPE tmpq,tmpgain; - if (stages==0) { - tmpq=q; - tmpgain=gain; - } else { - tmpq=(q>1.0 ? pow(q,1.0/(stages+1)) : q); - tmpgain=pow(gain,1.0/(stages+1)); - }; - - //most of theese are implementations of - //the "Cookbook formulae for audio EQ" by Robert Bristow-Johnson - //The original location of the Cookbook is: - //http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt - switch(type){ - case 0://LPF 1 pole - if (zerocoefs==0) tmp=exp(-2.0*PI*freq/SAMPLE_RATE); - else tmp=0.0; - c[0]=1.0-tmp;c[1]=0.0;c[2]=0.0; - d[1]=tmp;d[2]=0.0; - order=1; - break; - case 1://HPF 1 pole - if (zerocoefs==0) tmp=exp(-2.0*PI*freq/SAMPLE_RATE); - else tmp=0.0; - c[0]=(1.0+tmp)/2.0;c[1]=-(1.0+tmp)/2.0;c[2]=0.0; - d[1]=tmp;d[2]=0.0; - order=1; - break; - case 2://LPF 2 poles - if (zerocoefs==0){ - omega=2*PI*freq/SAMPLE_RATE; - sn=sin(omega); - cs=cos(omega); - alpha=sn/(2*tmpq); - tmp=1+alpha; - c[0]=(1.0-cs)/2.0/tmp; - c[1]=(1.0-cs)/tmp; - c[2]=(1.0-cs)/2.0/tmp; - d[1]=-2*cs/tmp*(-1); - d[2]=(1-alpha)/tmp*(-1); - } else { - c[0]=1.0;c[1]=0.0;c[2]=0.0; - d[1]=0.0;d[2]=0.0; - }; - order=2; - break; - case 3://HPF 2 poles - if (zerocoefs==0){ - omega=2*PI*freq/SAMPLE_RATE; - sn=sin(omega); - cs=cos(omega); - alpha=sn/(2*tmpq); - tmp=1+alpha; - c[0]=(1.0+cs)/2.0/tmp; - c[1]=-(1.0+cs)/tmp; - c[2]=(1.0+cs)/2.0/tmp; - d[1]=-2*cs/tmp*(-1); - d[2]=(1-alpha)/tmp*(-1); - } else { - c[0]=0.0;c[1]=0.0;c[2]=0.0; - d[1]=0.0;d[2]=0.0; - }; - order=2; - break; - case 4://BPF 2 poles - if (zerocoefs==0){ - omega=2*PI*freq/SAMPLE_RATE; - sn=sin(omega); - cs=cos(omega); - alpha=sn/(2*tmpq); - tmp=1+alpha; - c[0]=alpha/tmp*sqrt(tmpq+1); - c[1]=0; - c[2]=-alpha/tmp*sqrt(tmpq+1); - d[1]=-2*cs/tmp*(-1); - d[2]=(1-alpha)/tmp*(-1); - } else { - c[0]=0.0;c[1]=0.0;c[2]=0.0; - d[1]=0.0;d[2]=0.0; - }; - order=2; - break; - case 5://NOTCH 2 poles - if (zerocoefs==0){ - omega=2*PI*freq/SAMPLE_RATE; - sn=sin(omega); - cs=cos(omega); - alpha=sn/(2*sqrt(tmpq)); - tmp=1+alpha; - c[0]=1/tmp; - c[1]=-2*cs/tmp; - c[2]=1/tmp; - d[1]=-2*cs/tmp*(-1); - d[2]=(1-alpha)/tmp*(-1); - } else { - c[0]=1.0;c[1]=0.0;c[2]=0.0; - d[1]=0.0;d[2]=0.0; - }; - order=2; - break; - case 6://PEAK (2 poles) - if (zerocoefs==0){ - omega=2*PI*freq/SAMPLE_RATE; - sn=sin(omega); - cs=cos(omega); - tmpq*=3.0; - alpha=sn/(2*tmpq); - tmp=1+alpha/tmpgain; - c[0]=(1.0+alpha*tmpgain)/tmp; - c[1]=(-2.0*cs)/tmp; - c[2]=(1.0-alpha*tmpgain)/tmp; - d[1]=-2*cs/tmp*(-1); - d[2]=(1-alpha/tmpgain)/tmp*(-1); - } else { - c[0]=1.0;c[1]=0.0;c[2]=0.0; - d[1]=0.0;d[2]=0.0; - }; - order=2; - break; - case 7://Low Shelf - 2 poles - if (zerocoefs==0){ - omega=2*PI*freq/SAMPLE_RATE; - sn=sin(omega); - cs=cos(omega); - tmpq=sqrt(tmpq); - alpha=sn/(2*tmpq); - beta=sqrt(tmpgain)/tmpq; - tmp=(tmpgain+1.0)+(tmpgain-1.0)*cs+beta*sn; - - c[0]=tmpgain*((tmpgain+1.0)-(tmpgain-1.0)*cs+beta*sn)/tmp; - c[1]=2.0*tmpgain*((tmpgain-1.0)-(tmpgain+1.0)*cs)/tmp; - c[2]=tmpgain*((tmpgain+1.0)-(tmpgain-1.0)*cs-beta*sn)/tmp; - d[1]=-2.0*((tmpgain-1.0)+(tmpgain+1.0)*cs)/tmp*(-1); - d[2]=((tmpgain+1.0)+(tmpgain-1.0)*cs-beta*sn)/tmp*(-1); - } else { - c[0]=tmpgain;c[1]=0.0;c[2]=0.0; - d[1]=0.0;d[2]=0.0; - }; - order=2; - break; - case 8://High Shelf - 2 poles - if (zerocoefs==0){ - omega=2*PI*freq/SAMPLE_RATE; - sn=sin(omega); - cs=cos(omega); - tmpq=sqrt(tmpq); - alpha=sn/(2*tmpq); - beta=sqrt(tmpgain)/tmpq; - tmp=(tmpgain+1.0)-(tmpgain-1.0)*cs+beta*sn; - - c[0]=tmpgain*((tmpgain+1.0)+(tmpgain-1.0)*cs+beta*sn)/tmp; - c[1]=-2.0*tmpgain*((tmpgain-1.0)+(tmpgain+1.0)*cs)/tmp; - c[2]=tmpgain*((tmpgain+1.0)+(tmpgain-1.0)*cs-beta*sn)/tmp; - d[1]=2.0*((tmpgain-1.0)-(tmpgain+1.0)*cs)/tmp*(-1); - d[2]=((tmpgain+1.0)-(tmpgain-1.0)*cs-beta*sn)/tmp*(-1); - } else { - c[0]=1.0;c[1]=0.0;c[2]=0.0; - d[1]=0.0;d[2]=0.0; - }; - order=2; - break; - default://wrong type - type=0; - computefiltercoefs(); - break; - }; -}; - - -void AnalogFilter::setfreq(REALTYPE frequency){ - if (frequency<0.1) frequency=0.1; - REALTYPE rap=freq/frequency;if (rap<1.0) rap=1.0/rap; - - oldabovenq=abovenq;abovenq=frequency>(SAMPLE_RATE/2-500.0); - - int nyquistthresh=(abovenq^oldabovenq); - - - if ((rap>3.0)||(nyquistthresh!=0)){//if the frequency is changed fast, it needs interpolation (now, filter and coeficients backup) - for (int i=0;i<3;i++){ - oldc[i]=c[i];oldd[i]=d[i]; - }; - for (int i=0;i=MAX_FILTER_STAGES) stages_=MAX_FILTER_STAGES-1; - stages=stages_; - cleanup(); - computefiltercoefs(); -}; - -void AnalogFilter::singlefilterout(REALTYPE *smp,fstage &x,fstage &y,REALTYPE *c,REALTYPE *d){ - int i; - REALTYPE y0; - if (order==1) {//First order filter - for (i=0;i +#include +#include "AnalogFilter.h" + +AnalogFilter::AnalogFilter(unsigned char Ftype,REALTYPE Ffreq, REALTYPE Fq,unsigned char Fstages) +{ + stages=Fstages; + for (int i=0;i<3;i++) { + oldc[i]=0.0; + oldd[i]=0.0; + c[i]=0.0; + d[i]=0.0; + }; + type=Ftype; + freq=Ffreq; + q=Fq; + gain=1.0; + if (stages>=MAX_FILTER_STAGES) stages=MAX_FILTER_STAGES; + cleanup(); + firsttime=0; + abovenq=0; + oldabovenq=0; + setfreq_and_q(Ffreq,Fq); + firsttime=1; + d[0]=0;//this is not used + outgain=1.0; +}; + +AnalogFilter::~AnalogFilter() +{ +}; + +void AnalogFilter::cleanup() +{ + for (int i=0;ifreq; + if (freq>(SAMPLE_RATE/2-500.0)) { + freq=SAMPLE_RATE/2-500.0; + zerocoefs=1; + }; + if (freq<0.1) freq=0.1; + //do not allow bogus Q + if (q<0.0) q=0.0; + REALTYPE tmpq,tmpgain; + if (stages==0) { + tmpq=q; + tmpgain=gain; + } else { + tmpq=(q>1.0 ? pow(q,1.0/(stages+1)) : q); + tmpgain=pow(gain,1.0/(stages+1)); + }; + + //most of theese are implementations of + //the "Cookbook formulae for audio EQ" by Robert Bristow-Johnson + //The original location of the Cookbook is: + //http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt + switch (type) { + case 0://LPF 1 pole + if (zerocoefs==0) tmp=exp(-2.0*PI*freq/SAMPLE_RATE); + else tmp=0.0; + c[0]=1.0-tmp; + c[1]=0.0; + c[2]=0.0; + d[1]=tmp; + d[2]=0.0; + order=1; + break; + case 1://HPF 1 pole + if (zerocoefs==0) tmp=exp(-2.0*PI*freq/SAMPLE_RATE); + else tmp=0.0; + c[0]=(1.0+tmp)/2.0; + c[1]=-(1.0+tmp)/2.0; + c[2]=0.0; + d[1]=tmp; + d[2]=0.0; + order=1; + break; + case 2://LPF 2 poles + if (zerocoefs==0) { + omega=2*PI*freq/SAMPLE_RATE; + sn=sin(omega); + cs=cos(omega); + alpha=sn/(2*tmpq); + tmp=1+alpha; + c[0]=(1.0-cs)/2.0/tmp; + c[1]=(1.0-cs)/tmp; + c[2]=(1.0-cs)/2.0/tmp; + d[1]=-2*cs/tmp*(-1); + d[2]=(1-alpha)/tmp*(-1); + } else { + c[0]=1.0; + c[1]=0.0; + c[2]=0.0; + d[1]=0.0; + d[2]=0.0; + }; + order=2; + break; + case 3://HPF 2 poles + if (zerocoefs==0) { + omega=2*PI*freq/SAMPLE_RATE; + sn=sin(omega); + cs=cos(omega); + alpha=sn/(2*tmpq); + tmp=1+alpha; + c[0]=(1.0+cs)/2.0/tmp; + c[1]=-(1.0+cs)/tmp; + c[2]=(1.0+cs)/2.0/tmp; + d[1]=-2*cs/tmp*(-1); + d[2]=(1-alpha)/tmp*(-1); + } else { + c[0]=0.0; + c[1]=0.0; + c[2]=0.0; + d[1]=0.0; + d[2]=0.0; + }; + order=2; + break; + case 4://BPF 2 poles + if (zerocoefs==0) { + omega=2*PI*freq/SAMPLE_RATE; + sn=sin(omega); + cs=cos(omega); + alpha=sn/(2*tmpq); + tmp=1+alpha; + c[0]=alpha/tmp*sqrt(tmpq+1); + c[1]=0; + c[2]=-alpha/tmp*sqrt(tmpq+1); + d[1]=-2*cs/tmp*(-1); + d[2]=(1-alpha)/tmp*(-1); + } else { + c[0]=0.0; + c[1]=0.0; + c[2]=0.0; + d[1]=0.0; + d[2]=0.0; + }; + order=2; + break; + case 5://NOTCH 2 poles + if (zerocoefs==0) { + omega=2*PI*freq/SAMPLE_RATE; + sn=sin(omega); + cs=cos(omega); + alpha=sn/(2*sqrt(tmpq)); + tmp=1+alpha; + c[0]=1/tmp; + c[1]=-2*cs/tmp; + c[2]=1/tmp; + d[1]=-2*cs/tmp*(-1); + d[2]=(1-alpha)/tmp*(-1); + } else { + c[0]=1.0; + c[1]=0.0; + c[2]=0.0; + d[1]=0.0; + d[2]=0.0; + }; + order=2; + break; + case 6://PEAK (2 poles) + if (zerocoefs==0) { + omega=2*PI*freq/SAMPLE_RATE; + sn=sin(omega); + cs=cos(omega); + tmpq*=3.0; + alpha=sn/(2*tmpq); + tmp=1+alpha/tmpgain; + c[0]=(1.0+alpha*tmpgain)/tmp; + c[1]=(-2.0*cs)/tmp; + c[2]=(1.0-alpha*tmpgain)/tmp; + d[1]=-2*cs/tmp*(-1); + d[2]=(1-alpha/tmpgain)/tmp*(-1); + } else { + c[0]=1.0; + c[1]=0.0; + c[2]=0.0; + d[1]=0.0; + d[2]=0.0; + }; + order=2; + break; + case 7://Low Shelf - 2 poles + if (zerocoefs==0) { + omega=2*PI*freq/SAMPLE_RATE; + sn=sin(omega); + cs=cos(omega); + tmpq=sqrt(tmpq); + alpha=sn/(2*tmpq); + beta=sqrt(tmpgain)/tmpq; + tmp=(tmpgain+1.0)+(tmpgain-1.0)*cs+beta*sn; + + c[0]=tmpgain*((tmpgain+1.0)-(tmpgain-1.0)*cs+beta*sn)/tmp; + c[1]=2.0*tmpgain*((tmpgain-1.0)-(tmpgain+1.0)*cs)/tmp; + c[2]=tmpgain*((tmpgain+1.0)-(tmpgain-1.0)*cs-beta*sn)/tmp; + d[1]=-2.0*((tmpgain-1.0)+(tmpgain+1.0)*cs)/tmp*(-1); + d[2]=((tmpgain+1.0)+(tmpgain-1.0)*cs-beta*sn)/tmp*(-1); + } else { + c[0]=tmpgain; + c[1]=0.0; + c[2]=0.0; + d[1]=0.0; + d[2]=0.0; + }; + order=2; + break; + case 8://High Shelf - 2 poles + if (zerocoefs==0) { + omega=2*PI*freq/SAMPLE_RATE; + sn=sin(omega); + cs=cos(omega); + tmpq=sqrt(tmpq); + alpha=sn/(2*tmpq); + beta=sqrt(tmpgain)/tmpq; + tmp=(tmpgain+1.0)-(tmpgain-1.0)*cs+beta*sn; + + c[0]=tmpgain*((tmpgain+1.0)+(tmpgain-1.0)*cs+beta*sn)/tmp; + c[1]=-2.0*tmpgain*((tmpgain-1.0)+(tmpgain+1.0)*cs)/tmp; + c[2]=tmpgain*((tmpgain+1.0)+(tmpgain-1.0)*cs-beta*sn)/tmp; + d[1]=2.0*((tmpgain-1.0)-(tmpgain+1.0)*cs)/tmp*(-1); + d[2]=((tmpgain+1.0)-(tmpgain-1.0)*cs-beta*sn)/tmp*(-1); + } else { + c[0]=1.0; + c[1]=0.0; + c[2]=0.0; + d[1]=0.0; + d[2]=0.0; + }; + order=2; + break; + default://wrong type + type=0; + computefiltercoefs(); + break; + }; +}; + + +void AnalogFilter::setfreq(REALTYPE frequency) +{ + if (frequency<0.1) frequency=0.1; + REALTYPE rap=freq/frequency; + if (rap<1.0) rap=1.0/rap; + + oldabovenq=abovenq; + abovenq=frequency>(SAMPLE_RATE/2-500.0); + + int nyquistthresh=(abovenq^oldabovenq); + + + if ((rap>3.0)||(nyquistthresh!=0)) {//if the frequency is changed fast, it needs interpolation (now, filter and coeficients backup) + for (int i=0;i<3;i++) { + oldc[i]=c[i]; + oldd[i]=d[i]; + }; + for (int i=0;i=MAX_FILTER_STAGES) stages_=MAX_FILTER_STAGES-1; + stages=stages_; + cleanup(); + computefiltercoefs(); +}; + +void AnalogFilter::singlefilterout(REALTYPE *smp,fstage &x,fstage &y,REALTYPE *c,REALTYPE *d) +{ + int i; + REALTYPE y0; + if (order==1) {//First order filter + for (i=0;i #include "FFTwrapper.h" -FFTwrapper::FFTwrapper(int fftsize_){ +FFTwrapper::FFTwrapper(int fftsize_) +{ fftsize=fftsize_; tmpfftdata1=new fftw_real[fftsize]; tmpfftdata2=new fftw_real[fftsize]; #ifdef FFTW_VERSION_2 - planfftw=rfftwf_create_plan(fftsize,FFTW_REAL_TO_COMPLEX,FFTW_ESTIMATE|FFTW_IN_PLACE); - planfftwf_inv=rfftwf_create_plan(fftsize,FFTW_COMPLEX_TO_REAL,FFTW_ESTIMATE|FFTW_IN_PLACE); + planfftw=rfftw_create_plan(fftsize,FFTW_REAL_TO_COMPLEX,FFTW_ESTIMATE|FFTW_IN_PLACE); + planfftw_inv=rfftw_create_plan(fftsize,FFTW_COMPLEX_TO_REAL,FFTW_ESTIMATE|FFTW_IN_PLACE); #else planfftw=fftwf_plan_r2r_1d(fftsize,tmpfftdata1,tmpfftdata1,FFTW_R2HC,FFTW_ESTIMATE); planfftw_inv=fftwf_plan_r2r_1d(fftsize,tmpfftdata2,tmpfftdata2,FFTW_HC2R,FFTW_ESTIMATE); #endif }; -FFTwrapper::~FFTwrapper(){ +FFTwrapper::~FFTwrapper() +{ #ifdef FFTW_VERSION_2 - rfftwf_destroy_plan(planfftw); - rfftwf_destroy_plan(planfftwf_inv); -#else + rfftw_destroy_plan(planfftw); + rfftw_destroy_plan(planfftw_inv); +#else fftwf_destroy_plan(planfftw); fftwf_destroy_plan(planfftw_inv); #endif @@ -52,20 +54,21 @@ FFTwrapper::~FFTwrapper(){ /* * do the Fast Fourier Transform */ -void FFTwrapper::smps2freqs(REALTYPE *smps,FFTFREQS freqs){ +void FFTwrapper::smps2freqs(REALTYPE *smps,FFTFREQS freqs) +{ #ifdef FFTW_VERSION_2 for (int i=0;i + +/* If you got error messages about rfftw.h, replace the next include line with "#include " +or with "#include (if one doesn't work try the other). It may be necessary to replace +the with or . If the neither one doesn't work, +please install latest version of fftw(recomanded from the sources) from www.fftw.org. +If you'll install fftw3 you need to change the Makefile.inc +Hope all goes right." */ +#include + +#else + #include #define fftw_real float #define rfftw_plan fftwf_plan +#endif -class FFTwrapper{ - public: - FFTwrapper(int fftsize_); - ~FFTwrapper(); - void smps2freqs(REALTYPE *smps,FFTFREQS freqs); - void freqs2smps(FFTFREQS freqs,REALTYPE *smps); - private: - int fftsize; - fftw_real *tmpfftdata1,*tmpfftdata2; - rfftw_plan planfftw,planfftw_inv; +/**A wrapper for the FFTW library (Fast Fourier Transforms)*/ +class FFTwrapper +{ +public: + /**Constructor + * @param fftsize The size of samples to be fed to fftw*/ + FFTwrapper(int fftsize_); + /**Destructor*/ + ~FFTwrapper(); + /**Convert Samples to Frequencies using Fourier Transform + * @param smps Pointer to Samples to be converted; has length fftsize_ + * @param freqs Structure FFTFREQS which stores the frequencies*/ + void smps2freqs(REALTYPE *smps,FFTFREQS freqs); + void freqs2smps(FFTFREQS freqs,REALTYPE *smps); +private: + int fftsize; + fftw_real *tmpfftdata1,*tmpfftdata2; + rfftw_plan planfftw,planfftw_inv; }; #endif diff --git a/plugins/zynaddsubfx/src/DSP/Filter.C b/plugins/zynaddsubfx/src/DSP/Filter.cpp similarity index 61% rename from plugins/zynaddsubfx/src/DSP/Filter.C rename to plugins/zynaddsubfx/src/DSP/Filter.cpp index 75fc00336..f94a34214 100644 --- a/plugins/zynaddsubfx/src/DSP/Filter.C +++ b/plugins/zynaddsubfx/src/DSP/Filter.cpp @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Filter.C - Filters, uses analog,formant,etc. filters Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -25,48 +25,58 @@ #include "Filter.h" -Filter::Filter(FilterParams *pars){ +Filter::Filter(FilterParams *pars) +{ unsigned char Ftype=pars->Ptype; unsigned char Fstages=pars->Pstages; - + category=pars->Pcategory; - + switch (category) { - case 1:filter=new FormantFilter(pars); - break; - case 2:filter=new SVFilter(Ftype,1000.0,pars->getq(),Fstages); - filter->outgain=dB2rap(pars->getgain()); - if (filter->outgain>1.0) filter->outgain=sqrt(filter->outgain); - break; - default:filter=new AnalogFilter(Ftype,1000.0,pars->getq(),Fstages); - if ((Ftype>=6)&&(Ftype<=8)) filter->setgain(pars->getgain()); - else filter->outgain=dB2rap(pars->getgain()); - break; + case 1: + filter=new FormantFilter(pars); + break; + case 2: + filter=new SVFilter(Ftype,1000.0,pars->getq(),Fstages); + filter->outgain=dB2rap(pars->getgain()); + if (filter->outgain>1.0) filter->outgain=sqrt(filter->outgain); + break; + default: + filter=new AnalogFilter(Ftype,1000.0,pars->getq(),Fstages); + if ((Ftype>=6)&&(Ftype<=8)) filter->setgain(pars->getgain()); + else filter->outgain=dB2rap(pars->getgain()); + break; }; }; -Filter::~Filter(){ +Filter::~Filter() +{ delete (filter); }; -void Filter::filterout(REALTYPE *smp){ +void Filter::filterout(REALTYPE *smp) +{ filter->filterout(smp); }; -void Filter::setfreq(REALTYPE frequency){ +void Filter::setfreq(REALTYPE frequency) +{ filter->setfreq(frequency); }; -void Filter::setfreq_and_q(REALTYPE frequency,REALTYPE q_){ +void Filter::setfreq_and_q(REALTYPE frequency,REALTYPE q_) +{ filter->setfreq_and_q(frequency,q_); }; -void Filter::setq(REALTYPE q_){ +void Filter::setq(REALTYPE q_) +{ filter->setq(q_); }; -REALTYPE Filter::getrealfreq(REALTYPE freqpitch){ +REALTYPE Filter::getrealfreq(REALTYPE freqpitch) +{ if ((category==0)||(category==2)) return(pow(2.0,freqpitch+9.96578428));//log2(1000)=9.95748 - else return(freqpitch); + else return(freqpitch); }; diff --git a/plugins/zynaddsubfx/src/DSP/Filter.h b/plugins/zynaddsubfx/src/DSP/Filter.h index 4ca5f3ff0..42bef55ce 100644 --- a/plugins/zynaddsubfx/src/DSP/Filter.h +++ b/plugins/zynaddsubfx/src/DSP/Filter.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Filter.h - Filters, uses analog,formant,etc. filters Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -31,17 +31,18 @@ #include "SVFilter.h" #include "../Params/FilterParams.h" -class Filter{ - public: +class Filter +{ +public: Filter(FilterParams *pars); - ~Filter(); + ~Filter(); void filterout(REALTYPE *smp); void setfreq(REALTYPE frequency); void setfreq_and_q(REALTYPE frequency,REALTYPE q_); void setq(REALTYPE q_); REALTYPE getrealfreq(REALTYPE freqpitch); - private: +private: Filter_ *filter; unsigned char category; }; diff --git a/plugins/zynaddsubfx/src/DSP/Filter_.h b/plugins/zynaddsubfx/src/DSP/Filter_.h index 116a41bf6..b3f2badc1 100644 --- a/plugins/zynaddsubfx/src/DSP/Filter_.h +++ b/plugins/zynaddsubfx/src/DSP/Filter_.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Filter_.h - This class is inherited by filter classes Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -25,16 +25,17 @@ #include "../globals.h" -class Filter_{ - public: - virtual ~Filter_(){}; - virtual void filterout(REALTYPE *smp){}; - virtual void setfreq(REALTYPE frequency){}; - virtual void setfreq_and_q(REALTYPE frequency,REALTYPE q_){}; - virtual void setq(REALTYPE q_){}; - virtual void setgain(REALTYPE dBgain){}; +class Filter_ +{ +public: + virtual ~Filter_() {}; + virtual void filterout(REALTYPE *smp)=0; + virtual void setfreq(REALTYPE frequency)=0; + virtual void setfreq_and_q(REALTYPE frequency,REALTYPE q_)=0; + virtual void setq(REALTYPE q_)=0; + virtual void setgain(REALTYPE dBgain) {}; REALTYPE outgain; - private: +private: }; diff --git a/plugins/zynaddsubfx/src/DSP/FormantFilter.C b/plugins/zynaddsubfx/src/DSP/FormantFilter.C deleted file mode 100644 index f82df1e8d..000000000 --- a/plugins/zynaddsubfx/src/DSP/FormantFilter.C +++ /dev/null @@ -1,163 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - FormantFilter.C - formant filters - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include -#include "FormantFilter.h" - -FormantFilter::FormantFilter(FilterParams *pars){ - numformants=pars->Pnumformants; - for (int i=0;iPstages); - cleanup(); - inbuffer=new REALTYPE [SOUND_BUFFER_SIZE]; - tmpbuf=new REALTYPE [SOUND_BUFFER_SIZE]; - - for (int j=0;jgetformantfreq(pars->Pvowels[j].formants[i].freq); - formantpar[j][i].amp=pars->getformantamp(pars->Pvowels[j].formants[i].amp); - formantpar[j][i].q=pars->getformantq(pars->Pvowels[j].formants[i].q); - }; - for (int i=0;iPformantslowness/128.0),3.0); - - sequencesize=pars->Psequencesize;if (sequencesize==0) sequencesize=1; - for (int k=0;kPsequence[k].nvowel; - - vowelclearness=pow(10.0,(pars->Pvowelclearness-32.0)/48.0); - - sequencestretch=pow(0.1,(pars->Psequencestretch-32.0)/48.0); - if (pars->Psequencereversed) sequencestretch*= -1.0; - - outgain=dB2rap(pars->getgain()); - - oldinput=-1.0; - Qfactor=1.0;oldQfactor=Qfactor; - firsttime=1; -}; - -FormantFilter::~FormantFilter(){ - for (int i=0;icleanup(); -}; - -void FormantFilter::setpos(REALTYPE input){ - int p1,p2; - - if (firsttime!=0) slowinput=input; - else slowinput=slowinput*(1.0-formantslowness)+input*formantslowness; - - if ((fabs(oldinput-input)<0.001)&&(fabs(slowinput-input)<0.001)&& - (fabs(Qfactor-oldQfactor)<0.001)) { -// oldinput=input; daca setez asta, o sa faca probleme la schimbari foarte lente - firsttime=0; - return; - } else oldinput=input; - - - REALTYPE pos=fmod(input*sequencestretch,1.0);if (pos<0.0) pos+=1.0; - - F2I(pos*sequencesize,p2); - p1=p2-1;if (p1<0) p1+=sequencesize; - - pos=fmod(pos*sequencesize,1.0); - if (pos<0.0) pos=0.0; else if (pos>1.0) pos=1.0; - pos=(atan((pos*2.0-1.0)*vowelclearness)/atan(vowelclearness)+1.0)*0.5; - - p1=sequence[p1].nvowel; - p2=sequence[p2].nvowel; - - if (firsttime!=0) { - for (int i=0;isetfreq_and_q(currentformants[i].freq,currentformants[i].q*Qfactor); - oldformantamp[i]=currentformants[i].amp; - }; - firsttime=0; - } else { - for (int i=0;isetfreq_and_q(currentformants[i].freq,currentformants[i].q*Qfactor); - }; - }; - - oldQfactor=Qfactor; -}; - -void FormantFilter::setfreq(REALTYPE frequency){ - setpos(frequency); -}; - -void FormantFilter::setq(REALTYPE q_){ - Qfactor=q_; - for (int i=0;isetq(Qfactor*currentformants[i].q); -}; - -void FormantFilter::setfreq_and_q(REALTYPE frequency,REALTYPE q_){ - Qfactor=q_; - setpos(frequency); -}; - - -void FormantFilter::filterout(REALTYPE *smp){ - int i,j; - for (i=0;ifilterout(tmpbuf); - - if (ABOVE_AMPLITUDE_THRESHOLD(oldformantamp[j],currentformants[j].amp)) - for (i=0;i +#include +#include "FormantFilter.h" + +FormantFilter::FormantFilter(FilterParams *pars) +{ + numformants=pars->Pnumformants; + for (int i=0;iPstages); + cleanup(); + inbuffer=new REALTYPE [SOUND_BUFFER_SIZE]; + tmpbuf=new REALTYPE [SOUND_BUFFER_SIZE]; + + for (int j=0;jgetformantfreq(pars->Pvowels[j].formants[i].freq); + formantpar[j][i].amp=pars->getformantamp(pars->Pvowels[j].formants[i].amp); + formantpar[j][i].q=pars->getformantq(pars->Pvowels[j].formants[i].q); + }; + for (int i=0;iPformantslowness/128.0),3.0); + + sequencesize=pars->Psequencesize; + if (sequencesize==0) sequencesize=1; + for (int k=0;kPsequence[k].nvowel; + + vowelclearness=pow(10.0,(pars->Pvowelclearness-32.0)/48.0); + + sequencestretch=pow(0.1,(pars->Psequencestretch-32.0)/48.0); + if (pars->Psequencereversed) sequencestretch*= -1.0; + + outgain=dB2rap(pars->getgain()); + + oldinput=-1.0; + Qfactor=1.0; + oldQfactor=Qfactor; + firsttime=1; +}; + +FormantFilter::~FormantFilter() +{ + for (int i=0;icleanup(); +}; + +void FormantFilter::setpos(REALTYPE input) +{ + int p1,p2; + + if (firsttime!=0) slowinput=input; + else slowinput=slowinput*(1.0-formantslowness)+input*formantslowness; + + if ((fabs(oldinput-input)<0.001)&&(fabs(slowinput-input)<0.001)&& + (fabs(Qfactor-oldQfactor)<0.001)) { +// oldinput=input; daca setez asta, o sa faca probleme la schimbari foarte lente + firsttime=0; + return; + } else oldinput=input; + + + REALTYPE pos=fmod(input*sequencestretch,1.0); + if (pos<0.0) pos+=1.0; + + F2I(pos*sequencesize,p2); + p1=p2-1; + if (p1<0) p1+=sequencesize; + + pos=fmod(pos*sequencesize,1.0); + if (pos<0.0) pos=0.0; + else if (pos>1.0) pos=1.0; + pos=(atan((pos*2.0-1.0)*vowelclearness)/atan(vowelclearness)+1.0)*0.5; + + p1=sequence[p1].nvowel; + p2=sequence[p2].nvowel; + + if (firsttime!=0) { + for (int i=0;isetfreq_and_q(currentformants[i].freq,currentformants[i].q*Qfactor); + oldformantamp[i]=currentformants[i].amp; + }; + firsttime=0; + } else { + for (int i=0;isetfreq_and_q(currentformants[i].freq,currentformants[i].q*Qfactor); + }; + }; + + oldQfactor=Qfactor; +}; + +void FormantFilter::setfreq(REALTYPE frequency) +{ + setpos(frequency); +}; + +void FormantFilter::setq(REALTYPE q_) +{ + Qfactor=q_; + for (int i=0;isetq(Qfactor*currentformants[i].q); +}; + +void FormantFilter::setfreq_and_q(REALTYPE frequency,REALTYPE q_) +{ + Qfactor=q_; + setpos(frequency); +}; + + +void FormantFilter::filterout(REALTYPE *smp) +{ + int i,j; + for (i=0;ifilterout(tmpbuf); + + if (ABOVE_AMPLITUDE_THRESHOLD(oldformantamp[j],currentformants[j].amp)) + for (i=0;i #include "SVFilter.h" -SVFilter::SVFilter(unsigned char Ftype,REALTYPE Ffreq, REALTYPE Fq,unsigned char Fstages){ +SVFilter::SVFilter(unsigned char Ftype,REALTYPE Ffreq, REALTYPE Fq,unsigned char Fstages) +{ stages=Fstages; type=Ftype; freq=Ffreq; @@ -38,19 +39,24 @@ SVFilter::SVFilter(unsigned char Ftype,REALTYPE Ffreq, REALTYPE Fq,unsigned char setfreq_and_q(Ffreq,Fq); }; -SVFilter::~SVFilter(){ +SVFilter::~SVFilter() +{ }; -void SVFilter::cleanup(){ - for (int i=0;i0.99999) par.f=0.99999; par.q=1.0-atan(sqrt(q))*2.0/PI; @@ -59,18 +65,21 @@ void SVFilter::computefiltercoefs(){ }; -void SVFilter::setfreq(REALTYPE frequency){ +void SVFilter::setfreq(REALTYPE frequency) +{ if (frequency<0.1) frequency=0.1; - REALTYPE rap=freq/frequency;if (rap<1.0) rap=1.0/rap; - - oldabovenq=abovenq;abovenq=frequency>(SAMPLE_RATE/2-500.0); - + REALTYPE rap=freq/frequency; + if (rap<1.0) rap=1.0/rap; + + oldabovenq=abovenq; + abovenq=frequency>(SAMPLE_RATE/2-500.0); + int nyquistthresh=(abovenq^oldabovenq); - if ((rap>3.0)||(nyquistthresh!=0)){//if the frequency is changed fast, it needs interpolation (now, filter and coeficients backup) - if (firsttime==0) needsinterpolation=1; - ipar=par; + if ((rap>3.0)||(nyquistthresh!=0)) {//if the frequency is changed fast, it needs interpolation (now, filter and coeficients backup) + if (firsttime==0) needsinterpolation=1; + ipar=par; }; freq=frequency; computefiltercoefs(); @@ -78,72 +87,87 @@ void SVFilter::setfreq(REALTYPE frequency){ }; -void SVFilter::setfreq_and_q(REALTYPE frequency,REALTYPE q_){ +void SVFilter::setfreq_and_q(REALTYPE frequency,REALTYPE q_) +{ q=q_; setfreq(frequency); }; -void SVFilter::setq(REALTYPE q_){ +void SVFilter::setq(REALTYPE q_) +{ q=q_; computefiltercoefs(); }; -void SVFilter::settype(int type_){ +void SVFilter::settype(int type_) +{ type=type_; computefiltercoefs(); }; -void SVFilter::setgain(REALTYPE dBgain){ +void SVFilter::setgain(REALTYPE dBgain) +{ gain=dB2rap(dBgain); computefiltercoefs(); }; -void SVFilter::setstages(int stages_){ +void SVFilter::setstages(int stages_) +{ if (stages_>=MAX_FILTER_STAGES) stages_=MAX_FILTER_STAGES-1; stages=stages_; cleanup(); computefiltercoefs(); }; -void SVFilter::singlefilterout(REALTYPE *smp,fstage &x,parameters &par){ +void SVFilter::singlefilterout(REALTYPE *smp,fstage &x,parameters &par) +{ int i; REALTYPE *out=NULL; - switch(type){ - case 0: out=&x.low;break; - case 1: out=&x.high;break; - case 2: out=&x.band;break; - case 3: out=&x.notch;break; + switch (type) { + case 0: + out=&x.low; + break; + case 1: + out=&x.high; + break; + case 2: + out=&x.band; + break; + case 3: + out=&x.notch; + break; }; - - for (i=0;i(fb,0.0); }; -Alienwah::~Alienwah(){ +Alienwah::~Alienwah() +{ if (oldl!=NULL) delete [] oldl; if (oldr!=NULL) delete [] oldr ; }; @@ -41,7 +42,8 @@ Alienwah::~Alienwah(){ /* * Apply the effect */ -void Alienwah::out(REALTYPE *smpsl,REALTYPE *smpsr){ +void Alienwah::out(REALTYPE *smpsl,REALTYPE *smpsr) +{ REALTYPE lfol,lfor; //Left/Right LFOs complex clfol,clfor,out,tmp; /**\todo Rework, as optimization can be used when the new complex type is @@ -49,37 +51,37 @@ void Alienwah::out(REALTYPE *smpsl,REALTYPE *smpsr){ * Before all calculations needed to be done with individual REALTYPE, * but now they can be done together*/ lfo.effectlfoout(&lfol,&lfor); - lfol*=depth*PI*2.0;lfor*=depth*PI*2.0; + lfol*=depth*PI*2.0; + lfor*=depth*PI*2.0; clfol=complex(cos(lfol+phase)*fb,sin(lfol+phase)*fb); //rework clfor=complex(cos(lfor+phase)*fb,sin(lfor+phase)*fb); //rework - for (int i=0;i=Pdelay) oldk=0; - //LRcross - efxoutl[i]=l*(1.0-lrcross)+r*lrcross; - efxoutr[i]=r*(1.0-lrcross)+l*lrcross; + if (++oldk>=Pdelay) oldk=0; + //LRcross + efxoutl[i]=l*(1.0-lrcross)+r*lrcross; + efxoutr[i]=r*(1.0-lrcross)+l*lrcross; }; oldclfol=clfol; @@ -90,10 +92,11 @@ void Alienwah::out(REALTYPE *smpsl,REALTYPE *smpsr){ /* * Cleanup the effect */ -void Alienwah::cleanup(){ - for (int i=0;i(0.0,0.0); - oldr[i]=complex(0.0,0.0); +void Alienwah::cleanup() +{ + for (int i=0;i(0.0,0.0); + oldr[i]=complex(0.0,0.0); }; oldk=0; }; @@ -103,12 +106,14 @@ void Alienwah::cleanup(){ * Parameter control */ -void Alienwah::setdepth(const unsigned char &Pdepth){ +void Alienwah::setdepth(const unsigned char &Pdepth) +{ this->Pdepth=Pdepth; depth=(Pdepth/127.0); }; -void Alienwah::setfb(const unsigned char &Pfb){ +void Alienwah::setfb(const unsigned char &Pfb) +{ this->Pfb=Pfb; fb=fabs((Pfb-64.0)/64.1); fb=sqrt(fb); @@ -116,29 +121,34 @@ void Alienwah::setfb(const unsigned char &Pfb){ if (Pfb<64) fb=-fb; }; -void Alienwah::setvolume(const unsigned char &Pvolume){ +void Alienwah::setvolume(const unsigned char &Pvolume) +{ this->Pvolume=Pvolume; outvolume=Pvolume/127.0; if (insertion==0) volume=1.0; - else volume=outvolume; + else volume=outvolume; }; -void Alienwah::setpanning(const unsigned char &Ppanning){ +void Alienwah::setpanning(const unsigned char &Ppanning) +{ this->Ppanning=Ppanning; panning=Ppanning/127.0; }; -void Alienwah::setlrcross(const unsigned char &Plrcross){ +void Alienwah::setlrcross(const unsigned char &Plrcross) +{ this->Plrcross=Plrcross; lrcross=Plrcross/127.0; }; -void Alienwah::setphase(const unsigned char &Pphase){ +void Alienwah::setphase(const unsigned char &Pphase) +{ this->Pphase=Pphase; phase=(Pphase-64.0)/64.0*PI; }; -void Alienwah::setdelay(const unsigned char &Pdelay){ +void Alienwah::setdelay(const unsigned char &Pdelay) +{ if (oldl!=NULL) delete [] oldl; if (oldr!=NULL) delete [] oldr; if (Pdelay>=MAX_ALIENWAH_DELAY) this->Pdelay=MAX_ALIENWAH_DELAY; @@ -148,19 +158,21 @@ void Alienwah::setdelay(const unsigned char &Pdelay){ cleanup(); }; -void Alienwah::setpreset(unsigned char npreset){ +void Alienwah::setpreset(unsigned char npreset) +{ const int PRESET_SIZE=11; const int NUM_PRESETS=4; unsigned char presets[NUM_PRESETS][PRESET_SIZE]={ - //AlienWah1 - {127,64,70,0,0,62,60,105,25,0,64}, - //AlienWah2 - {127,64,73,106,0,101,60,105,17,0,64}, - //AlienWah3 - {127,64,63,0,1,100,112,105,31,0,42}, - //AlienWah4 - {93,64,25,0,1,66,101,11,47,0,86}}; - + //AlienWah1 + {127,64,70,0,0,62,60,105,25,0,64}, + //AlienWah2 + {127,64,73,106,0,101,60,105,17,0,64}, + //AlienWah3 + {127,64,63,0,1,100,112,105,31,0,42}, + //AlienWah4 + {93,64,25,0,1,66,101,11,47,0,86} + }; + if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1; for (int n=0;n *oldl,*oldr; - complex oldclfol,oldclfor; - int oldk; +private: + //Alienwah Parameters + EffectLFO lfo;//lfo-ul Alienwah + unsigned char Pvolume; + unsigned char Ppanning; + unsigned char Pdepth;//the depth of the Alienwah + unsigned char Pfb;//feedback + unsigned char Plrcross;//feedback + unsigned char Pdelay; + unsigned char Pphase; + + + //Control Parameters + void setvolume(const unsigned char &Pvolume); + void setpanning(const unsigned char &Ppanning); + void setdepth(const unsigned char &Pdepth); + void setfb(const unsigned char &Pfb); + void setlrcross(const unsigned char &Plrcross); + void setdelay(const unsigned char &Pdelay); + void setphase(const unsigned char &Pphase); + + //Internal Values + REALTYPE panning,fb,depth,lrcross,phase; + complex *oldl,*oldr; + complex oldclfol,oldclfor; + int oldk; }; #endif diff --git a/plugins/zynaddsubfx/src/Effects/CMakeLists.txt b/plugins/zynaddsubfx/src/Effects/CMakeLists.txt new file mode 100644 index 000000000..0c15dfa87 --- /dev/null +++ b/plugins/zynaddsubfx/src/Effects/CMakeLists.txt @@ -0,0 +1,19 @@ +set(zynaddsubfx_effect_SRCS + Alienwah.cpp + Chorus.cpp + Distorsion.cpp + DynamicFilter.cpp + Echo.cpp + Effect.cpp + EffectLFO.cpp + EffectMgr.cpp + EQ.cpp + Phaser.cpp + Reverb.cpp +) + +add_library(zynaddsubfx_effect STATIC + ${zynaddsubfx_effect_SRCS} + ) + +target_link_libraries(zynaddsubfx_effect) diff --git a/plugins/zynaddsubfx/src/Effects/Chorus.C b/plugins/zynaddsubfx/src/Effects/Chorus.C deleted file mode 100644 index d7462cc03..000000000 --- a/plugins/zynaddsubfx/src/Effects/Chorus.C +++ /dev/null @@ -1,275 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Chorus.C - Chorus and Flange effects - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include "Chorus.h" -#include - -using namespace std; - -Chorus::Chorus(const int &insertion_,REALTYPE *const efxoutl_,REALTYPE *const efxoutr_) - :Effect(insertion_,efxoutl_,efxoutr_,NULL,0) -{ - dlk=0;drk=0; - maxdelay=(int)(MAX_CHORUS_DELAY/1000.0*SAMPLE_RATE); - delayl=new REALTYPE[maxdelay]; - delayr=new REALTYPE[maxdelay]; - - setpreset(Ppreset); - - lfo.effectlfoout(&lfol,&lfor); - dl2=getdelay(lfol); - dr2=getdelay(lfor); - cleanup(); -}; - -Chorus::~Chorus(){ - delete [] delayl; - delete [] delayr; -}; - -/* - * get the delay value in samples; xlfo is the current lfo value - */ -REALTYPE Chorus::getdelay(REALTYPE xlfo){ - REALTYPE result; - if (Pflangemode==0){ - result=(delay+xlfo*depth)*SAMPLE_RATE; - } else result=0; - - //check if it is too big delay(caused bu errornous setdelay() and setdepth() - /**\todo fix setdelay() and setdepth(), so this error cannot occur*/ - if ((result+0.5)>=maxdelay) { - cerr << "WARNING: Chorus.C::getdelay(..) too big delay (see setdelay and setdepth funcs.)\n"; - result=maxdelay-1.0; - }; - return(result); -}; - -/* - * Apply the effect - */ -void Chorus::out(REALTYPE *smpsl,REALTYPE *smpsr){ - int i; - const REALTYPE one=1.0; - dl1=dl2;dr1=dr2; - lfo.effectlfoout(&lfol,&lfor); - - dl2=getdelay(lfol); - dr2=getdelay(lfor); - - for (i=0;i=maxdelay) dlk=0; - REALTYPE tmp=dlk-mdel+maxdelay*2.0;//where should I get the sample from - - F2I(tmp,dlhi); - dlhi%=maxdelay; - - dlhi2=(dlhi-1+maxdelay)%maxdelay; - dllo=1.0-fmod(tmp,one); - efxoutl[i]=delayl[dlhi2]*dllo+delayl[dlhi]*(1.0-dllo); - delayl[dlk]=inl+efxoutl[i]*fb; - - //Right channel - - //compute the delay in samples using linear interpolation between the lfo delays - mdel=(dr1*(SOUND_BUFFER_SIZE-i)+dr2*i)/SOUND_BUFFER_SIZE; - if (++drk>=maxdelay) drk=0; - tmp=drk*1.0-mdel+maxdelay*2.0;//where should I get the sample from - - F2I(tmp,dlhi); - dlhi%=maxdelay; - - dlhi2=(dlhi-1+maxdelay)%maxdelay; - dllo=1.0-fmod(tmp,one); - efxoutr[i]=delayr[dlhi2]*dllo+delayr[dlhi]*(1.0-dllo); - delayr[dlk]=inr+efxoutr[i]*fb; - - }; - - if (Poutsub!=0) - for (i=0;iPdepth=Pdepth; - depth=(pow(8.0,(Pdepth/127.0)*2.0)-1.0)/1000.0;//seconds -}; - -void Chorus::setdelay(const unsigned char &Pdelay){ - this->Pdelay=Pdelay; - delay=(pow(10.0,(Pdelay/127.0)*2.0)-1.0)/1000.0;//seconds -}; - -void Chorus::setfb(const unsigned char &Pfb){ - this->Pfb=Pfb; - fb=(Pfb-64.0)/64.1; -}; -void Chorus::setvolume(const unsigned char &Pvolume){ - this->Pvolume=Pvolume; - outvolume=Pvolume/127.0; - if (insertion==0) volume=1.0; - else volume=outvolume; -}; - -void Chorus::setpanning(const unsigned char &Ppanning){ - this->Ppanning=Ppanning; - panning=Ppanning/127.0; -}; - -void Chorus::setlrcross(const unsigned char &Plrcross){ - this->Plrcross=Plrcross; - lrcross=Plrcross/127.0; -}; - -void Chorus::setpreset(unsigned char npreset){ - const int PRESET_SIZE=12; - const int NUM_PRESETS=10; - unsigned char presets[NUM_PRESETS][PRESET_SIZE]={ - //Chorus1 - {64,64,50,0,0,90,40,85,64,119,0,0}, - //Chorus2 - {64,64,45,0,0,98,56,90,64,19,0,0}, - //Chorus3 - {64,64,29,0,1,42,97,95,90,127,0,0}, - //Celeste1 - {64,64,26,0,0,42,115,18,90,127,0,0}, - //Celeste2 - {64,64,29,117,0,50,115,9,31,127,0,1}, - //Flange1 - {64,64,57,0,0,60,23,3,62,0,0,0}, - //Flange2 - {64,64,33,34,1,40,35,3,109,0,0,0}, - //Flange3 - {64,64,53,34,1,94,35,3,54,0,0,1}, - //Flange4 - {64,64,40,0,1,62,12,19,97,0,0,0}, - //Flange5 - {64,64,55,105,0,24,39,19,17,0,0,1}}; - - if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1; - for (int n=0;n1) Pflangemode=1; - else Pflangemode=value; - break; - case 11:if (value>1) Poutsub=1; - else Poutsub=value; - break; - }; -}; - -unsigned char Chorus::getpar(const int &npar)const{ - switch (npar){ - case 0: return(Pvolume); - break; - case 1: return(Ppanning); - break; - case 2: return(lfo.Pfreq); - break; - case 3: return(lfo.Prandomness); - break; - case 4: return(lfo.PLFOtype); - break; - case 5: return(lfo.Pstereo); - break; - case 6: return(Pdepth); - break; - case 7: return(Pdelay); - break; - case 8: return(Pfb); - break; - case 9: return(Plrcross); - break; - case 10:return(Pflangemode); - break; - case 11:return(Poutsub); - break; - default:return (0); - }; - -}; - diff --git a/plugins/zynaddsubfx/src/Effects/Chorus.cpp b/plugins/zynaddsubfx/src/Effects/Chorus.cpp new file mode 100644 index 000000000..844e87f50 --- /dev/null +++ b/plugins/zynaddsubfx/src/Effects/Chorus.cpp @@ -0,0 +1,316 @@ +/* + ZynAddSubFX - a software synthesizer + + Chorus.C - Chorus and Flange effects + Copyright (C) 2002-2005 Nasca Octavian Paul + Author: Nasca Octavian Paul + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include +#include "Chorus.h" +#include + +using namespace std; + +Chorus::Chorus(const int &insertion_,REALTYPE *const efxoutl_,REALTYPE *const efxoutr_) + :Effect(insertion_,efxoutl_,efxoutr_,NULL,0), + maxdelay((int)(MAX_CHORUS_DELAY/1000.0*SAMPLE_RATE)), + delaySample(maxdelay) +{ + dlk=0; + drk=0; + //maxdelay=(int)(MAX_CHORUS_DELAY/1000.0*SAMPLE_RATE); + //delayl=new REALTYPE[maxdelay]; + //delayr=new REALTYPE[maxdelay]; + + setpreset(Ppreset); + + lfo.effectlfoout(&lfol,&lfor); + dl2=getdelay(lfol); + dr2=getdelay(lfor); + cleanup(); +}; + +Chorus::~Chorus() {}; + +/* + * get the delay value in samples; xlfo is the current lfo value + */ +REALTYPE Chorus::getdelay(REALTYPE xlfo) +{ + REALTYPE result; + if (Pflangemode==0) { + result=(delay+xlfo*depth)*SAMPLE_RATE; + } else result=0; + + //check if it is too big delay(caused bu errornous setdelay() and setdepth() + /**\todo fix setdelay() and setdepth(), so this error cannot occur*/ + if ((result+0.5)>=maxdelay) { + cerr << "WARNING: Chorus.C::getdelay(..) too big delay (see setdelay and setdepth funcs.)\n"; + result=maxdelay-1.0; + }; + return(result); +}; + +/* + * Apply the effect + */ +void Chorus::out(REALTYPE *smpsl,REALTYPE *smpsr) +{ + const Stereo input(AuSample(SOUND_BUFFER_SIZE,smpsl),AuSample(SOUND_BUFFER_SIZE,smpsr)); + out(input); +} + +void Chorus::out(const Stereo &input) +{ + const REALTYPE one=1.0; + dl1=dl2; + dr1=dr2; + lfo.effectlfoout(&lfol,&lfor); + + dl2=getdelay(lfol); + dr2=getdelay(lfor); + + for (int i=0;i tmpc(inl,inr); + //REALTYPE r=inr; + inl=tmpc.l()*(1.0-lrcross)+tmpc.r()*lrcross; + inr=tmpc.r()*(1.0-lrcross)+tmpc.l()*lrcross; + + //Left channel + + //compute the delay in samples using linear interpolation between the lfo delays + mdel=(dl1*(SOUND_BUFFER_SIZE-i)+dl2*i)/SOUND_BUFFER_SIZE; + if (++dlk>=maxdelay) dlk=0; + REALTYPE tmp=dlk-mdel+maxdelay*2.0;//where should I get the sample from + + F2I(tmp,dlhi); + dlhi%=maxdelay; + + dlhi2=(dlhi-1+maxdelay)%maxdelay; + dllo=1.0-fmod(tmp,one); + efxoutl[i]=delaySample.l()[dlhi2]*dllo+delaySample.l()[dlhi]*(1.0-dllo); + delaySample.l()[dlk]=inl+efxoutl[i]*fb; + + //Right channel + + //compute the delay in samples using linear interpolation between the lfo delays + mdel=(dr1*(SOUND_BUFFER_SIZE-i)+dr2*i)/SOUND_BUFFER_SIZE; + if (++drk>=maxdelay) drk=0; + tmp=drk*1.0-mdel+maxdelay*2.0;//where should I get the sample from + + F2I(tmp,dlhi); + dlhi%=maxdelay; + + dlhi2=(dlhi-1+maxdelay)%maxdelay; + dllo=1.0-fmod(tmp,one); + efxoutr[i]=delaySample.r()[dlhi2]*dllo+delaySample.r()[dlhi]*(1.0-dllo); + delaySample.r()[dlk]=inr+efxoutr[i]*fb; + + }; + + if (Poutsub!=0) + for (int i=0;iPdepth=Pdepth; + depth=(pow(8.0,(Pdepth/127.0)*2.0)-1.0)/1000.0;//seconds +}; + +void Chorus::setdelay(const unsigned char &Pdelay) +{ + this->Pdelay=Pdelay; + delay=(pow(10.0,(Pdelay/127.0)*2.0)-1.0)/1000.0;//seconds +}; + +void Chorus::setfb(const unsigned char &Pfb) +{ + this->Pfb=Pfb; + fb=(Pfb-64.0)/64.1; +}; +void Chorus::setvolume(const unsigned char &Pvolume) +{ + this->Pvolume=Pvolume; + outvolume=Pvolume/127.0; + if (insertion==0) volume=1.0; + else volume=outvolume; +}; + +void Chorus::setpanning(const unsigned char &Ppanning) +{ + this->Ppanning=Ppanning; + panning=Ppanning/127.0; +}; + +void Chorus::setlrcross(const unsigned char &Plrcross) +{ + this->Plrcross=Plrcross; + lrcross=Plrcross/127.0; +}; + +void Chorus::setpreset(unsigned char npreset) +{ + const int PRESET_SIZE=12; + const int NUM_PRESETS=10; + unsigned char presets[NUM_PRESETS][PRESET_SIZE]={ + //Chorus1 + {64,64,50,0,0,90,40,85,64,119,0,0}, + //Chorus2 + {64,64,45,0,0,98,56,90,64,19,0,0}, + //Chorus3 + {64,64,29,0,1,42,97,95,90,127,0,0}, + //Celeste1 + {64,64,26,0,0,42,115,18,90,127,0,0}, + //Celeste2 + {64,64,29,117,0,50,115,9,31,127,0,1}, + //Flange1 + {64,64,57,0,0,60,23,3,62,0,0,0}, + //Flange2 + {64,64,33,34,1,40,35,3,109,0,0,0}, + //Flange3 + {64,64,53,34,1,94,35,3,54,0,0,1}, + //Flange4 + {64,64,40,0,1,62,12,19,97,0,0,0}, + //Flange5 + {64,64,55,105,0,24,39,19,17,0,0,1} + }; + + if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1; + for (int n=0;n1) Pflangemode=1; + else Pflangemode=value; + break; + case 11: + if (value>1) Poutsub=1; + else Poutsub=value; + break; + }; +}; + +unsigned char Chorus::getpar(const int &npar)const +{ + switch (npar) { + case 0: + return(Pvolume); + break; + case 1: + return(Ppanning); + break; + case 2: + return(lfo.Pfreq); + break; + case 3: + return(lfo.Prandomness); + break; + case 4: + return(lfo.PLFOtype); + break; + case 5: + return(lfo.Pstereo); + break; + case 6: + return(Pdepth); + break; + case 7: + return(Pdelay); + break; + case 8: + return(Pfb); + break; + case 9: + return(Plrcross); + break; + case 10: + return(Pflangemode); + break; + case 11: + return(Poutsub); + break; + default: + return (0); + }; + +}; + diff --git a/plugins/zynaddsubfx/src/Effects/Chorus.h b/plugins/zynaddsubfx/src/Effects/Chorus.h index b53db141e..488e4d85d 100644 --- a/plugins/zynaddsubfx/src/Effects/Chorus.h +++ b/plugins/zynaddsubfx/src/Effects/Chorus.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Chorus.h - Chorus and Flange effects Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -25,86 +25,91 @@ #include "../globals.h" #include "Effect.h" #include "EffectLFO.h" +#include "../Samples/AuSample.h" +#include "../Misc/Stereo.h" #define MAX_CHORUS_DELAY 250.0 //ms /**Chorus and Flange effects*/ -class Chorus:public Effect { - public: - Chorus(const int &insetion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_); - /**Destructor*/ - ~Chorus(); - void out(REALTYPE *smpsl,REALTYPE *smpsr); - void setpreset(unsigned char npreset); - /** - * Sets the value of the chosen variable - * - * The possible parameters are: - * -# Volume - * -# Panning - * -# LFO Frequency - * -# LFO Randomness - * -# LFO Type - * -# LFO stereo - * -# Depth - * -# Delay - * -# Feedback - * -# Flange Mode - * -# Subtractive - * @param npar number of chosen parameter - * @param value the new value - */ - void changepar(const int &npar,const unsigned char &value); - /** - * Gets the value of the chosen variable - * - * The possible parameters are: - * -# Volume - * -# Panning - * -# LFO Frequency - * -# LFO Randomness - * -# LFO Type - * -# LFO stereo - * -# Depth - * -# Delay - * -# Feedback - * -# Flange Mode - * -# Subtractive - * @param npar number of chosen parameter - * @return the value of the parameter - */ - unsigned char getpar(const int &npar)const; - void cleanup(); - - private: - //Chorus Parameters - EffectLFO lfo;//lfo-ul chorus - unsigned char Pvolume; - unsigned char Ppanning; - unsigned char Pdepth;//the depth of the Chorus(ms) - unsigned char Pdelay;//the delay (ms) - unsigned char Pfb;//feedback - unsigned char Plrcross;//feedback - unsigned char Pflangemode;//how the LFO is scaled, to result chorus or flange - unsigned char Poutsub;//if I wish to substract the output instead of the adding it +class Chorus:public Effect +{ +public: + Chorus(const int &insetion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_); + /**Destructor*/ + ~Chorus(); + void out(REALTYPE *smpsl,REALTYPE *smpsr); + void out(const Stereo &input); + void setpreset(unsigned char npreset); + /** + * Sets the value of the chosen variable + * + * The possible parameters are: + * -# Volume + * -# Panning + * -# LFO Frequency + * -# LFO Randomness + * -# LFO Type + * -# LFO stereo + * -# Depth + * -# Delay + * -# Feedback + * -# Flange Mode + * -# Subtractive + * @param npar number of chosen parameter + * @param value the new value + */ + void changepar(const int &npar,const unsigned char &value); + /** + * Gets the value of the chosen variable + * + * The possible parameters are: + * -# Volume + * -# Panning + * -# LFO Frequency + * -# LFO Randomness + * -# LFO Type + * -# LFO stereo + * -# Depth + * -# Delay + * -# Feedback + * -# Flange Mode + * -# Subtractive + * @param npar number of chosen parameter + * @return the value of the parameter + */ + unsigned char getpar(const int &npar)const; + void cleanup(); - - //Parameter Controls - void setvolume(const unsigned char &Pvolume); - void setpanning(const unsigned char &Ppanning); - void setdepth(const unsigned char &Pdepth); - void setdelay(const unsigned char &Pdelay); - void setfb(const unsigned char &Pfb); - void setlrcross(const unsigned char &Plrcross); +private: + //Chorus Parameters + EffectLFO lfo;//lfo-ul chorus + unsigned char Pvolume; + unsigned char Ppanning; + unsigned char Pdepth;//the depth of the Chorus(ms) + unsigned char Pdelay;//the delay (ms) + unsigned char Pfb;//feedback + unsigned char Plrcross;//feedback + unsigned char Pflangemode;//how the LFO is scaled, to result chorus or flange + unsigned char Poutsub;//if I wish to substract the output instead of the adding it - //Internal Values - REALTYPE depth,delay,fb,lrcross,panning; - REALTYPE dl1,dl2,dr1,dr2,lfol,lfor; - int maxdelay; - REALTYPE *delayl,*delayr; - int dlk,drk,dlhi,dlhi2; - REALTYPE getdelay(REALTYPE xlfo); - REALTYPE dllo,mdel; + + //Parameter Controls + void setvolume(const unsigned char &Pvolume); + void setpanning(const unsigned char &Ppanning); + void setdepth(const unsigned char &Pdepth); + void setdelay(const unsigned char &Pdelay); + void setfb(const unsigned char &Pfb); + void setlrcross(const unsigned char &Plrcross); + + //Internal Values + REALTYPE depth,delay,fb,lrcross,panning; + REALTYPE dl1,dl2,dr1,dr2,lfol,lfor; + int maxdelay; + Stereo delaySample; + //REALTYPE *delayl,*delayr; + int dlk,drk,dlhi,dlhi2; + REALTYPE getdelay(REALTYPE xlfo); + REALTYPE dllo,mdel; }; #endif diff --git a/plugins/zynaddsubfx/src/Effects/Distorsion.C b/plugins/zynaddsubfx/src/Effects/Distorsion.C deleted file mode 100644 index 33dabe2a7..000000000 --- a/plugins/zynaddsubfx/src/Effects/Distorsion.C +++ /dev/null @@ -1,376 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Distorsion.C - Distorsion effect - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include "Distorsion.h" - - -/* - * Waveshape (this is called by OscilGen::waveshape and Distorsion::process) - */ - -void waveshapesmps(int n,REALTYPE *smps,unsigned char type,unsigned char drive){ - int i; - REALTYPE ws=drive/127.0; - REALTYPE tmpv; - - switch(type){ - case 1: ws=pow(10,ws*ws*3.0)-1.0+0.001;//Arctangent - for (i=0;iws) { - if (tmp>=0.0) smps[i]=1.0; - else smps[i]=-1.0; - } else smps[i]/=ws; - }; - break; - case 8: ws=pow(2.0,-ws*ws*8.0); //Upper Limiter - for (i=0;iws) smps[i]=ws; - smps[i]*=2.0; - }; - break; - case 9: ws=pow(2.0,-ws*ws*8.0); //Lower Limiter - for (i=0;iws) { - if (tmp>=0.0) smps[i]=tmp-ws; - else smps[i]=tmp+ws; - } else smps[i]=0; - }; - break; - case 11:ws=pow(5,ws*ws*1.0)-1.0;//Clip - for (i=0;i-2.0) && (tmp<1.0)) smps[i]=tmp*(1.0-tmp)*(tmp+2.0)/tmpv; - else smps[i]=0.0; - }; - break; - case 13:ws=ws*ws*ws*32.0+0.0001;//Pow2 - if (ws<1.0) tmpv=ws*(1+ws)/2.0; - else tmpv=1.0; - for (i=0;i-1.0)&&(tmp<1.618034)) smps[i]=tmp*(1.0-tmp)/tmpv; - else if (tmp>0.0) smps[i]=-1.0; - else smps[i]=-2.0; - }; - break; - case 14:ws=pow(ws,5.0)*80.0+0.0001;//sigmoid - if (ws>10.0) tmpv=0.5; - else tmpv=0.5-1.0/(exp(ws)+1.0); - for (i=0;i10.0) tmp=10.0; - tmp=0.5-1.0/(exp(tmp)+1.0); - smps[i]=tmp/tmpv; - }; - break; - /**\todo update to Distorsion::changepar (Ptype max) if there is added more waveshapings functions*/ - }; - -}; - - -Distorsion::Distorsion(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_) - :Effect(insertion_,efxoutl_,efxoutr_,NULL,0) -{ - - lpfl=new AnalogFilter(2,22000,1,0); - lpfr=new AnalogFilter(2,22000,1,0); - hpfl=new AnalogFilter(3,20,1,0); - hpfr=new AnalogFilter(3,20,1,0); - - - //default values - Pvolume=50; - Plrcross=40; - Pdrive=90; - Plevel=64; - Ptype=0; - Pnegate=0; - Plpf=127; - Phpf=0; - Pstereo=0; - Pprefiltering=0; - - setpreset(Ppreset); - cleanup(); -}; - -Distorsion::~Distorsion(){ - delete lpfl; - delete lpfr; - delete hpfl; - delete hpfr; - -}; - -/* - * Cleanup the effect - */ -void Distorsion::cleanup(){ - lpfl->cleanup(); - hpfl->cleanup(); - lpfr->cleanup(); - hpfr->cleanup(); -}; - - -/* - * Apply the filters - */ - -void Distorsion::applyfilters(REALTYPE *efxoutl,REALTYPE *efxoutr){ - lpfl->filterout(efxoutl); - hpfl->filterout(efxoutl); - if (Pstereo!=0){//stereo - lpfr->filterout(efxoutr); - hpfr->filterout(efxoutr); - }; - -}; - - -/* - * Effect output - */ -void Distorsion::out(REALTYPE *smpsl,REALTYPE *smpsr){ - int i; - REALTYPE l,r,lout,rout; - - REALTYPE inputvol=pow(5.0,(Pdrive-32.0)/127.0); - if (Pnegate!=0) inputvol*=-1.0; - - if (Pstereo!=0){//Stereo - for (i=0;iPvolume=Pvolume; - - if (insertion==0) { - outvolume=pow(0.01,(1.0-Pvolume/127.0))*4.0; - volume=1.0; - } else { - volume=outvolume=Pvolume/127.0; - }; - if (Pvolume==0) cleanup(); - -}; - -void Distorsion::setpanning(const unsigned char &Ppanning){ - this->Ppanning=Ppanning; - panning=(Ppanning+0.5)/127.0; -}; - - -void Distorsion::setlrcross(const unsigned char &Plrcross){ - this->Plrcross=Plrcross; - lrcross=Plrcross/127.0*1.0; -}; - -void Distorsion::setlpf(const unsigned char &Plpf){ - this->Plpf=Plpf; - REALTYPE fr=exp(pow(Plpf/127.0,0.5)*log(25000.0))+40; - lpfl->setfreq(fr); - lpfr->setfreq(fr); -}; - -void Distorsion::sethpf(const unsigned char &Phpf){ - this->Phpf=Phpf; - REALTYPE fr=exp(pow(Phpf/127.0,0.5)*log(25000.0))+20.0; - hpfl->setfreq(fr); - hpfr->setfreq(fr); -}; - - -void Distorsion::setpreset(unsigned char npreset){ - const int PRESET_SIZE=11; - const int NUM_PRESETS=6; - unsigned char presets[NUM_PRESETS][PRESET_SIZE]={ - //Overdrive 1 - {127,64,35,56,70,0,0,96,0,0,0}, - //Overdrive 2 - {127,64,35,29,75,1,0,127,0,0,0}, - //A. Exciter 1 - {64,64,35,75,80,5,0,127,105,1,0}, - //A. Exciter 2 - {64,64,35,85,62,1,0,127,118,1,0}, - //Guitar Amp - {127,64,35,63,75,2,0,55,0,0,0}, - //Quantisize - {127,64,35,88,75,4,0,127,0,1,0}}; - - - if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1; - for (int n=0;n13) Ptype=13;//this must be increased if more distorsion types are added - else Ptype=value; - break; - case 6: if (value>1) Pnegate=1; - else Pnegate=value; - break; - case 7: setlpf(value); - break; - case 8: sethpf(value); - break; - case 9: if (value>1) Pstereo=1; - else Pstereo=value; - break; - case 10:Pprefiltering=value; - break; - }; -}; - -unsigned char Distorsion::getpar(const int &npar)const{ - switch (npar){ - case 0: return(Pvolume); - break; - case 1: return(Ppanning); - break; - case 2: return(Plrcross); - break; - case 3: return(Pdrive); - break; - case 4: return(Plevel); - break; - case 5: return(Ptype); - break; - case 6: return(Pnegate); - break; - case 7: return(Plpf); - break; - case 8: return(Phpf); - break; - case 9: return(Pstereo); - break; - case 10:return(Pprefiltering); - break; - }; - return(0);//in case of bogus parameter number -}; - diff --git a/plugins/zynaddsubfx/src/Effects/Distorsion.cpp b/plugins/zynaddsubfx/src/Effects/Distorsion.cpp new file mode 100644 index 000000000..6aeaab4fb --- /dev/null +++ b/plugins/zynaddsubfx/src/Effects/Distorsion.cpp @@ -0,0 +1,427 @@ +/* + ZynAddSubFX - a software synthesizer + + Distorsion.C - Distorsion effect + Copyright (C) 2002-2005 Nasca Octavian Paul + Author: Nasca Octavian Paul + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include +#include "Distorsion.h" + + +/* + * Waveshape (this is called by OscilGen::waveshape and Distorsion::process) + */ + +void waveshapesmps(int n,REALTYPE *smps,unsigned char type,unsigned char drive) +{ + int i; + REALTYPE ws=drive/127.0; + REALTYPE tmpv; + + switch (type) { + case 1: + ws=pow(10,ws*ws*3.0)-1.0+0.001;//Arctangent + for (i=0;iws) { + if (tmp>=0.0) smps[i]=1.0; + else smps[i]=-1.0; + } else smps[i]/=ws; + }; + break; + case 8: + ws=pow(2.0,-ws*ws*8.0); //Upper Limiter + for (i=0;iws) smps[i]=ws; + smps[i]*=2.0; + }; + break; + case 9: + ws=pow(2.0,-ws*ws*8.0); //Lower Limiter + for (i=0;iws) { + if (tmp>=0.0) smps[i]=tmp-ws; + else smps[i]=tmp+ws; + } else smps[i]=0; + }; + break; + case 11: + ws=pow(5,ws*ws*1.0)-1.0;//Clip + for (i=0;i-2.0) && (tmp<1.0)) smps[i]=tmp*(1.0-tmp)*(tmp+2.0)/tmpv; + else smps[i]=0.0; + }; + break; + case 13: + ws=ws*ws*ws*32.0+0.0001;//Pow2 + if (ws<1.0) tmpv=ws*(1+ws)/2.0; + else tmpv=1.0; + for (i=0;i-1.0)&&(tmp<1.618034)) smps[i]=tmp*(1.0-tmp)/tmpv; + else if (tmp>0.0) smps[i]=-1.0; + else smps[i]=-2.0; + }; + break; + case 14: + ws=pow(ws,5.0)*80.0+0.0001;//sigmoid + if (ws>10.0) tmpv=0.5; + else tmpv=0.5-1.0/(exp(ws)+1.0); + for (i=0;i10.0) tmp=10.0; + tmp=0.5-1.0/(exp(tmp)+1.0); + smps[i]=tmp/tmpv; + }; + break; + /**\todo update to Distorsion::changepar (Ptype max) if there is added more waveshapings functions*/ + }; + +}; + + +Distorsion::Distorsion(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_) + :Effect(insertion_,efxoutl_,efxoutr_,NULL,0) +{ + + lpfl=new AnalogFilter(2,22000,1,0); + lpfr=new AnalogFilter(2,22000,1,0); + hpfl=new AnalogFilter(3,20,1,0); + hpfr=new AnalogFilter(3,20,1,0); + + + //default values + Pvolume=50; + Plrcross=40; + Pdrive=90; + Plevel=64; + Ptype=0; + Pnegate=0; + Plpf=127; + Phpf=0; + Pstereo=0; + Pprefiltering=0; + + setpreset(Ppreset); + cleanup(); +}; + +Distorsion::~Distorsion() +{ + delete lpfl; + delete lpfr; + delete hpfl; + delete hpfr; + +}; + +/* + * Cleanup the effect + */ +void Distorsion::cleanup() +{ + lpfl->cleanup(); + hpfl->cleanup(); + lpfr->cleanup(); + hpfr->cleanup(); +}; + + +/* + * Apply the filters + */ + +void Distorsion::applyfilters(REALTYPE *efxoutl,REALTYPE *efxoutr) +{ + lpfl->filterout(efxoutl); + hpfl->filterout(efxoutl); + if (Pstereo!=0) {//stereo + lpfr->filterout(efxoutr); + hpfr->filterout(efxoutr); + }; + +}; + + +/* + * Effect output + */ +void Distorsion::out(REALTYPE *smpsl,REALTYPE *smpsr) +{ + int i; + REALTYPE l,r,lout,rout; + + REALTYPE inputvol=pow(5.0,(Pdrive-32.0)/127.0); + if (Pnegate!=0) inputvol*=-1.0; + + if (Pstereo!=0) {//Stereo + for (i=0;iPvolume=Pvolume; + + if (insertion==0) { + outvolume=pow(0.01,(1.0-Pvolume/127.0))*4.0; + volume=1.0; + } else { + volume=outvolume=Pvolume/127.0; + }; + if (Pvolume==0) cleanup(); + +}; + +void Distorsion::setpanning(const unsigned char &Ppanning) +{ + this->Ppanning=Ppanning; + panning=(Ppanning+0.5)/127.0; +}; + + +void Distorsion::setlrcross(const unsigned char &Plrcross) +{ + this->Plrcross=Plrcross; + lrcross=Plrcross/127.0*1.0; +}; + +void Distorsion::setlpf(const unsigned char &Plpf) +{ + this->Plpf=Plpf; + REALTYPE fr=exp(pow(Plpf/127.0,0.5)*log(25000.0))+40; + lpfl->setfreq(fr); + lpfr->setfreq(fr); +}; + +void Distorsion::sethpf(const unsigned char &Phpf) +{ + this->Phpf=Phpf; + REALTYPE fr=exp(pow(Phpf/127.0,0.5)*log(25000.0))+20.0; + hpfl->setfreq(fr); + hpfr->setfreq(fr); +}; + + +void Distorsion::setpreset(unsigned char npreset) +{ + const int PRESET_SIZE=11; + const int NUM_PRESETS=6; + unsigned char presets[NUM_PRESETS][PRESET_SIZE]={ + //Overdrive 1 + {127,64,35,56,70,0,0,96,0,0,0}, + //Overdrive 2 + {127,64,35,29,75,1,0,127,0,0,0}, + //A. Exciter 1 + {64,64,35,75,80,5,0,127,105,1,0}, + //A. Exciter 2 + {64,64,35,85,62,1,0,127,118,1,0}, + //Guitar Amp + {127,64,35,63,75,2,0,55,0,0,0}, + //Quantisize + {127,64,35,88,75,4,0,127,0,1,0} + }; + + + if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1; + for (int n=0;n13) Ptype=13;//this must be increased if more distorsion types are added + else Ptype=value; + break; + case 6: + if (value>1) Pnegate=1; + else Pnegate=value; + break; + case 7: + setlpf(value); + break; + case 8: + sethpf(value); + break; + case 9: + if (value>1) Pstereo=1; + else Pstereo=value; + break; + case 10: + Pprefiltering=value; + break; + }; +}; + +unsigned char Distorsion::getpar(const int &npar)const +{ + switch (npar) { + case 0: + return(Pvolume); + break; + case 1: + return(Ppanning); + break; + case 2: + return(Plrcross); + break; + case 3: + return(Pdrive); + break; + case 4: + return(Plevel); + break; + case 5: + return(Ptype); + break; + case 6: + return(Pnegate); + break; + case 7: + return(Plpf); + break; + case 8: + return(Phpf); + break; + case 9: + return(Pstereo); + break; + case 10: + return(Pprefiltering); + break; + }; + return(0);//in case of bogus parameter number +}; + diff --git a/plugins/zynaddsubfx/src/Effects/Distorsion.h b/plugins/zynaddsubfx/src/Effects/Distorsion.h index c211168e0..efe3b8287 100644 --- a/plugins/zynaddsubfx/src/Effects/Distorsion.h +++ b/plugins/zynaddsubfx/src/Effects/Distorsion.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Distorsion.h - Distorsion Effect Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -30,40 +30,41 @@ //Waveshaping(called by Distorsion effect and waveshape from OscilGen) void waveshapesmps(int n,REALTYPE *smps,unsigned char type,unsigned char drive); /**Distortion Effect*/ -class Distorsion:public Effect{ - public: - Distorsion(const int &insertion,REALTYPE *efxoutl_,REALTYPE *efxoutr_); - ~Distorsion(); - void out(REALTYPE *smpsl,REALTYPE *smpr); - void setpreset(unsigned char npreset); - void changepar(const int &npar,const unsigned char &value); - unsigned char getpar(const int &npar)const; - void cleanup(); - void applyfilters(REALTYPE *efxoutl,REALTYPE *efxoutr); +class Distorsion:public Effect +{ +public: + Distorsion(const int &insertion,REALTYPE *efxoutl_,REALTYPE *efxoutr_); + ~Distorsion(); + void out(REALTYPE *smpsl,REALTYPE *smpr); + void setpreset(unsigned char npreset); + void changepar(const int &npar,const unsigned char &value); + unsigned char getpar(const int &npar)const; + void cleanup(); + void applyfilters(REALTYPE *efxoutl,REALTYPE *efxoutr); - private: - //Parametrii - unsigned char Pvolume; //Volumul or E/R - unsigned char Ppanning;//Panning - unsigned char Plrcross;// L/R Mixing - unsigned char Pdrive; //the input amplification - unsigned char Plevel; //the output amplification - unsigned char Ptype; //Distorsion type - unsigned char Pnegate; //if the input is negated - unsigned char Plpf; //lowpass filter - unsigned char Phpf; //highpass filter - unsigned char Pstereo; //0=mono,1=stereo - unsigned char Pprefiltering;//if you want to do the filtering before the distorsion - - void setvolume(const unsigned char &Pvolume); - void setpanning(const unsigned char &Ppanning); - void setlrcross(const unsigned char &Plrcross); - void setlpf(const unsigned char &Plpf); - void sethpf(const unsigned char &Phpf); - - //Real Parameters - REALTYPE panning,lrcross; - AnalogFilter *lpfl,*lpfr,*hpfl,*hpfr; +private: + //Parametrii + unsigned char Pvolume; //Volumul or E/R + unsigned char Ppanning;//Panning + unsigned char Plrcross;// L/R Mixing + unsigned char Pdrive; //the input amplification + unsigned char Plevel; //the output amplification + unsigned char Ptype; //Distorsion type + unsigned char Pnegate; //if the input is negated + unsigned char Plpf; //lowpass filter + unsigned char Phpf; //highpass filter + unsigned char Pstereo; //0=mono,1=stereo + unsigned char Pprefiltering;//if you want to do the filtering before the distorsion + + void setvolume(const unsigned char &Pvolume); + void setpanning(const unsigned char &Ppanning); + void setlrcross(const unsigned char &Plrcross); + void setlpf(const unsigned char &Plpf); + void sethpf(const unsigned char &Phpf); + + //Real Parameters + REALTYPE panning,lrcross; + AnalogFilter *lpfl,*lpfr,*hpfl,*hpfr; }; diff --git a/plugins/zynaddsubfx/src/Effects/DynamicFilter.C b/plugins/zynaddsubfx/src/Effects/DynamicFilter.C deleted file mode 100644 index 150c4c590..000000000 --- a/plugins/zynaddsubfx/src/Effects/DynamicFilter.C +++ /dev/null @@ -1,312 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - DynamicFilter.C - "WahWah" effect and others - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include "DynamicFilter.h" - -DynamicFilter::DynamicFilter(int insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_) - :Effect(insertion_,efxoutl_,efxoutr_,new FilterParams(0,64,64),0), - filterl(NULL),filterr(NULL) -{ - setpreset(Ppreset); - cleanup(); - /**\todo fix intialization issues here*/ -}; - -DynamicFilter::~DynamicFilter(){ - delete filterpars; - delete filterl; - delete filterr; -}; - - -/* - * Apply the effect - */ -void DynamicFilter::out(REALTYPE *smpsl,REALTYPE *smpsr){ - int i; - if (filterpars->changed){ - filterpars->changed=false; - cleanup(); - }; - - REALTYPE lfol,lfor; - lfo.effectlfoout(&lfol,&lfor); - lfol*=depth*5.0;lfor*=depth*5.0; - REALTYPE freq=filterpars->getfreq(); - REALTYPE q=filterpars->getq(); - - for (i=0;igetrealfreq(freq+lfol+rms); - REALTYPE frr=filterr->getrealfreq(freq+lfor+rms); - - filterl->setfreq_and_q(frl,q); - filterr->setfreq_and_q(frr,q); - - - filterl->filterout(efxoutl); - filterr->filterout(efxoutr); - - //panning - for (i=0;iPdepth=Pdepth; - depth=pow((Pdepth/127.0),2.0); -}; - - -void DynamicFilter::setvolume(const unsigned char &Pvolume){ - this->Pvolume=Pvolume; - outvolume=Pvolume/127.0; - if (insertion==0) volume=1.0; - else volume=outvolume; -}; - -void DynamicFilter::setpanning(const unsigned char &Ppanning){ - this->Ppanning=Ppanning; - panning=Ppanning/127.0; -}; - - -void DynamicFilter::setampsns(const unsigned char &Pampsns){ - ampsns=pow(Pampsns/127.0,2.5)*10.0; - if (Pampsnsinv!=0) ampsns=-ampsns; - ampsmooth=exp(-Pampsmooth/127.0*10.0)*0.99;/**\todo currently Pampsmooth is - * uninitialized when this is - * called. Please fix. - */ - this->Pampsns=Pampsns; -}; - -void DynamicFilter::reinitfilter(){ - if (filterl!=NULL) delete(filterl); - if (filterr!=NULL) delete(filterr); - filterl=new Filter(filterpars); - filterr=new Filter(filterpars); -}; - -void DynamicFilter::setpreset(unsigned char npreset){ - const int PRESET_SIZE=10; - const int NUM_PRESETS=5; - unsigned char presets[NUM_PRESETS][PRESET_SIZE]={ - //WahWah - {110,64,80,0,0,64,0,90,0,60}, - //AutoWah - {110,64,70,0,0,80,70,0,0,60}, - //Sweep - {100,64,30,0,0,50,80,0,0,60}, - //VocalMorph1 - {110,64,80,0,0,64,0,64,0,60}, - //VocalMorph1 - {127,64,50,0,0,96,64,0,0,60}}; - - if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1; - for (int n=0;ndefaults(); - switch(npreset){ - case 0: - filterpars->Pcategory=0; - filterpars->Ptype=2; - filterpars->Pfreq=45; - filterpars->Pq=64; - filterpars->Pstages=1; - filterpars->Pgain=64; - break; - case 1: - filterpars->Pcategory=2; - filterpars->Ptype=0; - filterpars->Pfreq=72; - filterpars->Pq=64; - filterpars->Pstages=0; - filterpars->Pgain=64; - break; - case 2: - filterpars->Pcategory=0; - filterpars->Ptype=4; - filterpars->Pfreq=64; - filterpars->Pq=64; - filterpars->Pstages=2; - filterpars->Pgain=64; - break; - case 3: - filterpars->Pcategory=1; - filterpars->Ptype=0; - filterpars->Pfreq=50; - filterpars->Pq=70; - filterpars->Pstages=1; - filterpars->Pgain=64; - - filterpars->Psequencesize=2; - // "I" - filterpars->Pvowels[0].formants[0].freq=34; - filterpars->Pvowels[0].formants[0].amp=127; - filterpars->Pvowels[0].formants[0].q=64; - filterpars->Pvowels[0].formants[1].freq=99; - filterpars->Pvowels[0].formants[1].amp=122; - filterpars->Pvowels[0].formants[1].q=64; - filterpars->Pvowels[0].formants[2].freq=108; - filterpars->Pvowels[0].formants[2].amp=112; - filterpars->Pvowels[0].formants[2].q=64; - // "A" - filterpars->Pvowels[1].formants[0].freq=61; - filterpars->Pvowels[1].formants[0].amp=127; - filterpars->Pvowels[1].formants[0].q=64; - filterpars->Pvowels[1].formants[1].freq=71; - filterpars->Pvowels[1].formants[1].amp=121; - filterpars->Pvowels[1].formants[1].q=64; - filterpars->Pvowels[1].formants[2].freq=99; - filterpars->Pvowels[1].formants[2].amp=117; - filterpars->Pvowels[1].formants[2].q=64; - break; - case 4: - filterpars->Pcategory=1; - filterpars->Ptype=0; - filterpars->Pfreq=64; - filterpars->Pq=70; - filterpars->Pstages=1; - filterpars->Pgain=64; - - filterpars->Psequencesize=2; - filterpars->Pnumformants=2; - filterpars->Pvowelclearness=0; - - filterpars->Pvowels[0].formants[0].freq=70; - filterpars->Pvowels[0].formants[0].amp=127; - filterpars->Pvowels[0].formants[0].q=64; - filterpars->Pvowels[0].formants[1].freq=80; - filterpars->Pvowels[0].formants[1].amp=122; - filterpars->Pvowels[0].formants[1].q=64; - - filterpars->Pvowels[1].formants[0].freq=20; - filterpars->Pvowels[1].formants[0].amp=127; - filterpars->Pvowels[1].formants[0].q=64; - filterpars->Pvowels[1].formants[1].freq=100; - filterpars->Pvowels[1].formants[1].amp=121; - filterpars->Pvowels[1].formants[1].q=64; - break; - }; - -// for (int i=0;i<5;i++){ -// printf("freq=%d amp=%d q=%d\n",filterpars->Pvowels[0].formants[i].freq,filterpars->Pvowels[0].formants[i].amp,filterpars->Pvowels[0].formants[i].q); -// }; - if (insertion==0) changepar(0,presets[npreset][0]/2);//lower the volume if this is system effect - Ppreset=npreset; - - reinitfilter(); -}; - - -void DynamicFilter::changepar(const int &npar,const unsigned char &value){ - switch(npar){ - case 0: setvolume(value); - break; - case 1: setpanning(value); - break; - case 2: lfo.Pfreq=value; - lfo.updateparams(); - break; - case 3: lfo.Prandomness=value; - lfo.updateparams(); - break; - case 4: lfo.PLFOtype=value; - lfo.updateparams(); - break; - case 5: lfo.Pstereo=value; - lfo.updateparams(); - break; - case 6: setdepth(value); - break; - case 7: setampsns(value); - break; - case 8: Pampsnsinv=value; - setampsns(Pampsns); - break; - case 9: Pampsmooth=value; - setampsns(Pampsns); - break; - }; -}; - -unsigned char DynamicFilter::getpar(const int &npar)const{ - switch (npar){ - case 0: return(Pvolume); - break; - case 1: return(Ppanning); - break; - case 2: return(lfo.Pfreq); - break; - case 3: return(lfo.Prandomness); - break; - case 4: return(lfo.PLFOtype); - break; - case 5: return(lfo.Pstereo); - break; - case 6: return(Pdepth); - break; - case 7: return(Pampsns); - break; - case 8: return(Pampsnsinv); - break; - case 9: return(Pampsmooth); - break; - default:return (0); - }; - -}; - diff --git a/plugins/zynaddsubfx/src/Effects/DynamicFilter.cpp b/plugins/zynaddsubfx/src/Effects/DynamicFilter.cpp new file mode 100644 index 000000000..b7b367ea3 --- /dev/null +++ b/plugins/zynaddsubfx/src/Effects/DynamicFilter.cpp @@ -0,0 +1,344 @@ +/* + ZynAddSubFX - a software synthesizer + + DynamicFilter.C - "WahWah" effect and others + Copyright (C) 2002-2005 Nasca Octavian Paul + Author: Nasca Octavian Paul + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include +#include "DynamicFilter.h" + +DynamicFilter::DynamicFilter(int insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_) + :Effect(insertion_,efxoutl_,efxoutr_,new FilterParams(0,64,64),0), + Pvolume(110),Ppanning(64),Pdepth(0),Pampsns(90), + Pampsnsinv(0),Pampsmooth(60), + filterl(NULL),filterr(NULL) +{ + setpreset(Ppreset); + cleanup(); +}; + +DynamicFilter::~DynamicFilter() +{ + delete filterpars; + delete filterl; + delete filterr; +}; + + +/* + * Apply the effect + */ +void DynamicFilter::out(REALTYPE *smpsl,REALTYPE *smpsr) +{ + int i; + if (filterpars->changed) { + filterpars->changed=false; + cleanup(); + }; + + REALTYPE lfol,lfor; + lfo.effectlfoout(&lfol,&lfor); + lfol*=depth*5.0; + lfor*=depth*5.0; + REALTYPE freq=filterpars->getfreq(); + REALTYPE q=filterpars->getq(); + + for (i=0;igetrealfreq(freq+lfol+rms); + REALTYPE frr=filterr->getrealfreq(freq+lfor+rms); + + filterl->setfreq_and_q(frl,q); + filterr->setfreq_and_q(frr,q); + + + filterl->filterout(efxoutl); + filterr->filterout(efxoutr); + + //panning + for (i=0;iPdepth=Pdepth; + depth=pow((Pdepth/127.0),2.0); +}; + + +void DynamicFilter::setvolume(const unsigned char &Pvolume) +{ + this->Pvolume=Pvolume; + outvolume=Pvolume/127.0; + if (insertion==0) volume=1.0; + else volume=outvolume; +}; + +void DynamicFilter::setpanning(const unsigned char &Ppanning) +{ + this->Ppanning=Ppanning; + panning=Ppanning/127.0; +}; + + +void DynamicFilter::setampsns(const unsigned char &Pampsns) +{ + ampsns=pow(Pampsns/127.0,2.5)*10.0; + if (Pampsnsinv!=0) ampsns=-ampsns; + ampsmooth=exp(-Pampsmooth/127.0*10.0)*0.99; + this->Pampsns=Pampsns; +}; + +void DynamicFilter::reinitfilter() +{ + if (filterl!=NULL) delete(filterl); + if (filterr!=NULL) delete(filterr); + filterl=new Filter(filterpars); + filterr=new Filter(filterpars); +}; + +void DynamicFilter::setpreset(unsigned char npreset) +{ + const int PRESET_SIZE=10; + const int NUM_PRESETS=5; + unsigned char presets[NUM_PRESETS][PRESET_SIZE]={ + //WahWah + {110,64,80,0,0,64,0,90,0,60}, + //AutoWah + {110,64,70,0,0,80,70,0,0,60}, + //Sweep + {100,64,30,0,0,50,80,0,0,60}, + //VocalMorph1 + {110,64,80,0,0,64,0,64,0,60}, + //VocalMorph1 + {127,64,50,0,0,96,64,0,0,60} + }; + + if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1; + for (int n=0;ndefaults(); + switch (npreset) { + case 0: + filterpars->Pcategory=0; + filterpars->Ptype=2; + filterpars->Pfreq=45; + filterpars->Pq=64; + filterpars->Pstages=1; + filterpars->Pgain=64; + break; + case 1: + filterpars->Pcategory=2; + filterpars->Ptype=0; + filterpars->Pfreq=72; + filterpars->Pq=64; + filterpars->Pstages=0; + filterpars->Pgain=64; + break; + case 2: + filterpars->Pcategory=0; + filterpars->Ptype=4; + filterpars->Pfreq=64; + filterpars->Pq=64; + filterpars->Pstages=2; + filterpars->Pgain=64; + break; + case 3: + filterpars->Pcategory=1; + filterpars->Ptype=0; + filterpars->Pfreq=50; + filterpars->Pq=70; + filterpars->Pstages=1; + filterpars->Pgain=64; + + filterpars->Psequencesize=2; + // "I" + filterpars->Pvowels[0].formants[0].freq=34; + filterpars->Pvowels[0].formants[0].amp=127; + filterpars->Pvowels[0].formants[0].q=64; + filterpars->Pvowels[0].formants[1].freq=99; + filterpars->Pvowels[0].formants[1].amp=122; + filterpars->Pvowels[0].formants[1].q=64; + filterpars->Pvowels[0].formants[2].freq=108; + filterpars->Pvowels[0].formants[2].amp=112; + filterpars->Pvowels[0].formants[2].q=64; + // "A" + filterpars->Pvowels[1].formants[0].freq=61; + filterpars->Pvowels[1].formants[0].amp=127; + filterpars->Pvowels[1].formants[0].q=64; + filterpars->Pvowels[1].formants[1].freq=71; + filterpars->Pvowels[1].formants[1].amp=121; + filterpars->Pvowels[1].formants[1].q=64; + filterpars->Pvowels[1].formants[2].freq=99; + filterpars->Pvowels[1].formants[2].amp=117; + filterpars->Pvowels[1].formants[2].q=64; + break; + case 4: + filterpars->Pcategory=1; + filterpars->Ptype=0; + filterpars->Pfreq=64; + filterpars->Pq=70; + filterpars->Pstages=1; + filterpars->Pgain=64; + + filterpars->Psequencesize=2; + filterpars->Pnumformants=2; + filterpars->Pvowelclearness=0; + + filterpars->Pvowels[0].formants[0].freq=70; + filterpars->Pvowels[0].formants[0].amp=127; + filterpars->Pvowels[0].formants[0].q=64; + filterpars->Pvowels[0].formants[1].freq=80; + filterpars->Pvowels[0].formants[1].amp=122; + filterpars->Pvowels[0].formants[1].q=64; + + filterpars->Pvowels[1].formants[0].freq=20; + filterpars->Pvowels[1].formants[0].amp=127; + filterpars->Pvowels[1].formants[0].q=64; + filterpars->Pvowels[1].formants[1].freq=100; + filterpars->Pvowels[1].formants[1].amp=121; + filterpars->Pvowels[1].formants[1].q=64; + break; + }; + +// for (int i=0;i<5;i++){ +// printf("freq=%d amp=%d q=%d\n",filterpars->Pvowels[0].formants[i].freq,filterpars->Pvowels[0].formants[i].amp,filterpars->Pvowels[0].formants[i].q); +// }; + if (insertion==0) changepar(0,presets[npreset][0]/2);//lower the volume if this is system effect + Ppreset=npreset; + + reinitfilter(); +}; + + +void DynamicFilter::changepar(const int &npar,const unsigned char &value) +{ + switch (npar) { + case 0: + setvolume(value); + break; + case 1: + setpanning(value); + break; + case 2: + lfo.Pfreq=value; + lfo.updateparams(); + break; + case 3: + lfo.Prandomness=value; + lfo.updateparams(); + break; + case 4: + lfo.PLFOtype=value; + lfo.updateparams(); + break; + case 5: + lfo.Pstereo=value; + lfo.updateparams(); + break; + case 6: + setdepth(value); + break; + case 7: + setampsns(value); + break; + case 8: + Pampsnsinv=value; + setampsns(Pampsns); + break; + case 9: + Pampsmooth=value; + setampsns(Pampsns); + break; + }; +}; + +unsigned char DynamicFilter::getpar(const int &npar)const +{ + switch (npar) { + case 0: + return(Pvolume); + break; + case 1: + return(Ppanning); + break; + case 2: + return(lfo.Pfreq); + break; + case 3: + return(lfo.Prandomness); + break; + case 4: + return(lfo.PLFOtype); + break; + case 5: + return(lfo.Pstereo); + break; + case 6: + return(Pdepth); + break; + case 7: + return(Pampsns); + break; + case 8: + return(Pampsnsinv); + break; + case 9: + return(Pampsmooth); + break; + default: + return (0); + }; + +}; + diff --git a/plugins/zynaddsubfx/src/Effects/DynamicFilter.h b/plugins/zynaddsubfx/src/Effects/DynamicFilter.h index ba8c04407..9c547c332 100644 --- a/plugins/zynaddsubfx/src/Effects/DynamicFilter.h +++ b/plugins/zynaddsubfx/src/Effects/DynamicFilter.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + DynamicFilter.h - "WahWah" effect and others Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -28,43 +28,44 @@ #include "../DSP/Filter.h" /**DynamicFilter Effect*/ -class DynamicFilter:public Effect { - public: - DynamicFilter(int insetion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_); - ~DynamicFilter(); - void out(REALTYPE *smpsl,REALTYPE *smpsr); +class DynamicFilter:public Effect +{ +public: + DynamicFilter(int insetion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_); + ~DynamicFilter(); + void out(REALTYPE *smpsl,REALTYPE *smpsr); - void setpreset(unsigned char npreset); - void changepar(const int &npar,const unsigned char &value); - unsigned char getpar(const int &npar)const; - void cleanup(); + void setpreset(unsigned char npreset); + void changepar(const int &npar,const unsigned char &value); + unsigned char getpar(const int &npar)const; + void cleanup(); // void setdryonly(); - - private: - //Parametrii DynamicFilter - EffectLFO lfo;//lfo-ul DynamicFilter - unsigned char Pvolume; - unsigned char Ppanning; - unsigned char Pdepth;/** -#include "EQ.h" - -EQ::EQ(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_) - :Effect(insertion_,efxoutl_,efxoutr_,NULL,0) -{ - - for (int i=0;icleanup(); - filter[i].r->cleanup(); - }; -}; - - - -/* - * Effect output - */ -void EQ::out(REALTYPE *smpsl,REALTYPE *smpsr){ - int i; - for (i=0;ifilterout(efxoutl); - filter[i].r->filterout(efxoutr); - }; -}; - - -/* - * Parameter control - */ -void EQ::setvolume(const unsigned char &Pvolume){ - this->Pvolume=Pvolume; - - outvolume=pow(0.005,(1.0-Pvolume/127.0))*10.0; - if (insertion==0) { - volume=1.0; - } else { - volume=outvolume; - }; - -}; - - -void EQ::setpreset(unsigned char npreset){ - const int PRESET_SIZE=1; - const int NUM_PRESETS=2; - unsigned char presets[NUM_PRESETS][PRESET_SIZE]={ - //EQ 1 - {67}, - //EQ 2 - {67}}; - - if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1; - for (int n=0;n=MAX_EQ_BANDS) return; - int bp=npar%5;//band paramenter - - REALTYPE tmp; - switch(bp){ - case 0: filter[nb].Ptype=value; - if (value>9) filter[nb].Ptype=0;//has to be changed if more filters will be added - if (filter[nb].Ptype!=0){ - filter[nb].l->settype(value-1); - filter[nb].r->settype(value-1); - }; - break; - case 1: filter[nb].Pfreq=value; - tmp=600.0*pow(30.0,(value-64.0)/64.0); - filter[nb].l->setfreq(tmp); - filter[nb].r->setfreq(tmp); - break; - case 2: filter[nb].Pgain=value; - tmp=30.0*(value-64.0)/64.0; - filter[nb].l->setgain(tmp); - filter[nb].r->setgain(tmp); - break; - case 3: filter[nb].Pq=value; - tmp=pow(30.0,(value-64.0)/64.0); - filter[nb].l->setq(tmp); - filter[nb].r->setq(tmp); - break; - case 4: filter[nb].Pstages=value; - if (value>=MAX_FILTER_STAGES) filter[nb].Pstages=MAX_FILTER_STAGES-1; - filter[nb].l->setstages(value); - filter[nb].r->setstages(value); - break; - }; -}; - -unsigned char EQ::getpar(const int &npar)const{ - switch (npar){ - case 0: return(Pvolume); - break; - }; - - if (npar<10) return(0); - - int nb=(npar-10)/5;//number of the band (filter) - if (nb>=MAX_EQ_BANDS) return(0); - int bp=npar%5;//band paramenter - switch(bp){ - case 0: return(filter[nb].Ptype); - break; - case 1: return(filter[nb].Pfreq); - break; - case 2: return(filter[nb].Pgain); - break; - case 3: return(filter[nb].Pq); - break; - case 4: return(filter[nb].Pstages); - break; - }; - - return(0);//in case of bogus parameter number -}; - - - - -REALTYPE EQ::getfreqresponse(REALTYPE freq){ - REALTYPE resp=1.0; - - for (int i=0;iH(freq); - }; - return(rap2dB(resp*outvolume)); -}; - - diff --git a/plugins/zynaddsubfx/src/Effects/EQ.cpp b/plugins/zynaddsubfx/src/Effects/EQ.cpp new file mode 100644 index 000000000..b5f92eacb --- /dev/null +++ b/plugins/zynaddsubfx/src/Effects/EQ.cpp @@ -0,0 +1,214 @@ +/* + ZynAddSubFX - a software synthesizer + + EQ.C - EQ effect + Copyright (C) 2002-2005 Nasca Octavian Paul + Author: Nasca Octavian Paul + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include +#include "EQ.h" + +EQ::EQ(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_) + :Effect(insertion_,efxoutl_,efxoutr_,NULL,0) +{ + + for (int i=0;icleanup(); + filter[i].r->cleanup(); + }; +}; + + + +/* + * Effect output + */ +void EQ::out(REALTYPE *smpsl,REALTYPE *smpsr) +{ + int i; + for (i=0;ifilterout(efxoutl); + filter[i].r->filterout(efxoutr); + }; +}; + + +/* + * Parameter control + */ +void EQ::setvolume(const unsigned char &Pvolume) +{ + this->Pvolume=Pvolume; + + outvolume=pow(0.005,(1.0-Pvolume/127.0))*10.0; + if (insertion==0) { + volume=1.0; + } else { + volume=outvolume; + }; + +}; + + +void EQ::setpreset(unsigned char npreset) +{ + const int PRESET_SIZE=1; + const int NUM_PRESETS=2; + unsigned char presets[NUM_PRESETS][PRESET_SIZE]={ + //EQ 1 + {67}, + //EQ 2 + {67} + }; + + if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1; + for (int n=0;n=MAX_EQ_BANDS) return; + int bp=npar%5;//band paramenter + + REALTYPE tmp; + switch (bp) { + case 0: + filter[nb].Ptype=value; + if (value>9) filter[nb].Ptype=0;//has to be changed if more filters will be added + if (filter[nb].Ptype!=0) { + filter[nb].l->settype(value-1); + filter[nb].r->settype(value-1); + }; + break; + case 1: + filter[nb].Pfreq=value; + tmp=600.0*pow(30.0,(value-64.0)/64.0); + filter[nb].l->setfreq(tmp); + filter[nb].r->setfreq(tmp); + break; + case 2: + filter[nb].Pgain=value; + tmp=30.0*(value-64.0)/64.0; + filter[nb].l->setgain(tmp); + filter[nb].r->setgain(tmp); + break; + case 3: + filter[nb].Pq=value; + tmp=pow(30.0,(value-64.0)/64.0); + filter[nb].l->setq(tmp); + filter[nb].r->setq(tmp); + break; + case 4: + filter[nb].Pstages=value; + if (value>=MAX_FILTER_STAGES) filter[nb].Pstages=MAX_FILTER_STAGES-1; + filter[nb].l->setstages(value); + filter[nb].r->setstages(value); + break; + }; +}; + +unsigned char EQ::getpar(const int &npar)const +{ + switch (npar) { + case 0: + return(Pvolume); + break; + }; + + if (npar<10) return(0); + + int nb=(npar-10)/5;//number of the band (filter) + if (nb>=MAX_EQ_BANDS) return(0); + int bp=npar%5;//band paramenter + switch (bp) { + case 0: + return(filter[nb].Ptype); + break; + case 1: + return(filter[nb].Pfreq); + break; + case 2: + return(filter[nb].Pgain); + break; + case 3: + return(filter[nb].Pq); + break; + case 4: + return(filter[nb].Pstages); + break; + }; + + return(0);//in case of bogus parameter number +}; + + + + +REALTYPE EQ::getfreqresponse(REALTYPE freq) +{ + REALTYPE resp=1.0; + + for (int i=0;iH(freq); + }; + return(rap2dB(resp*outvolume)); +}; + + diff --git a/plugins/zynaddsubfx/src/Effects/EQ.h b/plugins/zynaddsubfx/src/Effects/EQ.h index 315d51a34..810dd6ee6 100644 --- a/plugins/zynaddsubfx/src/Effects/EQ.h +++ b/plugins/zynaddsubfx/src/Effects/EQ.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + EQ.h - EQ Effect Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -28,29 +28,30 @@ #include "Effect.h" /**EQ Effect*/ -class EQ:public Effect{ - public: - EQ(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_); - ~EQ(); - void out(REALTYPE *smpsl,REALTYPE *smpr); - void setpreset(unsigned char npreset); - void changepar(const int &npar,const unsigned char &value); - unsigned char getpar(const int &npar)const; - void cleanup(); - REALTYPE getfreqresponse(REALTYPE freq); - private: - //Parameters - unsigned char Pvolume;/** -#include "Echo.h" - -Echo::Echo(const int & insertion_,REALTYPE *const efxoutl_,REALTYPE *const efxoutr_) - : Effect(insertion_,efxoutl_,efxoutr_,NULL,0), - Pvolume(50),Ppanning(64),Pdelay(60), - Plrdelay(100),Plrcross(100),Pfb(40),Phidamp(60), - lrdelay(0),ldelay(NULL),rdelay(NULL) -{ - setpreset(Ppreset); - cleanup(); -} - -Echo::~Echo(){ - delete[] ldelay; - delete[] rdelay; -} - -/* - * Cleanup the effect - */ -void Echo::cleanup(){ - int i; - for (i=0;i=dl) kl=0; - if (++kr>=dr) kr=0; - }; - -} - - -/* - * Parameter control - */ -void Echo::setvolume(const unsigned char & Pvolume){ - this->Pvolume=Pvolume; - - if (insertion==0) { - outvolume=pow(0.01,(1.0-Pvolume/127.0))*4.0; - volume=1.0; - } else { - volume=outvolume=Pvolume/127.0; - }; - if (Pvolume==0) cleanup(); - -} - -void Echo::setpanning(const unsigned char & Ppanning){ - this->Ppanning=Ppanning; - panning=(Ppanning+0.5)/127.0; -} - -void Echo::setdelay(const unsigned char & Pdelay){ - this->Pdelay=Pdelay; - delay=1+(int)(Pdelay/127.0*SAMPLE_RATE*1.5);//0 .. 1.5 sec - initdelays(); -} - -void Echo::setlrdelay(const unsigned char & Plrdelay){ - REALTYPE tmp; - this->Plrdelay=Plrdelay; - tmp=(pow(2,fabs(Plrdelay-64.0)/64.0*9)-1.0)/1000.0*SAMPLE_RATE; - if (Plrdelay<64.0) tmp=-tmp; - lrdelay=(int) tmp; - initdelays(); -} - -void Echo::setlrcross(const unsigned char & Plrcross){ - this->Plrcross=Plrcross; - lrcross=Plrcross/127.0*1.0; -} - -void Echo::setfb(const unsigned char & Pfb){ - this->Pfb=Pfb; - fb=Pfb/128.0; -} - -void Echo::sethidamp(const unsigned char & Phidamp){ - this->Phidamp=Phidamp; - hidamp=1.0-Phidamp/127.0; -} - -void Echo::setpreset(unsigned char npreset){ - /**\todo see if the preset array can be replaced with a struct or a class*/ - const int PRESET_SIZE=7; - const int NUM_PRESETS=9; - unsigned char presets[NUM_PRESETS][PRESET_SIZE]={ - //Echo 1 - {67,64,35,64,30,59,0}, - //Echo 2 - {67,64,21,64,30,59,0}, - //Echo 3 - {67,75,60,64,30,59,10}, - //Simple Echo - {67,60,44,64,30,0,0}, - //Canyon - {67,60,102,50,30,82,48}, - //Panning Echo 1 - {67,64,44,17,0,82,24}, - //Panning Echo 2 - {81,60,46,118,100,68,18}, - //Panning Echo 3 - {81,60,26,100,127,67,36}, - //Feedback Echo - {62,64,28,64,100,90,55}}; - - - if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1; - for (int n=0;n +#include +#include "Echo.h" + +Echo::Echo(const int & insertion_,REALTYPE *const efxoutl_,REALTYPE *const efxoutr_) + : Effect(insertion_,efxoutl_,efxoutr_,NULL,0), + Pvolume(50),Ppanning(64),//Pdelay(60), + Plrdelay(100),Plrcross(100),Pfb(40),Phidamp(60), + lrdelay(0),delaySample(1),old(0.0) +{ + setpreset(Ppreset); +} + +Echo::~Echo() {} + +/* + * Cleanup the effect + */ +void Echo::cleanup() +{ + delaySample.l().clear(); + delaySample.r().clear(); + old=Stereo(0.0); +} + + +/* + * Initialize the delays + */ +void Echo::initdelays() +{ + /**\todo make this adjust insted of destroy old delays*/ + kl=0; + kr=0; + dl=(int)(1+delay.getiVal()*SAMPLE_RATE-lrdelay); + if (dl<1) dl=1; + dr=(int)(1+delay.getiVal()*SAMPLE_RATE+lrdelay); + if (dr<1) dr=1; + + delaySample.l()=AuSample(dl); + delaySample.r()=AuSample(dr); + + old=Stereo(0.0); +} + +/* + * Effect output + */ +void Echo::out(REALTYPE *const smpsl,REALTYPE *const smpsr) +{ + Stereo input(AuSample(SOUND_BUFFER_SIZE,smpsl),AuSample(SOUND_BUFFER_SIZE,smpsr)); + out(input); +} + +void Echo::out(const Stereo &input) +{ +//void Echo::out(const Stereo & input){ //ideal + REALTYPE l,r,ldl,rdl;/**\todo move l+r->? ldl+rdl->?*/ + + for (int i=0;i=dl) kl=0; + if (++kr>=dr) kr=0; + }; + +} + + +/* + * Parameter control + */ +void Echo::setvolume(const unsigned char & Pvolume) +{ + this->Pvolume=Pvolume; + + if (insertion==0) { + outvolume=pow(0.01,(1.0-Pvolume/127.0))*4.0; + volume=1.0; + } else { + volume=outvolume=Pvolume/127.0; + }; + if (Pvolume==0) cleanup(); + +} + +void Echo::setpanning(const unsigned char & Ppanning) +{ + this->Ppanning=Ppanning; + panning=(Ppanning+0.5)/127.0; +} + +void Echo::setdelay(const unsigned char & Pdelay) +{ + delay.setmVal(Pdelay); + //this->Pdelay=Pdelay; + //delay=1+(int)(Pdelay/127.0*SAMPLE_RATE*1.5);//0 .. 1.5 sec + initdelays(); +} + +void Echo::setlrdelay(const unsigned char & Plrdelay) +{ + REALTYPE tmp; + this->Plrdelay=Plrdelay; + tmp=(pow(2,fabs(Plrdelay-64.0)/64.0*9)-1.0)/1000.0*SAMPLE_RATE; + if (Plrdelay<64.0) tmp=-tmp; + lrdelay=(int) tmp; + initdelays(); +} + +void Echo::setlrcross(const unsigned char & Plrcross) +{ + this->Plrcross=Plrcross; + lrcross=Plrcross/127.0*1.0; +} + +void Echo::setfb(const unsigned char & Pfb) +{ + this->Pfb=Pfb; + fb=Pfb/128.0; +} + +void Echo::sethidamp(const unsigned char & Phidamp) +{ + this->Phidamp=Phidamp; + hidamp=1.0-Phidamp/127.0; +} + +void Echo::setpreset(unsigned char npreset) +{ + /**\todo see if the preset array can be replaced with a struct or a class*/ + const int PRESET_SIZE=7; + const int NUM_PRESETS=9; + unsigned char presets[NUM_PRESETS][PRESET_SIZE]={ + //Echo 1 + {67,64,35,64,30,59,0}, + //Echo 2 + {67,64,21,64,30,59,0}, + //Echo 3 + {67,75,60,64,30,59,10}, + //Simple Echo + {67,60,44,64,30,0,0}, + //Canyon + {67,60,102,50,30,82,48}, + //Panning Echo 1 + {67,64,44,17,0,82,24}, + //Panning Echo 2 + {81,60,46,118,100,68,18}, + //Panning Echo 3 + {81,60,26,100,127,67,36}, + //Feedback Echo + {62,64,28,64,100,90,55} + }; + + + if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1; + for (int n=0;n &input); - /** - * Sets the value of the chosen variable - * - * The possible parameters are: - * -# Volume - * -# Panning - * -# Delay - * -# L/R Delay - * -# L/R Crossover - * -# Feedback - * -# Dampening - * @param npar number of chosen parameter - * @param value the new value - */ - void changepar(const int & npar,const unsigned char & value); + /** + * Sets the state of Echo to the specified preset + * @param npreset number of chosen preset + */ + void setpreset(unsigned char npreset); - /** - * Gets the specified parameter - * - * The possible parameters are - * -# Volume - * -# Panning - * -# Delay - * -# L/R Delay - * -# L/R Crossover - * -# Feedback - * -# Dampening - * @param npar number of chosen parameter - * @return value of parameter - * - * \todo make this method use constant variables by reference - *Currently doing so results in strange behavior - */ - unsigned char getpar(const int & npar)const; + /** + * Sets the value of the chosen variable + * + * The possible parameters are: + * -# Volume + * -# Panning + * -# Delay + * -# L/R Delay + * -# L/R Crossover + * -# Feedback + * -# Dampening + * @param npar number of chosen parameter + * @param value the new value + */ + void changepar(const int & npar,const unsigned char & value); - /**Zeros out the state of the Echo*/ - void cleanup(); - - /**\todo This function needs to be implemented or the prototype should be removed*/ - void setdryonly(); - private: - /**\todo remove all of these once they have been depreciated*/ - //Parameters - unsigned char Pvolume;/**<#1 Volume or Dry/Wetness*/ - unsigned char Ppanning;/**<#2 Panning*/ - unsigned char Pdelay;/**<#3 Delay of the Echo*/ - unsigned char Plrdelay;/**<#4 L/R delay difference*/ - unsigned char Plrcross;/**<#5 L/R Mixing*/ - unsigned char Pfb;/**<#6Feedback*/ - unsigned char Phidamp;/**<#7Dampening of the Echo*/ - - void setvolume(const unsigned char & Pvolume); - void setpanning(const unsigned char & Ppanning); - void setdelay(const unsigned char & Pdelay); - void setlrdelay(const unsigned char & Plrdelay); - void setlrcross(const unsigned char & Plrcross); - void setfb(const unsigned char & Pfb); - void sethidamp(const unsigned char & Phidamp); + /** + * Gets the specified parameter + * + * The possible parameters are + * -# Volume + * -# Panning + * -# Delay + * -# L/R Delay + * -# L/R Crossover + * -# Feedback + * -# Dampening + * @param npar number of chosen parameter + * @return value of parameter + */ + unsigned char getpar(const int & npar)const; - //Real Parameters - REALTYPE panning,lrcross,fb,hidamp; - int dl,dr,delay,lrdelay; - - void initdelays(); - REALTYPE *ldelay,*rdelay; - REALTYPE oldl,oldr;//pt. lpf - int kl,kr; + int getnumparams(); + + /**Zeros out the state of the Echo*/ + void cleanup(); + + /**\todo This function needs to be implemented or the prototype should be removed*/ + void setdryonly(); +private: + //Parameters + char Pvolume;/**<#1 Volume or Dry/Wetness*/ + char Ppanning;/**<#2 Panning*/ + DelayCtl delay;/**<#3 Delay of the Echo*/ + char Plrdelay;/**<#4 L/R delay difference*/ + char Plrcross;/**<#5 L/R Mixing*/ + char Pfb;/**<#6Feedback*/ + char Phidamp;/**<#7Dampening of the Echo*/ + + void setvolume(const unsigned char & Pvolume); + void setpanning(const unsigned char & Ppanning); + void setdelay(const unsigned char & Pdelay); + void setlrdelay(const unsigned char & Plrdelay); + void setlrcross(const unsigned char & Plrcross); + void setfb(const unsigned char & Pfb); + void sethidamp(const unsigned char & Phidamp); + + //Real Parameters + REALTYPE panning,lrcross,fb,hidamp; //needs better names + int dl,dr,lrdelay; //needs better names + + void initdelays(); + Stereo delaySample; + Stereo old; + + int kl,kr; }; #endif diff --git a/plugins/zynaddsubfx/src/Effects/Effect.C b/plugins/zynaddsubfx/src/Effects/Effect.cpp similarity index 83% rename from plugins/zynaddsubfx/src/Effects/Effect.C rename to plugins/zynaddsubfx/src/Effects/Effect.cpp index da59e1a47..b0b4dac30 100644 --- a/plugins/zynaddsubfx/src/Effects/Effect.C +++ b/plugins/zynaddsubfx/src/Effects/Effect.cpp @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Effect.C - this class is inherited by the all effects(Reverb, Echo, ..) Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -22,9 +22,9 @@ #include "Effect.h" - -Effect::Effect(const int & insertion_,REALTYPE *const efxoutl_, + +Effect::Effect(bool insertion_,REALTYPE *const efxoutl_, REALTYPE *const efxoutr_,FilterParams *filterpars_, const unsigned char & Ppreset_) - :Ppreset(Ppreset_),efxoutl(efxoutl_),efxoutr(efxoutr_), - filterpars(filterpars_),insertion(insertion_){} + :Ppreset(Ppreset_),efxoutl(efxoutl_),efxoutr(efxoutr_), + filterpars(filterpars_),insertion(insertion_) {} diff --git a/plugins/zynaddsubfx/src/Effects/Effect.h b/plugins/zynaddsubfx/src/Effects/Effect.h index 6c3f1d1ce..0da3d8317 100644 --- a/plugins/zynaddsubfx/src/Effects/Effect.h +++ b/plugins/zynaddsubfx/src/Effects/Effect.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Effect.h - this class is inherited by the all effects(Reverb, Echo, ..) Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -23,82 +23,81 @@ #ifndef EFFECT_H #define EFFECT_H -#include #include "../Misc/Util.h" #include "../globals.h" #include "../Params/FilterParams.h" /**this class is inherited by the all effects(Reverb, Echo, ..)*/ -class Effect{ - public: - /** - * Effect Constructor - * @param insertion_ 1 when it is an insertion Effect and 0 when it - * is not an insertion Effect - * @param efxoutl_ Effect output buffer Left channel - * @param efxoutr_ Effect output buffer Right channel - * @param filterpars_ pointer to FilterParams array - * @param Ppreset_ chosen preset - * @return Initialized Effect object*/ - Effect(const int & insertion_,REALTYPE *const efxoutl_, - REALTYPE *const efxoutr_,FilterParams *filterpars_, - const unsigned char & Ppreset_); - /**Deconstructor - * - * Deconstructs the Effect and releases any resouces that it has - * allocated for itself*/ - virtual ~Effect(){}; - /** - * Choose a preset - * @param npreset number of chosen preset*/ - virtual void setpreset(unsigned char npreset)=0; - /**Change parameter npar to value - * @param npar chosen parameter - * @param value chosen new value*/ - virtual void changepar(const int &npar,const unsigned char &value)=0; - /**Get the value of parameter npar - * @param npar chosen parameter - * @return the value of the parameter in an unsigned char or 0 if it - * does not exist*/ - virtual unsigned char getpar(const int &npar)const=0; - /**Output result of effect based on the given buffers - * - * This method should result in the effect generating its results - * and placing them into the efxoutl and efxoutr buffers. - * Every Effect should overide this method. - * - * @param smpsl Input buffer for the Left channel - * @param smpsr Input buffer for the Right channel - */ - virtual void out(REALTYPE *const smpsl,REALTYPE *const smpsr)=0; - /**Reset the state of the effect*/ - virtual void cleanup(){}; - /**This is only used for EQ (for user interface)*/ - virtual REALTYPE getfreqresponse(REALTYPE freq){return (0);}; +class Effect +{ +public: + /** + * Effect Constructor + * @param insertion_ 1 when it is an insertion Effect and 0 when it + * is not an insertion Effect + * @param efxoutl_ Effect output buffer Left channel + * @param efxoutr_ Effect output buffer Right channel + * @param filterpars_ pointer to FilterParams array + * @param Ppreset_ chosen preset + * @return Initialized Effect object*/ + Effect(bool insertion_,REALTYPE *const efxoutl_, + REALTYPE *const efxoutr_,FilterParams *filterpars_, + const unsigned char & Ppreset_); + /**Deconstructor + * + * Deconstructs the Effect and releases any resouces that it has + * allocated for itself*/ + virtual ~Effect() {}; + /** + * Choose a preset + * @param npreset number of chosen preset*/ + virtual void setpreset(unsigned char npreset)=0; + /**Change parameter npar to value + * @param npar chosen parameter + * @param value chosen new value*/ + virtual void changepar(const int &npar,const unsigned char &value)=0; + /**Get the value of parameter npar + * @param npar chosen parameter + * @return the value of the parameter in an unsigned char or 0 if it + * does not exist*/ + virtual unsigned char getpar(const int &npar)const=0; + /**Output result of effect based on the given buffers + * + * This method should result in the effect generating its results + * and placing them into the efxoutl and efxoutr buffers. + * Every Effect should overide this method. + * + * @param smpsl Input buffer for the Left channel + * @param smpsr Input buffer for the Right channel + */ + virtual void out(REALTYPE *const smpsl,REALTYPE *const smpsr)=0; + /**Reset the state of the effect*/ + virtual void cleanup() {}; + /**This is only used for EQ (for user interface)*/ + virtual REALTYPE getfreqresponse(REALTYPE freq) { + return (0); + }; - unsigned char Ppreset;/**0.49999999) incx=0.499999999; //Limit the Frequency lfornd=Prandomness/127.0; - if (lfornd<0.0) lfornd=0.0; else if (lfornd>1.0) lfornd=1.0; + if (lfornd<0.0) lfornd=0.0; + else if (lfornd>1.0) lfornd=1.0; if (PLFOtype>1) PLFOtype=1;//this has to be updated if more lfo's are added lfotype=PLFOtype; @@ -66,16 +71,18 @@ void EffectLFO::updateparams(){ /* * Compute the shape of the LFO */ -REALTYPE EffectLFO::getlfoshape(REALTYPE x){ +REALTYPE EffectLFO::getlfoshape(REALTYPE x) +{ REALTYPE out; - switch (lfotype){ - case 1: //EffectLFO_TRIANGLE - if ((x>0.0)&&(x<0.25)) out=4.0*x; - else if ((x>0.25)&&(x<0.75)) out=2-4*x; - else out=4.0*x-4.0; - break; - /**\todo more to be added here; also ::updateparams() need to be updated (to allow more lfotypes)*/ - default:out=cos(x*2*PI);//EffectLFO_SINE + switch (lfotype) { + case 1: //EffectLFO_TRIANGLE + if ((x>0.0)&&(x<0.25)) out=4.0*x; + else if ((x>0.25)&&(x<0.75)) out=2-4*x; + else out=4.0*x-4.0; + break; + /**\todo more to be added here; also ::updateparams() need to be updated (to allow more lfotypes)*/ + default: + out=cos(x*2*PI);//EffectLFO_SINE }; return(out); }; @@ -83,16 +90,17 @@ REALTYPE EffectLFO::getlfoshape(REALTYPE x){ /* * LFO output */ -void EffectLFO::effectlfoout(REALTYPE *outl,REALTYPE *outr){ - REALTYPE out; - +void EffectLFO::effectlfoout(REALTYPE *outl,REALTYPE *outr) +{ + REALTYPE out; + out=getlfoshape(xl); if ((lfotype==0)||(lfotype==1)) out*=(ampl1+xl*(ampl2-ampl1)); xl+=incx; if (xl>1.0) { - xl-=1.0; - ampl1=ampl2; - ampl2=(1.0-lfornd)+lfornd*RND; + xl-=1.0; + ampl1=ampl2; + ampl2=(1.0-lfornd)+lfornd*RND; }; *outl=(out+1.0)*0.5; @@ -100,9 +108,9 @@ void EffectLFO::effectlfoout(REALTYPE *outl,REALTYPE *outr){ if ((lfotype==0)||(lfotype==1)) out*=(ampr1+xr*(ampr2-ampr1)); xr+=incx; if (xr>1.0) { - xr-=1.0; - ampr1=ampr2; - ampr2=(1.0-lfornd)+lfornd*RND; + xr-=1.0; + ampr1=ampr2; + ampr2=(1.0-lfornd)+lfornd*RND; }; *outr=(out+1.0)*0.5; }; diff --git a/plugins/zynaddsubfx/src/Effects/EffectLFO.h b/plugins/zynaddsubfx/src/Effects/EffectLFO.h index ca78b8414..54a595110 100644 --- a/plugins/zynaddsubfx/src/Effects/EffectLFO.h +++ b/plugins/zynaddsubfx/src/Effects/EffectLFO.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + EffectLFO.h - Stereo LFO used by some effects Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -24,9 +24,11 @@ #define EFFECT_LFO_H #include "../globals.h" -/**LFO for some of the Effect objects*/ -class EffectLFO{ - public: +/**LFO for some of the Effect objects + * \todo see if this should inherit LFO*/ +class EffectLFO +{ +public: EffectLFO(); ~EffectLFO(); void effectlfoout(REALTYPE *outl,REALTYPE *outr); @@ -35,15 +37,15 @@ class EffectLFO{ unsigned char Prandomness; unsigned char PLFOtype; unsigned char Pstereo;//"64"=0 - private: +private: REALTYPE getlfoshape(REALTYPE x); - + REALTYPE xl,xr; REALTYPE incx; REALTYPE ampl1,ampl2,ampr1,ampr2;//necessary for "randomness" REALTYPE lfointensity; REALTYPE lfornd; - char lfotype; /**\todo GET RID OF CHAR (use a subclass if types are needed)*/ + char lfotype; /**\todo GET RID OF CHAR (replace with short or enum)*/ }; diff --git a/plugins/zynaddsubfx/src/Effects/EffectMgr.C b/plugins/zynaddsubfx/src/Effects/EffectMgr.C deleted file mode 100644 index f61896f6c..000000000 --- a/plugins/zynaddsubfx/src/Effects/EffectMgr.C +++ /dev/null @@ -1,295 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - EffectMgr.C - Effect manager, an interface betwen the program and effects - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include "EffectMgr.h" - -EffectMgr::EffectMgr(int insertion_,pthread_mutex_t *mutex_) - :insertion(insertion_), - efxoutl(new REALTYPE[SOUND_BUFFER_SIZE]), - efxoutr(new REALTYPE[SOUND_BUFFER_SIZE]), - filterpars(NULL),nefx(0),efx(NULL),mutex(mutex_),dryonly(false) -{ - setpresettype("Peffect"); /**\todo Figure out what this is doing - * , as it might be another leaky abstraction.*/ -// efx=NULL; -// nefx=0; -// insertion=insertion_; -// mutex=mutex_; -// efxoutl=new REALTYPE[SOUND_BUFFER_SIZE]; -// efxoutr=new REALTYPE[SOUND_BUFFER_SIZE]; - for (int i=0;ifilterpars; -} - -/* - * Obtain the effect number - */ -int EffectMgr::geteffect(){ - return (nefx); -} - -/* - * Cleanup the current effect - */ -void EffectMgr::cleanup(){ - if (efx!=NULL) efx->cleanup(); -} - - -/* - * Get the preset of the current effect - */ - -unsigned char EffectMgr::getpreset(){ - if (efx!=NULL) return(efx->Ppreset); - else return(0); -} - -/* - * Change the preset of the current effect - */ -void EffectMgr::changepreset_nolock(unsigned char npreset){ - if (efx!=NULL) efx->setpreset(npreset); -} - -/* - * Change the preset of the current effect(with thread locking) - */ -void EffectMgr::changepreset(unsigned char npreset){ - pthread_mutex_lock(mutex); - changepreset_nolock(npreset); - pthread_mutex_unlock(mutex); -} - - -/* - * Change a parameter of the current effect - */ -void EffectMgr::seteffectpar_nolock(int npar,unsigned char value){ - if (efx==NULL) return; - efx->changepar(npar,value); -} - -/* - * Change a parameter of the current effect (with thread locking) - */ -void EffectMgr::seteffectpar(int npar,unsigned char value){ - pthread_mutex_lock(mutex); - seteffectpar_nolock(npar,value); - pthread_mutex_unlock(mutex); -} - -/* - * Get a parameter of the current effect - */ -unsigned char EffectMgr::geteffectpar(int npar){ - if (efx==NULL) return(0); - return(efx->getpar(npar)); -} - - -/* - * Apply the effect - */ -void EffectMgr::out(REALTYPE *smpsl,REALTYPE *smpsr){ - int i; - if (efx==NULL){ - if (insertion==0) - for (i=0;iout(smpsl,smpsr); - - REALTYPE volume=efx->volume; - - if (nefx==7){//this is need only for the EQ effect - /**\todo figure out why*/ - for (i=0;ioutvolume); -} - - -/* - * Get the EQ response - */ -REALTYPE EffectMgr::getEQfreqresponse(REALTYPE freq){ - if (nefx==7) return(efx->getfreqresponse(freq)); - else return(0.0); -} - - -void EffectMgr::setdryonly(bool value){ - dryonly=value; -} - -void EffectMgr::add2XML(XMLwrapper *xml){ - xml->addpar("type",geteffect()); - - if ((efx==NULL)||(geteffect()==0)) return; - xml->addpar("preset",efx->Ppreset); - - xml->beginbranch("EFFECT_PARAMETERS"); - for (int n=0;n<128;n++){ /**\todo evaluate who should oversee saving - * and loading of parameters*/ - int par=geteffectpar(n); - if (par==0) continue; - xml->beginbranch("par_no",n); - xml->addpar("par",par); - xml->endbranch(); - }; - if (filterpars!=NULL){ - xml->beginbranch("FILTER"); - filterpars->add2XML(xml); - xml->endbranch(); - }; - xml->endbranch(); -} - -void EffectMgr::getfromXML(XMLwrapper *xml){ - changeeffect(xml->getpar127("type",geteffect())); - - if ((efx==NULL)||(geteffect()==0)) return; - - efx->Ppreset=xml->getpar127("preset",efx->Ppreset); - - if (xml->enterbranch("EFFECT_PARAMETERS")){ - for (int n=0;n<128;n++){ - seteffectpar_nolock(n,0);//erase effect parameter - if (xml->enterbranch("par_no",n)==0) continue; - - int par=geteffectpar(n); - seteffectpar_nolock(n,xml->getpar127("par",par)); - xml->exitbranch(); - }; - if (filterpars!=NULL){ - if (xml->enterbranch("FILTER")){ - filterpars->getfromXML(xml); - xml->exitbranch(); - }; - }; - xml->exitbranch(); - }; - cleanup(); -} - diff --git a/plugins/zynaddsubfx/src/Effects/EffectMgr.cpp b/plugins/zynaddsubfx/src/Effects/EffectMgr.cpp new file mode 100644 index 000000000..081101184 --- /dev/null +++ b/plugins/zynaddsubfx/src/Effects/EffectMgr.cpp @@ -0,0 +1,332 @@ +/* + ZynAddSubFX - a software synthesizer + + EffectMgr.C - Effect manager, an interface betwen the program and effects + Copyright (C) 2002-2005 Nasca Octavian Paul + Author: Nasca Octavian Paul + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "EffectMgr.h" + +EffectMgr::EffectMgr(int insertion_,pthread_mutex_t *mutex_) + :insertion(insertion_), + efxoutl(new REALTYPE[SOUND_BUFFER_SIZE]), + efxoutr(new REALTYPE[SOUND_BUFFER_SIZE]), + filterpars(NULL),nefx(0),efx(NULL),mutex(mutex_),dryonly(false) +{ + setpresettype("Peffect"); /**\todo Figure out what this is doing + * , as it might be another leaky abstraction.*/ +// efx=NULL; +// nefx=0; +// insertion=insertion_; +// mutex=mutex_; +// efxoutl=new REALTYPE[SOUND_BUFFER_SIZE]; +// efxoutr=new REALTYPE[SOUND_BUFFER_SIZE]; + for (int i=0;ifilterpars; +} + +/* + * Obtain the effect number + */ +int EffectMgr::geteffect() +{ + return (nefx); +} + +/* + * Cleanup the current effect + */ +void EffectMgr::cleanup() +{ + if (efx!=NULL) efx->cleanup(); +} + + +/* + * Get the preset of the current effect + */ + +unsigned char EffectMgr::getpreset() +{ + if (efx!=NULL) return(efx->Ppreset); + else return(0); +} + +/* + * Change the preset of the current effect + */ +void EffectMgr::changepreset_nolock(unsigned char npreset) +{ + if (efx!=NULL) efx->setpreset(npreset); +} + +/* + * Change the preset of the current effect(with thread locking) + */ +void EffectMgr::changepreset(unsigned char npreset) +{ + pthread_mutex_lock(mutex); + changepreset_nolock(npreset); + pthread_mutex_unlock(mutex); +} + + +/* + * Change a parameter of the current effect + */ +void EffectMgr::seteffectpar_nolock(int npar,unsigned char value) +{ + if (efx==NULL) return; + efx->changepar(npar,value); +} + +/* + * Change a parameter of the current effect (with thread locking) + */ +void EffectMgr::seteffectpar(int npar,unsigned char value) +{ + pthread_mutex_lock(mutex); + seteffectpar_nolock(npar,value); + pthread_mutex_unlock(mutex); +} + +/* + * Get a parameter of the current effect + */ +unsigned char EffectMgr::geteffectpar(int npar) +{ + if (efx==NULL) return(0); + return(efx->getpar(npar)); +} + + +/* + * Apply the effect + */ +void EffectMgr::out(REALTYPE *smpsl,REALTYPE *smpsr) +{ + int i; + if (efx==NULL) { + if (insertion==0) + for (i=0;iout(smpsl,smpsr); + + REALTYPE volume=efx->volume; + + if (nefx==7) {//this is need only for the EQ effect + /**\todo figure out why*/ + for (i=0;ioutvolume); +} + + +/* + * Get the EQ response + */ +REALTYPE EffectMgr::getEQfreqresponse(REALTYPE freq) +{ + if (nefx==7) return(efx->getfreqresponse(freq)); + else return(0.0); +} + + +void EffectMgr::setdryonly(bool value) +{ + dryonly=value; +} + +void EffectMgr::add2XML(XMLwrapper *xml) +{ + xml->addpar("type",geteffect()); + + if ((efx==NULL)||(geteffect()==0)) return; + xml->addpar("preset",efx->Ppreset); + + xml->beginbranch("EFFECT_PARAMETERS"); + for (int n=0;n<128;n++) { /**\todo evaluate who should oversee saving + * and loading of parameters*/ + int par=geteffectpar(n); + if (par==0) continue; + xml->beginbranch("par_no",n); + xml->addpar("par",par); + xml->endbranch(); + }; + if (filterpars!=NULL) { + xml->beginbranch("FILTER"); + filterpars->add2XML(xml); + xml->endbranch(); + }; + xml->endbranch(); +} + +void EffectMgr::getfromXML(XMLwrapper *xml) +{ + changeeffect(xml->getpar127("type",geteffect())); + + if ((efx==NULL)||(geteffect()==0)) return; + + efx->Ppreset=xml->getpar127("preset",efx->Ppreset); + + if (xml->enterbranch("EFFECT_PARAMETERS")) { + for (int n=0;n<128;n++) { + seteffectpar_nolock(n,0);//erase effect parameter + if (xml->enterbranch("par_no",n)==0) continue; + + int par=geteffectpar(n); + seteffectpar_nolock(n,xml->getpar127("par",par)); + xml->exitbranch(); + }; + if (filterpars!=NULL) { + if (xml->enterbranch("FILTER")) { + filterpars->getfromXML(xml); + xml->exitbranch(); + }; + }; + xml->exitbranch(); + }; + cleanup(); +} + diff --git a/plugins/zynaddsubfx/src/Effects/EffectMgr.h b/plugins/zynaddsubfx/src/Effects/EffectMgr.h index c680b335f..dd5d52ce6 100644 --- a/plugins/zynaddsubfx/src/Effects/EffectMgr.h +++ b/plugins/zynaddsubfx/src/Effects/EffectMgr.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + EffectMgr.h - Effect manager, an interface betwen the program and effects Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -39,67 +39,64 @@ /**Effect manager, an interface betwen the program and effects*/ -class EffectMgr:public Presets{ - public: - EffectMgr(int insertion_,pthread_mutex_t *mutex_); - ~EffectMgr(); +class EffectMgr:public Presets +{ +public: + EffectMgr(int insertion_,pthread_mutex_t *mutex_); + ~EffectMgr(); - void add2XML(XMLwrapper *xml); - void defaults(); - void getfromXML(XMLwrapper *xml); + void add2XML(XMLwrapper *xml); + void defaults(); + void getfromXML(XMLwrapper *xml); - void out(REALTYPE *smpsl,REALTYPE *smpsr); + void out(REALTYPE *smpsl,REALTYPE *smpsr); - void setdryonly(bool value); - - /**get the output(to speakers) volume of the systemeffect*/ - REALTYPE sysefxgetvolume(); + void setdryonly(bool value); - void cleanup();/** -#include "Phaser.h" -/**\todo figure out why this define was made*/ -#define PHASER_LFO_SHAPE 2 - -Phaser::Phaser(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_) - :Effect(insertion_,efxoutl_,efxoutr_,NULL,0),oldl(NULL),oldr(NULL) -{ - setpreset(Ppreset); - cleanup(); -}; - -Phaser::~Phaser(){ - if (oldl!=NULL) delete [] oldl; - if (oldr!=NULL) delete [] oldr; -}; - - -/* - * Effect output - */ -void Phaser::out(REALTYPE *smpsl,REALTYPE *smpsr){ - int i,j; - REALTYPE lfol,lfor,lgain,rgain,tmp; - - lfo.effectlfoout(&lfol,&lfor); - lgain=lfol; - rgain=lfor; - lgain=(exp(lgain*PHASER_LFO_SHAPE)-1)/(exp(PHASER_LFO_SHAPE)-1.0); - rgain=(exp(rgain*PHASER_LFO_SHAPE)-1)/(exp(PHASER_LFO_SHAPE)-1.0); - - - lgain=1.0-phase*(1.0-depth)-(1.0-phase)*lgain*depth; - rgain=1.0-phase*(1.0-depth)-(1.0-phase)*rgain*depth; - - if (lgain>1.0) lgain=1.0;else if (lgain<0.0) lgain=0.0; - if (rgain>1.0) rgain=1.0;else if (rgain<0.0) rgain=0.0; - - for (i=0;iPdepth=Pdepth; - depth=(Pdepth/127.0); -}; - - -void Phaser::setfb(const unsigned char &Pfb){ - this->Pfb=Pfb; - fb=(Pfb-64.0)/64.1; -}; - -void Phaser::setvolume(const unsigned char &Pvolume){ - this->Pvolume=Pvolume; - outvolume=Pvolume/127.0; - if (insertion==0) volume=1.0; - else volume=outvolume; -}; - -void Phaser::setpanning(const unsigned char &Ppanning){ - this->Ppanning=Ppanning; - panning=Ppanning/127.0; -}; - -void Phaser::setlrcross(const unsigned char &Plrcross){ - this->Plrcross=Plrcross; - lrcross=Plrcross/127.0; -}; - -void Phaser::setstages(const unsigned char &Pstages){ - if (oldl!=NULL) delete [] oldl; - if (oldr!=NULL) delete [] oldr; - if (Pstages>=MAX_PHASER_STAGES) this->Pstages=MAX_PHASER_STAGES-1; - else this->Pstages=Pstages; - oldl=new REALTYPE[Pstages*2]; - oldr=new REALTYPE[Pstages*2]; - cleanup(); -}; - -void Phaser::setphase(const unsigned char &Pphase){ - this->Pphase=Pphase; - phase=(Pphase/127.0); -}; - - -void Phaser::setpreset(unsigned char npreset){ - const int PRESET_SIZE=12; - const int NUM_PRESETS=6; - unsigned char presets[NUM_PRESETS][PRESET_SIZE]={ - //Phaser1 - {64,64,36,0,0,64,110,64,1,0,0,20}, - //Phaser2 - {64,64,35,0,0,88,40,64,3,0,0,20}, - //Phaser3 - {64,64,31,0,0,66,68,107,2,0,0,20}, - //Phaser4 - {39,64,22,0,0,66,67,10,5,0,1,20}, - //Phaser5 - {64,64,20,0,1,110,67,78,10,0,0,20}, - //Phaser6 - {64,64,53,100,0,58,37,78,3,0,0,20}}; - if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1; - for (int n=0;n1) Poutsub=1; - else Poutsub=value; - break; - case 11:setphase(value); - break; - }; -}; - -unsigned char Phaser::getpar(const int &npar)const{ - switch (npar){ - case 0: return(Pvolume); - break; - case 1: return(Ppanning); - break; - case 2: return(lfo.Pfreq); - break; - case 3: return(lfo.Prandomness); - break; - case 4: return(lfo.PLFOtype); - break; - case 5: return(lfo.Pstereo); - break; - case 6: return(Pdepth); - break; - case 7: return(Pfb); - break; - case 8: return(Pstages); - break; - case 9: return(Plrcross); - break; - case 10:return(Poutsub); - break; - case 11:return(Pphase); - break; - default:return (0); - }; - -}; - diff --git a/plugins/zynaddsubfx/src/Effects/Phaser.cpp b/plugins/zynaddsubfx/src/Effects/Phaser.cpp new file mode 100644 index 000000000..ed1fee1d3 --- /dev/null +++ b/plugins/zynaddsubfx/src/Effects/Phaser.cpp @@ -0,0 +1,283 @@ +/* + ZynAddSubFX - a software synthesizer + + Phaser.C - Phaser effect + Copyright (C) 2002-2005 Nasca Octavian Paul + Author: Nasca Octavian Paul + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include +#include "Phaser.h" +#define PHASER_LFO_SHAPE 2 + +Phaser::Phaser(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_) + :Effect(insertion_,efxoutl_,efxoutr_,NULL,0),old(1),oldgain(0.0) +{ + setpreset(Ppreset); + cleanup(); +}; + +Phaser::~Phaser() +{ +}; + + +/* + * Effect output + */ +void Phaser::out(REALTYPE *smpsl,REALTYPE *smpsr) +{ + int i,j; + REALTYPE lfol,lfor,lgain,rgain,tmp; + + lfo.effectlfoout(&lfol,&lfor); + lgain=lfol; + rgain=lfor; + lgain=(exp(lgain*PHASER_LFO_SHAPE)-1)/(exp(PHASER_LFO_SHAPE)-1.0); + rgain=(exp(rgain*PHASER_LFO_SHAPE)-1)/(exp(PHASER_LFO_SHAPE)-1.0); + + + lgain=1.0-phase*(1.0-depth)-(1.0-phase)*lgain*depth; + rgain=1.0-phase*(1.0-depth)-(1.0-phase)*rgain*depth; + + if (lgain>1.0) lgain=1.0; + else if (lgain<0.0) lgain=0.0; + if (rgain>1.0) rgain=1.0; + else if (rgain<0.0) rgain=0.0; + + for (i=0;i(lgain,rgain); + + if (Poutsub!=0) + for (i=0;i(0.0); + old.l().clear(); + old.r().clear(); +}; + +/* + * Parameter control + */ +void Phaser::setdepth(const unsigned char &Pdepth) +{ + this->Pdepth=Pdepth; + depth=(Pdepth/127.0); +}; + + +void Phaser::setfb(const unsigned char &Pfb) +{ + this->Pfb=Pfb; + fb=(Pfb-64.0)/64.1; +}; + +void Phaser::setvolume(const unsigned char &Pvolume) +{ + this->Pvolume=Pvolume; + outvolume=Pvolume/127.0; + if (insertion==0) volume=1.0; + else volume=outvolume; +}; + +void Phaser::setpanning(const unsigned char &Ppanning) +{ + this->Ppanning=Ppanning; + panning=Ppanning/127.0; +}; + +void Phaser::setlrcross(const unsigned char &Plrcross) +{ + this->Plrcross=Plrcross; + lrcross=Plrcross/127.0; +}; + +void Phaser::setstages(const unsigned char &Pstages) +{ + if (Pstages>=MAX_PHASER_STAGES) this->Pstages=MAX_PHASER_STAGES-1; + else this->Pstages=Pstages; + old=Stereo(Pstages*2); + cleanup(); +}; + +void Phaser::setphase(const unsigned char &Pphase) +{ + this->Pphase=Pphase; + phase=(Pphase/127.0); +}; + + +void Phaser::setpreset(unsigned char npreset) +{ + const int PRESET_SIZE=12; + const int NUM_PRESETS=6; + unsigned char presets[NUM_PRESETS][PRESET_SIZE]={ + //Phaser1 + {64,64,36,0,0,64,110,64,1,0,0,20}, + //Phaser2 + {64,64,35,0,0,88,40,64,3,0,0,20}, + //Phaser3 + {64,64,31,0,0,66,68,107,2,0,0,20}, + //Phaser4 + {39,64,22,0,0,66,67,10,5,0,1,20}, + //Phaser5 + {64,64,20,0,1,110,67,78,10,0,0,20}, + //Phaser6 + {64,64,53,100,0,58,37,78,3,0,0,20} + }; + if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1; + for (int n=0;n1) Poutsub=1; + else Poutsub=value; + break; + case 11: + setphase(value); + break; + }; +}; + +unsigned char Phaser::getpar(const int &npar)const +{ + switch (npar) { + case 0: + return(Pvolume); + break; + case 1: + return(Ppanning); + break; + case 2: + return(lfo.Pfreq); + break; + case 3: + return(lfo.Prandomness); + break; + case 4: + return(lfo.PLFOtype); + break; + case 5: + return(lfo.Pstereo); + break; + case 6: + return(Pdepth); + break; + case 7: + return(Pfb); + break; + case 8: + return(Pstages); + break; + case 9: + return(Plrcross); + break; + case 10: + return(Poutsub); + break; + case 11: + return(Pphase); + break; + default: + return (0); + }; + +}; + diff --git a/plugins/zynaddsubfx/src/Effects/Phaser.h b/plugins/zynaddsubfx/src/Effects/Phaser.h index d74390f89..700af3dfc 100644 --- a/plugins/zynaddsubfx/src/Effects/Phaser.h +++ b/plugins/zynaddsubfx/src/Effects/Phaser.h @@ -1,71 +1,76 @@ -/* - ZynAddSubFX - a software synthesizer - - Phaser.h - Phaser effect - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef PHASER_H -#define PHASER_H -#include "../globals.h" -#include "Effect.h" -#include "EffectLFO.h" - -#define MAX_PHASER_STAGES 12 -/**Phaser Effect*/ -class Phaser:public Effect { - public: - Phaser(const int &insetion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_); - ~Phaser(); - void out(REALTYPE *smpsl,REALTYPE *smpsr); - void setpreset(unsigned char npreset); - void changepar(const int &npar,const unsigned char &value); - unsigned char getpar(const int &npar)const; - void cleanup(); - void setdryonly(); - - private: - //Parametrii Phaser - EffectLFO lfo;/** old; + //REALTYPE oldlgain,oldrgain; + Stereo oldgain; +}; + +#endif + diff --git a/plugins/zynaddsubfx/src/Effects/Reverb.C b/plugins/zynaddsubfx/src/Effects/Reverb.C deleted file mode 100644 index 9c231e696..000000000 --- a/plugins/zynaddsubfx/src/Effects/Reverb.C +++ /dev/null @@ -1,430 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Reverb.C - Reverberation effect - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include "Reverb.h" - -/**\todo: EarlyReflections,Prdelay,Perbalance */ - -Reverb::Reverb(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_) - :Effect(insertion_,efxoutl_,efxoutr_,NULL,0) -{ - inputbuf=new REALTYPE[SOUND_BUFFER_SIZE]; - - //defaults - Pvolume=48; - Ppan=64; - Ptime=64; - Pidelay=40; - Pidelayfb=0; - Prdelay=0; - Plpf=127; - Phpf=0; - Perbalance=64; - Plohidamp=80; - Ptype=1; - Proomsize=64;roomsize=1.0;rs=1.0; - - for (int i=0;icleanup(); - if (lpf!=NULL) lpf->cleanup(); - -}; - -/* - * Process one channel; 0=left,1=right - */ -void Reverb::processmono(int ch,REALTYPE *output){ - int i,j; - REALTYPE fbout,tmp; - /**\todo: implement the high part from lohidamp*/ - - for (j=REV_COMBS*ch;j=comblength) ck=0; - }; - - combk[j]=ck; - lpcomb[j]=lpcombj; - }; - - for (j=REV_APS*ch;j=aplength) ak=0; - }; - apk[j]=ak; - }; -}; - -/* - * Effect output - */ -void Reverb::out(REALTYPE *smps_l, REALTYPE *smps_r){ - int i; - if ((Pvolume==0)&&(insertion!=0)) return; - - for (i=0;i=idelaylen) idelayk=0; - }; - }; - - if (lpf!=NULL) lpf->filterout(inputbuf); - if (hpf!=NULL) hpf->filterout(inputbuf); - - processmono(0,efxoutl);//left - processmono(1,efxoutr);//right - - REALTYPE lvol=rs/REV_COMBS*pan; - REALTYPE rvol=rs/REV_COMBS*(1.0-pan); - if (insertion!=0){ - lvol*=2;rvol*=2; - }; - for (int i=0;iPvolume=Pvolume; - if (insertion==0) { - outvolume=pow(0.01,(1.0-Pvolume/127.0))*4.0; - volume=1.0; - } else { - volume=outvolume=Pvolume/127.0; - if (Pvolume==0) cleanup(); - }; -}; - -void Reverb::setpan(const unsigned char &Ppan){ - this->Ppan=Ppan; - pan=(REALTYPE)Ppan/127.0; -}; - -void Reverb::settime(const unsigned char &Ptime){ - int i; - REALTYPE t; - this->Ptime=Ptime; - t=pow(60.0,(REALTYPE)Ptime/127.0)-0.97; - - for (i=0;iPlohidamp=Plohidamp; - if (Plohidamp==64) { - lohidamptype=0; - lohifb=0.0; - } else { - if (Plohidamp<64) lohidamptype=1; - if (Plohidamp>64) lohidamptype=2; - x=fabs((REALTYPE)(Plohidamp-64)/64.1); - lohifb=x*x; - }; -}; - -void Reverb::setidelay(const unsigned char &Pidelay){ - REALTYPE delay; - this->Pidelay=Pidelay; - delay=pow(50*Pidelay/127.0,2)-1.0; - - if (idelay!=NULL) delete []idelay; - idelay=NULL; - - idelaylen=(int) (SAMPLE_RATE*delay/1000); - if (idelaylen>1) { - idelayk=0; - idelay=new REALTYPE[idelaylen]; - for (int i=0;iPidelayfb=Pidelayfb; - idelayfb=Pidelayfb/128.0; -}; - -void Reverb::sethpf(const unsigned char &Phpf){ - this->Phpf=Phpf; - if (Phpf==0) {//No HighPass - if (hpf!=NULL) delete hpf; - hpf=NULL; - } - else{ - REALTYPE fr=exp(pow(Phpf/127.0,0.5)*log(10000.0))+20.0; - if (hpf==NULL) hpf=new AnalogFilter(3,fr,1,0); - else hpf->setfreq(fr); - }; -}; - -void Reverb::setlpf(const unsigned char &Plpf){ - this->Plpf=Plpf; - if (Plpf==127) {//No LowPass - if (lpf!=NULL) delete lpf; - lpf=NULL; - } - else{ - REALTYPE fr=exp(pow(Plpf/127.0,0.5)*log(25000.0))+40; - if (lpf==NULL) lpf=new AnalogFilter(2,fr,1,0); - else lpf->setfreq(fr); - }; -}; - -void Reverb::settype(unsigned char Ptype){ - const int NUM_TYPES=2; - int combtunings[NUM_TYPES][REV_COMBS]={ - //this is unused (for random) - {0,0,0,0,0,0,0,0}, - //Freeverb by Jezar at Dreampoint - {1116,1188,1277,1356,1422,1491,1557,1617} - }; - int aptunings[NUM_TYPES][REV_APS]={ - //this is unused (for random) - {0,0,0,0}, - //Freeverb by Jezar at Dreampoint - {225,341,441,556} - }; - - if (Ptype>=NUM_TYPES) Ptype=NUM_TYPES-1; - this->Ptype=Ptype; - - REALTYPE tmp; - for (int i=0;iREV_COMBS) tmp+=23.0; - tmp*=SAMPLE_RATE/44100.0;//adjust the combs according to the samplerate - if (tmp<10) tmp=10; - - comblen[i]=(int) tmp; - combk[i]=0; - lpcomb[i]=0; - if (comb[i]!=NULL) delete []comb[i]; - comb[i]=new REALTYPE[comblen[i]]; - }; - - for (int i=0;iREV_APS) tmp+=23.0; - tmp*=SAMPLE_RATE/44100.0;//adjust the combs according to the samplerate - if (tmp<10) tmp=10; - aplen[i]=(int) tmp; - apk[i]=0; - if (ap[i]!=NULL) delete []ap[i]; - ap[i]=new REALTYPE[aplen[i]]; - }; - settime(Ptime); - cleanup(); -}; - -void Reverb::setroomsize(const unsigned char &Proomsize){ - this->Proomsize=Proomsize; - if (Proomsize==0) this->Proomsize=64;//this is because the older versions consider roomsize=0 - roomsize=(this->Proomsize-64.0)/64.0; - if (roomsize>0.0) roomsize*=2.0; - roomsize=pow(10.0,roomsize); - rs=sqrt(roomsize); - settype(Ptype); -}; - -void Reverb::setpreset(unsigned char npreset){ - const int PRESET_SIZE=12; - const int NUM_PRESETS=13; - unsigned char presets[NUM_PRESETS][PRESET_SIZE]={ - //Cathedral1 - {80,64,63,24,0,0,0,85,5,83,1,64}, - //Cathedral2 - {80,64,69,35,0,0,0,127,0,71,0,64}, - //Cathedral3 - {80,64,69,24,0,0,0,127,75,78,1,85}, - //Hall1 - {90,64,51,10,0,0,0,127,21,78,1,64}, - //Hall2 - {90,64,53,20,0,0,0,127,75,71,1,64}, - //Room1 - {100,64,33,0,0,0,0,127,0,106,0,30}, - //Room2 - {100,64,21,26,0,0,0,62,0,77,1,45}, - //Basement - {110,64,14,0,0,0,0,127,5,71,0,25}, - //Tunnel - {85,80,84,20,42,0,0,51,0,78,1,105}, - //Echoed1 - {95,64,26,60,71,0,0,114,0,64,1,64}, - //Echoed2 - {90,64,40,88,71,0,0,114,0,88,1,64}, - //VeryLong1 - {90,64,93,15,0,0,0,114,0,77,0,95}, - //VeryLong2 - {90,64,111,30,0,0,0,114,90,74,1,80}}; - - if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1; - for (int n=0;n +#include "Reverb.h" + +/**\todo: EarlyReflections,Prdelay,Perbalance */ + +Reverb::Reverb(const int &insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_) + :Effect(insertion_,efxoutl_,efxoutr_,NULL,0) +{ + inputbuf=new REALTYPE[SOUND_BUFFER_SIZE]; + + //defaults + Pvolume=48; + Ppan=64; + Ptime=64; + Pidelay=40; + Pidelayfb=0; + Prdelay=0; + Plpf=127; + Phpf=0; + Perbalance=64; + Plohidamp=80; + Ptype=1; + Proomsize=64; + roomsize=1.0; + rs=1.0; + + for (int i=0;icleanup(); + if (lpf!=NULL) lpf->cleanup(); + +}; + +/* + * Process one channel; 0=left,1=right + */ +void Reverb::processmono(int ch,REALTYPE *output) +{ + int i,j; + REALTYPE fbout,tmp; + /**\todo: implement the high part from lohidamp*/ + + for (j=REV_COMBS*ch;j=comblength) ck=0; + }; + + combk[j]=ck; + lpcomb[j]=lpcombj; + }; + + for (j=REV_APS*ch;j=aplength) ak=0; + }; + apk[j]=ak; + }; +}; + +/* + * Effect output + */ +void Reverb::out(REALTYPE *smps_l, REALTYPE *smps_r) +{ + int i; + if ((Pvolume==0)&&(insertion!=0)) return; + + for (i=0;i=idelaylen) idelayk=0; + }; + }; + + if (lpf!=NULL) lpf->filterout(inputbuf); + if (hpf!=NULL) hpf->filterout(inputbuf); + + processmono(0,efxoutl);//left + processmono(1,efxoutr);//right + + REALTYPE lvol=rs/REV_COMBS*pan; + REALTYPE rvol=rs/REV_COMBS*(1.0-pan); + if (insertion!=0) { + lvol*=2; + rvol*=2; + }; + for (int i=0;iPvolume=Pvolume; + if (insertion==0) { + outvolume=pow(0.01,(1.0-Pvolume/127.0))*4.0; + volume=1.0; + } else { + volume=outvolume=Pvolume/127.0; + if (Pvolume==0) cleanup(); + }; +}; + +void Reverb::setpan(const unsigned char &Ppan) +{ + this->Ppan=Ppan; + pan=(REALTYPE)Ppan/127.0; +}; + +void Reverb::settime(const unsigned char &Ptime) +{ + int i; + REALTYPE t; + this->Ptime=Ptime; + t=pow(60.0,(REALTYPE)Ptime/127.0)-0.97; + + for (i=0;iPlohidamp=Plohidamp; + if (Plohidamp==64) { + lohidamptype=0; + lohifb=0.0; + } else { + if (Plohidamp<64) lohidamptype=1; + if (Plohidamp>64) lohidamptype=2; + x=fabs((REALTYPE)(Plohidamp-64)/64.1); + lohifb=x*x; + }; +}; + +void Reverb::setidelay(const unsigned char &Pidelay) +{ + REALTYPE delay; + this->Pidelay=Pidelay; + delay=pow(50*Pidelay/127.0,2)-1.0; + + if (idelay!=NULL) delete []idelay; + idelay=NULL; + + idelaylen=(int) (SAMPLE_RATE*delay/1000); + if (idelaylen>1) { + idelayk=0; + idelay=new REALTYPE[idelaylen]; + for (int i=0;iPidelayfb=Pidelayfb; + idelayfb=Pidelayfb/128.0; +}; + +void Reverb::sethpf(const unsigned char &Phpf) +{ + this->Phpf=Phpf; + if (Phpf==0) {//No HighPass + if (hpf!=NULL) delete hpf; + hpf=NULL; + } else { + REALTYPE fr=exp(pow(Phpf/127.0,0.5)*log(10000.0))+20.0; + if (hpf==NULL) hpf=new AnalogFilter(3,fr,1,0); + else hpf->setfreq(fr); + }; +}; + +void Reverb::setlpf(const unsigned char &Plpf) +{ + this->Plpf=Plpf; + if (Plpf==127) {//No LowPass + if (lpf!=NULL) delete lpf; + lpf=NULL; + } else { + REALTYPE fr=exp(pow(Plpf/127.0,0.5)*log(25000.0))+40; + if (lpf==NULL) lpf=new AnalogFilter(2,fr,1,0); + else lpf->setfreq(fr); + }; +}; + +void Reverb::settype(unsigned char Ptype) +{ + const int NUM_TYPES=2; + int combtunings[NUM_TYPES][REV_COMBS]={ + //this is unused (for random) + {0,0,0,0,0,0,0,0}, + //Freeverb by Jezar at Dreampoint + {1116,1188,1277,1356,1422,1491,1557,1617} + }; + int aptunings[NUM_TYPES][REV_APS]={ + //this is unused (for random) + {0,0,0,0}, + //Freeverb by Jezar at Dreampoint + {225,341,441,556} + }; + + if (Ptype>=NUM_TYPES) Ptype=NUM_TYPES-1; + this->Ptype=Ptype; + + REALTYPE tmp; + for (int i=0;iREV_COMBS) tmp+=23.0; + tmp*=SAMPLE_RATE/44100.0;//adjust the combs according to the samplerate + if (tmp<10) tmp=10; + + comblen[i]=(int) tmp; + combk[i]=0; + lpcomb[i]=0; + if (comb[i]!=NULL) delete []comb[i]; + comb[i]=new REALTYPE[comblen[i]]; + }; + + for (int i=0;iREV_APS) tmp+=23.0; + tmp*=SAMPLE_RATE/44100.0;//adjust the combs according to the samplerate + if (tmp<10) tmp=10; + aplen[i]=(int) tmp; + apk[i]=0; + if (ap[i]!=NULL) delete []ap[i]; + ap[i]=new REALTYPE[aplen[i]]; + }; + settime(Ptime); + cleanup(); +}; + +void Reverb::setroomsize(const unsigned char &Proomsize) +{ + this->Proomsize=Proomsize; + if (Proomsize==0) this->Proomsize=64;//this is because the older versions consider roomsize=0 + roomsize=(this->Proomsize-64.0)/64.0; + if (roomsize>0.0) roomsize*=2.0; + roomsize=pow(10.0,roomsize); + rs=sqrt(roomsize); + settype(Ptype); +}; + +void Reverb::setpreset(unsigned char npreset) +{ + const int PRESET_SIZE=12; + const int NUM_PRESETS=13; + unsigned char presets[NUM_PRESETS][PRESET_SIZE]={ + //Cathedral1 + {80,64,63,24,0,0,0,85,5,83,1,64}, + //Cathedral2 + {80,64,69,35,0,0,0,127,0,71,0,64}, + //Cathedral3 + {80,64,69,24,0,0,0,127,75,78,1,85}, + //Hall1 + {90,64,51,10,0,0,0,127,21,78,1,64}, + //Hall2 + {90,64,53,20,0,0,0,127,75,71,1,64}, + //Room1 + {100,64,33,0,0,0,0,127,0,106,0,30}, + //Room2 + {100,64,21,26,0,0,0,62,0,77,1,45}, + //Basement + {110,64,14,0,0,0,0,127,5,71,0,25}, + //Tunnel + {85,80,84,20,42,0,0,51,0,78,1,105}, + //Echoed1 + {95,64,26,60,71,0,0,114,0,64,1,64}, + //Echoed2 + {90,64,40,88,71,0,0,114,0,88,1,64}, + //VeryLong1 + {90,64,93,15,0,0,0,114,0,77,0,95}, + //VeryLong2 + {90,64,111,30,0,0,0,114,90,74,1,80} + }; + + if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1; + for (int n=0;n -#include - - -ALSAMidiIn::ALSAMidiIn(){ - int alsaport; - inputok=0; - char portname[50]; - sprintf(portname,"ZynAddSubFX"); - - midi_handle=NULL; - - if (snd_seq_open(&midi_handle,"default",SND_SEQ_OPEN_INPUT,0)!=0) return; - - snd_seq_set_client_name(midi_handle,"ZynAddSubFX");//thanks to Frank Neumann - - alsaport = snd_seq_create_simple_port(midi_handle,portname - ,SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE - ,SND_SEQ_PORT_TYPE_SYNTH); - if (alsaport<0) return; - - inputok=1; -}; - -ALSAMidiIn::~ALSAMidiIn(){ - if (midi_handle) - snd_seq_close(midi_handle); -}; - - -/* - * Get the midi command,channel and parameters - */ -void ALSAMidiIn::getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams){ - snd_seq_event_t *midievent=NULL; - cmdtype=MidiNull; - - if (inputok==0){ - /* The input is broken. We need to block for a while anyway so other - non-RT threads get a chance to run. */ - sleep(1); - return; - }; - - snd_seq_event_input(midi_handle,&midievent); - - if (midievent==NULL) return; - switch (midievent->type){ - case SND_SEQ_EVENT_NOTEON: - cmdtype=MidiNoteON; - cmdchan=midievent->data.note.channel; - cmdparams[0]=midievent->data.note.note; - cmdparams[1]=midievent->data.note.velocity; - break; - case SND_SEQ_EVENT_NOTEOFF: - cmdtype=MidiNoteOFF; - cmdchan=midievent->data.note.channel; - cmdparams[0]=midievent->data.note.note; - break; - case SND_SEQ_EVENT_PITCHBEND: - cmdtype=MidiController; - cmdchan=midievent->data.control.channel; - cmdparams[0]=C_pitchwheel;//Pitch Bend - cmdparams[1]=midievent->data.control.value; - break; - case SND_SEQ_EVENT_CONTROLLER: - cmdtype=MidiController; - cmdchan=midievent->data.control.channel; - cmdparams[0]=getcontroller(midievent->data.control.param); - cmdparams[1]=midievent->data.control.value; - //fprintf(stderr,"t=%d val=%d\n",midievent->data.control.param,midievent->data.control.value); - break; - - }; -}; - - -int ALSAMidiIn::getalsaid() { - if (midi_handle) { - snd_seq_client_info_t* seq_info; - snd_seq_client_info_malloc(&seq_info); - snd_seq_get_client_info(midi_handle, seq_info); - int id = snd_seq_client_info_get_client(seq_info); - snd_seq_client_info_free(seq_info); - return id; - } - return -1; -} diff --git a/plugins/zynaddsubfx/src/Input/ALSAMidiIn.cpp b/plugins/zynaddsubfx/src/Input/ALSAMidiIn.cpp new file mode 100644 index 000000000..5e27081fa --- /dev/null +++ b/plugins/zynaddsubfx/src/Input/ALSAMidiIn.cpp @@ -0,0 +1,110 @@ +/* + ZynAddSubFX - a software synthesizer + + ALSAMidiIn.C - Midi input for ALSA (this creates an ALSA virtual port) + Copyright (C) 2002-2005 Nasca Octavian Paul + Author: Nasca Octavian Paul + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "ALSAMidiIn.h" + +ALSAMidiIn::ALSAMidiIn() +{ + int alsaport; + inputok=false; + + midi_handle=NULL; + + if (snd_seq_open(&midi_handle,"default",SND_SEQ_OPEN_INPUT,0)!=0) return; + + snd_seq_set_client_name(midi_handle,"ZynAddSubFX");//thanks to Frank Neumann + + alsaport = snd_seq_create_simple_port(midi_handle,"ZynAddSubFX" + ,SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE + ,SND_SEQ_PORT_TYPE_SYNTH); + if (alsaport<0) return; + + inputok=true; +}; + +ALSAMidiIn::~ALSAMidiIn() +{ + if (midi_handle) snd_seq_close(midi_handle); +}; + + +/* + * Get the midi command,channel and parameters + */ +void ALSAMidiIn::getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams) +{ + snd_seq_event_t *midievent=NULL; + cmdtype=MidiNull; + + if (inputok==false) { + /* The input is broken. We need to block for a while anyway so other + non-RT threads get a chance to run. */ + sleep(1); + return; + }; + + snd_seq_event_input(midi_handle,&midievent); + + if (midievent==NULL) return; + switch (midievent->type) { + case SND_SEQ_EVENT_NOTEON: + cmdtype=MidiNoteON; + cmdchan=midievent->data.note.channel; + cmdparams[0]=midievent->data.note.note; + cmdparams[1]=midievent->data.note.velocity; + break; + case SND_SEQ_EVENT_NOTEOFF: + cmdtype=MidiNoteOFF; + cmdchan=midievent->data.note.channel; + cmdparams[0]=midievent->data.note.note; + break; + case SND_SEQ_EVENT_PITCHBEND: + cmdtype=MidiController; + cmdchan=midievent->data.control.channel; + cmdparams[0]=C_pitchwheel;//Pitch Bend + cmdparams[1]=midievent->data.control.value; + break; + case SND_SEQ_EVENT_CONTROLLER: + cmdtype=MidiController; + cmdchan=midievent->data.control.channel; + cmdparams[0]=getcontroller(midievent->data.control.param); + cmdparams[1]=midievent->data.control.value; + //fprintf(stderr,"t=%d val=%d\n",midievent->data.control.param,midievent->data.control.value); + break; + + }; +}; + + +int ALSAMidiIn::getalsaid() +{ + if (midi_handle) { + snd_seq_client_info_t* seq_info; + snd_seq_client_info_malloc(&seq_info); + snd_seq_get_client_info(midi_handle, seq_info); + int id = snd_seq_client_info_get_client(seq_info); + snd_seq_client_info_free(seq_info); + return id; + } + return -1; +} + diff --git a/plugins/zynaddsubfx/src/Input/ALSAMidiIn.h b/plugins/zynaddsubfx/src/Input/ALSAMidiIn.h index 947d74ba2..e4671014f 100644 --- a/plugins/zynaddsubfx/src/Input/ALSAMidiIn.h +++ b/plugins/zynaddsubfx/src/Input/ALSAMidiIn.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + ALSAMidiIn.h - Midi input for ALSA (this creates an ALSA virtual port) Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -27,17 +27,23 @@ #include "MidiIn.h" -class ALSAMidiIn:public MidiIn{ - public: - ALSAMidiIn(); - ~ALSAMidiIn(); - void getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams); - int getalsaid(); +/**Midi input for ALSA (this creates an ALSA virtual port)*/ +class ALSAMidiIn:public MidiIn +{ +public: + /**Constructor*/ + ALSAMidiIn(); + /**Destructor*/ + ~ALSAMidiIn(); - private: - snd_seq_t *midi_handle; + void getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams); + /**Get the ALSA id + * @return ALSA id*/ + int getalsaid(); + +private: + snd_seq_t *midi_handle; }; - #endif diff --git a/plugins/zynaddsubfx/src/Input/CMakeLists.txt b/plugins/zynaddsubfx/src/Input/CMakeLists.txt new file mode 100644 index 000000000..dac041748 --- /dev/null +++ b/plugins/zynaddsubfx/src/Input/CMakeLists.txt @@ -0,0 +1,19 @@ +set(zynaddsubfx_input_SRCS + MidiIn.cpp + NULLMidiIn.cpp + #OSSMidiIn.cpp #[TODO] get OSS midi detection and + #WINMidiIn.cpp # Win midi detection working +) + +if(AlsaMidiInput) + set(zynaddsubfx_input_SRCS + ${zynaddsubfx_input_SRCS} + ALSAMidiIn.cpp + ) + message(STATUS "Alsa midi input enabled") + set(MIDIINPUT_LIBRARIES ${ASOUND_LIBRARY} PARENT_SCOPE) +endif(AlsaMidiInput) + +add_library(zynaddsubfx_input STATIC + ${zynaddsubfx_input_SRCS} + ) diff --git a/plugins/zynaddsubfx/src/Input/MidiIn.C b/plugins/zynaddsubfx/src/Input/MidiIn.C deleted file mode 100644 index 84e2373ca..000000000 --- a/plugins/zynaddsubfx/src/Input/MidiIn.C +++ /dev/null @@ -1,73 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - MidiIn.C - This class is inherited by all the Midi input classes - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include "../globals.h" -#include "MidiIn.h" - -int MidiIn::getcontroller(unsigned char b){ - int ctl=C_NULL; - switch (b){ - case 1:ctl=C_modwheel;//Modulation Wheel - break; - case 7:ctl=C_volume;//Volume - break; - case 10:ctl=C_panning;//Panning - break; - case 11:ctl=C_expression;//Expression - break; - case 64:ctl=C_sustain;//Sustain pedal - break; - case 65:ctl=C_portamento;//Portamento - break; - case 71:ctl=C_filterq;//Filter Q (Sound Timbre) - break; - case 74:ctl=C_filtercutoff;//Filter Cutoff (Brightness) - break; - case 75:ctl=C_bandwidth;//BandWidth - break; - case 76:ctl=C_fmamp;//FM amplitude - break; - case 77:ctl=C_resonance_center;//Resonance Center Frequency - break; - case 78:ctl=C_resonance_bandwidth;//Resonance Bandwith - break; - case 120:ctl=C_allsoundsoff;//All Sounds OFF - break; - case 121:ctl=C_resetallcontrollers;//Reset All Controllers - break; - case 123:ctl=C_allnotesoff;//All Notes OFF - break; - //RPN and NRPN - case 0x06:ctl=C_dataentryhi;//Data Entry (Coarse) - break; - case 0x26:ctl=C_dataentrylo;//Data Entry (Fine) - break; - case 99:ctl=C_nrpnhi;//NRPN (Coarse) - break; - case 98:ctl=C_nrpnlo;//NRPN (Fine) - break; - default:ctl=C_NULL;//unknown controller - //fprintf(stderr,"Controller=%d , par=%d\n",midievent->data.control.param,cmdparams[1]); - break; - }; - return(ctl); -}; diff --git a/plugins/zynaddsubfx/src/Input/MidiIn.cpp b/plugins/zynaddsubfx/src/Input/MidiIn.cpp new file mode 100644 index 000000000..2355b3a64 --- /dev/null +++ b/plugins/zynaddsubfx/src/Input/MidiIn.cpp @@ -0,0 +1,95 @@ +/* + ZynAddSubFX - a software synthesizer + + MidiIn.C - This class is inherited by all the Midi input classes + Copyright (C) 2002-2005 Nasca Octavian Paul + Author: Nasca Octavian Paul + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "../globals.h" +#include "MidiIn.h" + +int MidiIn::getcontroller(unsigned char b) +{ + /**\todo there might be a better way to do this*/ + int ctl=C_NULL; + switch (b) { + case 1: + ctl=C_modwheel;//Modulation Wheel + break; + case 7: + ctl=C_volume;//Volume + break; + case 10: + ctl=C_panning;//Panning + break; + case 11: + ctl=C_expression;//Expression + break; + case 64: + ctl=C_sustain;//Sustain pedal + break; + case 65: + ctl=C_portamento;//Portamento + break; + case 71: + ctl=C_filterq;//Filter Q (Sound Timbre) + break; + case 74: + ctl=C_filtercutoff;//Filter Cutoff (Brightness) + break; + case 75: + ctl=C_bandwidth;//BandWidth + break; + case 76: + ctl=C_fmamp;//FM amplitude + break; + case 77: + ctl=C_resonance_center;//Resonance Center Frequency + break; + case 78: + ctl=C_resonance_bandwidth;//Resonance Bandwith + break; + case 120: + ctl=C_allsoundsoff;//All Sounds OFF + break; + case 121: + ctl=C_resetallcontrollers;//Reset All Controllers + break; + case 123: + ctl=C_allnotesoff;//All Notes OFF + break; + //RPN and NRPN + case 0x06: + ctl=C_dataentryhi;//Data Entry (Coarse) + break; + case 0x26: + ctl=C_dataentrylo;//Data Entry (Fine) + break; + case 99: + ctl=C_nrpnhi;//NRPN (Coarse) + break; + case 98: + ctl=C_nrpnlo;//NRPN (Fine) + break; + default: + ctl=C_NULL;//unknown controller + //fprintf(stderr,"Controller=%d , par=%d\n",midievent->data.control.param,cmdparams[1]); + break; + }; + return(ctl); +}; diff --git a/plugins/zynaddsubfx/src/Input/MidiIn.h b/plugins/zynaddsubfx/src/Input/MidiIn.h index 196b6b739..f02d10e76 100644 --- a/plugins/zynaddsubfx/src/Input/MidiIn.h +++ b/plugins/zynaddsubfx/src/Input/MidiIn.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + MidiIn.h - This class is inherited by all the Midi input classes Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -25,18 +25,24 @@ #include "../globals.h" -enum MidiCmdType{MidiNull,MidiNoteOFF,MidiNoteON,MidiController}; +enum MidiCmdType {MidiNull,MidiNoteOFF,MidiNoteON,MidiController}; #define MP_MAX_BYTES 4000 //in case of loooong SYS_EXes -class MidiIn{ - public: - virtual void getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams){}; - virtual ~MidiIn(){}; - int getcontroller(unsigned char b); - protected: - int inputok;//1 if I can read midi bytes from input ports +/**This class is inherited by all the Midi input classes*/ +class MidiIn +{ +public: + /**Get the command,channel and parameters of the MIDI + * + * \todo make pure virtual + * @param cmdtype the referece to the variable that will store the type + * @param cmdchan the channel for the event + * @param parameters for the event*/ + virtual void getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams)=0; + int getcontroller(unsigned char b); +protected: + bool inputok;/**<1 if I can read midi bytes from input ports*/ }; - #endif diff --git a/plugins/zynaddsubfx/src/Input/NULLMidiIn.C b/plugins/zynaddsubfx/src/Input/NULLMidiIn.cpp similarity index 85% rename from plugins/zynaddsubfx/src/Input/NULLMidiIn.C rename to plugins/zynaddsubfx/src/Input/NULLMidiIn.cpp index a0f339df8..2a727ac7e 100644 --- a/plugins/zynaddsubfx/src/Input/NULLMidiIn.C +++ b/plugins/zynaddsubfx/src/Input/NULLMidiIn.cpp @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + NULLMidiIn.C - a dummy Midi port Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -21,23 +21,21 @@ */ #include "NULLMidiIn.h" -#include -#include -#include -NULLMidiIn::NULLMidiIn(){ +NULLMidiIn::NULLMidiIn() +{ }; -NULLMidiIn::~NULLMidiIn(){ +NULLMidiIn::~NULLMidiIn() +{ }; - /* * Get the midi command,channel and parameters * It returns MidiNull because it is a dummy driver */ -void NULLMidiIn::getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,unsigned char *cmdparams){ - cmdtype=MidiNull; +void NULLMidiIn::getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams) +{ + cmdtype=MidiNull; }; - diff --git a/plugins/zynaddsubfx/src/Input/NULLMidiIn.h b/plugins/zynaddsubfx/src/Input/NULLMidiIn.h index 2c2300641..636302c57 100644 --- a/plugins/zynaddsubfx/src/Input/NULLMidiIn.h +++ b/plugins/zynaddsubfx/src/Input/NULLMidiIn.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + NULLMidiIn.h - a dummy Midi port Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -26,15 +26,23 @@ #include "MidiIn.h" -class NULLMidiIn:public MidiIn{ - public: - NULLMidiIn(); - ~NULLMidiIn(); - void getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,unsigned char *cmdparams); +/**a dummy Midi port*/ +class NULLMidiIn:public MidiIn +{ +public: + /**Dummy Constructor + * \todo see if the default constructor would work here*/ + NULLMidiIn(); + /**Dummy Destructor + * \todo see if the default destructor would work here*/ + ~NULLMidiIn(); + /**Get the midi command,channel and parameters + * It returns MidiNull because it is a dummy driver + */ + void getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams); - private: +private: }; - #endif diff --git a/plugins/zynaddsubfx/src/Input/OSSMidiIn.C b/plugins/zynaddsubfx/src/Input/OSSMidiIn.cpp similarity index 50% rename from plugins/zynaddsubfx/src/Input/OSSMidiIn.C rename to plugins/zynaddsubfx/src/Input/OSSMidiIn.cpp index 67b745d7f..440775abd 100644 --- a/plugins/zynaddsubfx/src/Input/OSSMidiIn.C +++ b/plugins/zynaddsubfx/src/Input/OSSMidiIn.cpp @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + OSSMidiIn.C - Midi input for Open Sound System Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -31,34 +31,38 @@ #include "OSSMidiIn.h" #include "../Misc/Util.h" -OSSMidiIn::OSSMidiIn(){ - inputok=0; +OSSMidiIn::OSSMidiIn() +{ + inputok=false; midi_handle=open(config.cfg.LinuxOSSSeqInDev,O_RDONLY,0); - if (midi_handle!=-1) inputok=1; - + if (midi_handle!=-1) inputok=true; + lastmidicmd=0; cmdtype=0; cmdchan=0; }; -OSSMidiIn::~OSSMidiIn(){ +OSSMidiIn::~OSSMidiIn() +{ close(midi_handle); }; -unsigned char OSSMidiIn::readbyte(){ +unsigned char OSSMidiIn::readbyte() +{ unsigned char tmp[4]; read(midi_handle,&tmp[0],1); - while (tmp[0]!=SEQ_MIDIPUTC){ - read(midi_handle,&tmp[0],4); - }; + while (tmp[0]!=SEQ_MIDIPUTC) { + read(midi_handle,&tmp[0],4); + } return(tmp[1]); }; -unsigned char OSSMidiIn::getmidibyte(){ +unsigned char OSSMidiIn::getmidibyte() +{ unsigned char b; do { - b=readbyte(); + b=readbyte(); } while (b==0xfe);//drops the Active Sense Messages return(b); }; @@ -66,50 +70,51 @@ unsigned char OSSMidiIn::getmidibyte(){ /* * Get the midi command,channel and parameters */ -void OSSMidiIn::getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams){ +void OSSMidiIn::getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams) +{ unsigned char tmp,i; - if (inputok==0) { - cmdtype=MidiNull; - return; - }; + if (inputok==false) { + cmdtype=MidiNull; + return; + } i=0; - if (lastmidicmd==0){//asteapta prima data pana cand vine prima comanda midi - while (tmp<0x80) tmp=getmidibyte(); - lastmidicmd=tmp; - }; + if (lastmidicmd==0) {//asteapta prima data pana cand vine prima comanda midi + while (tmp<0x80) tmp=getmidibyte(); + lastmidicmd=tmp; + } tmp=getmidibyte(); if (tmp>=0x80) { - lastmidicmd=tmp; - tmp=getmidibyte(); - }; + lastmidicmd=tmp; + tmp=getmidibyte(); + } - if ((lastmidicmd>=0x80)&&(lastmidicmd<=0x8f)){//Note OFF - cmdtype=MidiNoteOFF; - cmdchan=lastmidicmd%16; - cmdparams[0]=tmp;//note number - }; + if ((lastmidicmd>=0x80)&&(lastmidicmd<=0x8f)) {//Note OFF + cmdtype=MidiNoteOFF; + cmdchan=lastmidicmd%16; + cmdparams[0]=tmp;//note number + } - if ((lastmidicmd>=0x90)&&(lastmidicmd<=0x9f)){//Note ON - cmdtype=MidiNoteON; - cmdchan=lastmidicmd%16; - cmdparams[0]=tmp;//note number - cmdparams[1]=getmidibyte();//velocity - if (cmdparams[1]==0) cmdtype=MidiNoteOFF;//if velocity==0 then is note off - }; - if ((lastmidicmd>=0xB0)&&(lastmidicmd<=0xBF)){//Controllers - cmdtype=MidiController; - cmdchan=lastmidicmd%16; - cmdparams[0]=getcontroller(tmp); - cmdparams[1]=getmidibyte(); - }; - if ((lastmidicmd>=0xE0)&&(lastmidicmd<=0xEF)){//Pitch Wheel - cmdtype=MidiController; - cmdchan=lastmidicmd%16; - cmdparams[0]=C_pitchwheel; - cmdparams[1]=(tmp+getmidibyte()*(int) 128)-8192;//hope this is correct - }; + if ((lastmidicmd>=0x90)&&(lastmidicmd<=0x9f)) {//Note ON + cmdtype=MidiNoteON; + cmdchan=lastmidicmd%16; + cmdparams[0]=tmp;//note number + cmdparams[1]=getmidibyte();//velocity + if (cmdparams[1]==0) cmdtype=MidiNoteOFF;//if velocity==0 then is note off + } + if ((lastmidicmd>=0xB0)&&(lastmidicmd<=0xBF)) {//Controllers + cmdtype=MidiController; + cmdchan=lastmidicmd%16; + cmdparams[0]=getcontroller(tmp); + cmdparams[1]=getmidibyte(); + } + if ((lastmidicmd>=0xE0)&&(lastmidicmd<=0xEF)) {//Pitch Wheel + cmdtype=MidiController; + cmdchan=lastmidicmd%16; + cmdparams[0]=C_pitchwheel; + cmdparams[1]=(tmp+getmidibyte()*(int) 128)-8192;//hope this is correct + } }; diff --git a/plugins/zynaddsubfx/src/Input/OSSMidiIn.h b/plugins/zynaddsubfx/src/Input/OSSMidiIn.h index 7780b38db..7626950ed 100644 --- a/plugins/zynaddsubfx/src/Input/OSSMidiIn.h +++ b/plugins/zynaddsubfx/src/Input/OSSMidiIn.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + OSSMidiIn.h - Midi input for Open Sound System Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -25,21 +25,22 @@ #include "MidiIn.h" -class OSSMidiIn:public MidiIn{ - public: - OSSMidiIn(); - ~OSSMidiIn(); - unsigned char getmidibyte(); - unsigned char readbyte(); +class OSSMidiIn:public MidiIn +{ +public: + OSSMidiIn(); + ~OSSMidiIn(); + unsigned char getmidibyte(); + unsigned char readbyte(); - //Midi parser - void getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams); - unsigned char cmdtype;//the Message Type (noteon,noteof,sysex..) - unsigned char cmdchan;//the channel number + //Midi parser + void getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams); + unsigned char cmdtype;//the Message Type (noteon,noteof,sysex..) + unsigned char cmdchan;//the channel number - private: - int midi_handle; - unsigned char lastmidicmd;//last byte (>=80) received from the Midi +private: + int midi_handle; + unsigned char lastmidicmd;//last byte (>=80) received from the Midi }; diff --git a/plugins/zynaddsubfx/src/Input/WINMidiIn.C b/plugins/zynaddsubfx/src/Input/WINMidiIn.C deleted file mode 100644 index 804378557..000000000 --- a/plugins/zynaddsubfx/src/Input/WINMidiIn.C +++ /dev/null @@ -1,83 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - WINMidiIn.C - Midi input for Windows - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include -#include -#include -#include - -#include "WINMidiIn.h" -#include "MidiIn.h" -#include "../Misc/Util.h" - -Master *winmaster; -HMIDIIN winmidiinhandle; -MidiIn midictl;//used to convert the controllers to ZynAddSubFX controllers - -void CALLBACK WinMidiInProc(HMIDIIN hMidiIn,UINT wMsg,DWORD dwInstance, - DWORD dwParam1,DWORD dwParam2){ - int midicommand=MidiNull; - if (wMsg==MIM_DATA){ - int cmd,par1,par2; - cmd=dwParam1&0xff; - if (cmd==0xfe) return; - par1=(dwParam1>>8)&0xff; - par2=dwParam1>>16; - //printf("%x %x %x\n",cmd,par1,par2);fflush(stdout); - int cmdchan=cmd&0x0f; - int cmdtype=(cmd>>4)&0x0f; - - int tmp=0; - pthread_mutex_lock(&winmaster->mutex); - switch(cmdtype){ - case(0x8)://noteon - winmaster->NoteOff(cmdchan,par1); - break; - case(0x9)://noteoff - winmaster->NoteOn(cmdchan,par1,par2&0xff); - break; - case(0xb)://controller - winmaster->SetController(cmdchan,midictl.getcontroller(par1),par2&0xff); - break; - case(0xe)://pitch wheel - tmp=(par1+par2*(long int) 128)-8192; - winmaster->SetController(cmdchan,C_pitchwheel,tmp); - break; - default:break; - }; - pthread_mutex_unlock(&winmaster->mutex); - - }; -}; - -void InitWinMidi(Master *master_){ - winmaster=master_; - - long int result=midiInOpen(&winmidiinhandle,config.cfg.WindowsMidiInId,(DWORD)WinMidiInProc,0,CALLBACK_FUNCTION); - result=midiInStart(winmidiinhandle); -}; - -void StopWinMidi(){ - midiInStop(winmidiinhandle); - midiInClose(winmidiinhandle); -}; diff --git a/plugins/zynaddsubfx/src/Input/WINMidiIn.cpp b/plugins/zynaddsubfx/src/Input/WINMidiIn.cpp new file mode 100644 index 000000000..155aa7375 --- /dev/null +++ b/plugins/zynaddsubfx/src/Input/WINMidiIn.cpp @@ -0,0 +1,87 @@ +/* + ZynAddSubFX - a software synthesizer + + WINMidiIn.C - Midi input for Windows + Copyright (C) 2002-2005 Nasca Octavian Paul + Author: Nasca Octavian Paul + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include +#include +#include +#include +#include + +#include "WINMidiIn.h" +#include "MidiIn.h" +#include "../Misc/Util.h" + +Master *winmaster; +HMIDIIN winmidiinhandle; +MidiIn midictl;//used to convert the controllers to ZynAddSubFX controllers + +void CALLBACK WinMidiInProc(HMIDIIN hMidiIn,UINT wMsg,DWORD dwInstance, + DWORD dwParam1,DWORD dwParam2) +{ + int midicommand=MidiNull; + if (wMsg==MIM_DATA) { + int cmd,par1,par2; + cmd=dwParam1&0xff; + if (cmd==0xfe) return; + par1=(dwParam1>>8)&0xff; + par2=dwParam1>>16; + //printf("%x %x %x\n",cmd,par1,par2);fflush(stdout); + int cmdchan=cmd&0x0f; + int cmdtype=(cmd>>4)&0x0f; + + int tmp=0; + pthread_mutex_lock(&winmaster->mutex); + switch (cmdtype) { + case(0x8)://noteon + winmaster->NoteOff(cmdchan,par1); + break; + case(0x9)://noteoff + winmaster->NoteOn(cmdchan,par1,par2&0xff); + break; + case(0xb)://controller + winmaster->SetController(cmdchan,midictl.getcontroller(par1),par2&0xff); + break; + case(0xe)://pitch wheel + tmp=(par1+par2*(long int) 128)-8192; + winmaster->SetController(cmdchan,C_pitchwheel,tmp); + break; + default: + break; + }; + pthread_mutex_unlock(&winmaster->mutex); + + }; +}; + +void InitWinMidi(Master *master_) +{ + winmaster=master_; + + long int result=midiInOpen(&winmidiinhandle,config.cfg.WindowsMidiInId,(DWORD)WinMidiInProc,0,CALLBACK_FUNCTION); + result=midiInStart(winmidiinhandle); +}; + +void StopWinMidi() +{ + midiInStop(winmidiinhandle); + midiInClose(winmidiinhandle); +}; diff --git a/plugins/zynaddsubfx/src/Input/WINMidiIn.h b/plugins/zynaddsubfx/src/Input/WINMidiIn.h index d9cc036db..db9fc79d5 100644 --- a/plugins/zynaddsubfx/src/Input/WINMidiIn.h +++ b/plugins/zynaddsubfx/src/Input/WINMidiIn.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + WINMidiIn.h - Midi input for Windows Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, diff --git a/plugins/zynaddsubfx/src/Misc/Bank.C b/plugins/zynaddsubfx/src/Misc/Bank.cpp similarity index 50% rename from plugins/zynaddsubfx/src/Misc/Bank.C rename to plugins/zynaddsubfx/src/Misc/Bank.cpp index 2a76cd74f..4c1b27a96 100644 --- a/plugins/zynaddsubfx/src/Misc/Bank.C +++ b/plugins/zynaddsubfx/src/Misc/Bank.cpp @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - - Bank.h - Instrument Bank + + Bank.h - Instrument Bank Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -39,37 +39,39 @@ //if this file exists into a directory, this make the directory to be considered as a bank, even if it not contains a instrument file #define FORCE_BANK_DIR_FILE ".bankdir" -Bank::Bank(){ +Bank::Bank() +{ ZERO(defaultinsname,PART_MAX_NAME_LEN); snprintf(defaultinsname,PART_MAX_NAME_LEN,"%s"," "); - - for (int i=0;i=0) snprintf(tmpfilename,100,"%4d-%s",newslot+1,newname); - else snprintf(tmpfilename,100,"%4d-%s",ninstrument+1,newname); - + else snprintf(tmpfilename,100,"%4d-%s",ninstrument+1,newname); + //add the zeroes at the start of filename for (int i=0;i<4;i++) if (tmpfilename[i]==' ') tmpfilename[i]='0'; //make the filenames legal for (int i=0;i<(int) strlen(tmpfilename);i++) { - char c=tmpfilename[i]; - if ((c>='0')&&(c<='9')) continue; - if ((c>='A')&&(c<='Z')) continue; - if ((c>='a')&&(c<='z')) continue; - if ((c=='-')||(c==' ')) continue; - - tmpfilename[i]='_'; + char c=tmpfilename[i]; + if ((c>='0')&&(c<='9')) continue; + if ((c>='A')&&(c<='Z')) continue; + if ((c>='a')&&(c<='z')) continue; + if ((c=='-')||(c==' ')) continue; + + tmpfilename[i]='_'; }; snprintf(newfilename,1000,"%s/%s.xiz",dirname,tmpfilename); @@ -128,39 +133,42 @@ void Bank::setname(unsigned int ninstrument,const char *newname,int newslot){ ins[ninstrument].filename=new char[strlen(newfilename)+5]; snprintf(ins[ninstrument].filename,strlen(newfilename)+1,"%s",newfilename); snprintf(ins[ninstrument].name,PART_MAX_NAME_LEN,"%s",&tmpfilename[5]); - + }; /* * Check if there is no instrument on a slot from the bank */ -int Bank::emptyslot(unsigned int ninstrument){ +int Bank::emptyslot(unsigned int ninstrument) +{ if (ninstrument>=BANK_SIZE) return (1); if (ins[ninstrument].filename==NULL) return(1); if (ins[ninstrument].used) return (0); - else return(1); + else return(1); }; /* * Removes the instrument from the bank */ -void Bank::clearslot(unsigned int ninstrument){ +void Bank::clearslot(unsigned int ninstrument) +{ if (emptyslot(ninstrument)) return; - + // printf("remove %s \n",ins[ninstrument].filename);//////////////////////// - - + + remove(ins[ninstrument].filename); deletefrombank(ninstrument); }; /* - * Save the instrument to a slot + * Save the instrument to a slot */ -void Bank::savetoslot(unsigned int ninstrument,Part *part){ +void Bank::savetoslot(unsigned int ninstrument,Part *part) +{ clearslot(ninstrument); - + const int maxfilename=200; char tmpfilename[maxfilename+20]; ZERO(tmpfilename,maxfilename+20); @@ -169,16 +177,16 @@ void Bank::savetoslot(unsigned int ninstrument,Part *part){ //add the zeroes at the start of filename for (int i=0;i<4;i++) if (tmpfilename[i]==' ') tmpfilename[i]='0'; - + //make the filenames legal for (int i=0;i<(int)strlen(tmpfilename);i++) { - char c=tmpfilename[i]; - if ((c>='0')&&(c<='9')) continue; - if ((c>='A')&&(c<='Z')) continue; - if ((c>='a')&&(c<='z')) continue; - if ((c=='-')||(c==' ')) continue; - - tmpfilename[i]='_'; + char c=tmpfilename[i]; + if ((c>='0')&&(c<='9')) continue; + if ((c>='A')&&(c<='Z')) continue; + if ((c>='a')&&(c<='z')) continue; + if ((c=='-')||(c==' ')) continue; + + tmpfilename[i]='_'; }; strncat(tmpfilename,".xiz",maxfilename+10); @@ -192,29 +200,31 @@ void Bank::savetoslot(unsigned int ninstrument,Part *part){ remove(filename); part->saveXML(filename); addtobank(ninstrument,tmpfilename,(char *) part->Pname); - + delete[]filename; }; /* * Loads the instrument from the bank */ -void Bank::loadfromslot(unsigned int ninstrument,Part *part){ +void Bank::loadfromslot(unsigned int ninstrument,Part *part) +{ if (emptyslot(ninstrument)) return; - + part->defaultsinstrument(); // printf("load: %s\n",ins[ninstrument].filename); - + part->loadXMLinstrument(ins[ninstrument].filename); - + }; /* * Makes current a bank directory */ -int Bank::loadbank(const char *bankdirname){ +int Bank::loadbank(const char *bankdirname) +{ DIR *dir=opendir(bankdirname); clearbank(); @@ -223,59 +233,59 @@ int Bank::loadbank(const char *bankdirname){ if (dirname!=NULL) delete[]dirname; dirname=new char[strlen(bankdirname)+1]; snprintf(dirname,strlen(bankdirname)+1,"%s",bankdirname); - + bankfiletitle=dirname; - // printf("loadbank %s/\n",bankdirname); + // printf("loadbank %s/\n",bankdirname); struct dirent *fn; - - while ((fn=readdir(dir))){ - const char *filename= fn->d_name; - - //sa verific daca e si extensia dorita - if (strstr(filename,INSTRUMENT_EXTENSION)==NULL) continue; - - //verify if the name is like this NNNN-name (where N is a digit) - int no=0; - unsigned int startname=0; - - for (unsigned int i=0;i<4;i++) { - if (strlen(filename)<=i) break; - if ((filename[i]>='0')&&(filename[i]<='9')) { - no=no*10+(filename[i]-'0'); - startname++; - }; - }; - - - if ((startname+1)=2;i--){ - if (name[i]=='.') { - name[i]='\0'; - break; - }; - }; - - if (no!=0){//the instrument position in the bank is found - addtobank(no-1,filename,&name[startname]); - } else { - addtobank(-1,filename,name); - }; - + while ((fn=readdir(dir))) { + const char *filename= fn->d_name; + + //sa verific daca e si extensia dorita + if (strstr(filename,INSTRUMENT_EXTENSION)==NULL) continue; + + //verify if the name is like this NNNN-name (where N is a digit) + int no=0; + unsigned int startname=0; + + for (unsigned int i=0;i<4;i++) { + if (strlen(filename)<=i) break; + + if ((filename[i]>='0')&&(filename[i]<='9')) { + no=no*10+(filename[i]-'0'); + startname++; + }; + }; + + + if ((startname+1)=2;i--) { + if (name[i]=='.') { + name[i]='\0'; + break; + }; + }; + + if (no!=0) {//the instrument position in the bank is found + addtobank(no-1,filename,&name[startname]); + } else { + addtobank(-1,filename,name); + }; + }; - - + + closedir(dir); if (dirname!=NULL) { - sprintf(config.cfg.currentBankDir,"%s",dirname); + sprintf(config.cfg.currentBankDir,"%s",dirname); }; return(0); @@ -284,16 +294,17 @@ int Bank::loadbank(const char *bankdirname){ /* * Makes a new bank, put it on a file and makes it current bank */ -int Bank::newbank(const char *newbankdirname){ +int Bank::newbank(const char *newbankdirname) +{ int result; char tmpfilename[MAX_STRING_SIZE]; char bankdir[MAX_STRING_SIZE]; snprintf(bankdir,MAX_STRING_SIZE,"%s",config.cfg.bankRootDirList[0]); - if (((bankdir[strlen(bankdir)-1])!='/')&&((bankdir[strlen(bankdir)-1])!='\\')){ - strncat(bankdir,"/",MAX_STRING_SIZE); + if (((bankdir[strlen(bankdir)-1])!='/')&&((bankdir[strlen(bankdir)-1])!='\\')) { + strncat(bankdir,"/",MAX_STRING_SIZE); }; - strncat(bankdir,newbankdirname,MAX_STRING_SIZE-1); + strncat(bankdir,newbankdirname,MAX_STRING_SIZE); #ifdef OS_WINDOWS result=mkdir(bankdir); #else @@ -305,57 +316,62 @@ int Bank::newbank(const char *newbankdirname){ // printf("%s\n",tmpfilename); FILE *tmpfile=fopen(tmpfilename,"w+"); fclose(tmpfile); - + return(loadbank(bankdir)); }; /* * Check if the bank is locked (i.e. the file opened was readonly) */ -int Bank::locked(){ +int Bank::locked() +{ return(dirname==NULL); }; /* * Swaps a slot with another */ -void Bank::swapslot(unsigned int n1, unsigned int n2){ +void Bank::swapslot(unsigned int n1, unsigned int n2) +{ if ((n1==n2)||(locked())) return; if (emptyslot(n1)&&(emptyslot(n2))) return; - if (emptyslot(n1)){//change n1 to n2 in order to make - int tmp=n2;n2=n1;n1=tmp; + if (emptyslot(n1)) {//change n1 to n2 in order to make + int tmp=n2; + n2=n1; + n1=tmp; }; - - if (emptyslot(n2)){//this is just a movement from slot1 to slot2 - setname(n1,getname(n1),n2); - ins[n2]=ins[n1]; - ins[n1].used=false; - ins[n1].name[0]='\0'; - ins[n1].filename=NULL; - ins[n1].info.PADsynth_used=0; + + if (emptyslot(n2)) {//this is just a movement from slot1 to slot2 + setname(n1,getname(n1),n2); + ins[n2]=ins[n1]; + ins[n1].used=false; + ins[n1].name[0]='\0'; + ins[n1].filename=NULL; + ins[n1].info.PADsynth_used=0; } else {//if both slots are used - if (strcmp(ins[n1].name,ins[n2].name)==0){//change the name of the second instrument if the name are equal - strncat(ins[n2].name,"2",PART_MAX_NAME_LEN); - }; - setname(n1,getname(n1),n2); - setname(n2,getname(n2),n1); - ins_t tmp; - tmp.used=true; - strcpy(tmp.name,ins[n2].name); - char *tmpfilename=ins[n2].filename; - bool padsynth_used=ins[n2].info.PADsynth_used; - - ins[n2]=ins[n1]; - strcpy(ins[n1].name,tmp.name); - ins[n1].filename=tmpfilename; - ins[n1].info.PADsynth_used=padsynth_used; + if (strcmp(ins[n1].name,ins[n2].name)==0) {//change the name of the second instrument if the name are equal + strncat(ins[n2].name,"2",PART_MAX_NAME_LEN); + }; + setname(n1,getname(n1),n2); + setname(n2,getname(n2),n1); + ins_t tmp; + tmp.used=true; + strcpy(tmp.name,ins[n2].name); + char *tmpfilename=ins[n2].filename; + bool padsynth_used=ins[n2].info.PADsynth_used; + + ins[n2]=ins[n1]; + strcpy(ins[n1].name,tmp.name); + ins[n1].filename=tmpfilename; + ins[n1].info.PADsynth_used=padsynth_used; }; - + }; //a helper function that compares 2 banks[] arrays -int Bank_compar(const void *a,const void *b){ +int Bank_compar(const void *a,const void *b) +{ struct Bank::bankstruct *bank1= (Bank::bankstruct *)a; struct Bank::bankstruct *bank2= (Bank::bankstruct *)b; if (((bank1->name)==NULL)||((bank2->name)==NULL)) return(0); @@ -369,156 +385,160 @@ int Bank_compar(const void *a,const void *b){ * Re-scan for directories containing instrument banks */ -void Bank::rescanforbanks(){ - for (int i=0;id_name; - if (dirname[0]=='.') continue; - - snprintf(bank.dir,maxdirsize,"%s%s%s/",rootdir,separator,dirname); - snprintf(bank.name,maxdirsize,"%s",dirname); - //find out if the directory contains at least 1 instrument - bool isbank=false; - - DIR *d=opendir(bank.dir); - if (d==NULL) continue; - - struct dirent *fname; - while((fname=readdir(d))){ - if ((strstr(fname->d_name,INSTRUMENT_EXTENSION)!=NULL)|| - (strstr(fname->d_name,FORCE_BANK_DIR_FILE)!=NULL)){ - isbank=true; - break;//aici as putea pune in loc de break un update la un counter care imi arata nr. de instrumente din bank - }; - }; - - closedir(d); - - if (isbank) { - int pos=-1; - for (int i=1;i=0) { - banks[pos].name=new char[maxdirsize]; - banks[pos].dir=new char[maxdirsize]; - snprintf(banks[pos].name,maxdirsize,"%s",bank.name); - snprintf(banks[pos].dir,maxdirsize,"%s",bank.dir); - }; - - }; - + struct dirent *fn; + while ((fn=readdir(dir))) { + const char *dirname=fn->d_name; + if (dirname[0]=='.') continue; + + snprintf(bank.dir,maxdirsize,"%s%s%s/",rootdir,separator,dirname); + snprintf(bank.name,maxdirsize,"%s",dirname); + //find out if the directory contains at least 1 instrument + bool isbank=false; + + DIR *d=opendir(bank.dir); + if (d==NULL) continue; + + struct dirent *fname; + + while ((fname=readdir(d))) { + if ((strstr(fname->d_name,INSTRUMENT_EXTENSION)!=NULL)|| + (strstr(fname->d_name,FORCE_BANK_DIR_FILE)!=NULL)) { + isbank=true; + break;//aici as putea pune in loc de break un update la un counter care imi arata nr. de instrumente din bank + }; + }; + + closedir(d); + + if (isbank) { + int pos=-1; + for (int i=1;i=0) { + banks[pos].name=new char[maxdirsize]; + banks[pos].dir=new char[maxdirsize]; + snprintf(banks[pos].name,maxdirsize,"%s",bank.name); + snprintf(banks[pos].dir,maxdirsize,"%s",bank.dir); + }; + + }; + }; closedir(dir); - + }; -void Bank::clearbank(){ +void Bank::clearbank() +{ for (int i=0;i=0)&&(pos=0)&&(pos=BANK_SIZE) pos=-1; - - + + if (pos<0) {//find a free position - for (int i=BANK_SIZE-1;i>=0;i--) - if (!ins[i].used) { - pos=i; - break; - }; - + for (int i=BANK_SIZE-1;i>=0;i--) + if (!ins[i].used) { + pos=i; + break; + }; + }; - + if (pos<0) return (-1);//the bank is full - // printf("%s %d\n",filename,pos); + // printf("%s %d\n",filename,pos); deletefrombank(pos); - + ins[pos].used=true; snprintf(ins[pos].name,PART_MAX_NAME_LEN,"%s",name); @@ -530,33 +550,35 @@ int Bank::addtobank(int pos, const char *filename, const char* name){ snprintf(ins[pos].filename,len+1,"%s/%s",dirname,filename); //see if PADsynth is used - if (config.cfg.CheckPADsynth){ - XMLwrapper *xml=new XMLwrapper(); - xml->checkfileinformation(ins[pos].filename); - - ins[pos].info.PADsynth_used=xml->information.PADsynth_used; - delete xml; + if (config.cfg.CheckPADsynth) { + XMLwrapper *xml=new XMLwrapper(); + xml->checkfileinformation(ins[pos].filename); + + ins[pos].info.PADsynth_used=xml->information.PADsynth_used; + delete xml; } else ins[pos].info.PADsynth_used=false; - + return(0); }; -bool Bank::isPADsynth_used(unsigned int ninstrument){ +bool Bank::isPADsynth_used(unsigned int ninstrument) +{ if (config.cfg.CheckPADsynth==0) return(0); - else return(ins[ninstrument].info.PADsynth_used); + else return(ins[ninstrument].info.PADsynth_used); }; -void Bank::deletefrombank(int pos){ +void Bank::deletefrombank(int pos) +{ if ((pos<0)||(pos>=BANK_SIZE)) return; ins[pos].used=false; ZERO(ins[pos].name,PART_MAX_NAME_LEN+1); if (ins[pos].filename!=NULL) { - delete []ins[pos].filename; - ins[pos].filename=NULL; + delete []ins[pos].filename; + ins[pos].filename=NULL; }; - + ZERO(tmpinsname[pos],PART_MAX_NAME_LEN+20); - + }; diff --git a/plugins/zynaddsubfx/src/Misc/Bank.h b/plugins/zynaddsubfx/src/Misc/Bank.h index dc35d77aa..8359b541b 100644 --- a/plugins/zynaddsubfx/src/Misc/Bank.h +++ b/plugins/zynaddsubfx/src/Misc/Bank.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Bank.C - Instrument Bank Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -29,71 +29,79 @@ #define BANK_SIZE 160 -/* +/** * The max. number of banks that are used */ #define MAX_NUM_BANKS 400 +/**The instrument Bank + * \todo add in strings to replace char* */ +class Bank +{ +public: + /**Constructor*/ + Bank(); + ~Bank(); + char *getname(unsigned int ninstrument); + char *getnamenumbered(unsigned int ninstrument); + void setname(unsigned int ninstrument,const char *newname,int newslot);//if newslot==-1 then this is ignored, else it will be put on that slot + bool isPADsynth_used(unsigned int ninstrument); -class Bank{ - public: - Bank(); - ~Bank(); - char *getname(unsigned int ninstrument); - char *getnamenumbered(unsigned int ninstrument); - void setname(unsigned int ninstrument,const char *newname,int newslot);//if newslot==-1 then this is ignored, else it will be put on that slot - bool isPADsynth_used(unsigned int ninstrument); - - //returns 0 if the slot is not empty or 1 if the slot is empty - int emptyslot(unsigned int ninstrument); + /**returns 0 if the slot is not empty or 1 if the slot is empty + * \todo start using bool before facepalm*/ + int emptyslot(unsigned int ninstrument); - void clearslot(unsigned int ninstrument); - void savetoslot(unsigned int ninstrument,Part *part); - void loadfromslot(unsigned int ninstrument,Part *part); + /**Empties out the selected slot*/ + void clearslot(unsigned int ninstrument); + /**Saves the given Part to slot*/ + void savetoslot(unsigned int ninstrument,Part *part); + /**Loads the given slot into a Part*/ + void loadfromslot(unsigned int ninstrument,Part *part); - void swapslot(unsigned int n1,unsigned int n2); + /**Swaps Slots*/ + void swapslot(unsigned int n1,unsigned int n2); - int loadbank(const char *bankdirname); - int newbank(const char *newbankdirname); - - char *bankfiletitle; //this is shown on the UI of the bank (the title of the window) - int locked(); - - void rescanforbanks(); - - struct bankstruct{ - char *dir; - char *name; - }; - - bankstruct banks[MAX_NUM_BANKS]; - - private: - - //it adds a filename to the bank - //if pos is -1 it try to find a position - //returns -1 if the bank is full, or 0 if the instrument was added - int addtobank(int pos,const char* filename,const char* name); - - void deletefrombank(int pos); - - void clearbank(); - - char defaultinsname[PART_MAX_NAME_LEN]; - char tmpinsname[BANK_SIZE][PART_MAX_NAME_LEN+20];//this keeps the numbered names - - struct ins_t{ - bool used; - char name[PART_MAX_NAME_LEN+1]; - char *filename; - struct{ - bool PADsynth_used; - } info; - }ins[BANK_SIZE]; - - char *dirname; + int loadbank(const char *bankdirname); + int newbank(const char *newbankdirname); - void scanrootdir(char *rootdir);//scans a root dir for banks + char *bankfiletitle; //this is shown on the UI of the bank (the title of the window) + int locked(); + + void rescanforbanks(); + + struct bankstruct { + char *dir; + char *name; + }; + + bankstruct banks[MAX_NUM_BANKS]; + +private: + + //it adds a filename to the bank + //if pos is -1 it try to find a position + //returns -1 if the bank is full, or 0 if the instrument was added + int addtobank(int pos,const char* filename,const char* name); + + void deletefrombank(int pos); + + void clearbank(); + + char defaultinsname[PART_MAX_NAME_LEN]; + char tmpinsname[BANK_SIZE][PART_MAX_NAME_LEN+20];//this keeps the numbered names + + struct ins_t { + bool used; + char name[PART_MAX_NAME_LEN+1]; + char *filename; + struct { + bool PADsynth_used; + } info; + }ins[BANK_SIZE]; + + char *dirname; + + void scanrootdir(char *rootdir);//scans a root dir for banks }; #endif diff --git a/plugins/zynaddsubfx/src/Misc/CMakeLists.txt b/plugins/zynaddsubfx/src/Misc/CMakeLists.txt new file mode 100644 index 000000000..877cd54a6 --- /dev/null +++ b/plugins/zynaddsubfx/src/Misc/CMakeLists.txt @@ -0,0 +1,18 @@ +include_directories(${MXML_INCLUDE_DIR}) + +set(zynaddsubfx_misc_SRCS + Bank.cpp + Config.cpp + Dump.cpp + Master.cpp + Microtonal.cpp + Part.cpp + Util.cpp + XMLwrapper.cpp +) + +add_library(zynaddsubfx_misc STATIC + ${zynaddsubfx_misc_SRCS} + ) + +target_link_libraries(zynaddsubfx_misc zynaddsubfx_output) diff --git a/plugins/zynaddsubfx/src/Misc/Config.C b/plugins/zynaddsubfx/src/Misc/Config.C deleted file mode 100644 index e8f54f8d6..000000000 --- a/plugins/zynaddsubfx/src/Misc/Config.C +++ /dev/null @@ -1,331 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Config.C - Configuration file functions - Copyright (C) 2003-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ -#include -#include -#include -#include - -#ifdef OS_WINDOWS -#include -#include -#endif - -#include "Config.h" -#include "XMLwrapper.h" - -Config::Config(){ -}; -void Config::init(){ - maxstringsize=MAX_STRING_SIZE;//for ui - //defaults - cfg.SampleRate=44100; - cfg.SoundBufferSize=256; - cfg.OscilSize=1024; - cfg.SwapStereo=0; - - cfg.LinuxOSSWaveOutDev=new char[MAX_STRING_SIZE]; - snprintf(cfg.LinuxOSSWaveOutDev,MAX_STRING_SIZE,"/dev/dsp"); - cfg.LinuxOSSSeqInDev=new char[MAX_STRING_SIZE]; - snprintf(cfg.LinuxOSSSeqInDev,MAX_STRING_SIZE,"/dev/sequencer"); - - cfg.DumpFile=new char[MAX_STRING_SIZE]; - snprintf(cfg.DumpFile,MAX_STRING_SIZE,"zynaddsubfx_dump.txt"); - - cfg.WindowsWaveOutId=0; - cfg.WindowsMidiInId=0; - - cfg.BankUIAutoClose=0; - cfg.DumpNotesToFile=0; - cfg.DumpAppend=1; - - cfg.GzipCompression=3; - - cfg.Interpolation=0; - cfg.CheckPADsynth=1; - - cfg.UserInterfaceMode=0; - cfg.VirKeybLayout=1; - winwavemax=1;winmidimax=1; -//try to find out how many input midi devices are there -#ifdef WINMIDIIN - winmidimax=midiInGetNumDevs(); - if (winmidimax==0) winmidimax=1; -#endif - winmididevices=new winmidionedevice[winmidimax]; - for (int i=0;iloadXMLfile(filename)<0) return; - if (xmlcfg->enterbranch("CONFIGURATION")){ - cfg.SampleRate=xmlcfg->getpar("sample_rate",cfg.SampleRate,4000,1024000); - cfg.SoundBufferSize=xmlcfg->getpar("sound_buffer_size",cfg.SoundBufferSize,16,8192); - cfg.OscilSize=xmlcfg->getpar("oscil_size",cfg.OscilSize,MAX_AD_HARMONICS*2,131072); - cfg.SwapStereo=xmlcfg->getpar("swap_stereo",cfg.SwapStereo,0,1); - cfg.BankUIAutoClose=xmlcfg->getpar("bank_window_auto_close",cfg.BankUIAutoClose,0,1); - - cfg.DumpNotesToFile=xmlcfg->getpar("dump_notes_to_file",cfg.DumpNotesToFile,0,1); - cfg.DumpAppend=xmlcfg->getpar("dump_append",cfg.DumpAppend,0,1); - xmlcfg->getparstr("dump_file",cfg.DumpFile,MAX_STRING_SIZE); - - cfg.GzipCompression=xmlcfg->getpar("gzip_compression",cfg.GzipCompression,0,9); - - xmlcfg->getparstr("bank_current",cfg.currentBankDir,MAX_STRING_SIZE); - cfg.Interpolation=xmlcfg->getpar("interpolation",cfg.Interpolation,0,1); - - cfg.CheckPADsynth=xmlcfg->getpar("check_pad_synth",cfg.CheckPADsynth,0,1); - - - cfg.UserInterfaceMode=xmlcfg->getpar("user_interface_mode",cfg.UserInterfaceMode,0,2); - cfg.VirKeybLayout=xmlcfg->getpar("virtual_keyboard_layout",cfg.VirKeybLayout,0,10); - - //get bankroot dirs - for (int i=0;ienterbranch("BANKROOT",i)){ - cfg.bankRootDirList[i]=new char[MAX_STRING_SIZE]; - xmlcfg->getparstr("bank_root",cfg.bankRootDirList[i],MAX_STRING_SIZE); - xmlcfg->exitbranch(); - }; - }; - - //get preset root dirs - for (int i=0;ienterbranch("PRESETSROOT",i)){ - cfg.presetsDirList[i]=new char[MAX_STRING_SIZE]; - xmlcfg->getparstr("presets_root",cfg.presetsDirList[i],MAX_STRING_SIZE); - xmlcfg->exitbranch(); - }; - }; - - //linux stuff - xmlcfg->getparstr("linux_oss_wave_out_dev",cfg.LinuxOSSWaveOutDev,MAX_STRING_SIZE); - xmlcfg->getparstr("linux_oss_seq_in_dev",cfg.LinuxOSSSeqInDev,MAX_STRING_SIZE); - - //windows stuff - cfg.WindowsWaveOutId=xmlcfg->getpar("windows_wave_out_id",cfg.WindowsWaveOutId,0,winwavemax); - cfg.WindowsMidiInId=xmlcfg->getpar("windows_midi_in_id",cfg.WindowsMidiInId,0,winmidimax); - - xmlcfg->exitbranch(); - }; - delete(xmlcfg); - - cfg.OscilSize=(int) pow(2,ceil(log (cfg.OscilSize-1.0)/log(2.0))); - -}; - -void Config::saveConfig(const char *filename){ - XMLwrapper *xmlcfg=new XMLwrapper(); - - xmlcfg->beginbranch("CONFIGURATION"); - - xmlcfg->addpar("sample_rate",cfg.SampleRate); - xmlcfg->addpar("sound_buffer_size",cfg.SoundBufferSize); - xmlcfg->addpar("oscil_size",cfg.OscilSize); - xmlcfg->addpar("swap_stereo",cfg.SwapStereo); - xmlcfg->addpar("bank_window_auto_close",cfg.BankUIAutoClose); - - xmlcfg->addpar("dump_notes_to_file",cfg.DumpNotesToFile); - xmlcfg->addpar("dump_append",cfg.DumpAppend); - xmlcfg->addparstr("dump_file",cfg.DumpFile); - - xmlcfg->addpar("gzip_compression",cfg.GzipCompression); - - xmlcfg->addpar("check_pad_synth",cfg.CheckPADsynth); - - xmlcfg->addparstr("bank_current",cfg.currentBankDir); - - xmlcfg->addpar("user_interface_mode",cfg.UserInterfaceMode); - xmlcfg->addpar("virtual_keyboard_layout",cfg.VirKeybLayout); - - - for (int i=0;ibeginbranch("BANKROOT",i); - xmlcfg->addparstr("bank_root",cfg.bankRootDirList[i]); - xmlcfg->endbranch(); - }; - - for (int i=0;ibeginbranch("PRESETSROOT",i); - xmlcfg->addparstr("presets_root",cfg.presetsDirList[i]); - xmlcfg->endbranch(); - }; - - xmlcfg->addpar("interpolation",cfg.Interpolation); - - //linux stuff - xmlcfg->addparstr("linux_oss_wave_out_dev",cfg.LinuxOSSWaveOutDev); - xmlcfg->addparstr("linux_oss_seq_in_dev",cfg.LinuxOSSSeqInDev); - - //windows stuff - xmlcfg->addpar("windows_wave_out_id",cfg.WindowsWaveOutId); - xmlcfg->addpar("windows_midi_in_id",cfg.WindowsMidiInId); - - xmlcfg->endbranch(); - - int tmp=cfg.GzipCompression; - cfg.GzipCompression=0; - xmlcfg->saveXMLfile(filename); - cfg.GzipCompression=tmp; - - delete(xmlcfg); -}; - -void Config::getConfigFileName(char *name, int namesize){ - name[0]=0; -#ifdef OS_LINUX - snprintf(name,namesize,"%s%s",getenv("HOME"),"/.zynaddsubfxXML.cfg"); -#else - snprintf(name,namesize,"%s","zynaddsubfxXML.cfg"); -#endif - -}; - diff --git a/plugins/zynaddsubfx/src/Misc/Config.cpp b/plugins/zynaddsubfx/src/Misc/Config.cpp new file mode 100644 index 000000000..9a290158c --- /dev/null +++ b/plugins/zynaddsubfx/src/Misc/Config.cpp @@ -0,0 +1,341 @@ +/* + ZynAddSubFX - a software synthesizer + + Config.C - Configuration file functions + Copyright (C) 2003-2005 Nasca Octavian Paul + Author: Nasca Octavian Paul + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ +#include +#include +#include +#include + +#ifdef OS_WINDOWS +#include +#include +#endif + +#include "Config.h" +#include "XMLwrapper.h" + +Config::Config() +{ +}; +void Config::init() +{ + maxstringsize=MAX_STRING_SIZE;//for ui + //defaults + cfg.SampleRate=44100; + cfg.SoundBufferSize=256; + cfg.OscilSize=1024; + cfg.SwapStereo=0; + + cfg.LinuxOSSWaveOutDev=new char[MAX_STRING_SIZE]; + snprintf(cfg.LinuxOSSWaveOutDev,MAX_STRING_SIZE,"/dev/dsp"); + cfg.LinuxOSSSeqInDev=new char[MAX_STRING_SIZE]; + snprintf(cfg.LinuxOSSSeqInDev,MAX_STRING_SIZE,"/dev/sequencer"); + + cfg.DumpFile=new char[MAX_STRING_SIZE]; + snprintf(cfg.DumpFile,MAX_STRING_SIZE,"zynaddsubfx_dump.txt"); + + cfg.WindowsWaveOutId=0; + cfg.WindowsMidiInId=0; + + cfg.BankUIAutoClose=0; + cfg.DumpNotesToFile=0; + cfg.DumpAppend=1; + + cfg.GzipCompression=3; + + cfg.Interpolation=0; + cfg.CheckPADsynth=1; + + cfg.UserInterfaceMode=0; + cfg.VirKeybLayout=1; + winwavemax=1; + winmidimax=1; +//try to find out how many input midi devices are there +#ifdef WINMIDIIN + winmidimax=midiInGetNumDevs(); + if (winmidimax==0) winmidimax=1; +#endif + winmididevices=new winmidionedevice[winmidimax]; + for (int i=0;iloadXMLfile(filename)<0) return; + if (xmlcfg->enterbranch("CONFIGURATION")) { + cfg.SampleRate=xmlcfg->getpar("sample_rate",cfg.SampleRate,4000,1024000); + cfg.SoundBufferSize=xmlcfg->getpar("sound_buffer_size",cfg.SoundBufferSize,16,8192); + cfg.OscilSize=xmlcfg->getpar("oscil_size",cfg.OscilSize,MAX_AD_HARMONICS*2,131072); + cfg.SwapStereo=xmlcfg->getpar("swap_stereo",cfg.SwapStereo,0,1); + cfg.BankUIAutoClose=xmlcfg->getpar("bank_window_auto_close",cfg.BankUIAutoClose,0,1); + + cfg.DumpNotesToFile=xmlcfg->getpar("dump_notes_to_file",cfg.DumpNotesToFile,0,1); + cfg.DumpAppend=xmlcfg->getpar("dump_append",cfg.DumpAppend,0,1); + xmlcfg->getparstr("dump_file",cfg.DumpFile,MAX_STRING_SIZE); + + cfg.GzipCompression=xmlcfg->getpar("gzip_compression",cfg.GzipCompression,0,9); + + xmlcfg->getparstr("bank_current",cfg.currentBankDir,MAX_STRING_SIZE); + cfg.Interpolation=xmlcfg->getpar("interpolation",cfg.Interpolation,0,1); + + cfg.CheckPADsynth=xmlcfg->getpar("check_pad_synth",cfg.CheckPADsynth,0,1); + + + cfg.UserInterfaceMode=xmlcfg->getpar("user_interface_mode",cfg.UserInterfaceMode,0,2); + cfg.VirKeybLayout=xmlcfg->getpar("virtual_keyboard_layout",cfg.VirKeybLayout,0,10); + + //get bankroot dirs + for (int i=0;ienterbranch("BANKROOT",i)) { + cfg.bankRootDirList[i]=new char[MAX_STRING_SIZE]; + xmlcfg->getparstr("bank_root",cfg.bankRootDirList[i],MAX_STRING_SIZE); + xmlcfg->exitbranch(); + }; + }; + + //get preset root dirs + for (int i=0;ienterbranch("PRESETSROOT",i)) { + cfg.presetsDirList[i]=new char[MAX_STRING_SIZE]; + xmlcfg->getparstr("presets_root",cfg.presetsDirList[i],MAX_STRING_SIZE); + xmlcfg->exitbranch(); + }; + }; + + //linux stuff + xmlcfg->getparstr("linux_oss_wave_out_dev",cfg.LinuxOSSWaveOutDev,MAX_STRING_SIZE); + xmlcfg->getparstr("linux_oss_seq_in_dev",cfg.LinuxOSSSeqInDev,MAX_STRING_SIZE); + + //windows stuff + cfg.WindowsWaveOutId=xmlcfg->getpar("windows_wave_out_id",cfg.WindowsWaveOutId,0,winwavemax); + cfg.WindowsMidiInId=xmlcfg->getpar("windows_midi_in_id",cfg.WindowsMidiInId,0,winmidimax); + + xmlcfg->exitbranch(); + }; + delete(xmlcfg); + + cfg.OscilSize=(int) pow(2,ceil(log (cfg.OscilSize-1.0)/log(2.0))); + +}; + +void Config::saveConfig(const char *filename) +{ + XMLwrapper *xmlcfg=new XMLwrapper(); + + xmlcfg->beginbranch("CONFIGURATION"); + + xmlcfg->addpar("sample_rate",cfg.SampleRate); + xmlcfg->addpar("sound_buffer_size",cfg.SoundBufferSize); + xmlcfg->addpar("oscil_size",cfg.OscilSize); + xmlcfg->addpar("swap_stereo",cfg.SwapStereo); + xmlcfg->addpar("bank_window_auto_close",cfg.BankUIAutoClose); + + xmlcfg->addpar("dump_notes_to_file",cfg.DumpNotesToFile); + xmlcfg->addpar("dump_append",cfg.DumpAppend); + xmlcfg->addparstr("dump_file",cfg.DumpFile); + + xmlcfg->addpar("gzip_compression",cfg.GzipCompression); + + xmlcfg->addpar("check_pad_synth",cfg.CheckPADsynth); + + xmlcfg->addparstr("bank_current",cfg.currentBankDir); + + xmlcfg->addpar("user_interface_mode",cfg.UserInterfaceMode); + xmlcfg->addpar("virtual_keyboard_layout",cfg.VirKeybLayout); + + + for (int i=0;ibeginbranch("BANKROOT",i); + xmlcfg->addparstr("bank_root",cfg.bankRootDirList[i]); + xmlcfg->endbranch(); + }; + + for (int i=0;ibeginbranch("PRESETSROOT",i); + xmlcfg->addparstr("presets_root",cfg.presetsDirList[i]); + xmlcfg->endbranch(); + }; + + xmlcfg->addpar("interpolation",cfg.Interpolation); + + //linux stuff + xmlcfg->addparstr("linux_oss_wave_out_dev",cfg.LinuxOSSWaveOutDev); + xmlcfg->addparstr("linux_oss_seq_in_dev",cfg.LinuxOSSSeqInDev); + + //windows stuff + xmlcfg->addpar("windows_wave_out_id",cfg.WindowsWaveOutId); + xmlcfg->addpar("windows_midi_in_id",cfg.WindowsMidiInId); + + xmlcfg->endbranch(); + + int tmp=cfg.GzipCompression; + cfg.GzipCompression=0; + xmlcfg->saveXMLfile(filename); + cfg.GzipCompression=tmp; + + delete(xmlcfg); +}; + +void Config::getConfigFileName(char *name, int namesize) +{ + name[0]=0; +#ifdef OS_LINUX + snprintf(name,namesize,"%s%s",getenv("HOME"),"/.zynaddsubfxXML.cfg"); +#else + snprintf(name,namesize,"%s","zynaddsubfxXML.cfg"); +#endif + +}; + diff --git a/plugins/zynaddsubfx/src/Misc/Config.h b/plugins/zynaddsubfx/src/Misc/Config.h index 597d62bc2..9d4fef615 100644 --- a/plugins/zynaddsubfx/src/Misc/Config.h +++ b/plugins/zynaddsubfx/src/Misc/Config.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Config.h - Configuration file functions Copyright (C) 2003-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -26,42 +26,46 @@ #define MAX_STRING_SIZE 4000 #define MAX_BANK_ROOT_DIRS 100 -class Config{ - public: - Config(); - ~Config(); - struct { - char *LinuxOSSWaveOutDev,*LinuxOSSSeqInDev; - int SampleRate,SoundBufferSize,OscilSize,SwapStereo; - int WindowsWaveOutId,WindowsMidiInId; - int BankUIAutoClose; - int DumpNotesToFile,DumpAppend; - int GzipCompression; - int Interpolation; - char *DumpFile; - char *bankRootDirList[MAX_BANK_ROOT_DIRS],*currentBankDir; - char *presetsDirList[MAX_BANK_ROOT_DIRS]; - int CheckPADsynth; - int UserInterfaceMode; - int VirKeybLayout; - } cfg; - int winwavemax,winmidimax;//number of wave/midi devices on Windows - int maxstringsize; - - struct winmidionedevice{ - char *name; - }; - winmidionedevice *winmididevices; +/**Configuration file functions*/ +class Config +{ +public: + /** Constructor*/ + Config(); + /** Destructor*/ + ~Config(); + struct { + char *LinuxOSSWaveOutDev,*LinuxOSSSeqInDev; + int SampleRate,SoundBufferSize,OscilSize,SwapStereo; + int WindowsWaveOutId,WindowsMidiInId; + int BankUIAutoClose; + int DumpNotesToFile,DumpAppend; + int GzipCompression; + int Interpolation; + char *DumpFile; + char *bankRootDirList[MAX_BANK_ROOT_DIRS],*currentBankDir; + char *presetsDirList[MAX_BANK_ROOT_DIRS]; + int CheckPADsynth; + int UserInterfaceMode; + int VirKeybLayout; + } cfg; + int winwavemax,winmidimax;//number of wave/midi devices on Windows + int maxstringsize; - void clearbankrootdirlist(); - void clearpresetsdirlist(); - void init(); - void save(); - - private: - void readConfig(const char *filename); - void saveConfig(const char *filename); - void getConfigFileName(char *name,int namesize); + struct winmidionedevice { + char *name; + }; + winmidionedevice *winmididevices; + + void clearbankrootdirlist(); + void clearpresetsdirlist(); + void init(); + void save(); + +private: + void readConfig(const char *filename); + void saveConfig(const char *filename); + void getConfigFileName(char *name,int namesize); }; #endif diff --git a/plugins/zynaddsubfx/src/Misc/Control.h b/plugins/zynaddsubfx/src/Misc/Control.h new file mode 100644 index 000000000..780d4b9e6 --- /dev/null +++ b/plugins/zynaddsubfx/src/Misc/Control.h @@ -0,0 +1,100 @@ +/* + ZynAddSubFX - a software synthesizer + + Control.h - Defines a variable that can be controled from a frontend + + Copyright (C) 2009 Harald Hvaal + Author: Harald Hvaal + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _CONTROL_H_ +#define _CONTROL_H_ + +#include + +class Control +{ +public: + /** + * The parent is the logical owner of this control. Parent should only + * be null for the root node. + * The id is a string uniquely identifying this control within the + * context of the parent control. No spaces or dots are allowed in this + * id. + * Children id's are denoted by ., so that one + * can refer to any control in the hierarchy by separating them with + * dots. Example: Main.AddSynth.FrequencyLFO.Amplitude + */ + Control(Control *parent, string id); + + /** + * Will recursively get the XML representation for all the subcontrols. + * Used for saving to file and copy-pasting settings + */ + string getXMLRepresentation(); + + /** + * Set the value of this (and possibly subcomponents as well) based on + * a xml description. + */ + void restoreFromXML(string xml); + + /** + * Register a controluser. This will cause this user to be notified + * whenever the contents of the control changes. + */ + void registerControlUser(ControlUser *user); + + /** + * This should return a string representation of the controls internal + * value + */ + virtual string getStringRepresentation() = 0; + +}; + +class FloatControl : public Control +{ +public: + /** + * Set the value of this control. If the ControlUser variable is set, + * then this user will not be updated with the new value. This is to + * avoid setting a value being set back to the source that set it + * (which would be redundant, or possibly causing infinite setValue + * loops). + * NOTE: this function is thread-safe (using a mutex internally) + */ + void setValue(float value, ControlUser *user = NULL); + + /** + * Reimplemented from Control + */ + virtual string getStringRepresentation(); + + float value(); +}; + +class ControlUser +{ +public: + /** + * Pure virtual method, to notify the controluser that the value has + * been changed internally, and needs to be read again. + */ + virtual void controlUpdated(Control *control) = 0; +}; + +#endif /* _CONTROL_H_ */ diff --git a/plugins/zynaddsubfx/src/Misc/Dump.C b/plugins/zynaddsubfx/src/Misc/Dump.C deleted file mode 100644 index bf26d9e32..000000000 --- a/plugins/zynaddsubfx/src/Misc/Dump.C +++ /dev/null @@ -1,99 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Dump.C - It dumps the notes to a text file - - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -#include -#include -#include "Util.h" -#include "Dump.h" - -Dump dump; - -Dump::Dump(){ - file=NULL; - tick=0; - k=0; - keyspressed=0; -}; - -Dump::~Dump(){ - if (file!=NULL) { - double duration=(double)tick*(double) SOUND_BUFFER_SIZE/(double) SAMPLE_RATE; - fprintf(file,"\n# statistics: duration = %d seconds; keyspressed = %d\n\n\n\n",(int) duration,keyspressed); - fclose(file); - }; -}; - -void Dump::startnow(){ - if (file!=NULL) return;//the file is already open - - if (config.cfg.DumpNotesToFile!=0){ - if (config.cfg.DumpAppend!=0) file=fopen(config.cfg.DumpFile,"a"); - else file=fopen(config.cfg.DumpFile,"w"); - if (file==NULL) return; - if (config.cfg.DumpAppend!=0) fprintf(file,"%s","#************************************\n"); - - time_t tm=time(NULL); - - fprintf(file,"#date/time = %s\n",ctime(&tm)); - fprintf(file,"#1 tick = %g milliseconds\n",SOUND_BUFFER_SIZE*1000.0/SAMPLE_RATE); - fprintf(file,"SAMPLERATE = %d\n",SAMPLE_RATE); - fprintf(file,"TICKSIZE = %d #samples\n",SOUND_BUFFER_SIZE); - fprintf(file,"\n\nSTART\n"); - }; -}; - -void Dump::inctick(){ - tick++; -}; - - -void Dump::dumpnote(char chan,char note, char vel){ - if (file==NULL) return; - if (note==0) return; - if (vel==0) fprintf(file,"n %d -> %d %d \n",tick,chan,note);//note off - else fprintf(file,"N %d -> %d %d %d \n",tick,chan,note,vel);//note on - - if (vel!=0) keyspressed++; -#ifndef JACKAUDIOOUT - if (k++>25) { - fflush(file); - k=0; - }; -#endif -}; - -void Dump::dumpcontroller(char chan,unsigned int type,int par){ - if (file==NULL) return; - switch(type){ - case C_pitchwheel:fprintf(file,"P %d -> %d %d\n",tick,chan,par); - break; - default:fprintf(file,"C %d -> %d %d %d\n",tick,chan,type,par); - break; - }; -#ifndef JACKAUDIOOUT - if (k++>25) { - fflush(file); - k=0; - }; -#endif -}; - - diff --git a/plugins/zynaddsubfx/src/Misc/Dump.cpp b/plugins/zynaddsubfx/src/Misc/Dump.cpp new file mode 100644 index 000000000..cb1728ec6 --- /dev/null +++ b/plugins/zynaddsubfx/src/Misc/Dump.cpp @@ -0,0 +1,107 @@ +/* + ZynAddSubFX - a software synthesizer + + Dump.C - It dumps the notes to a text file + + Copyright (C) 2002-2005 Nasca Octavian Paul + Author: Nasca Octavian Paul + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include +#include +#include "Util.h" +#include "Dump.h" + +Dump dump; + +Dump::Dump() +{ + file=NULL; + tick=0; + k=0; + keyspressed=0; +}; + +Dump::~Dump() +{ + if (file!=NULL) { + double duration=(double)tick*(double) SOUND_BUFFER_SIZE/(double) SAMPLE_RATE; + fprintf(file,"\n# statistics: duration = %d seconds; keyspressed = %d\n\n\n\n",(int) duration,keyspressed); + fclose(file); + }; +}; + +void Dump::startnow() +{ + if (file!=NULL) return;//the file is already open + + if (config.cfg.DumpNotesToFile!=0) { + if (config.cfg.DumpAppend!=0) file=fopen(config.cfg.DumpFile,"a"); + else file=fopen(config.cfg.DumpFile,"w"); + if (file==NULL) return; + if (config.cfg.DumpAppend!=0) fprintf(file,"%s","#************************************\n"); + + time_t tm=time(NULL); + + fprintf(file,"#date/time = %s\n",ctime(&tm)); + fprintf(file,"#1 tick = %g milliseconds\n",SOUND_BUFFER_SIZE*1000.0/SAMPLE_RATE); + fprintf(file,"SAMPLERATE = %d\n",SAMPLE_RATE); + fprintf(file,"TICKSIZE = %d #samples\n",SOUND_BUFFER_SIZE); + fprintf(file,"\n\nSTART\n"); + }; +}; + +void Dump::inctick() +{ + tick++; +}; + + +void Dump::dumpnote(char chan,char note, char vel) +{ + if (file==NULL) return; + if (note==0) return; + if (vel==0) fprintf(file,"n %d -> %d %d \n",tick,chan,note);//note off + else fprintf(file,"N %d -> %d %d %d \n",tick,chan,note,vel);//note on + + if (vel!=0) keyspressed++; +#ifndef JACKAUDIOOUT + if (k++>25) { + fflush(file); + k=0; + }; +#endif +}; + +void Dump::dumpcontroller(char chan,unsigned int type,int par) +{ + if (file==NULL) return; + switch (type) { + case C_pitchwheel: + fprintf(file,"P %d -> %d %d\n",tick,chan,par); + break; + default: + fprintf(file,"C %d -> %d %d %d\n",tick,chan,type,par); + break; + }; +#ifndef JACKAUDIOOUT + if (k++>25) { + fflush(file); + k=0; + }; +#endif +}; + + diff --git a/plugins/zynaddsubfx/src/Misc/Dump.h b/plugins/zynaddsubfx/src/Misc/Dump.h index 8304ddd61..d285eb936 100644 --- a/plugins/zynaddsubfx/src/Misc/Dump.h +++ b/plugins/zynaddsubfx/src/Misc/Dump.h @@ -1,13 +1,13 @@ /* ZynAddSubFX - a software synthesizer - + Dump.h - It dumps the notes to a text file Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -24,20 +24,40 @@ #include -class Dump{ - public: - Dump(); - ~Dump(); - void startnow(); - void inctick(); - - void dumpnote(char chan,char note, char vel); - void dumpcontroller(char chan,unsigned int type,int par); - - private: - FILE *file; - int tick; - int k; - int keyspressed; +/**Object used to dump the notes into a text file + * \todo see if this object should have knowledge about the file + * that it will write to + * \todo upgrade from stdio to iostream*/ +class Dump +{ +public: + /**Constructor*/ + Dump(); + /**Destructor + * Closes the dumpfile*/ + ~Dump(); + /**Open dumpfile and prepare it for dumps + * \todo see if this fits better in the constructor*/ + void startnow(); + /**Tick the timestamp*/ + void inctick(); + /**Dump Note to dumpfile + * @param chan The channel of the note + * @param note The note + * @param vel The velocity of the note*/ + void dumpnote(char chan,char note, char vel); + /** Dump the Controller + * @param chan The channel of the Controller + * @param type The type + * @param par The value of the controller + * \todo figure out what type is exactly meaning*/ + void dumpcontroller(char chan,unsigned int type,int par); + +private: + FILE *file; + int tick; + int k;//This appears to be a constant used to flush the file + //periodically when JACK is used + int keyspressed; }; #endif diff --git a/plugins/zynaddsubfx/src/Misc/LASHClient.cpp b/plugins/zynaddsubfx/src/Misc/LASHClient.cpp new file mode 100644 index 000000000..3434a05fb --- /dev/null +++ b/plugins/zynaddsubfx/src/Misc/LASHClient.cpp @@ -0,0 +1,104 @@ +/* + ZynAddSubFX - a software synthesizer + + LASHClient.C - LASH support + Copyright (C) 2006-2009 Lars Luthman + Author: Lars Luthman + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ +#include +#include +#include + +#include "LASHClient.h" + + +LASHClient::LASHClient(int* argc, char*** argv) +{ + client = lash_init(lash_extract_args(argc, argv), "ZynAddSubFX", + LASH_Config_File, LASH_PROTOCOL(2, 0)); +} + + +void LASHClient::setalsaid(int id) +{ + if (lash_enabled(client)) { + if (id != -1) + lash_alsa_client_id(client, id); + } +} + + +void LASHClient::setjackname(const char* name) +{ + if (lash_enabled(client)) { + if (name != NULL) { + lash_jack_client_name(client, name); + + lash_event_t *event = lash_event_new_with_type(LASH_Client_Name); + lash_event_set_string(event, name); + lash_send_event(client, event); + } + } +} + + +LASHClient::Event LASHClient::checkevents(std::string& filename) +{ + + if (!lash_enabled(client)) + return NoEvent; + + Event received = NoEvent; + lash_event_t* event; + while (event = lash_get_event(client)) { + + // save + if (lash_event_get_type(event) == LASH_Save_File) { + std::cerr<<"LASH event: LASH_Save_File"< +#include +#include + + +/** This class wraps up some functions for initialising and polling + * the LASH daemon. + * \todo fix indentation nonconformism + * \todo see why there is no destructor*/ +class LASHClient +{ +public: + /**Enum to represent the LASH events that are currently handled*/ + enum Event { + Save, + Restore, + Quit, + NoEvent + }; + + /** Constructor + * @param argc number of arguments + * @param argv the text arguments*/ + LASHClient(int* argc, char*** argv); + + /**set the ALSA id + * @param id new ALSA id*/ + void setalsaid(int id); + /**Set the JACK name + * @param name the new name*/ + void setjackname(const char* name); + Event checkevents(std::string& filename); + void confirmevent(Event event); + +private: + + lash_client_t* client; +}; + + +#endif + diff --git a/plugins/zynaddsubfx/src/Misc/Master.C b/plugins/zynaddsubfx/src/Misc/Master.C deleted file mode 100644 index 095eba469..000000000 --- a/plugins/zynaddsubfx/src/Misc/Master.C +++ /dev/null @@ -1,738 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Master.C - It sends Midi Messages to Parts, receives samples from parts, - process them with system/insertion effects and mix them - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include "Master.h" - -#include -#include -#include - -#include - -Master::Master(){ - swaplr=0; - - pthread_mutex_init(&mutex,NULL); - fft=new FFTwrapper(OSCIL_SIZE); - - tmpmixl=new REALTYPE[SOUND_BUFFER_SIZE]; - tmpmixr=new REALTYPE[SOUND_BUFFER_SIZE]; - audiooutl=new REALTYPE[SOUND_BUFFER_SIZE]; - audiooutr=new REALTYPE[SOUND_BUFFER_SIZE]; - - ksoundbuffersample=-1;//this is only time when this is -1; this means that the GetAudioOutSamples was never called - ksoundbuffersamplelow=0.0; - oldsamplel=0.0;oldsampler=0.0; - shutup=0; - for (int npart=0;npartdefaults(); - part[npart]->Prcvchn=npart%NUM_MIDI_CHANNELS; - }; - - partonoff(0,1);//enable the first part - - for (int nefx=0;nefxdefaults(); - Pinsparts[nefx]=-1; - }; - - //System Effects init - for (int nefx=0;nefxdefaults(); - for (int npart=0;npartchangeeffect(1); - microtonal.defaults(); - ShutUp(); -}; - -/* - * Note On Messages (velocity=0 for NoteOff) - */ -void Master::NoteOn(unsigned char chan,unsigned char note,unsigned char velocity){ - dump.dumpnote(chan,note,velocity); - - noteon(chan,note,velocity); -}; - -/* - * Internal Note On (velocity=0 for NoteOff) - */ -void Master::noteon(unsigned char chan,unsigned char note,unsigned char velocity){ - int npart; - if (velocity!=0){ - for (npart=0;npartPrcvchn){ - fakepeakpart[npart]=velocity*2; - if (part[npart]->Penabled!=0) part[npart]->NoteOn(note,velocity,keyshift); - }; - }; - }else{ - this->NoteOff(chan,note); - }; - HDDRecorder.triggernow(); -}; - -/* - * Note Off Messages - */ -void Master::NoteOff(unsigned char chan,unsigned char note){ - dump.dumpnote(chan,note,0); - - noteoff(chan,note); -}; - -/* - * Internal Note Off - */ -void Master::noteoff(unsigned char chan,unsigned char note){ - int npart; - for (npart=0;npartPrcvchn) && (part[npart]->Penabled!=0)) - part[npart]->NoteOff(note); - }; -}; - -/* - * Controllers - */ -void Master::SetController(unsigned char chan,unsigned int type,int par){ - dump.dumpcontroller(chan,type,par); - - setcontroller(chan,type,par); -}; - -/* - * Internal Controllers - */ -void Master::setcontroller(unsigned char chan,unsigned int type,int par){ - if ((type==C_dataentryhi)||(type==C_dataentrylo)|| - (type==C_nrpnhi)||(type==C_nrpnlo)){//Process RPN and NRPN by the Master (ignore the chan) - ctl.setparameternumber(type,par); - - int parhi=-1,parlo=-1,valhi=-1,vallo=-1; - if (ctl.getnrpn(&parhi,&parlo,&valhi,&vallo)==0){//this is NRPN - //fprintf(stderr,"rcv. NRPN: %d %d %d %d\n",parhi,parlo,valhi,vallo); - switch (parhi){ - case 0x04://System Effects - if (parloseteffectpar_nolock(valhi,vallo); - }; - break; - case 0x08://Insertion Effects - if (parloseteffectpar_nolock(valhi,vallo); - }; - break; - - }; - }; - } else {//other controllers - for (int npart=0;npartPrcvchn) && (part[npart]->Penabled!=0)) - part[npart]->SetController(type,par); - }; - }; -}; - - -/* - * Enable/Disable a part - */ -void Master::partonoff(int npart,int what){ - if (npart>=NUM_MIDI_PARTS) return; - if (what==0){//disable part - fakepeakpart[npart]=0; - part[npart]->Penabled=0; - part[npart]->cleanup(); - for (int nefx=0;nefxcleanup(); - }; - }; - } else {//enabled - part[npart]->Penabled=1; - fakepeakpart[npart]=0; - }; -}; - -/* - * Master audio out (the final sound) - */ -void Master::AudioOut(REALTYPE *outl,REALTYPE *outr){ - int i,npart,nefx; - -/* //test!!!!!!!!!!!!! se poate bloca aici (mutex) - if (seq.play){ - int type,par1,par2,again,midichan; - int ntrack=1; -// do{ - again=seq.getevent(ntrack,&midichan,&type,&par1,&par2); - if (type>0) { -// printf("aaa\n"); - - if (type==1){//note_on or note_off - if (par2!=0) NoteOn(midichan,par1,par2); - else NoteOff(midichan,par1); - }; - }; -// } while (again); - }; -*/ - - -// printf("zzzz\n"); - - - //Swaps the Left channel with Right Channel (if it is asked for) - if (swaplr!=0){ - REALTYPE *tmp=outl; - outl=outr; - outr=tmp; - }; - - //clean up the output samples - for (i=0;ipartoutl,partoutr - for (npart=0;npartPenabled!=0) part[npart]->ComputePartSmps(); - - //Insertion effects - for (nefx=0;nefx=0) { - int efxpart=Pinsparts[nefx]; - if (part[efxpart]->Penabled!=0) - insefx[nefx]->out(part[efxpart]->partoutl,part[efxpart]->partoutr); - }; - }; - - - //Apply the part volumes and pannings (after insertion effects) - for (npart=0;npartPenabled==0) continue; - - REALTYPE newvol_l=part[npart]->volume; - REALTYPE newvol_r=part[npart]->volume; - REALTYPE oldvol_l=part[npart]->oldvolumel; - REALTYPE oldvol_r=part[npart]->oldvolumer; - REALTYPE pan=part[npart]->panning; - if (pan<0.5) newvol_l*=pan*2.0; - else newvol_r*=(1.0-pan)*2.0; - - if (ABOVE_AMPLITUDE_THRESHOLD(oldvol_l,newvol_l)|| - ABOVE_AMPLITUDE_THRESHOLD(oldvol_r,newvol_r)){//the volume or the panning has changed and needs interpolation - - for (i=0;ipartoutl[i]*=vol_l; - part[npart]->partoutr[i]*=vol_r; - }; - part[npart]->oldvolumel=newvol_l; - part[npart]->oldvolumer=newvol_r; - - } else { - for (i=0;ipartoutl[i]*=newvol_l; - part[npart]->partoutr[i]*=newvol_r; - }; - }; - }; - - - //System effects - for (nefx=0;nefxgeteffect()==0) continue;//the effect is disabled - - //Clean up the samples used by the system effects - for (i=0;iPenabled==0) continue; - - //the output volume of each part to system effect - REALTYPE vol=sysefxvol[nefx][npart]; - for (i=0;ipartoutl[i]*vol; - tmpmixr[i]+=part[npart]->partoutr[i]*vol; - }; - }; - - // system effect send to next ones - for (int nefxfrom=0;nefxfromefxoutl[i]*v; - tmpmixr[i]+=sysefx[nefxfrom]->efxoutr[i]*v; - }; - }; - }; - - sysefx[nefx]->out(tmpmixl,tmpmixr); - - //Add the System Effect to sound output - REALTYPE outvol=sysefx[nefx]->sysefxgetvolume(); - for (i=0;ipartoutl[i]; - outr[i]+=part[npart]->partoutr[i]; - }; - }; - - //Insertion effects for Master Out - for (nefx=0;nefxout(outl,outr); - }; - - //Master Volume - for (i=0;ivuoutpeakl) vuoutpeakl=fabs(outl[i]); - if (fabs(outr[i])>vuoutpeakr) vuoutpeakr=fabs(outr[i]); - }; - if ((vuoutpeakl>1.0)||(vuoutpeakr>1.0)) vuclipped=1; - if (vumaxoutpeaklPenabled!=0) { - REALTYPE *outl=part[npart]->partoutl, - *outr=part[npart]->partoutr; - for (i=0;ivuoutpeakpart[npart]) vuoutpeakpart[npart]=tmp; - }; - vuoutpeakpart[npart]*=volume; - } else { - if (fakepeakpart[npart]>1) fakepeakpart[npart]--; - }; - }; - - - //Shutup if it is asked (with fade-out) - if (shutup!=0){ - for (i=0;i=SOUND_BUFFER_SIZE){ - AudioOut(&audiooutl[0],&audiooutr[0]); - ksoundbuffersample=0; - }; - }; - } else {//Resample - int ksample=0; - REALTYPE srinc=SAMPLE_RATE/(REALTYPE)samplerate; - - while (ksample=1.0){ - ksoundbuffersample+=(int) floor(ksoundbuffersamplelow); - ksoundbuffersamplelow=ksoundbuffersamplelow-floor(ksoundbuffersamplelow); - }; - - if (ksoundbuffersample>=SOUND_BUFFER_SIZE){ - oldsamplel=audiooutl[SOUND_BUFFER_SIZE-1]; - oldsampler=audiooutr[SOUND_BUFFER_SIZE-1]; - AudioOut(&audiooutl[0],&audiooutr[0]); - ksoundbuffersample=0; - }; - }; - }; -}; - - -Master::~Master(){ - for (int npart=0;npartcleanup(); - fakepeakpart[npart]=0; - }; - for (int nefx=0;nefxcleanup(); - for (int nefx=0;nefxcleanup(); - vuresetpeaks(); - shutup=0; -}; - - -/* - * Reset peaks and clear the "cliped" flag (for VU-meter) - */ -void Master::vuresetpeaks(){ - vuoutpeakl=1e-9;vuoutpeakr=1e-9;vumaxoutpeakl=1e-9;vumaxoutpeakr=1e-9; - vuclipped=0; -}; - - - -void Master::applyparameters(){ - for (int npart=0;npartapplyparameters(); - }; -}; - -void Master::add2XML(XMLwrapper *xml){ - xml->addpar("volume",Pvolume); - xml->addpar("key_shift",Pkeyshift); - xml->addparbool("nrpn_receive",ctl.NRPN.receive); - - xml->beginbranch("MICROTONAL"); - microtonal.add2XML(xml); - xml->endbranch(); - - for (int npart=0;npartbeginbranch("PART",npart); - part[npart]->add2XML(xml); - xml->endbranch(); - }; - - xml->beginbranch("SYSTEM_EFFECTS"); - for (int nefx=0;nefxbeginbranch("SYSTEM_EFFECT",nefx); - xml->beginbranch("EFFECT"); - sysefx[nefx]->add2XML(xml); - xml->endbranch(); - - for (int pefx=0;pefxbeginbranch("VOLUME",pefx); - xml->addpar("vol",Psysefxvol[nefx][pefx]); - xml->endbranch(); - }; - - for (int tonefx=nefx+1;tonefxbeginbranch("SENDTO",tonefx); - xml->addpar("send_vol",Psysefxsend[nefx][tonefx]); - xml->endbranch(); - }; - - - xml->endbranch(); - }; - xml->endbranch(); - - xml->beginbranch("INSERTION_EFFECTS"); - for (int nefx=0;nefxbeginbranch("INSERTION_EFFECT",nefx); - xml->addpar("part",Pinsparts[nefx]); - - xml->beginbranch("EFFECT"); - insefx[nefx]->add2XML(xml); - xml->endbranch(); - xml->endbranch(); - }; - - xml->endbranch(); - -}; - - -int Master::getalldata(char **data){ - XMLwrapper *xml=new XMLwrapper(); - - xml->beginbranch("MASTER"); - - pthread_mutex_lock(&mutex); - add2XML(xml); - pthread_mutex_unlock(&mutex); - - xml->endbranch(); - - *data=xml->getXMLdata(); - delete (xml); - return(strlen(*data)+1); -}; - -void Master::putalldata(char *data,int size){ - XMLwrapper *xml=new XMLwrapper(); - if (!xml->putXMLdata(data)) { - delete(xml); - return; - }; - - if (xml->enterbranch("MASTER")==0) return; - - pthread_mutex_lock(&mutex); - getfromXML(xml); - pthread_mutex_unlock(&mutex); - - xml->exitbranch(); - - delete(xml); -}; - -int Master::saveXML(char *filename){ - XMLwrapper *xml=new XMLwrapper(); - - xml->beginbranch("MASTER"); - add2XML(xml); - xml->endbranch(); - - int result=xml->saveXMLfile(filename); - delete (xml); - return(result); -}; - - - -int Master::loadXML(char *filename){ - XMLwrapper *xml=new XMLwrapper(); - if (xml->loadXMLfile(filename)<0) { - delete(xml); - return(-1); - }; - - if (xml->enterbranch("MASTER")==0) return(-10); - getfromXML(xml); - xml->exitbranch(); - - delete(xml); - return(0); -}; - -void Master::getfromXML(XMLwrapper *xml){ - setPvolume(xml->getpar127("volume",Pvolume)); - setPkeyshift(xml->getpar127("key_shift",Pkeyshift)); - ctl.NRPN.receive=xml->getparbool("nrpn_receive",ctl.NRPN.receive); - - - part[0]->Penabled=0; - for (int npart=0;npartenterbranch("PART",npart)==0) continue; - part[npart]->getfromXML(xml); - xml->exitbranch(); - }; - - if (xml->enterbranch("MICROTONAL")){ - microtonal.getfromXML(xml); - xml->exitbranch(); - }; - - sysefx[0]->changeeffect(0); - if (xml->enterbranch("SYSTEM_EFFECTS")){ - for (int nefx=0;nefxenterbranch("SYSTEM_EFFECT",nefx)==0) continue; - if (xml->enterbranch("EFFECT")){ - sysefx[nefx]->getfromXML(xml); - xml->exitbranch(); - }; - - for (int partefx=0;partefxenterbranch("VOLUME",partefx)==0) continue; - setPsysefxvol(partefx,nefx,xml->getpar127("vol",Psysefxvol[partefx][nefx])); - xml->exitbranch(); - }; - - for (int tonefx=nefx+1;tonefxenterbranch("SENDTO",tonefx)==0) continue; - setPsysefxsend(nefx,tonefx,xml->getpar127("send_vol",Psysefxsend[nefx][tonefx])); - xml->exitbranch(); - }; - xml->exitbranch(); - }; - xml->exitbranch(); - }; - - - if (xml->enterbranch("INSERTION_EFFECTS")){ - for (int nefx=0;nefxenterbranch("INSERTION_EFFECT",nefx)==0) continue; - Pinsparts[nefx]=xml->getpar("part",Pinsparts[nefx],-2,NUM_MIDI_PARTS); - if (xml->enterbranch("EFFECT")){ - insefx[nefx]->getfromXML(xml); - xml->exitbranch(); - }; - xml->exitbranch(); - - }; - - xml->exitbranch(); - }; - - -}; - - - - diff --git a/plugins/zynaddsubfx/src/Misc/Master.cpp b/plugins/zynaddsubfx/src/Misc/Master.cpp new file mode 100644 index 000000000..d925ba057 --- /dev/null +++ b/plugins/zynaddsubfx/src/Misc/Master.cpp @@ -0,0 +1,778 @@ +/* + ZynAddSubFX - a software synthesizer + + Master.C - It sends Midi Messages to Parts, receives samples from parts, + process them with system/insertion effects and mix them + Copyright (C) 2002-2005 Nasca Octavian Paul + Author: Nasca Octavian Paul + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "Master.h" + +#include +#include +#include + +#include + +Master::Master() +{ + swaplr=0; + + pthread_mutex_init(&mutex,NULL); + fft=new FFTwrapper(OSCIL_SIZE); + + tmpmixl=new REALTYPE[SOUND_BUFFER_SIZE]; + tmpmixr=new REALTYPE[SOUND_BUFFER_SIZE]; + audiooutl=new REALTYPE[SOUND_BUFFER_SIZE]; + audiooutr=new REALTYPE[SOUND_BUFFER_SIZE]; + + ksoundbuffersample=-1;//this is only time when this is -1; this means that the GetAudioOutSamples was never called + ksoundbuffersamplelow=0.0; + oldsamplel=0.0; + oldsampler=0.0; + shutup=0; + for (int npart=0;npartdefaults(); + part[npart]->Prcvchn=npart%NUM_MIDI_CHANNELS; + }; + + partonoff(0,1);//enable the first part + + for (int nefx=0;nefxdefaults(); + Pinsparts[nefx]=-1; + }; + + //System Effects init + for (int nefx=0;nefxdefaults(); + for (int npart=0;npartchangeeffect(1); + microtonal.defaults(); + ShutUp(); +}; + +/* + * Note On Messages (velocity=0 for NoteOff) + */ +void Master::NoteOn(unsigned char chan,unsigned char note,unsigned char velocity) +{ + dump.dumpnote(chan,note,velocity); + + noteon(chan,note,velocity); +}; + +/* + * Internal Note On (velocity=0 for NoteOff) + */ +void Master::noteon(unsigned char chan,unsigned char note,unsigned char velocity) +{ + int npart; + if (velocity!=0) { + for (npart=0;npartPrcvchn) { + fakepeakpart[npart]=velocity*2; + if (part[npart]->Penabled!=0) part[npart]->NoteOn(note,velocity,keyshift); + }; + }; + } else { + this->NoteOff(chan,note); + }; + HDDRecorder.triggernow(); +}; + +/* + * Note Off Messages + */ +void Master::NoteOff(unsigned char chan,unsigned char note) +{ + dump.dumpnote(chan,note,0); + + noteoff(chan,note); +}; + +/* + * Internal Note Off + */ +void Master::noteoff(unsigned char chan,unsigned char note) +{ + int npart; + for (npart=0;npartPrcvchn) && (part[npart]->Penabled!=0)) + part[npart]->NoteOff(note); + }; +}; + +/* + * Controllers + */ +void Master::SetController(unsigned char chan,unsigned int type,int par) +{ + dump.dumpcontroller(chan,type,par); + + setcontroller(chan,type,par); +}; + +/* + * Internal Controllers + */ +void Master::setcontroller(unsigned char chan,unsigned int type,int par) +{ + if ((type==C_dataentryhi)||(type==C_dataentrylo)|| + (type==C_nrpnhi)||(type==C_nrpnlo)) {//Process RPN and NRPN by the Master (ignore the chan) + ctl.setparameternumber(type,par); + + int parhi=-1,parlo=-1,valhi=-1,vallo=-1; + if (ctl.getnrpn(&parhi,&parlo,&valhi,&vallo)==0) {//this is NRPN + //fprintf(stderr,"rcv. NRPN: %d %d %d %d\n",parhi,parlo,valhi,vallo); + switch (parhi) { + case 0x04://System Effects + if (parloseteffectpar_nolock(valhi,vallo); + }; + break; + case 0x08://Insertion Effects + if (parloseteffectpar_nolock(valhi,vallo); + }; + break; + + }; + }; + } else {//other controllers + for (int npart=0;npartPrcvchn) && (part[npart]->Penabled!=0)) + part[npart]->SetController(type,par); + }; + + if (type==C_allsoundsoff) { //cleanup insertion/system FX + for (int nefx=0;nefxcleanup(); + } + for (int nefx=0;nefxcleanup(); + } + } + }; +}; + + +/* + * Enable/Disable a part + */ +void Master::partonoff(int npart,int what) +{ + if (npart>=NUM_MIDI_PARTS) return; + if (what==0) {//disable part + fakepeakpart[npart]=0; + part[npart]->Penabled=0; + part[npart]->cleanup(); + for (int nefx=0;nefxcleanup(); + }; + }; + } else {//enabled + part[npart]->Penabled=1; + fakepeakpart[npart]=0; + }; +}; + +/* + * Master audio out (the final sound) + */ +void Master::AudioOut(REALTYPE *outl,REALTYPE *outr) +{ + int i,npart,nefx; + + /* //test!!!!!!!!!!!!! se poate bloca aici (mutex) + if (seq.play){ + int type,par1,par2,again,midichan; + int ntrack=1; + // do{ + again=seq.getevent(ntrack,&midichan,&type,&par1,&par2); + if (type>0) { + // printf("aaa\n"); + + if (type==1){//note_on or note_off + if (par2!=0) NoteOn(midichan,par1,par2); + else NoteOff(midichan,par1); + }; + }; + // } while (again); + }; + */ + + +// printf("zzzz\n"); + + + //Swaps the Left channel with Right Channel (if it is asked for) + if (swaplr!=0) { + REALTYPE *tmp=outl; + outl=outr; + outr=tmp; + }; + + //clean up the output samples + for (i=0;ipartoutl,partoutr + for (npart=0;npartPenabled!=0) part[npart]->ComputePartSmps(); + + //Insertion effects + for (nefx=0;nefx=0) { + int efxpart=Pinsparts[nefx]; + if (part[efxpart]->Penabled!=0) + insefx[nefx]->out(part[efxpart]->partoutl,part[efxpart]->partoutr); + }; + }; + + + //Apply the part volumes and pannings (after insertion effects) + for (npart=0;npartPenabled==0) continue; + + REALTYPE newvol_l=part[npart]->volume; + REALTYPE newvol_r=part[npart]->volume; + REALTYPE oldvol_l=part[npart]->oldvolumel; + REALTYPE oldvol_r=part[npart]->oldvolumer; + REALTYPE pan=part[npart]->panning; + if (pan<0.5) newvol_l*=pan*2.0; + else newvol_r*=(1.0-pan)*2.0; + + if (ABOVE_AMPLITUDE_THRESHOLD(oldvol_l,newvol_l)|| + ABOVE_AMPLITUDE_THRESHOLD(oldvol_r,newvol_r)) {//the volume or the panning has changed and needs interpolation + + for (i=0;ipartoutl[i]*=vol_l; + part[npart]->partoutr[i]*=vol_r; + }; + part[npart]->oldvolumel=newvol_l; + part[npart]->oldvolumer=newvol_r; + + } else { + for (i=0;ipartoutl[i]*=newvol_l; + part[npart]->partoutr[i]*=newvol_r; + }; + }; + }; + + + //System effects + for (nefx=0;nefxgeteffect()==0) continue;//the effect is disabled + + //Clean up the samples used by the system effects + for (i=0;iPenabled==0) continue; + + //the output volume of each part to system effect + REALTYPE vol=sysefxvol[nefx][npart]; + for (i=0;ipartoutl[i]*vol; + tmpmixr[i]+=part[npart]->partoutr[i]*vol; + }; + }; + + // system effect send to next ones + for (int nefxfrom=0;nefxfromefxoutl[i]*v; + tmpmixr[i]+=sysefx[nefxfrom]->efxoutr[i]*v; + }; + }; + }; + + sysefx[nefx]->out(tmpmixl,tmpmixr); + + //Add the System Effect to sound output + REALTYPE outvol=sysefx[nefx]->sysefxgetvolume(); + for (i=0;ipartoutl[i]; + outr[i]+=part[npart]->partoutr[i]; + }; + }; + + //Insertion effects for Master Out + for (nefx=0;nefxout(outl,outr); + }; + + //Master Volume + for (i=0;ivuoutpeakl) vuoutpeakl=fabs(outl[i]); + if (fabs(outr[i])>vuoutpeakr) vuoutpeakr=fabs(outr[i]); + }; + if ((vuoutpeakl>1.0)||(vuoutpeakr>1.0)) vuclipped=1; + if (vumaxoutpeaklPenabled!=0) { + REALTYPE *outl=part[npart]->partoutl, + *outr=part[npart]->partoutr; + for (i=0;ivuoutpeakpart[npart]) vuoutpeakpart[npart]=tmp; + }; + vuoutpeakpart[npart]*=volume; + } else { + if (fakepeakpart[npart]>1) fakepeakpart[npart]--; + }; + }; + + + //Shutup if it is asked (with fade-out) + if (shutup!=0) { + for (i=0;i=SOUND_BUFFER_SIZE) { + AudioOut(&audiooutl[0],&audiooutr[0]); + ksoundbuffersample=0; + }; + }; + } else {//Resample + int ksample=0; + REALTYPE srinc=SAMPLE_RATE/(REALTYPE)samplerate; + + while (ksample=1.0) { + ksoundbuffersample+=(int) floor(ksoundbuffersamplelow); + ksoundbuffersamplelow=ksoundbuffersamplelow-floor(ksoundbuffersamplelow); + }; + + if (ksoundbuffersample>=SOUND_BUFFER_SIZE) { + oldsamplel=audiooutl[SOUND_BUFFER_SIZE-1]; + oldsampler=audiooutr[SOUND_BUFFER_SIZE-1]; + AudioOut(&audiooutl[0],&audiooutr[0]); + ksoundbuffersample=0; + }; + }; + }; +}; + + +Master::~Master() +{ + for (int npart=0;npartcleanup(); + fakepeakpart[npart]=0; + }; + for (int nefx=0;nefxcleanup(); + for (int nefx=0;nefxcleanup(); + vuresetpeaks(); + shutup=0; +}; + + +/* + * Reset peaks and clear the "cliped" flag (for VU-meter) + */ +void Master::vuresetpeaks() +{ + vuoutpeakl=1e-9; + vuoutpeakr=1e-9; + vumaxoutpeakl=1e-9; + vumaxoutpeakr=1e-9; + vuclipped=0; +}; + + + +void Master::applyparameters() +{ + for (int npart=0;npartapplyparameters(); + }; +}; + +void Master::add2XML(XMLwrapper *xml) +{ + xml->addpar("volume",Pvolume); + xml->addpar("key_shift",Pkeyshift); + xml->addparbool("nrpn_receive",ctl.NRPN.receive); + + xml->beginbranch("MICROTONAL"); + microtonal.add2XML(xml); + xml->endbranch(); + + for (int npart=0;npartbeginbranch("PART",npart); + part[npart]->add2XML(xml); + xml->endbranch(); + }; + + xml->beginbranch("SYSTEM_EFFECTS"); + for (int nefx=0;nefxbeginbranch("SYSTEM_EFFECT",nefx); + xml->beginbranch("EFFECT"); + sysefx[nefx]->add2XML(xml); + xml->endbranch(); + + for (int pefx=0;pefxbeginbranch("VOLUME",pefx); + xml->addpar("vol",Psysefxvol[nefx][pefx]); + xml->endbranch(); + }; + + for (int tonefx=nefx+1;tonefxbeginbranch("SENDTO",tonefx); + xml->addpar("send_vol",Psysefxsend[nefx][tonefx]); + xml->endbranch(); + }; + + + xml->endbranch(); + }; + xml->endbranch(); + + xml->beginbranch("INSERTION_EFFECTS"); + for (int nefx=0;nefxbeginbranch("INSERTION_EFFECT",nefx); + xml->addpar("part",Pinsparts[nefx]); + + xml->beginbranch("EFFECT"); + insefx[nefx]->add2XML(xml); + xml->endbranch(); + xml->endbranch(); + }; + + xml->endbranch(); + +}; + + +int Master::getalldata(char **data) +{ + XMLwrapper *xml=new XMLwrapper(); + + xml->beginbranch("MASTER"); + + pthread_mutex_lock(&mutex); + add2XML(xml); + pthread_mutex_unlock(&mutex); + + xml->endbranch(); + + *data=xml->getXMLdata(); + delete (xml); + return(strlen(*data)+1); +}; + +void Master::putalldata(char *data,int size) +{ + XMLwrapper *xml=new XMLwrapper(); + if (!xml->putXMLdata(data)) { + delete(xml); + return; + }; + + if (xml->enterbranch("MASTER")==0) return; + + pthread_mutex_lock(&mutex); + getfromXML(xml); + pthread_mutex_unlock(&mutex); + + xml->exitbranch(); + + delete(xml); +}; + +int Master::saveXML(const char *filename) +{ + XMLwrapper *xml=new XMLwrapper(); + + xml->beginbranch("MASTER"); + add2XML(xml); + xml->endbranch(); + + int result=xml->saveXMLfile(filename); + delete (xml); + return(result); +}; + + + +int Master::loadXML(const char *filename) +{ + XMLwrapper *xml=new XMLwrapper(); + if (xml->loadXMLfile(filename)<0) { + delete(xml); + return(-1); + }; + + if (xml->enterbranch("MASTER")==0) return(-10); + getfromXML(xml); + xml->exitbranch(); + + delete(xml); + return(0); +}; + +void Master::getfromXML(XMLwrapper *xml) +{ + setPvolume(xml->getpar127("volume",Pvolume)); + setPkeyshift(xml->getpar127("key_shift",Pkeyshift)); + ctl.NRPN.receive=xml->getparbool("nrpn_receive",ctl.NRPN.receive); + + + part[0]->Penabled=0; + for (int npart=0;npartenterbranch("PART",npart)==0) continue; + part[npart]->getfromXML(xml); + xml->exitbranch(); + }; + + if (xml->enterbranch("MICROTONAL")) { + microtonal.getfromXML(xml); + xml->exitbranch(); + }; + + sysefx[0]->changeeffect(0); + if (xml->enterbranch("SYSTEM_EFFECTS")) { + for (int nefx=0;nefxenterbranch("SYSTEM_EFFECT",nefx)==0) continue; + if (xml->enterbranch("EFFECT")) { + sysefx[nefx]->getfromXML(xml); + xml->exitbranch(); + }; + + for (int partefx=0;partefxenterbranch("VOLUME",partefx)==0) continue; + setPsysefxvol(partefx,nefx,xml->getpar127("vol",Psysefxvol[partefx][nefx])); + xml->exitbranch(); + }; + + for (int tonefx=nefx+1;tonefxenterbranch("SENDTO",tonefx)==0) continue; + setPsysefxsend(nefx,tonefx,xml->getpar127("send_vol",Psysefxsend[nefx][tonefx])); + xml->exitbranch(); + }; + xml->exitbranch(); + }; + xml->exitbranch(); + }; + + + if (xml->enterbranch("INSERTION_EFFECTS")) { + for (int nefx=0;nefxenterbranch("INSERTION_EFFECT",nefx)==0) continue; + Pinsparts[nefx]=xml->getpar("part",Pinsparts[nefx],-2,NUM_MIDI_PARTS); + if (xml->enterbranch("EFFECT")) { + insefx[nefx]->getfromXML(xml); + xml->exitbranch(); + }; + xml->exitbranch(); + + }; + + xml->exitbranch(); + }; + + +}; + + + + diff --git a/plugins/zynaddsubfx/src/Misc/Master.h b/plugins/zynaddsubfx/src/Misc/Master.h index 527670e36..69f1a1ec2 100644 --- a/plugins/zynaddsubfx/src/Misc/Master.h +++ b/plugins/zynaddsubfx/src/Misc/Master.h @@ -1,13 +1,13 @@ /* ZynAddSubFX - a software synthesizer - + Master.h - It sends Midi Messages to Parts, receives samples from parts, process them with system/insertion effects and mix them Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -36,127 +36,132 @@ #include "XMLwrapper.h" extern Dump dump; -class Master{ - public: - Master(); - ~Master(); +/** It sends Midi Messages to Parts, receives samples from parts, + * process them with system/insertion effects and mix them */ +class Master +{ +public: + /** Constructor*/ + Master(); + /** Destructor*/ + ~Master(); - //saves all settings to a XML file - //returns 0 for ok or <0 if there is an error - int saveXML(char *filename); + /**Saves all settings to a XML file + * @return 0 for ok or <0 if there is an error*/ + int saveXML(const char *filename); - //this adds the parameters to the XML data - void add2XML(XMLwrapper *xml); + /**This adds the parameters to the XML data*/ + void add2XML(XMLwrapper *xml); - void defaults(); + void defaults(); - //loads all settings from a XML file - //returns 0 for ok or -1 if there is an error - int loadXML(char *filename); - void applyparameters(); + /**loads all settings from a XML file + * @return 0 for ok or -1 if there is an error*/ + int loadXML(const char *filename); + void applyparameters(); - void getfromXML(XMLwrapper *xml); - - //get all data to a newly allocated array (used for VST) - //returns the datasize - int getalldata(char **data); - //put all data from the *data array to zynaddsubfx parameters (used for VST) - void putalldata(char *data,int size); + void getfromXML(XMLwrapper *xml); + + /**get all data to a newly allocated array (used for VST) + * @return the datasize*/ + int getalldata(char **data); + /**put all data from the *data array to zynaddsubfx parameters (used for VST)*/ + void putalldata(char *data,int size); - //Midi IN - void NoteOn(unsigned char chan,unsigned char note,unsigned char velocity); - void NoteOff(unsigned char chan,unsigned char note); - void SetController(unsigned char chan,unsigned int type,int par); - //void NRPN... - - - void ShutUp(); - int shutup; - - //Audio Output - void AudioOut(REALTYPE *outl,REALTYPE *outr); - //Audio Output (for callback mode). This allows the program to be controled by an external program - void GetAudioOutSamples(int nsamples,int samplerate,REALTYPE *outl,REALTYPE *outr); + //Midi IN + void NoteOn(unsigned char chan,unsigned char note,unsigned char velocity); + void NoteOff(unsigned char chan,unsigned char note); + void SetController(unsigned char chan,unsigned int type,int par); + //void NRPN... - void partonoff(int npart,int what); - - //parts - Part *part[NUM_MIDI_PARTS]; - - //parameters - unsigned char Pvolume; - unsigned char Pkeyshift; - unsigned char Psysefxvol[NUM_SYS_EFX][NUM_MIDI_PARTS]; - unsigned char Psysefxsend[NUM_SYS_EFX][NUM_SYS_EFX]; - - //parameters control - void setPvolume(char Pvolume_); - void setPkeyshift(char Pkeyshift_); - void setPsysefxvol(int Ppart,int Pefx,char Pvol); - void setPsysefxsend(int Pefxfrom,int Pefxto,char Pvol); + void ShutUp(); + int shutup; - //effects - EffectMgr *sysefx[NUM_SYS_EFX];//system - EffectMgr *insefx[NUM_INS_EFX];//insertion + /**Audio Output*/ + void AudioOut(REALTYPE *outl,REALTYPE *outr); + /**Audio Output (for callback mode). This allows the program to be controled by an external program*/ + void GetAudioOutSamples(int nsamples,int samplerate,REALTYPE *outl,REALTYPE *outr); + + + void partonoff(int npart,int what); + + /**parts \todo see if this can be made to be dynamic*/ + Part *part[NUM_MIDI_PARTS]; + + //parameters + unsigned char Pvolume; + unsigned char Pkeyshift; + unsigned char Psysefxvol[NUM_SYS_EFX][NUM_MIDI_PARTS]; + unsigned char Psysefxsend[NUM_SYS_EFX][NUM_SYS_EFX]; + + //parameters control + void setPvolume(char Pvolume_); + void setPkeyshift(char Pkeyshift_); + void setPsysefxvol(int Ppart,int Pefx,char Pvol); + void setPsysefxsend(int Pefxfrom,int Pefxto,char Pvol); + + //effects + EffectMgr *sysefx[NUM_SYS_EFX];//system + EffectMgr *insefx[NUM_INS_EFX];//insertion // void swapcopyeffects(int what,int type,int neff1,int neff2); - //HDD recorder - Recorder HDDRecorder; + //HDD recorder + Recorder HDDRecorder; - //part that's apply the insertion effect; -1 to disable - short int Pinsparts[NUM_INS_EFX]; - - //peaks for VU-meter - void vuresetpeaks(); - REALTYPE vuoutpeakl,vuoutpeakr,vumaxoutpeakl,vumaxoutpeakr,vurmspeakl,vurmspeakr; - int vuclipped; - - //peaks for part VU-meters - REALTYPE vuoutpeakpart[NUM_MIDI_PARTS]; - unsigned char fakepeakpart[NUM_MIDI_PARTS];//this is used to compute the "peak" when the part is disabled + //part that's apply the insertion effect; -1 to disable + short int Pinsparts[NUM_INS_EFX]; - Controller ctl; - int swaplr;//1 if L and R are swapped + //peaks for VU-meter + void vuresetpeaks(); + REALTYPE vuoutpeakl,vuoutpeakr,vumaxoutpeakl,vumaxoutpeakr,vurmspeakl,vurmspeakr; + int vuclipped; - //Sequencer - Sequencer seq; - - //other objects - Microtonal microtonal; - Bank bank; - - FFTwrapper *fft; - pthread_mutex_t mutex; + //peaks for part VU-meters + REALTYPE vuoutpeakpart[NUM_MIDI_PARTS]; + unsigned char fakepeakpart[NUM_MIDI_PARTS];//this is used to compute the "peak" when the part is disabled - private: - REALTYPE volume; - REALTYPE sysefxvol[NUM_SYS_EFX][NUM_MIDI_PARTS]; - REALTYPE sysefxsend[NUM_SYS_EFX][NUM_SYS_EFX]; + Controller ctl; + int swaplr;//1 if L and R are swapped - //Temporary mixing samples for part samples which is sent to system effect - REALTYPE *tmpmixl; - REALTYPE *tmpmixr; + //Sequencer + Sequencer seq; + + //other objects + Microtonal microtonal; + Bank bank; + + FFTwrapper *fft; + pthread_mutex_t mutex; + +private: + REALTYPE volume; + REALTYPE sysefxvol[NUM_SYS_EFX][NUM_MIDI_PARTS]; + REALTYPE sysefxsend[NUM_SYS_EFX][NUM_SYS_EFX]; + + //Temporary mixing samples for part samples which is sent to system effect + REALTYPE *tmpmixl; + REALTYPE *tmpmixr; - int keyshift; + int keyshift; - //Audio Output samples (if it used GetAudioOutSamples - eg. for Jack output; elsewhere is unused) - REALTYPE *audiooutl; - REALTYPE *audiooutr; - - int ksoundbuffersample;//this is used to know if there is need to call AudioOut by GetAudioOutSamples method - REALTYPE ksoundbuffersamplelow;//this is used for resampling (eg. if Jack samplerate!= SAMPLE_RATE) - REALTYPE oldsamplel,oldsampler;//this is used for resampling + //Audio Output samples (if it used GetAudioOutSamples - eg. for Jack output; elsewhere is unused) + REALTYPE *audiooutl; + REALTYPE *audiooutr; - //Theese are called by the NoteOn, NoteOff,SetController (which are from external sources like MIDI, Virtual Keyboard) - //and are called by internal parts of the program (like sequencer) - void noteon(unsigned char chan,unsigned char note,unsigned char velocity); - void noteoff(unsigned char chan,unsigned char note); - void setcontroller(unsigned char chan,unsigned int type,int par); + int ksoundbuffersample;//this is used to know if there is need to call AudioOut by GetAudioOutSamples method + REALTYPE ksoundbuffersamplelow;//this is used for resampling (eg. if Jack samplerate!= SAMPLE_RATE) + REALTYPE oldsamplel,oldsampler;//this is used for resampling + + //These are called by the NoteOn, NoteOff,SetController (which are from external sources like MIDI, Virtual Keyboard) + //and are called by internal parts of the program (like sequencer) + void noteon(unsigned char chan,unsigned char note,unsigned char velocity); + void noteoff(unsigned char chan,unsigned char note); + void setcontroller(unsigned char chan,unsigned int type,int par); }; diff --git a/plugins/zynaddsubfx/src/Misc/Microtonal.C b/plugins/zynaddsubfx/src/Misc/Microtonal.C deleted file mode 100644 index 14eab7439..000000000 --- a/plugins/zynaddsubfx/src/Misc/Microtonal.C +++ /dev/null @@ -1,514 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Microtonal.C - Tuning settings and microtonal capabilities - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include -#include "Microtonal.h" - -#define MAX_LINE_SIZE 80 - -Microtonal::Microtonal(){ - Pname=new unsigned char[MICROTONAL_MAX_NAME_LEN]; - Pcomment=new unsigned char[MICROTONAL_MAX_NAME_LEN]; - defaults(); -}; - -void Microtonal::defaults(){ - Pinvertupdown=0; - Pinvertupdowncenter=60; - octavesize=12; - Penabled=0; - PAnote=69; - PAfreq=440.0; - Pscaleshift=64; - - Pfirstkey=0;Plastkey=127; - Pmiddlenote=60;Pmapsize=12; - Pmappingenabled=0; - - for (int i=0;i<128;i++) Pmapping[i]=i; - - for (int i=0;iPlastkey)) return (-1.0); - //Compute how many mapped keys are from middle note to reference note - //and find out the proportion between the freq. of middle note and "A" note - int tmp=PAnote-Pmiddlenote,minus=0; - if (tmp<0) { tmp=-tmp; minus=1; }; - int deltanote=0; - for (int i=0;i=0) deltanote++; - REALTYPE rap_anote_middlenote=(deltanote==0) ? (1.0) : (octave[(deltanote-1)%octavesize].tuning); - if (deltanote!=0) rap_anote_middlenote*=pow(octave[octavesize-1].tuning,(deltanote-1)/octavesize); - if (minus!=0) rap_anote_middlenote=1.0/rap_anote_middlenote; - - //Convert from note (midi) to degree (note from the tunning) - int degoct=(note-(int)Pmiddlenote+(int) Pmapsize*200)/(int)Pmapsize-200; - int degkey=(note-Pmiddlenote+(int)Pmapsize*100)%Pmapsize; - degkey=Pmapping[degkey]; - if (degkey<0) return(-1.0);//this key is not mapped - - //invert the keyboard upside-down if it is asked for - //TODO: do the right way by using Pinvertupdowncenter - if (Pinvertupdown!=0){ - degkey=octavesize-degkey-1; - degoct=-degoct; - }; - //compute the frequency of the note - degkey=degkey+scaleshift; - degoct+=degkey/octavesize; - degkey%=octavesize; - - REALTYPE freq=(degkey==0) ? (1.0):octave[degkey-1].tuning; - freq*=pow(octave[octavesize-1].tuning,degoct); - freq*=PAfreq/rap_anote_middlenote; - freq*=globalfinedetunerap; - if (scaleshift!=0) freq/=octave[scaleshift-1].tuning; - return(freq*rap_keyshift); - } else {//if the mapping is disabled - int nt=note-PAnote+scaleshift; - int ntkey=(nt+(int)octavesize*100)%octavesize; - int ntoct=(nt-ntkey)/octavesize; - - REALTYPE oct=octave[octavesize-1].tuning; - REALTYPE freq=octave[(ntkey+octavesize-1)%octavesize].tuning*pow(oct,ntoct)*PAfreq; - if (ntkey==0) freq/=oct; - if (scaleshift!=0) freq/=octave[scaleshift-1].tuning; -// fprintf(stderr,"note=%d freq=%.3f cents=%d\n",note,freq,(int)floor(log(freq/PAfreq)/log(2.0)*1200.0+0.5)); - freq*=globalfinedetunerap; - return(freq*rap_keyshift); - }; -}; - - -/* - * Convert a line to tunings; returns -1 if it ok - */ -int Microtonal::linetotunings(unsigned int nline,const char *line){ - int x1=-1,x2=-1,type=-1; - REALTYPE x=-1.0,tmp,tuning=1.0; - if (strstr(line,"/")==NULL){ - if (strstr(line,".")==NULL){// M case (M=M/1) - sscanf(line,"%d",&x1); - x2=1; - type=2;//division - } else {// float number case - sscanf(line,"%f",&x); - if (x<0.000001) return(1); - type=1;//float type(cents) - }; - } else {// M/N case - sscanf(line,"%d/%d",&x1,&x2); - if ((x1<0)||(x2<0)) return(1); - if (x2==0) x2=1; - type=2;//division - }; - - if (x1<=0) x1=1;//not allow zero frequency sounds (consider 0 as 1) - - //convert to float if the number are too big - if ((type==2)&&((x1>(128*128*128-1))||(x2>(128*128*128-1)))){ - type=1; - x=((REALTYPE) x1)/x2; - }; - switch (type){ - case 1: x1=(int) floor(x); - tmp=fmod(x,1.0); - x2=(int) (floor (tmp*1e6)); - tuning=pow(2.0,x/1200.0); - break; - case 2: x=((REALTYPE)x1)/x2; - tuning=x; - break; - }; - - tmpoctave[nline].tuning=tuning; - tmpoctave[nline].type=type; - tmpoctave[nline].x1=x1; - tmpoctave[nline].x2=x2; - - return(-1);//ok -}; - -/* - * Convert the text to tunnings - */ -int Microtonal::texttotunings(const char *text){ - unsigned int i,k=0,nl=0; - char *lin; - lin=new char[MAX_LINE_SIZE+1]; - while (kMAX_OCTAVE_SIZE) nl=MAX_OCTAVE_SIZE; - if (nl==0) return(-2);//the input is empty - octavesize=nl; - for (i=0;i127) break; - }; - delete [] lin; - - if (tx==0) tx=1; - Pmapsize=tx; -}; - -/* - * Convert tunning to text line - */ -void Microtonal::tuningtoline(int n,char *line,int maxn){ - if ((n>octavesize) || (n>MAX_OCTAVE_SIZE)) { - line[0]='\0'; - return; - }; - if (octave[n].type==1) snprintf(line,maxn,"%d.%d",octave[n].x1,octave[n].x2); - if (octave[n].type==2) snprintf(line,maxn,"%d/%d",octave[n].x1,octave[n].x2); -}; - - -int Microtonal::loadline(FILE *file,char *line){ - do { - if (fgets(line,500,file)==0) return(1); - } while (line[0]=='!'); - return(0); -}; -/* - * Loads the tunnings from a scl file - */ -int Microtonal::loadscl(const char *filename){ - FILE *file=fopen(filename, "r"); - char tmp[500]; - fseek(file,0,SEEK_SET); - //loads the short description - if (loadline(file,&tmp[0])!=0) return(2); - for (int i=0;i<500;i++) if (tmp[i]<32) tmp[i]=0; - snprintf((char *) Pname,MICROTONAL_MAX_NAME_LEN,"%s",tmp); - snprintf((char *) Pcomment,MICROTONAL_MAX_NAME_LEN,"%s",tmp); - //loads the number of the notes - if (loadline(file,&tmp[0])!=0) return(2); - int nnotes=MAX_OCTAVE_SIZE; - sscanf(&tmp[0],"%d",&nnotes); - if (nnotes>MAX_OCTAVE_SIZE) return (2); - //load the tunnings - for (int nline=0;nline127) x=127;//just in case... - Pmapsize=x; - //loads first MIDI note to retune - if (loadline(file,&tmp[0])!=0) return(2); - if (sscanf(&tmp[0],"%d",&x)==0) return(2); - if (x<1) x=0;if (x>127) x=127;//just in case... - Pfirstkey=x; - //loads last MIDI note to retune - if (loadline(file,&tmp[0])!=0) return(2); - if (sscanf(&tmp[0],"%d",&x)==0) return(2); - if (x<1) x=0;if (x>127) x=127;//just in case... - Plastkey=x; - //loads last the middle note where scale fro scale degree=0 - if (loadline(file,&tmp[0])!=0) return(2); - if (sscanf(&tmp[0],"%d",&x)==0) return(2); - if (x<1) x=0;if (x>127) x=127;//just in case... - Pmiddlenote=x; - //loads the reference note - if (loadline(file,&tmp[0])!=0) return(2); - if (sscanf(&tmp[0],"%d",&x)==0) return(2); - if (x<1) x=0;if (x>127) x=127;//just in case... - PAnote=x; - //loads the reference freq. - if (loadline(file,&tmp[0])!=0) return(2); - REALTYPE tmpPAfreq=440.0; - if (sscanf(&tmp[0],"%f",&tmpPAfreq)==0) return(2); - PAfreq=tmpPAfreq; - - //the scale degree(which is the octave) is not loaded, it is obtained by the tunnings with getoctavesize() method - if (loadline(file,&tmp[0])!=0) return(2); - - //load the mappings - if (Pmapsize!=0){ - for (int nline=0;nlineaddparstr("name",(char *) Pname); - xml->addparstr("comment",(char *) Pcomment); - - xml->addparbool("invert_up_down",Pinvertupdown); - xml->addparbool("invert_up_down_center",Pinvertupdowncenter); - - xml->addparbool("enabled",Penabled); - xml->addpar("global_fine_detune",Pglobalfinedetune); - - xml->addpar("a_note",PAnote); - xml->addparreal("a_freq",PAfreq); - - if ((Penabled==0)&&(xml->minimal)) return; - - xml->beginbranch("SCALE"); - xml->addpar("scale_shift",Pscaleshift); - xml->addpar("first_key",Pfirstkey); - xml->addpar("last_key",Plastkey); - xml->addpar("middle_note",Pmiddlenote); - - xml->beginbranch("OCTAVE"); - xml->addpar("octave_size",octavesize); - for (int i=0;ibeginbranch("DEGREE",i); - if (octave[i].type==1){ - xml->addparreal("cents",octave[i].tuning); - }; - if (octave[i].type==2){ - xml->addpar("numerator",octave[i].x1); - xml->addpar("denominator",octave[i].x2); - }; - xml->endbranch(); - }; - xml->endbranch(); - - xml->beginbranch("KEYBOARD_MAPPING"); - xml->addpar("map_size",Pmapsize); - xml->addpar("mapping_enabled",Pmappingenabled); - for (int i=0;ibeginbranch("KEYMAP",i); - xml->addpar("degree",Pmapping[i]); - xml->endbranch(); - }; - xml->endbranch(); - xml->endbranch(); -}; - -void Microtonal::getfromXML(XMLwrapper *xml){ - xml->getparstr("name",(char *) Pname,MICROTONAL_MAX_NAME_LEN); - xml->getparstr("comment",(char *) Pcomment,MICROTONAL_MAX_NAME_LEN); - - Pinvertupdown=xml->getparbool("invert_up_down",Pinvertupdown); - Pinvertupdowncenter=xml->getparbool("invert_up_down_center",Pinvertupdowncenter); - - Penabled=xml->getparbool("enabled",Penabled); - Pglobalfinedetune=xml->getpar127("global_fine_detune",Pglobalfinedetune); - - PAnote=xml->getpar127("a_note",PAnote); - PAfreq=xml->getparreal("a_freq",PAfreq,1.0,10000.0); - - if (xml->enterbranch("SCALE")){ - Pscaleshift=xml->getpar127("scale_shift",Pscaleshift); - Pfirstkey=xml->getpar127("first_key",Pfirstkey); - Plastkey=xml->getpar127("last_key",Plastkey); - Pmiddlenote=xml->getpar127("middle_note",Pmiddlenote); - - if (xml->enterbranch("OCTAVE")){ - octavesize=xml->getpar127("octave_size",octavesize); - for (int i=0;ienterbranch("DEGREE",i)==0) continue; - octave[i].x2=0; - octave[i].tuning=xml->getparreal("cents",octave[i].tuning); - octave[i].x1=xml->getpar127("numerator",octave[i].x1); - octave[i].x2=xml->getpar127("denominator",octave[i].x2); - - if (octave[i].x2!=0) octave[i].type=2; - else octave[i].type=1; - - xml->exitbranch(); - }; - xml->exitbranch(); - }; - - if (xml->enterbranch("KEYBOARD_MAPPING")){ - Pmapsize=xml->getpar127("map_size",Pmapsize); - Pmappingenabled=xml->getpar127("mapping_enabled",Pmappingenabled); - for (int i=0;ienterbranch("KEYMAP",i)==0) continue; - Pmapping[i]=xml->getpar127("degree",Pmapping[i]); - xml->exitbranch(); - }; - xml->exitbranch(); - }; - xml->exitbranch(); - }; -}; - - -int Microtonal::saveXML(char *filename){ - XMLwrapper *xml=new XMLwrapper(); - - xml->beginbranch("MICROTONAL"); - add2XML(xml); - xml->endbranch(); - - int result=xml->saveXMLfile(filename); - delete (xml); - return(result); -}; - -int Microtonal::loadXML(char *filename){ - XMLwrapper *xml=new XMLwrapper(); - if (xml->loadXMLfile(filename)<0) { - delete(xml); - return(-1); - }; - - if (xml->enterbranch("MICROTONAL")==0) return(-10); - getfromXML(xml); - xml->exitbranch(); - - delete(xml); - return(0); -}; - - diff --git a/plugins/zynaddsubfx/src/Misc/Microtonal.cpp b/plugins/zynaddsubfx/src/Misc/Microtonal.cpp new file mode 100644 index 000000000..b389059c8 --- /dev/null +++ b/plugins/zynaddsubfx/src/Misc/Microtonal.cpp @@ -0,0 +1,597 @@ +/* + ZynAddSubFX - a software synthesizer + + Microtonal.C - Tuning settings and microtonal capabilities + Copyright (C) 2002-2005 Nasca Octavian Paul + Author: Nasca Octavian Paul + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include +#include +#include "Microtonal.h" + +#define MAX_LINE_SIZE 80 + +Microtonal::Microtonal() +{ + Pname=new unsigned char[MICROTONAL_MAX_NAME_LEN]; + Pcomment=new unsigned char[MICROTONAL_MAX_NAME_LEN]; + defaults(); +}; + +void Microtonal::defaults() +{ + Pinvertupdown=0; + Pinvertupdowncenter=60; + octavesize=12; + Penabled=0; + PAnote=69; + PAfreq=440.0; + Pscaleshift=64; + + Pfirstkey=0; + Plastkey=127; + Pmiddlenote=60; + Pmapsize=12; + Pmappingenabled=0; + + for (int i=0;i<128;i++) Pmapping[i]=i; + + for (int i=0;iPlastkey)) return (-1.0); + //Compute how many mapped keys are from middle note to reference note + //and find out the proportion between the freq. of middle note and "A" note + int tmp=PAnote-Pmiddlenote,minus=0; + if (tmp<0) { + tmp=-tmp; + minus=1; + }; + int deltanote=0; + for (int i=0;i=0) deltanote++; + REALTYPE rap_anote_middlenote=(deltanote==0) ? (1.0) : (octave[(deltanote-1)%octavesize].tuning); + if (deltanote!=0) rap_anote_middlenote*=pow(octave[octavesize-1].tuning,(deltanote-1)/octavesize); + if (minus!=0) rap_anote_middlenote=1.0/rap_anote_middlenote; + + //Convert from note (midi) to degree (note from the tunning) + int degoct=(note-(int)Pmiddlenote+(int) Pmapsize*200)/(int)Pmapsize-200; + int degkey=(note-Pmiddlenote+(int)Pmapsize*100)%Pmapsize; + degkey=Pmapping[degkey]; + if (degkey<0) return(-1.0);//this key is not mapped + + //invert the keyboard upside-down if it is asked for + //TODO: do the right way by using Pinvertupdowncenter + if (Pinvertupdown!=0) { + degkey=octavesize-degkey-1; + degoct=-degoct; + }; + //compute the frequency of the note + degkey=degkey+scaleshift; + degoct+=degkey/octavesize; + degkey%=octavesize; + + REALTYPE freq=(degkey==0) ? (1.0):octave[degkey-1].tuning; + freq*=pow(octave[octavesize-1].tuning,degoct); + freq*=PAfreq/rap_anote_middlenote; + freq*=globalfinedetunerap; + if (scaleshift!=0) freq/=octave[scaleshift-1].tuning; + return(freq*rap_keyshift); + } else {//if the mapping is disabled + int nt=note-PAnote+scaleshift; + int ntkey=(nt+(int)octavesize*100)%octavesize; + int ntoct=(nt-ntkey)/octavesize; + + REALTYPE oct=octave[octavesize-1].tuning; + REALTYPE freq=octave[(ntkey+octavesize-1)%octavesize].tuning*pow(oct,ntoct)*PAfreq; + if (ntkey==0) freq/=oct; + if (scaleshift!=0) freq/=octave[scaleshift-1].tuning; +// fprintf(stderr,"note=%d freq=%.3f cents=%d\n",note,freq,(int)floor(log(freq/PAfreq)/log(2.0)*1200.0+0.5)); + freq*=globalfinedetunerap; + return(freq*rap_keyshift); + }; +}; + +bool Microtonal::operator==(const Microtonal µ) const +{ + return(!(*this!=micro)); +} + +bool Microtonal::operator!=(const Microtonal µ) const +{ + + //A simple macro to test equality MiCRotonal EQuals (not the perfect + //approach, but good enough) +#define MCREQ( x ) if(x!=micro.x)return true; + + //for floats +#define FMCREQ( x ) if(!((xmicro.x-0.0001)))return true; + + MCREQ(Pinvertupdown); + MCREQ(Pinvertupdowncenter); + MCREQ(octavesize); + MCREQ(Penabled); + MCREQ(PAnote); + FMCREQ(PAfreq); + MCREQ(Pscaleshift); + + MCREQ(Pfirstkey); + MCREQ(Plastkey); + MCREQ(Pmiddlenote); + MCREQ(Pmapsize); + MCREQ(Pmappingenabled); + + for (int i=0;i<128;i++) + MCREQ(Pmapping[i]); + + for (int i=0;iPname,(const char *)micro.Pname)) + return true; + if(strcmp((const char *)this->Pcomment,(const char *)micro.Pcomment)) + return true; + MCREQ(Pglobalfinedetune); + return false; + + //undefine macros, as they are no longer needed +#undef MCREQ +#undef FMCREQ + +} + + +/* + * Convert a line to tunings; returns -1 if it ok + */ +int Microtonal::linetotunings(unsigned int nline,const char *line) +{ + int x1=-1,x2=-1,type=-1; + REALTYPE x=-1.0,tmp,tuning=1.0; + if (strstr(line,"/")==NULL) { + if (strstr(line,".")==NULL) {// M case (M=M/1) + sscanf(line,"%d",&x1); + x2=1; + type=2;//division + } else {// float number case + sscanf(line,"%f",&x); + if (x<0.000001) return(1); + type=1;//float type(cents) + }; + } else {// M/N case + sscanf(line,"%d/%d",&x1,&x2); + if ((x1<0)||(x2<0)) return(1); + if (x2==0) x2=1; + type=2;//division + }; + + if (x1<=0) x1=1;//not allow zero frequency sounds (consider 0 as 1) + + //convert to float if the number are too big + if ((type==2)&&((x1>(128*128*128-1))||(x2>(128*128*128-1)))) { + type=1; + x=((REALTYPE) x1)/x2; + }; + switch (type) { + case 1: + x1=(int) floor(x); + tmp=fmod(x,1.0); + x2=(int) (floor (tmp*1e6)); + tuning=pow(2.0,x/1200.0); + break; + case 2: + x=((REALTYPE)x1)/x2; + tuning=x; + break; + }; + + tmpoctave[nline].tuning=tuning; + tmpoctave[nline].type=type; + tmpoctave[nline].x1=x1; + tmpoctave[nline].x2=x2; + + return(-1);//ok +}; + +/* + * Convert the text to tunnings + */ +int Microtonal::texttotunings(const char *text) +{ + unsigned int i,k=0,nl=0; + char *lin; + lin=new char[MAX_LINE_SIZE+1]; + while (kMAX_OCTAVE_SIZE) nl=MAX_OCTAVE_SIZE; + if (nl==0) return(-2);//the input is empty + octavesize=nl; + for (i=0;i127) break; + }; + delete [] lin; + + if (tx==0) tx=1; + Pmapsize=tx; +}; + +/* + * Convert tunning to text line + */ +void Microtonal::tuningtoline(int n,char *line,int maxn) +{ + if ((n>octavesize) || (n>MAX_OCTAVE_SIZE)) { + line[0]='\0'; + return; + }; + if (octave[n].type==1) snprintf(line,maxn,"%d.%d",octave[n].x1,octave[n].x2); + if (octave[n].type==2) snprintf(line,maxn,"%d/%d",octave[n].x1,octave[n].x2); +}; + + +int Microtonal::loadline(FILE *file,char *line) +{ + do { + if (fgets(line,500,file)==0) return(1); + } while (line[0]=='!'); + return(0); +}; +/* + * Loads the tunnings from a scl file + */ +int Microtonal::loadscl(const char *filename) +{ + FILE *file=fopen(filename, "r"); + char tmp[500]; + fseek(file,0,SEEK_SET); + //loads the short description + if (loadline(file,&tmp[0])!=0) return(2); + for (int i=0;i<500;i++) if (tmp[i]<32) tmp[i]=0; + snprintf((char *) Pname,MICROTONAL_MAX_NAME_LEN,"%s",tmp); + snprintf((char *) Pcomment,MICROTONAL_MAX_NAME_LEN,"%s",tmp); + //loads the number of the notes + if (loadline(file,&tmp[0])!=0) return(2); + int nnotes=MAX_OCTAVE_SIZE; + sscanf(&tmp[0],"%d",&nnotes); + if (nnotes>MAX_OCTAVE_SIZE) return (2); + //load the tunnings + for (int nline=0;nline127) x=127;//just in case... + Pmapsize=x; + //loads first MIDI note to retune + if (loadline(file,&tmp[0])!=0) return(2); + if (sscanf(&tmp[0],"%d",&x)==0) return(2); + if (x<1) x=0; + if (x>127) x=127;//just in case... + Pfirstkey=x; + //loads last MIDI note to retune + if (loadline(file,&tmp[0])!=0) return(2); + if (sscanf(&tmp[0],"%d",&x)==0) return(2); + if (x<1) x=0; + if (x>127) x=127;//just in case... + Plastkey=x; + //loads last the middle note where scale fro scale degree=0 + if (loadline(file,&tmp[0])!=0) return(2); + if (sscanf(&tmp[0],"%d",&x)==0) return(2); + if (x<1) x=0; + if (x>127) x=127;//just in case... + Pmiddlenote=x; + //loads the reference note + if (loadline(file,&tmp[0])!=0) return(2); + if (sscanf(&tmp[0],"%d",&x)==0) return(2); + if (x<1) x=0; + if (x>127) x=127;//just in case... + PAnote=x; + //loads the reference freq. + if (loadline(file,&tmp[0])!=0) return(2); + REALTYPE tmpPAfreq=440.0; + if (sscanf(&tmp[0],"%f",&tmpPAfreq)==0) return(2); + PAfreq=tmpPAfreq; + + //the scale degree(which is the octave) is not loaded, it is obtained by the tunnings with getoctavesize() method + if (loadline(file,&tmp[0])!=0) return(2); + + //load the mappings + if (Pmapsize!=0) { + for (int nline=0;nlineaddparstr("name",(char *) Pname); + xml->addparstr("comment",(char *) Pcomment); + + xml->addparbool("invert_up_down",Pinvertupdown); + xml->addpar("invert_up_down_center",Pinvertupdowncenter); + + xml->addparbool("enabled",Penabled); + xml->addpar("global_fine_detune",Pglobalfinedetune); + + xml->addpar("a_note",PAnote); + xml->addparreal("a_freq",PAfreq); + + if ((Penabled==0)&&(xml->minimal)) return; + + xml->beginbranch("SCALE"); + xml->addpar("scale_shift",Pscaleshift); + xml->addpar("first_key",Pfirstkey); + xml->addpar("last_key",Plastkey); + xml->addpar("middle_note",Pmiddlenote); + + xml->beginbranch("OCTAVE"); + xml->addpar("octave_size",octavesize); + for (int i=0;ibeginbranch("DEGREE",i); + if (octave[i].type==1) { + xml->addparreal("cents",octave[i].tuning); + }; + if (octave[i].type==2) { + xml->addpar("numerator",octave[i].x1); + xml->addpar("denominator",octave[i].x2); + }; + xml->endbranch(); + }; + xml->endbranch(); + + xml->beginbranch("KEYBOARD_MAPPING"); + xml->addpar("map_size",Pmapsize); + xml->addpar("mapping_enabled",Pmappingenabled); + for (int i=0;ibeginbranch("KEYMAP",i); + xml->addpar("degree",Pmapping[i]); + xml->endbranch(); + }; + + xml->endbranch(); + xml->endbranch(); +}; + +void Microtonal::getfromXML(XMLwrapper *xml) +{ + xml->getparstr("name",(char *) Pname,MICROTONAL_MAX_NAME_LEN); + xml->getparstr("comment",(char *) Pcomment,MICROTONAL_MAX_NAME_LEN); + + Pinvertupdown=xml->getparbool("invert_up_down",Pinvertupdown); + Pinvertupdowncenter=xml->getpar127("invert_up_down_center",Pinvertupdowncenter); + + Penabled=xml->getparbool("enabled",Penabled); + Pglobalfinedetune=xml->getpar127("global_fine_detune",Pglobalfinedetune); + + PAnote=xml->getpar127("a_note",PAnote); + PAfreq=xml->getparreal("a_freq",PAfreq,1.0,10000.0); + + if (xml->enterbranch("SCALE")) { + Pscaleshift=xml->getpar127("scale_shift",Pscaleshift); + Pfirstkey=xml->getpar127("first_key",Pfirstkey); + Plastkey=xml->getpar127("last_key",Plastkey); + Pmiddlenote=xml->getpar127("middle_note",Pmiddlenote); + + if (xml->enterbranch("OCTAVE")) { + octavesize=xml->getpar127("octave_size",octavesize); + for (int i=0;ienterbranch("DEGREE",i)==0) continue; + octave[i].x2=0; + octave[i].tuning=xml->getparreal("cents",octave[i].tuning); + octave[i].x1=xml->getpar127("numerator",octave[i].x1); + octave[i].x2=xml->getpar127("denominator",octave[i].x2); + + if (octave[i].x2!=0) octave[i].type=2; + else octave[i].type=1; + + xml->exitbranch(); + }; + xml->exitbranch(); + }; + + if (xml->enterbranch("KEYBOARD_MAPPING")) { + Pmapsize=xml->getpar127("map_size",Pmapsize); + Pmappingenabled=xml->getpar127("mapping_enabled",Pmappingenabled); + for (int i=0;ienterbranch("KEYMAP",i)==0) continue; + Pmapping[i]=xml->getpar127("degree",Pmapping[i]); + xml->exitbranch(); + }; + xml->exitbranch(); + }; + xml->exitbranch(); + }; +}; + + + +int Microtonal::saveXML(const char *filename)const +{ + XMLwrapper *xml=new XMLwrapper(); + + xml->beginbranch("MICROTONAL"); + add2XML(xml); + xml->endbranch(); + + int result=xml->saveXMLfile(filename); + delete (xml); + return(result); +}; + +int Microtonal::loadXML(const char *filename) +{ + XMLwrapper *xml=new XMLwrapper(); + if (xml->loadXMLfile(filename)<0) { + delete(xml); + return(-1); + }; + + if (xml->enterbranch("MICROTONAL")==0) return(-10); + getfromXML(xml); + xml->exitbranch(); + + delete(xml); + return(0); +}; + + diff --git a/plugins/zynaddsubfx/src/Misc/Microtonal.h b/plugins/zynaddsubfx/src/Misc/Microtonal.h index 8aff5fe26..99d73a24d 100644 --- a/plugins/zynaddsubfx/src/Misc/Microtonal.h +++ b/plugins/zynaddsubfx/src/Misc/Microtonal.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Microtonal.h - Tuning settings and microtonal capabilities Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -31,81 +31,107 @@ #include -class Microtonal{ - public: - Microtonal(); - ~Microtonal(); - void defaults(); - REALTYPE getnotefreq(int note,int keyshift); - - //Parameters - //if the keys are inversed (the pitch is lower to keys from the right direction) - unsigned char Pinvertupdown; +/**Tuning settings and microtonal capabilities*/ +class Microtonal +{ +public: + /**Constructor*/ + Microtonal(); + /**Destructor*/ + ~Microtonal(); + void defaults(); + /**Calculates the frequency for a given note + */ + REALTYPE getnotefreq(int note,int keyshift) const; - //the central key of the inversion - unsigned char Pinvertupdowncenter; - //0 for 12 key temperate scale, 1 for microtonal - unsigned char Penabled; + //Parameters + /**if the keys are inversed (the pitch is lower to keys from the right direction)*/ + unsigned char Pinvertupdown; - //the note of "A" key - unsigned char PAnote; + /**the central key of the inversion*/ + unsigned char Pinvertupdowncenter; - //the frequency of the "A" note - REALTYPE PAfreq; - - //if the scale is "tuned" to a note, you can tune to other note - unsigned char Pscaleshift; + /**0 for 12 key temperate scale, 1 for microtonal*/ + unsigned char Penabled; - //first and last key (to retune) - unsigned char Pfirstkey; - unsigned char Plastkey; - - //The middle note where scale degree 0 is mapped to - unsigned char Pmiddlenote; - - //Map size - unsigned char Pmapsize; + /**the note of "A" key*/ + unsigned char PAnote; - //Mapping ON/OFF - unsigned char Pmappingenabled; - //Mapping (keys) - short int Pmapping[128]; - - unsigned char Pglobalfinedetune; - - // Functions - unsigned char getoctavesize(); - void tuningtoline(int n,char *line,int maxn); - int loadscl(const char *filename);//load the tunnings from a .scl file - int loadkbm(const char *filename);//load the mapping from .kbm file - int texttotunings(const char *text); - void texttomapping(const char *text); - unsigned char *Pname; - unsigned char *Pcomment; + /**the frequency of the "A" note*/ + REALTYPE PAfreq; - void add2XML(XMLwrapper *xml); - void getfromXML(XMLwrapper *xml); - int saveXML(char *filename); - int loadXML(char *filename); + /**if the scale is "tuned" to a note, you can tune to other note*/ + unsigned char Pscaleshift; - private: - int linetotunings(unsigned int nline,const char *line); - int loadline(FILE *file,char *line);//loads a line from the text file, while ignoring the lines beggining with "!" - unsigned char octavesize; - struct { - unsigned char type;//1 for cents or 2 for division + //first and last key (to retune) + unsigned char Pfirstkey; + unsigned char Plastkey; + + /**The middle note where scale degree 0 is mapped to*/ + unsigned char Pmiddlenote; + + /**Map size*/ + unsigned char Pmapsize; + + /**Mapping ON/OFF*/ + unsigned char Pmappingenabled; + /**Mapping (keys)*/ + short int Pmapping[128]; + + /**Fine detune to be applied to all notes*/ + unsigned char Pglobalfinedetune; + + // Functions + /** Return the current octave size*/ + unsigned char getoctavesize() const; + /**Convert tunning to string*/ + void tuningtoline(int n,char *line,int maxn); + /**load the tunnings from a .scl file*/ + int loadscl(const char *filename); + /**load the mapping from .kbm file*/ + int loadkbm(const char *filename); + /**Load text into the internal tunings + * + *\todo better description*/ + int texttotunings(const char *text); + /**Load text into the internal mappings + * + *\todo better description*/ + void texttomapping(const char *text); + + /**Name of Microtonal tuning*/ + unsigned char *Pname; + /**Comment about the tuning*/ + unsigned char *Pcomment; + + void add2XML(XMLwrapper *xml)const; + void getfromXML(XMLwrapper *xml); + int saveXML(const char *filename)const; + int loadXML(const char *filename); + + //simple operators primarily for debug + bool operator==(const Microtonal µ) const; + bool operator!=(const Microtonal µ) const; + +private: + int linetotunings(unsigned int nline,const char *line); + int loadline(FILE *file,char *line);//loads a line from the text file, while ignoring the lines beggining with "!" + unsigned char octavesize; + struct { + unsigned char type;//1 for cents or 2 for division + + // the real tuning (eg. +1.05946 for one halftone) + // or 2.0 for one octave + REALTYPE tuning; + + //the real tunning is x1/x2 + unsigned int x1,x2; + + } octave[MAX_OCTAVE_SIZE],tmpoctave[MAX_OCTAVE_SIZE]; - // the real tuning (eg. +1.05946 for one halftone) - // or 2.0 for one octave - REALTYPE tuning; - - //the real tunning is x1/x2 - unsigned int x1,x2; - - } octave[MAX_OCTAVE_SIZE],tmpoctave[MAX_OCTAVE_SIZE]; - }; #endif + diff --git a/plugins/zynaddsubfx/src/Misc/Part.C b/plugins/zynaddsubfx/src/Misc/Part.C deleted file mode 100644 index d54cf6f61..000000000 --- a/plugins/zynaddsubfx/src/Misc/Part.C +++ /dev/null @@ -1,1077 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Part.C - Part implementation - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include "Part.h" -#include "Microtonal.h" -#include -#include -#include - -Part::Part(Microtonal *microtonal_,FFTwrapper *fft_, pthread_mutex_t *mutex_){ - microtonal=microtonal_; - fft=fft_; - mutex=mutex_; - partoutl=new REALTYPE [SOUND_BUFFER_SIZE]; - partoutr=new REALTYPE [SOUND_BUFFER_SIZE]; - tmpoutl=new REALTYPE [SOUND_BUFFER_SIZE]; - tmpoutr=new REALTYPE [SOUND_BUFFER_SIZE]; - - for (int n=0;ndefaults(); - kit[0].subpars->defaults(); - kit[0].padpars->defaults(); - - for (int nefx=0;nefxdefaults(); - Pefxroute[nefx]=0;//route to next effect - }; - -}; - - - -/* - * Cleanup the part - */ -void Part::cleanup(){ - for (int k=0;kcleanup(); - for (int n=0;nPmaxkey)) return; - - // MonoMem stuff: - if (Ppolymode==0){ // If Poly is off - monomemnotes.push_back(note); // Add note to the list. - monomem[note].velocity=velocity; // Store this note's velocity. - monomem[note].mkeyshift=masterkeyshift; /* Store masterkeyshift too, - I'm not sure why though... */ - if ((partnote[lastpos].status!=KEY_PLAYING) - && (partnote[lastpos].status!=KEY_RELASED_AND_SUSTAINED)){ - ismonofirstnote=true; // No other keys are held or sustained. - } - } else { - // Poly mode is On so just make sure the list is empty. - if (not monomemnotes.empty()) monomemnotes.clear(); - } - - lastnote=note; - - pos=-1; - for (i=0;i POLIPHONY) - (Part.C::NoteOn(..))\n"); - } else { - - //start the note - partnote[pos].status=KEY_PLAYING; - partnote[pos].note=note; - if (legatomodevalid){ - partnote[posb].status=KEY_PLAYING; - partnote[posb].note=note; - } - - //this computes the velocity sensing of the part - REALTYPE vel=VelF(velocity/127.0,Pvelsns); - - //compute the velocity offset - vel+=(Pveloffs-64.0)/64.0; - if (vel<0.0) vel=0.0; else if (vel>1.0) vel=1.0; - - //compute the keyshift - int partkeyshift=(int)Pkeyshift-64; - int keyshift=masterkeyshift+partkeyshift; - - //initialise note frequency - REALTYPE notebasefreq; - if (Pdrummode==0){ - notebasefreq=microtonal->getnotefreq(note,keyshift); - if (notebasefreq<0.0) return;//the key is no mapped - } else { - notebasefreq=440.0*pow(2.0,(note-69.0)/12.0); - }; - - //Portamento - if (oldfreq<1.0) oldfreq=notebasefreq;//this is only the first note is played - - // For Mono/Legato: Force Portamento Off on first - // notes. That means it is required that the previous note is - // still held down or sustained for the Portamento to activate - // (that's like Legato). - int portamento=0; - if ((Ppolymode!=0) || (not ismonofirstnote)){ - // I added a third argument to the - // ctl.initportamento(...) function to be able - // to tell it if we're doing a legato note. - portamento=ctl.initportamento(oldfreq,notebasefreq,doinglegato); - } - - if (portamento!=0) ctl.portamento.noteusing=pos; - oldfreq=notebasefreq; - - lastpos=pos; // Keep a trace of used pos. - - if (doinglegato){ - // Do Legato note - if (Pkitmode==0){ // "normal mode" legato note - if ((kit[0].Padenabled!=0) - && (partnote[pos].kititem[0].adnote!=NULL) - && (partnote[posb].kititem[0].adnote!=NULL)){ - partnote[pos].kititem[0].adnote->ADlegatonote(notebasefreq, vel, portamento, note, true);//'true' is to tell it it's being called from here. - partnote[posb].kititem[0].adnote->ADlegatonote(notebasefreq, vel, portamento, note, true); - } - - if ((kit[0].Psubenabled!=0) - && (partnote[pos].kititem[0].subnote!=NULL) - && (partnote[posb].kititem[0].subnote!=NULL)){ - partnote[pos].kititem[0].subnote->SUBlegatonote(notebasefreq, vel, portamento, note, true); - partnote[posb].kititem[0].subnote->SUBlegatonote(notebasefreq, vel, portamento, note, true); - } - - if ((kit[0].Ppadenabled!=0) - && (partnote[pos].kititem[0].padnote!=NULL) - && (partnote[posb].kititem[0].padnote!=NULL)){ - partnote[pos].kititem[0].padnote->PADlegatonote(notebasefreq, vel, portamento, note, true); - partnote[posb].kititem[0].padnote->PADlegatonote(notebasefreq, vel, portamento, note, true); - } - - } else { // "kit mode" legato note - int ci=0; - for (int item=0;itemkit[item].Pmaxkey)) continue; - - if ((lastnotecopykit[item].Pmaxkey)) - continue; // We will not perform legato across 2 key regions. - - partnote[pos].kititem[ci].sendtoparteffect=( kit[item].PsendtoparteffectADlegatonote(notebasefreq,vel,portamento,note,true); - partnote[posb].kititem[ci].adnote->ADlegatonote(notebasefreq,vel,portamento,note,true); - } - if ((kit[item].Psubenabled!=0) && (kit[item].subpars!=NULL) - && (partnote[pos].kititem[ci].subnote!=NULL) - && (partnote[posb].kititem[ci].subnote!=NULL)){ - partnote[pos].kititem[ci].subnote->SUBlegatonote(notebasefreq,vel,portamento,note,true); - partnote[posb].kititem[ci].subnote->SUBlegatonote(notebasefreq,vel,portamento,note,true); - } - if ((kit[item].Ppadenabled!=0) && (kit[item].padpars!=NULL) - && (partnote[pos].kititem[ci].padnote!=NULL) - && (partnote[posb].kititem[ci].padnote!=NULL)){ - partnote[pos].kititem[ci].padnote->PADlegatonote(notebasefreq,vel,portamento,note,true); - partnote[posb].kititem[ci].padnote->PADlegatonote(notebasefreq,vel,portamento,note,true); - } - - if ((kit[item].adpars!=NULL)||(kit[item].subpars!=NULL)||(kit[item].padpars!=NULL)) { - ci++; - if ( ((kit[item].Padenabled!=0)||(kit[item].Psubenabled!=0)||(kit[item].Ppadenabled!=0)) && (Pkitmode==2) ) break; - } - } - if (ci==0){ - // No legato were performed at all, so pretend nothing happened: - monomemnotes.pop_back(); // Remove last note from the list. - lastnote=lastnotecopy; // Set lastnote back to previous value. - } - } - return; // Ok, Legato note done, return. - } - - partnote[pos].itemsplaying=0; - if (legatomodevalid) partnote[posb].itemsplaying=0; - - if (Pkitmode==0){//init the notes for the "normal mode" - partnote[pos].kititem[0].sendtoparteffect=0; - if (kit[0].Padenabled!=0) partnote[pos].kititem[0].adnote=new ADnote(kit[0].adpars,&ctl,notebasefreq,vel,portamento,note,false); - if (kit[0].Psubenabled!=0) partnote[pos].kititem[0].subnote=new SUBnote(kit[0].subpars,&ctl,notebasefreq,vel,portamento,note,false); - if (kit[0].Ppadenabled!=0) partnote[pos].kititem[0].padnote=new PADnote(kit[0].padpars,&ctl,notebasefreq,vel,portamento,note,false); - if ((kit[0].Padenabled!=0)||(kit[0].Psubenabled!=0)||(kit[0].Ppadenabled!=0)) partnote[pos].itemsplaying++; - - // Spawn another note (but silent) if legatomodevalid==true - if (legatomodevalid){ - partnote[posb].kititem[0].sendtoparteffect=0; - if (kit[0].Padenabled!=0) partnote[posb].kititem[0].adnote=new ADnote(kit[0].adpars,&ctl,notebasefreq,vel,portamento,note,true);//true for silent. - if (kit[0].Psubenabled!=0) partnote[posb].kititem[0].subnote=new SUBnote(kit[0].subpars,&ctl,notebasefreq,vel,portamento,note,true); - if (kit[0].Ppadenabled!=0) partnote[posb].kititem[0].padnote=new PADnote(kit[0].padpars,&ctl,notebasefreq,vel,portamento,note,true); - if ((kit[0].Padenabled!=0)||(kit[0].Psubenabled!=0)||(kit[0].Ppadenabled!=0)) partnote[posb].itemsplaying++; - } - - } else {//init the notes for the "kit mode" - for (int item=0;itemkit[item].Pmaxkey)) continue; - - int ci=partnote[pos].itemsplaying;//ci=current item - - partnote[pos].kititem[ci].sendtoparteffect=( kit[item].Psendtoparteffect=0;i--){ //first note in, is first out if there are same note multiple times - if ((partnote[i].status==KEY_PLAYING)&&(partnote[i].note==note)) { - if (ctl.sustain.sustain==0){ //the sustain pedal is not pushed - if ((Ppolymode==0) && (not monomemnotes.empty())){ - MonoMemRenote(); // To play most recent still held note. - } else { - RelaseNotePos(i); - /// break; - } - } else {//the sustain pedal is pushed - partnote[i].status=KEY_RELASED_AND_SUSTAINED; - } - } - } -}; - -/* - * Controllers - */ -void Part::SetController(unsigned int type,int par){ - switch (type){ - case C_pitchwheel:ctl.setpitchwheel(par); - break; - case C_expression:ctl.setexpression(par); - setPvolume(Pvolume);//update the volume - break; - case C_portamento:ctl.setportamento(par); - break; - case C_panning:ctl.setpanning(par); - setPpanning(Ppanning);//update the panning - break; - case C_filtercutoff:ctl.setfiltercutoff(par); - break; - case C_filterq:ctl.setfilterq(par); - break; - case C_bandwidth:ctl.setbandwidth(par); - break; - case C_modwheel:ctl.setmodwheel(par); - break; - case C_fmamp:ctl.setfmamp(par); - break; - case C_volume:ctl.setvolume(par); - if (ctl.volume.receive!=0) volume=ctl.volume.volume; - else setPvolume(Pvolume); - break; - case C_sustain:ctl.setsustain(par); - if (ctl.sustain.sustain==0) RelaseSustainedKeys(); - break; - case C_allsoundsoff:AllNotesOff();//Panic - break; - case C_resetallcontrollers: - ctl.resetall(); - RelaseSustainedKeys(); - if (ctl.volume.receive!=0) volume=ctl.volume.volume; - else setPvolume(Pvolume); - setPvolume(Pvolume);//update the volume - setPpanning(Ppanning);//update the panning - - for (int item=0;itemGlobalPar.Reson-> - sendcontroller(C_resonance_center,1.0); - - kit[item].adpars->GlobalPar.Reson-> - sendcontroller(C_resonance_bandwidth,1.0); - }; - //more update to add here if I add controllers - break; - case C_allnotesoff:RelaseAllKeys(); - break; - case C_resonance_center: - ctl.setresonancecenter(par); - for (int item=0;itemGlobalPar.Reson-> - sendcontroller(C_resonance_center,ctl.resonancecenter.relcenter); - }; - break; - case C_resonance_bandwidth: - ctl.setresonancebw(par); - kit[0].adpars->GlobalPar.Reson-> - sendcontroller(C_resonance_bandwidth,ctl.resonancebandwidth.relbw); - break; - }; -}; -/* - * Relase the sustained keys - */ - -void Part::RelaseSustainedKeys(){ - // Let's call MonoMemRenote() on some conditions: - if ((Ppolymode==0) && (not monomemnotes.empty())) - if (monomemnotes.back()!=lastnote) // Sustain controller manipulation would cause repeated same note respawn without this check. - MonoMemRenote(); // To play most recent still held note. - - for (int i=0;irelasekey(); - - if (partnote[pos].kititem[j].subnote!=NULL) - if (partnote[pos].kititem[j].subnote!=NULL) - partnote[pos].kititem[j].subnote->relasekey(); - - if (partnote[pos].kititem[j].padnote!=NULL) - if (partnote[pos].kititem[j].padnote) - partnote[pos].kititem[j].padnote->relasekey(); - }; - partnote[pos].status=KEY_RELASED; -}; - - -/* - * Kill note at position - */ -void Part::KillNotePos(int pos){ - partnote[pos].status=KEY_OFF; - partnote[pos].note=-1; - partnote[pos].time=0; - partnote[pos].itemsplaying=0; - - for (int j=0;jPkeylimit=Pkeylimit; - int keylimit=Pkeylimit; - if (keylimit==0) keylimit=POLIPHONY-5; - - //release old keys if the number of notes>keylimit - if (Ppolymode!=0){ - int notecount=0; - for (int i=0;ikeylimit){//find out the oldest note - for (int i=0;imaxtime)){ - maxtime=partnote[i].time; - oldestnotepos=i; - }; - }; - }; - if (oldestnotepos!=-1) RelaseNotePos(oldestnotepos); - }; -}; - - -/* - * Prepare all notes to be turned off - */ -void Part::AllNotesOff(){ - killallnotes=1; -}; - - -/* - * Compute Part samples and store them in the partoutl[] and partoutr[] - */ -void Part::ComputePartSmps(){ - int i,k; - int noteplay;//0 if there is nothing activated - for (int nefx=0;nefxready!=0) adnote->noteout(&tmpoutl[0],&tmpoutr[0]); - else for (i=0;ifinished()!=0){ - delete (adnote); - partnote[k].kititem[item].adnote=NULL; - }; - for (i=0;iready!=0) subnote->noteout(&tmpoutl[0],&tmpoutr[0]); - else for (i=0;ifinished()!=0){ - delete (subnote); - partnote[k].kititem[item].subnote=NULL; - }; - }; - //get from the PADnote - if (padnote!=NULL) { - noteplay++; - if (padnote->ready!=0) padnote->noteout(&tmpoutl[0],&tmpoutr[0]); - else for (i=0;ifinished()!=0){ - delete (padnote); - partnote[k].kititem[item].padnote=NULL; - }; - for (i=0;iout(partfxinputl[nefx],partfxinputr[nefx]); - if (Pefxroute[nefx]==2){ - for (i=0;iefxoutl[i]; - partfxinputr[nefx+1][i]+=partefx[nefx]->efxoutr[i]; - }; - }; - }; - int routeto=((Pefxroute[nefx]==0) ? nefx+1 : NUM_PART_EFX); - for (i=0;icleanup(); - }; - }; - ctl.updateportamento(); -}; - -/* - * Parameter control - */ -void Part::setPvolume(char Pvolume_){ - Pvolume=Pvolume_; - volume=dB2rap((Pvolume-96.0)/96.0*40.0)*ctl.expression.relvolume; -}; - -void Part::setPpanning(char Ppanning_){ - Ppanning=Ppanning_; - panning=Ppanning/127.0+ctl.panning.pan; - if (panning<0.0) panning=0.0;else if (panning>1.0) panning=1.0; - -}; - -/* - * Enable or disable a kit item - */ -void Part::setkititemstatus(int kititem,int Penabled_){ - if ((kititem==0)&&(kititem>=NUM_KIT_ITEMS)) return;//nonexistent kit item and the first kit item is always enabled - kit[kititem].Penabled=Penabled_; - - bool resetallnotes=false; - if (Penabled_==0){ - if (kit[kititem].adpars!=NULL) delete (kit[kititem].adpars); - if (kit[kititem].subpars!=NULL) delete (kit[kititem].subpars); - if (kit[kititem].padpars!=NULL) { - delete (kit[kititem].padpars); - resetallnotes=true; - }; - kit[kititem].adpars=NULL;kit[kititem].subpars=NULL;kit[kititem].padpars=NULL; - kit[kititem].Pname[0]='\0'; - } else { - if (kit[kititem].adpars==NULL) kit[kititem].adpars=new ADnoteParameters(fft); - if (kit[kititem].subpars==NULL) kit[kititem].subpars=new SUBnoteParameters(); - if (kit[kititem].padpars==NULL) kit[kititem].padpars=new PADnoteParameters(fft,mutex); - }; - - if (resetallnotes) for (int k=0;kbeginbranch("INFO"); - xml->addparstr("name",(char *)Pname); - xml->addparstr("author",(char *)info.Pauthor); - xml->addparstr("comments",(char *)info.Pcomments); - xml->addpar("type",info.Ptype); - xml->endbranch(); - - - xml->beginbranch("INSTRUMENT_KIT"); - xml->addpar("kit_mode",Pkitmode); - xml->addparbool("drum_mode",Pdrummode); - - for (int i=0;ibeginbranch("INSTRUMENT_KIT_ITEM",i); - xml->addparbool("enabled",kit[i].Penabled); - if (kit[i].Penabled!=0) { - xml->addparstr("name",(char *)kit[i].Pname); - - xml->addparbool("muted",kit[i].Pmuted); - xml->addpar("min_key",kit[i].Pminkey); - xml->addpar("max_key",kit[i].Pmaxkey); - - xml->addpar("send_to_instrument_effect",kit[i].Psendtoparteffect); - - xml->addparbool("add_enabled",kit[i].Padenabled); - if ((kit[i].Padenabled!=0)&&(kit[i].adpars!=NULL)){ - xml->beginbranch("ADD_SYNTH_PARAMETERS"); - kit[i].adpars->add2XML(xml); - xml->endbranch(); - }; - - xml->addparbool("sub_enabled",kit[i].Psubenabled); - if ((kit[i].Psubenabled!=0)&&(kit[i].subpars!=NULL)){ - xml->beginbranch("SUB_SYNTH_PARAMETERS"); - kit[i].subpars->add2XML(xml); - xml->endbranch(); - }; - - xml->addparbool("pad_enabled",kit[i].Ppadenabled); - if ((kit[i].Ppadenabled!=0)&&(kit[i].padpars!=NULL)){ - xml->beginbranch("PAD_SYNTH_PARAMETERS"); - kit[i].padpars->add2XML(xml); - xml->endbranch(); - }; - - }; - xml->endbranch(); - }; - xml->endbranch(); - - xml->beginbranch("INSTRUMENT_EFFECTS"); - for (int nefx=0;nefxbeginbranch("INSTRUMENT_EFFECT",nefx); - xml->beginbranch("EFFECT"); - partefx[nefx]->add2XML(xml); - xml->endbranch(); - - xml->addpar("route",Pefxroute[nefx]); - partefx[nefx]->setdryonly(Pefxroute[nefx]==2); - xml->addparbool("bypass",Pefxbypass[nefx]); - xml->endbranch(); - }; - xml->endbranch(); -}; - - -void Part::add2XML(XMLwrapper *xml){ - //parameters - xml->addparbool("enabled",Penabled); - if ((Penabled==0)&&(xml->minimal)) return; - - xml->addpar("volume",Pvolume); - xml->addpar("panning",Ppanning); - - xml->addpar("min_key",Pminkey); - xml->addpar("max_key",Pmaxkey); - xml->addpar("key_shift",Pkeyshift); - xml->addpar("rcv_chn",Prcvchn); - - xml->addpar("velocity_sensing",Pvelsns); - xml->addpar("velocity_offset",Pveloffs); - - xml->addparbool("note_on",Pnoteon); - xml->addparbool("poly_mode",Ppolymode); - xml->addpar("legato_mode",Plegatomode); - xml->addpar("key_limit",Pkeylimit); - - xml->beginbranch("INSTRUMENT"); - add2XMLinstrument(xml); - xml->endbranch(); - - xml->beginbranch("CONTROLLER"); - ctl.add2XML(xml); - xml->endbranch(); -}; - -int Part::saveXML(char *filename){ - XMLwrapper *xml; - xml=new XMLwrapper(); - - xml->beginbranch("INSTRUMENT"); - add2XMLinstrument(xml); - xml->endbranch(); - - int result=xml->saveXMLfile(filename); - delete (xml); - return(result); -}; - -int Part::loadXMLinstrument(const char *filename){ - XMLwrapper *xml=new XMLwrapper(); - if (xml->loadXMLfile(filename)<0) { - delete(xml); - return(-1); - }; - - if (xml->enterbranch("INSTRUMENT")==0) return(-10); - getfromXMLinstrument(xml); - xml->exitbranch(); - - delete(xml); - return(0); -}; - - -void Part::applyparameters(){ - for (int n=0;napplyparameters(true); - }; -}; - -void Part::getfromXMLinstrument(XMLwrapper *xml){ - if (xml->enterbranch("INFO")){ - xml->getparstr("name",(char *)Pname,PART_MAX_NAME_LEN); - xml->getparstr("author",(char *)info.Pauthor,MAX_INFO_TEXT_SIZE); - xml->getparstr("comments",(char *)info.Pcomments,MAX_INFO_TEXT_SIZE); - info.Ptype=xml->getpar("type",info.Ptype,0,16); - - xml->exitbranch(); - }; - - if (xml->enterbranch("INSTRUMENT_KIT")){ - Pkitmode=xml->getpar127("kit_mode",Pkitmode); - Pdrummode=xml->getparbool("drum_mode",Pdrummode); - - setkititemstatus(0,0); - for (int i=0;ienterbranch("INSTRUMENT_KIT_ITEM",i)==0) continue; - setkititemstatus(i,xml->getparbool("enabled",kit[i].Penabled)); - if (kit[i].Penabled==0) { - xml->exitbranch(); - continue; - }; - - xml->getparstr("name",(char *)kit[i].Pname,PART_MAX_NAME_LEN); - - kit[i].Pmuted=xml->getparbool("muted",kit[i].Pmuted); - kit[i].Pminkey=xml->getpar127("min_key",kit[i].Pminkey); - kit[i].Pmaxkey=xml->getpar127("max_key",kit[i].Pmaxkey); - - kit[i].Psendtoparteffect=xml->getpar127("send_to_instrument_effect",kit[i].Psendtoparteffect); - - kit[i].Padenabled=xml->getparbool("add_enabled",kit[i].Padenabled); - if (xml->enterbranch("ADD_SYNTH_PARAMETERS")){ - kit[i].adpars->getfromXML(xml); - xml->exitbranch(); - }; - - kit[i].Psubenabled=xml->getparbool("sub_enabled",kit[i].Psubenabled); - if (xml->enterbranch("SUB_SYNTH_PARAMETERS")){ - kit[i].subpars->getfromXML(xml); - xml->exitbranch(); - }; - - kit[i].Ppadenabled=xml->getparbool("pad_enabled",kit[i].Ppadenabled); - if (xml->enterbranch("PAD_SYNTH_PARAMETERS")){ - kit[i].padpars->getfromXML(xml); - xml->exitbranch(); - }; - - xml->exitbranch(); - }; - - xml->exitbranch(); - }; - - - if (xml->enterbranch("INSTRUMENT_EFFECTS")){ - for (int nefx=0;nefxenterbranch("INSTRUMENT_EFFECT",nefx)==0) continue; - if (xml->enterbranch("EFFECT")){ - partefx[nefx]->getfromXML(xml); - xml->exitbranch(); - }; - - Pefxroute[nefx]=xml->getpar("route",Pefxroute[nefx],0,NUM_PART_EFX); - partefx[nefx]->setdryonly(Pefxroute[nefx]==2); - Pefxbypass[nefx]=xml->getparbool("bypass",Pefxbypass[nefx]); - xml->exitbranch(); - }; - xml->exitbranch(); - }; - -}; - -void Part::getfromXML(XMLwrapper *xml){ - Penabled=xml->getparbool("enabled",Penabled); - - setPvolume(xml->getpar127("volume",Pvolume)); - setPpanning(xml->getpar127("panning",Ppanning)); - - Pminkey=xml->getpar127("min_key",Pminkey); - Pmaxkey=xml->getpar127("max_key",Pmaxkey); - Pkeyshift=xml->getpar127("key_shift",Pkeyshift); - Prcvchn=xml->getpar127("rcv_chn",Prcvchn); - - Pvelsns=xml->getpar127("velocity_sensing",Pvelsns); - Pveloffs=xml->getpar127("velocity_offset",Pveloffs); - - Pnoteon=xml->getparbool("note_on",Pnoteon); - Ppolymode=xml->getparbool("poly_mode",Ppolymode); - Plegatomode=xml->getparbool("legato_mode",Plegatomode);//older versions - if (!Plegatomode) Plegatomode=xml->getpar127("legato_mode",Plegatomode); - Pkeylimit=xml->getpar127("key_limit",Pkeylimit); - - - if (xml->enterbranch("INSTRUMENT")){ - getfromXMLinstrument(xml); - xml->exitbranch(); - }; - - if (xml->enterbranch("CONTROLLER")){ - ctl.getfromXML(xml); - xml->exitbranch(); - }; - -}; - - - diff --git a/plugins/zynaddsubfx/src/Misc/Part.cpp b/plugins/zynaddsubfx/src/Misc/Part.cpp new file mode 100644 index 000000000..2adf152d7 --- /dev/null +++ b/plugins/zynaddsubfx/src/Misc/Part.cpp @@ -0,0 +1,1138 @@ +/* + ZynAddSubFX - a software synthesizer + + Part.C - Part implementation + Copyright (C) 2002-2005 Nasca Octavian Paul + Author: Nasca Octavian Paul + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "Part.h" +#include "Microtonal.h" +#include +#include +#include + +Part::Part(Microtonal *microtonal_,FFTwrapper *fft_, pthread_mutex_t *mutex_) +{ + microtonal=microtonal_; + fft=fft_; + mutex=mutex_; + partoutl=new REALTYPE [SOUND_BUFFER_SIZE]; + partoutr=new REALTYPE [SOUND_BUFFER_SIZE]; + tmpoutl=new REALTYPE [SOUND_BUFFER_SIZE]; + tmpoutr=new REALTYPE [SOUND_BUFFER_SIZE]; + + for (int n=0;ndefaults(); + kit[0].subpars->defaults(); + kit[0].padpars->defaults(); + + for (int nefx=0;nefxdefaults(); + Pefxroute[nefx]=0;//route to next effect + }; + +}; + + + +/* + * Cleanup the part + */ +void Part::cleanup() +{ + for (int k=0;kcleanup(); + for (int n=0;nPmaxkey)) return; + + // MonoMem stuff: + if (Ppolymode==0) { // If Poly is off + monomemnotes.push_back(note); // Add note to the list. + monomem[note].velocity=velocity; // Store this note's velocity. + monomem[note].mkeyshift=masterkeyshift; /* Store masterkeyshift too, + I'm not sure why though... */ + if ((partnote[lastpos].status!=KEY_PLAYING) + && (partnote[lastpos].status!=KEY_RELASED_AND_SUSTAINED)) { + ismonofirstnote=true; // No other keys are held or sustained. + } + } else { + // Poly mode is On so just make sure the list is empty. + if (not monomemnotes.empty()) monomemnotes.clear(); + } + + lastnote=note; + + pos=-1; + for (i=0;i POLIPHONY) - (Part.C::NoteOn(..))\n"); + } else { + + //start the note + partnote[pos].status=KEY_PLAYING; + partnote[pos].note=note; + if (legatomodevalid) { + partnote[posb].status=KEY_PLAYING; + partnote[posb].note=note; + } + + //this computes the velocity sensing of the part + REALTYPE vel=VelF(velocity/127.0,Pvelsns); + + //compute the velocity offset + vel+=(Pveloffs-64.0)/64.0; + if (vel<0.0) vel=0.0; + else if (vel>1.0) vel=1.0; + + //compute the keyshift + int partkeyshift=(int)Pkeyshift-64; + int keyshift=masterkeyshift+partkeyshift; + + //initialise note frequency + REALTYPE notebasefreq; + if (Pdrummode==0) { + notebasefreq=microtonal->getnotefreq(note,keyshift); + if (notebasefreq<0.0) return;//the key is no mapped + } else { + notebasefreq=440.0*pow(2.0,(note-69.0)/12.0); + }; + + //Portamento + if (oldfreq<1.0) oldfreq=notebasefreq;//this is only the first note is played + + // For Mono/Legato: Force Portamento Off on first + // notes. That means it is required that the previous note is + // still held down or sustained for the Portamento to activate + // (that's like Legato). + int portamento=0; + if ((Ppolymode!=0) || (not ismonofirstnote)) { + // I added a third argument to the + // ctl.initportamento(...) function to be able + // to tell it if we're doing a legato note. + portamento=ctl.initportamento(oldfreq,notebasefreq,doinglegato); + } + + if (portamento!=0) ctl.portamento.noteusing=pos; + oldfreq=notebasefreq; + + lastpos=pos; // Keep a trace of used pos. + + if (doinglegato) { + // Do Legato note + if (Pkitmode==0) { // "normal mode" legato note + if ((kit[0].Padenabled!=0) + && (partnote[pos].kititem[0].adnote!=NULL) + && (partnote[posb].kititem[0].adnote!=NULL)) { + partnote[pos].kititem[0].adnote->ADlegatonote(notebasefreq, vel, portamento, note, true);//'true' is to tell it it's being called from here. + partnote[posb].kititem[0].adnote->ADlegatonote(notebasefreq, vel, portamento, note, true); + } + + if ((kit[0].Psubenabled!=0) + && (partnote[pos].kititem[0].subnote!=NULL) + && (partnote[posb].kititem[0].subnote!=NULL)) { + partnote[pos].kititem[0].subnote->SUBlegatonote(notebasefreq, vel, portamento, note, true); + partnote[posb].kititem[0].subnote->SUBlegatonote(notebasefreq, vel, portamento, note, true); + } + + if ((kit[0].Ppadenabled!=0) + && (partnote[pos].kititem[0].padnote!=NULL) + && (partnote[posb].kititem[0].padnote!=NULL)) { + partnote[pos].kititem[0].padnote->PADlegatonote(notebasefreq, vel, portamento, note, true); + partnote[posb].kititem[0].padnote->PADlegatonote(notebasefreq, vel, portamento, note, true); + } + + } else { // "kit mode" legato note + int ci=0; + for (int item=0;itemkit[item].Pmaxkey)) continue; + + if ((lastnotecopykit[item].Pmaxkey)) + continue; // We will not perform legato across 2 key regions. + + partnote[pos].kititem[ci].sendtoparteffect=( kit[item].PsendtoparteffectADlegatonote(notebasefreq,vel,portamento,note,true); + partnote[posb].kititem[ci].adnote->ADlegatonote(notebasefreq,vel,portamento,note,true); + } + if ((kit[item].Psubenabled!=0) && (kit[item].subpars!=NULL) + && (partnote[pos].kititem[ci].subnote!=NULL) + && (partnote[posb].kititem[ci].subnote!=NULL)) { + partnote[pos].kititem[ci].subnote->SUBlegatonote(notebasefreq,vel,portamento,note,true); + partnote[posb].kititem[ci].subnote->SUBlegatonote(notebasefreq,vel,portamento,note,true); + } + if ((kit[item].Ppadenabled!=0) && (kit[item].padpars!=NULL) + && (partnote[pos].kititem[ci].padnote!=NULL) + && (partnote[posb].kititem[ci].padnote!=NULL)) { + partnote[pos].kititem[ci].padnote->PADlegatonote(notebasefreq,vel,portamento,note,true); + partnote[posb].kititem[ci].padnote->PADlegatonote(notebasefreq,vel,portamento,note,true); + } + + if ((kit[item].adpars!=NULL)||(kit[item].subpars!=NULL)||(kit[item].padpars!=NULL)) { + ci++; + if ( ((kit[item].Padenabled!=0)||(kit[item].Psubenabled!=0)||(kit[item].Ppadenabled!=0)) && (Pkitmode==2) ) break; + } + } + if (ci==0) { + // No legato were performed at all, so pretend nothing happened: + monomemnotes.pop_back(); // Remove last note from the list. + lastnote=lastnotecopy; // Set lastnote back to previous value. + } + } + return; // Ok, Legato note done, return. + } + + partnote[pos].itemsplaying=0; + if (legatomodevalid) partnote[posb].itemsplaying=0; + + if (Pkitmode==0) {//init the notes for the "normal mode" + partnote[pos].kititem[0].sendtoparteffect=0; + if (kit[0].Padenabled!=0) partnote[pos].kititem[0].adnote=new ADnote(kit[0].adpars,&ctl,notebasefreq,vel,portamento,note,false); + if (kit[0].Psubenabled!=0) partnote[pos].kititem[0].subnote=new SUBnote(kit[0].subpars,&ctl,notebasefreq,vel,portamento,note,false); + if (kit[0].Ppadenabled!=0) partnote[pos].kititem[0].padnote=new PADnote(kit[0].padpars,&ctl,notebasefreq,vel,portamento,note,false); + if ((kit[0].Padenabled!=0)||(kit[0].Psubenabled!=0)||(kit[0].Ppadenabled!=0)) partnote[pos].itemsplaying++; + + // Spawn another note (but silent) if legatomodevalid==true + if (legatomodevalid) { + partnote[posb].kititem[0].sendtoparteffect=0; + if (kit[0].Padenabled!=0) partnote[posb].kititem[0].adnote=new ADnote(kit[0].adpars,&ctl,notebasefreq,vel,portamento,note,true);//true for silent. + if (kit[0].Psubenabled!=0) partnote[posb].kititem[0].subnote=new SUBnote(kit[0].subpars,&ctl,notebasefreq,vel,portamento,note,true); + if (kit[0].Ppadenabled!=0) partnote[posb].kititem[0].padnote=new PADnote(kit[0].padpars,&ctl,notebasefreq,vel,portamento,note,true); + if ((kit[0].Padenabled!=0)||(kit[0].Psubenabled!=0)||(kit[0].Ppadenabled!=0)) partnote[posb].itemsplaying++; + } + + } else {//init the notes for the "kit mode" + for (int item=0;itemkit[item].Pmaxkey)) continue; + + int ci=partnote[pos].itemsplaying;//ci=current item + + partnote[pos].kititem[ci].sendtoparteffect=( kit[item].Psendtoparteffect=0;i--) { //first note in, is first out if there are same note multiple times + if ((partnote[i].status==KEY_PLAYING)&&(partnote[i].note==note)) { + if (ctl.sustain.sustain==0) { //the sustain pedal is not pushed + if ((Ppolymode==0) && (not monomemnotes.empty())) { + MonoMemRenote(); // To play most recent still held note. + } else { + RelaseNotePos(i); + /// break; + } + } else {//the sustain pedal is pushed + partnote[i].status=KEY_RELASED_AND_SUSTAINED; + } + } + } +}; + +/* + * Controllers + */ +void Part::SetController(unsigned int type,int par) +{ + switch (type) { + case C_pitchwheel: + ctl.setpitchwheel(par); + break; + case C_expression: + ctl.setexpression(par); + setPvolume(Pvolume);//update the volume + break; + case C_portamento: + ctl.setportamento(par); + break; + case C_panning: + ctl.setpanning(par); + setPpanning(Ppanning);//update the panning + break; + case C_filtercutoff: + ctl.setfiltercutoff(par); + break; + case C_filterq: + ctl.setfilterq(par); + break; + case C_bandwidth: + ctl.setbandwidth(par); + break; + case C_modwheel: + ctl.setmodwheel(par); + break; + case C_fmamp: + ctl.setfmamp(par); + break; + case C_volume: + ctl.setvolume(par); + if (ctl.volume.receive!=0) volume=ctl.volume.volume; + else setPvolume(Pvolume); + break; + case C_sustain: + ctl.setsustain(par); + if (ctl.sustain.sustain==0) RelaseSustainedKeys(); + break; + case C_allsoundsoff: + AllNotesOff();//Panic + break; + case C_resetallcontrollers: + ctl.resetall(); + RelaseSustainedKeys(); + if (ctl.volume.receive!=0) volume=ctl.volume.volume; + else setPvolume(Pvolume); + setPvolume(Pvolume);//update the volume + setPpanning(Ppanning);//update the panning + + for (int item=0;itemGlobalPar.Reson-> + sendcontroller(C_resonance_center,1.0); + + kit[item].adpars->GlobalPar.Reson-> + sendcontroller(C_resonance_bandwidth,1.0); + }; + //more update to add here if I add controllers + break; + case C_allnotesoff: + RelaseAllKeys(); + break; + case C_resonance_center: + ctl.setresonancecenter(par); + for (int item=0;itemGlobalPar.Reson-> + sendcontroller(C_resonance_center,ctl.resonancecenter.relcenter); + }; + break; + case C_resonance_bandwidth: + ctl.setresonancebw(par); + kit[0].adpars->GlobalPar.Reson-> + sendcontroller(C_resonance_bandwidth,ctl.resonancebandwidth.relbw); + break; + }; +}; +/* + * Relase the sustained keys + */ + +void Part::RelaseSustainedKeys() +{ + // Let's call MonoMemRenote() on some conditions: + if ((Ppolymode==0) && (not monomemnotes.empty())) + if (monomemnotes.back()!=lastnote) // Sustain controller manipulation would cause repeated same note respawn without this check. + MonoMemRenote(); // To play most recent still held note. + + for (int i=0;irelasekey(); + + if (partnote[pos].kititem[j].subnote!=NULL) + if (partnote[pos].kititem[j].subnote!=NULL) + partnote[pos].kititem[j].subnote->relasekey(); + + if (partnote[pos].kititem[j].padnote!=NULL) + if (partnote[pos].kititem[j].padnote) + partnote[pos].kititem[j].padnote->relasekey(); + }; + partnote[pos].status=KEY_RELASED; +}; + + +/* + * Kill note at position + */ +void Part::KillNotePos(int pos) +{ + partnote[pos].status=KEY_OFF; + partnote[pos].note=-1; + partnote[pos].time=0; + partnote[pos].itemsplaying=0; + + for (int j=0;jPkeylimit=Pkeylimit; + int keylimit=Pkeylimit; + if (keylimit==0) keylimit=POLIPHONY-5; + + //release old keys if the number of notes>keylimit + if (Ppolymode!=0) { + int notecount=0; + for (int i=0;ikeylimit) {//find out the oldest note + for (int i=0;imaxtime)) { + maxtime=partnote[i].time; + oldestnotepos=i; + }; + }; + }; + if (oldestnotepos!=-1) RelaseNotePos(oldestnotepos); + }; +}; + + +/* + * Prepare all notes to be turned off + */ +void Part::AllNotesOff() +{ + killallnotes=1; +}; + + +/* + * Compute Part samples and store them in the partoutl[] and partoutr[] + */ +void Part::ComputePartSmps() +{ + int i,k; + int noteplay;//0 if there is nothing activated + for (int nefx=0;nefxready!=0) adnote->noteout(&tmpoutl[0],&tmpoutr[0]); + else for (i=0;ifinished()!=0) { + delete (adnote); + partnote[k].kititem[item].adnote=NULL; + }; + for (i=0;iready!=0) subnote->noteout(&tmpoutl[0],&tmpoutr[0]); + else for (i=0;ifinished()!=0) { + delete (subnote); + partnote[k].kititem[item].subnote=NULL; + }; + }; + //get from the PADnote + if (padnote!=NULL) { + noteplay++; + if (padnote->ready!=0) padnote->noteout(&tmpoutl[0],&tmpoutr[0]); + else for (i=0;ifinished()!=0) { + delete (padnote); + partnote[k].kititem[item].padnote=NULL; + }; + for (i=0;iout(partfxinputl[nefx],partfxinputr[nefx]); + if (Pefxroute[nefx]==2) { + for (i=0;iefxoutl[i]; + partfxinputr[nefx+1][i]+=partefx[nefx]->efxoutr[i]; + }; + }; + }; + int routeto=((Pefxroute[nefx]==0) ? nefx+1 : NUM_PART_EFX); + for (i=0;icleanup(); + }; + }; + ctl.updateportamento(); +}; + +/* + * Parameter control + */ +void Part::setPvolume(char Pvolume_) +{ + Pvolume=Pvolume_; + volume=dB2rap((Pvolume-96.0)/96.0*40.0)*ctl.expression.relvolume; +}; + +void Part::setPpanning(char Ppanning_) +{ + Ppanning=Ppanning_; + panning=Ppanning/127.0+ctl.panning.pan; + if (panning<0.0) panning=0.0; + else if (panning>1.0) panning=1.0; + +}; + +/* + * Enable or disable a kit item + */ +void Part::setkititemstatus(int kititem,int Penabled_) +{ + if ((kititem==0)&&(kititem>=NUM_KIT_ITEMS)) return;//nonexistent kit item and the first kit item is always enabled + kit[kititem].Penabled=Penabled_; + + bool resetallnotes=false; + if (Penabled_==0) { + if (kit[kititem].adpars!=NULL) delete (kit[kititem].adpars); + if (kit[kititem].subpars!=NULL) delete (kit[kititem].subpars); + if (kit[kititem].padpars!=NULL) { + delete (kit[kititem].padpars); + resetallnotes=true; + }; + kit[kititem].adpars=NULL; + kit[kititem].subpars=NULL; + kit[kititem].padpars=NULL; + kit[kititem].Pname[0]='\0'; + } else { + if (kit[kititem].adpars==NULL) kit[kititem].adpars=new ADnoteParameters(fft); + if (kit[kititem].subpars==NULL) kit[kititem].subpars=new SUBnoteParameters(); + if (kit[kititem].padpars==NULL) kit[kititem].padpars=new PADnoteParameters(fft,mutex); + }; + + if (resetallnotes) for (int k=0;kbeginbranch("INFO"); + xml->addparstr("name",(char *)Pname); + xml->addparstr("author",(char *)info.Pauthor); + xml->addparstr("comments",(char *)info.Pcomments); + xml->addpar("type",info.Ptype); + xml->endbranch(); + + + xml->beginbranch("INSTRUMENT_KIT"); + xml->addpar("kit_mode",Pkitmode); + xml->addparbool("drum_mode",Pdrummode); + + for (int i=0;ibeginbranch("INSTRUMENT_KIT_ITEM",i); + xml->addparbool("enabled",kit[i].Penabled); + if (kit[i].Penabled!=0) { + xml->addparstr("name",(char *)kit[i].Pname); + + xml->addparbool("muted",kit[i].Pmuted); + xml->addpar("min_key",kit[i].Pminkey); + xml->addpar("max_key",kit[i].Pmaxkey); + + xml->addpar("send_to_instrument_effect",kit[i].Psendtoparteffect); + + xml->addparbool("add_enabled",kit[i].Padenabled); + if ((kit[i].Padenabled!=0)&&(kit[i].adpars!=NULL)) { + xml->beginbranch("ADD_SYNTH_PARAMETERS"); + kit[i].adpars->add2XML(xml); + xml->endbranch(); + }; + + xml->addparbool("sub_enabled",kit[i].Psubenabled); + if ((kit[i].Psubenabled!=0)&&(kit[i].subpars!=NULL)) { + xml->beginbranch("SUB_SYNTH_PARAMETERS"); + kit[i].subpars->add2XML(xml); + xml->endbranch(); + }; + + xml->addparbool("pad_enabled",kit[i].Ppadenabled); + if ((kit[i].Ppadenabled!=0)&&(kit[i].padpars!=NULL)) { + xml->beginbranch("PAD_SYNTH_PARAMETERS"); + kit[i].padpars->add2XML(xml); + xml->endbranch(); + }; + + }; + xml->endbranch(); + }; + xml->endbranch(); + + xml->beginbranch("INSTRUMENT_EFFECTS"); + for (int nefx=0;nefxbeginbranch("INSTRUMENT_EFFECT",nefx); + xml->beginbranch("EFFECT"); + partefx[nefx]->add2XML(xml); + xml->endbranch(); + + xml->addpar("route",Pefxroute[nefx]); + partefx[nefx]->setdryonly(Pefxroute[nefx]==2); + xml->addparbool("bypass",Pefxbypass[nefx]); + xml->endbranch(); + }; + xml->endbranch(); +}; + + +void Part::add2XML(XMLwrapper *xml) +{ + //parameters + xml->addparbool("enabled",Penabled); + if ((Penabled==0)&&(xml->minimal)) return; + + xml->addpar("volume",Pvolume); + xml->addpar("panning",Ppanning); + + xml->addpar("min_key",Pminkey); + xml->addpar("max_key",Pmaxkey); + xml->addpar("key_shift",Pkeyshift); + xml->addpar("rcv_chn",Prcvchn); + + xml->addpar("velocity_sensing",Pvelsns); + xml->addpar("velocity_offset",Pveloffs); + + xml->addparbool("note_on",Pnoteon); + xml->addparbool("poly_mode",Ppolymode); + xml->addpar("legato_mode",Plegatomode); + xml->addpar("key_limit",Pkeylimit); + + xml->beginbranch("INSTRUMENT"); + add2XMLinstrument(xml); + xml->endbranch(); + + xml->beginbranch("CONTROLLER"); + ctl.add2XML(xml); + xml->endbranch(); +}; + +int Part::saveXML(char *filename) +{ + XMLwrapper *xml; + xml=new XMLwrapper(); + + xml->beginbranch("INSTRUMENT"); + add2XMLinstrument(xml); + xml->endbranch(); + + int result=xml->saveXMLfile(filename); + delete (xml); + return(result); +}; + +int Part::loadXMLinstrument(const char *filename) +{ + XMLwrapper *xml=new XMLwrapper(); + if (xml->loadXMLfile(filename)<0) { + delete(xml); + return(-1); + }; + + if (xml->enterbranch("INSTRUMENT")==0) return(-10); + getfromXMLinstrument(xml); + xml->exitbranch(); + + delete(xml); + return(0); +}; + + +void Part::applyparameters() +{ + for (int n=0;napplyparameters(true); + }; +}; + +void Part::getfromXMLinstrument(XMLwrapper *xml) +{ + if (xml->enterbranch("INFO")) { + xml->getparstr("name",(char *)Pname,PART_MAX_NAME_LEN); + xml->getparstr("author",(char *)info.Pauthor,MAX_INFO_TEXT_SIZE); + xml->getparstr("comments",(char *)info.Pcomments,MAX_INFO_TEXT_SIZE); + info.Ptype=xml->getpar("type",info.Ptype,0,16); + + xml->exitbranch(); + }; + + if (xml->enterbranch("INSTRUMENT_KIT")) { + Pkitmode=xml->getpar127("kit_mode",Pkitmode); + Pdrummode=xml->getparbool("drum_mode",Pdrummode); + + setkititemstatus(0,0); + for (int i=0;ienterbranch("INSTRUMENT_KIT_ITEM",i)==0) continue; + setkititemstatus(i,xml->getparbool("enabled",kit[i].Penabled)); + if (kit[i].Penabled==0) { + xml->exitbranch(); + continue; + }; + + xml->getparstr("name",(char *)kit[i].Pname,PART_MAX_NAME_LEN); + + kit[i].Pmuted=xml->getparbool("muted",kit[i].Pmuted); + kit[i].Pminkey=xml->getpar127("min_key",kit[i].Pminkey); + kit[i].Pmaxkey=xml->getpar127("max_key",kit[i].Pmaxkey); + + kit[i].Psendtoparteffect=xml->getpar127("send_to_instrument_effect",kit[i].Psendtoparteffect); + + kit[i].Padenabled=xml->getparbool("add_enabled",kit[i].Padenabled); + if (xml->enterbranch("ADD_SYNTH_PARAMETERS")) { + kit[i].adpars->getfromXML(xml); + xml->exitbranch(); + }; + + kit[i].Psubenabled=xml->getparbool("sub_enabled",kit[i].Psubenabled); + if (xml->enterbranch("SUB_SYNTH_PARAMETERS")) { + kit[i].subpars->getfromXML(xml); + xml->exitbranch(); + }; + + kit[i].Ppadenabled=xml->getparbool("pad_enabled",kit[i].Ppadenabled); + if (xml->enterbranch("PAD_SYNTH_PARAMETERS")) { + kit[i].padpars->getfromXML(xml); + xml->exitbranch(); + }; + + xml->exitbranch(); + }; + + xml->exitbranch(); + }; + + + if (xml->enterbranch("INSTRUMENT_EFFECTS")) { + for (int nefx=0;nefxenterbranch("INSTRUMENT_EFFECT",nefx)==0) continue; + if (xml->enterbranch("EFFECT")) { + partefx[nefx]->getfromXML(xml); + xml->exitbranch(); + }; + + Pefxroute[nefx]=xml->getpar("route",Pefxroute[nefx],0,NUM_PART_EFX); + partefx[nefx]->setdryonly(Pefxroute[nefx]==2); + Pefxbypass[nefx]=xml->getparbool("bypass",Pefxbypass[nefx]); + xml->exitbranch(); + }; + xml->exitbranch(); + }; + +}; + +void Part::getfromXML(XMLwrapper *xml) +{ + Penabled=xml->getparbool("enabled",Penabled); + + setPvolume(xml->getpar127("volume",Pvolume)); + setPpanning(xml->getpar127("panning",Ppanning)); + + Pminkey=xml->getpar127("min_key",Pminkey); + Pmaxkey=xml->getpar127("max_key",Pmaxkey); + Pkeyshift=xml->getpar127("key_shift",Pkeyshift); + Prcvchn=xml->getpar127("rcv_chn",Prcvchn); + + Pvelsns=xml->getpar127("velocity_sensing",Pvelsns); + Pveloffs=xml->getpar127("velocity_offset",Pveloffs); + + Pnoteon=xml->getparbool("note_on",Pnoteon); + Ppolymode=xml->getparbool("poly_mode",Ppolymode); + Plegatomode=xml->getparbool("legato_mode",Plegatomode);//older versions + if (!Plegatomode) Plegatomode=xml->getpar127("legato_mode",Plegatomode); + Pkeylimit=xml->getpar127("key_limit",Pkeylimit); + + + if (xml->enterbranch("INSTRUMENT")) { + getfromXMLinstrument(xml); + xml->exitbranch(); + }; + + if (xml->enterbranch("CONTROLLER")) { + ctl.getfromXML(xml); + xml->exitbranch(); + }; + +}; + + + diff --git a/plugins/zynaddsubfx/src/Misc/Part.h b/plugins/zynaddsubfx/src/Misc/Part.h index 5cf6ea320..1ac12a50b 100644 --- a/plugins/zynaddsubfx/src/Misc/Part.h +++ b/plugins/zynaddsubfx/src/Misc/Part.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Part.h - Part implementation Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -40,140 +40,147 @@ #include // For the monomemnotes list. -class Part{ +/** Part implementation*/ +class Part +{ - public: - Part(Microtonal *microtonal_,FFTwrapper *fft_,pthread_mutex_t *mutex_); - ~Part(); +public: + /**Constructor + * @param microtonal_ Pointer to the microtonal object + * @param fft_ Pointer to the FFTwrapper + * @param mutex_ Pointer to the master pthread_mutex_t*/ + Part(Microtonal *microtonal_,FFTwrapper *fft_,pthread_mutex_t *mutex_); + /**Destructor*/ + ~Part(); - /* Midi commands implemented */ - void NoteOn(unsigned char note,unsigned char velocity,int masterkeyshift); - void NoteOff(unsigned char note); - void AllNotesOff();//panic - void SetController(unsigned int type,int par); - void RelaseSustainedKeys();//this is called when the sustain pedal is relased - void RelaseAllKeys();//this is called on AllNotesOff controller + // Midi commands implemented + void NoteOn(unsigned char note,unsigned char velocity,int masterkeyshift); + void NoteOff(unsigned char note); + void AllNotesOff();//panic + void SetController(unsigned int type,int par); + void RelaseSustainedKeys();//this is called when the sustain pedal is relased + void RelaseAllKeys();//this is called on AllNotesOff controller - /* The synthesizer part output */ - void ComputePartSmps();//Part output - - //instrumentonly: 0 - save all, 1 - save only instrumnet, 2 - save only instrument without the name(used in bank) + /* The synthesizer part output */ + void ComputePartSmps();//Part output + + //instrumentonly: 0 - save all, 1 - save only instrumnet, 2 - save only instrument without the name(used in bank) - //saves the instrument settings to a XML file - //returns 0 for ok or <0 if there is an error - int saveXML(char *filename); - int loadXMLinstrument(const char *filename); + //saves the instrument settings to a XML file + //returns 0 for ok or <0 if there is an error + int saveXML(char *filename); + int loadXMLinstrument(const char *filename); - void add2XML(XMLwrapper *xml); - void add2XMLinstrument(XMLwrapper *xml); - - void defaults(); - void defaultsinstrument(); - - void applyparameters(); - - void getfromXML(XMLwrapper *xml); - void getfromXMLinstrument(XMLwrapper *xml); + void add2XML(XMLwrapper *xml); + void add2XMLinstrument(XMLwrapper *xml); - void cleanup(); + void defaults(); + void defaultsinstrument(); + + void applyparameters(); + + void getfromXML(XMLwrapper *xml); + void getfromXMLinstrument(XMLwrapper *xml); + + void cleanup(); // ADnoteParameters *ADPartParameters; // SUBnoteParameters *SUBPartParameters; - //the part's kit - struct { + //the part's kit + struct { unsigned char Penabled,Pmuted,Pminkey,Pmaxkey; - unsigned char *Pname; - unsigned char Padenabled,Psubenabled,Ppadenabled; - unsigned char Psendtoparteffect; + unsigned char *Pname; + unsigned char Padenabled,Psubenabled,Ppadenabled; + unsigned char Psendtoparteffect; ADnoteParameters *adpars; SUBnoteParameters *subpars; PADnoteParameters *padpars; - } kit[NUM_KIT_ITEMS]; + } kit[NUM_KIT_ITEMS]; - - //Part parameters - void setkeylimit(unsigned char Pkeylimit); - void setkititemstatus(int kititem,int Penabled_); - unsigned char Penabled;//if the part is enabled - unsigned char Pvolume;//part volume - unsigned char Pminkey;//the minimum key that the part receives noteon messages - unsigned char Pmaxkey;//the maximum key that the part receives noteon messages - void setPvolume(char Pvolume); - unsigned char Pkeyshift;//Part keyshift - unsigned char Prcvchn;//from what midi channel it receive commnads - unsigned char Ppanning;//part panning - void setPpanning(char Ppanning); - unsigned char Pvelsns;//velocity sensing (amplitude velocity scale) - unsigned char Pveloffs;//velocity offset - unsigned char Pnoteon;//if the part receives NoteOn messages - unsigned char Pkitmode;//if the kitmode is enabled - unsigned char Pdrummode;//if all keys are mapped and the system is 12tET (used for drums) + //Part parameters + void setkeylimit(unsigned char Pkeylimit); + void setkititemstatus(int kititem,int Penabled_); - unsigned char Ppolymode;//Part mode - 0=monophonic , 1=polyphonic - unsigned char Plegatomode;// 0=normal, 1=legato - unsigned char Pkeylimit;//how many keys are alowed to be played same time (0=off), the older will be relased - - unsigned char *Pname; //name of the instrument - struct{//instrument additional information - unsigned char Ptype; - unsigned char Pauthor[MAX_INFO_TEXT_SIZE+1]; - unsigned char Pcomments[MAX_INFO_TEXT_SIZE+1]; - } info; - - - REALTYPE *partoutl;//Left channel output of the part - REALTYPE *partoutr;//Right channel output of the part + unsigned char Penabled;/** monomemnotes; // A list to remember held notes. - struct { - unsigned char velocity; - int mkeyshift;// I'm not sure masterkeyshift should be remembered. - } monomem[256]; /* 256 is to cover all possible note values. + // MonoMem stuff + std::list monomemnotes; // A list to remember held notes. + struct { + unsigned char velocity; + int mkeyshift;// I'm not sure masterkeyshift should be remembered. + } monomem[256]; /* 256 is to cover all possible note values. monomem[] is used in conjunction with the list to store the velocity and masterkeyshift values of a given note (the list only store note values). @@ -181,14 +188,14 @@ class Part{ velocity value of the note 'note'. */ - PartNotes partnote[POLIPHONY]; - - REALTYPE *tmpoutl;//used to get the note - REALTYPE *tmpoutr; - - REALTYPE oldfreq;//this is used for portamento - Microtonal *microtonal; - FFTwrapper *fft; + PartNotes partnote[POLIPHONY]; + + REALTYPE *tmpoutl;//used to get the note + REALTYPE *tmpoutr; + + REALTYPE oldfreq;//this is used for portamento + Microtonal *microtonal; + FFTwrapper *fft; }; #endif diff --git a/plugins/zynaddsubfx/src/Misc/Stereo.cpp b/plugins/zynaddsubfx/src/Misc/Stereo.cpp new file mode 100644 index 000000000..fde296043 --- /dev/null +++ b/plugins/zynaddsubfx/src/Misc/Stereo.cpp @@ -0,0 +1,37 @@ +/* + ZynAddSubFX - a software synthesizer + + Stereo.C - Object for storing a pair of objects + Copyright (C) 2009-2009 Mark McCurry + Author: Mark McCurry + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +template +Stereo::Stereo(const T &left, const T &right) + :leftChannel(left),rightChannel(right) +{} + +template +Stereo::Stereo(const T &val) + :leftChannel(val),rightChannel(val) +{} + +template +void Stereo::operator=(const Stereo & nstr) +{ + leftChannel=nstr.leftChannel; + rightChannel=nstr.rightChannel; +} diff --git a/plugins/zynaddsubfx/src/Misc/Stereo.h b/plugins/zynaddsubfx/src/Misc/Stereo.h new file mode 100644 index 000000000..b9c71b359 --- /dev/null +++ b/plugins/zynaddsubfx/src/Misc/Stereo.h @@ -0,0 +1,67 @@ +/* + ZynAddSubFX - a software synthesizer + + Stereo.h - Object for storing a pair of objects + Copyright (C) 2009-2009 Mark McCurry + Author: Mark McCurry + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#ifndef STEREO_H +#define STEREO_H + +template +class Stereo +{ +public: + Stereo(const T &left,const T &right); + + /**Initializes Stereo with left and right set to val + * @param val the value for both channels*/ + Stereo(const T &val); + ~Stereo() {}; + + void operator=(const Stereo &smp); + T &left() { + return leftChannel; + }; + T &right() { + return rightChannel; + }; + T &l() { + return leftChannel; + }; + T &r() { + return rightChannel; + }; + const T &left()const { + return leftChannel; + }; + const T &right()const { + return rightChannel; + }; + const T &l()const { + return leftChannel; + }; + const T &r()const { + return rightChannel; + }; +private: + T leftChannel; + T rightChannel; + +}; +#include "Stereo.cpp" +#endif + diff --git a/plugins/zynaddsubfx/src/Misc/Util.C b/plugins/zynaddsubfx/src/Misc/Util.cpp similarity index 68% rename from plugins/zynaddsubfx/src/Misc/Util.C rename to plugins/zynaddsubfx/src/Misc/Util.cpp index 049e5e898..5069a9ea6 100644 --- a/plugins/zynaddsubfx/src/Misc/Util.C +++ b/plugins/zynaddsubfx/src/Misc/Util.cpp @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Util.C - Miscellaneous functions Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -42,17 +42,19 @@ REALTYPE *denormalkillbuf; /* * Transform the velocity according the scaling parameter (velocity sensing) */ -REALTYPE VelF(REALTYPE velocity,unsigned char scaling){ +REALTYPE VelF(REALTYPE velocity,unsigned char scaling) +{ REALTYPE x; x=pow(VELOCITY_MAX_SCALE,(64.0-scaling)/64.0); if ((scaling==127)||(velocity>0.99)) return(1.0); - else return(pow(velocity,x)); + else return(pow(velocity,x)); }; /* - * Get the detune in cents + * Get the detune in cents */ -REALTYPE getdetune(unsigned char type,unsigned short int coarsedetune,unsigned short int finedetune){ +REALTYPE getdetune(unsigned char type,unsigned short int coarsedetune,unsigned short int finedetune) +{ REALTYPE det=0.0,octdet=0.0,cdet=0.0,findet=0.0; //Get Octave int octave=coarsedetune/1024; @@ -62,49 +64,57 @@ REALTYPE getdetune(unsigned char type,unsigned short int coarsedetune,unsigned s //Coarse and fine detune int cdetune=coarsedetune%1024; if (cdetune>512) cdetune-=1024; - + int fdetune=finedetune-8192; - switch (type){ + switch (type) { // case 1: is used for the default (see below) - case 2: cdet=fabs(cdetune*10.0); - findet=fabs(fdetune/8192.0)*10.0; - break; - case 3: cdet=fabs(cdetune*100); - findet=pow(10,fabs(fdetune/8192.0)*3.0)/10.0-0.1; - break; - case 4: cdet=fabs(cdetune*701.95500087);//perfect fifth - findet=(pow(2,fabs(fdetune/8192.0)*12.0)-1.0)/4095*1200; - break; - //case ...: need to update N_DETUNE_TYPES, if you'll add more - default:cdet=fabs(cdetune*50.0); - findet=fabs(fdetune/8192.0)*35.0;//almost like "Paul's Sound Designer 2" - break; + case 2: + cdet=fabs(cdetune*10.0); + findet=fabs(fdetune/8192.0)*10.0; + break; + case 3: + cdet=fabs(cdetune*100); + findet=pow(10,fabs(fdetune/8192.0)*3.0)/10.0-0.1; + break; + case 4: + cdet=fabs(cdetune*701.95500087);//perfect fifth + findet=(pow(2,fabs(fdetune/8192.0)*12.0)-1.0)/4095*1200; + break; + //case ...: need to update N_DETUNE_TYPES, if you'll add more + default: + cdet=fabs(cdetune*50.0); + findet=fabs(fdetune/8192.0)*35.0;//almost like "Paul's Sound Designer 2" + break; }; if (finedetune<8192) findet=-findet; if (cdetune<0) cdet=-cdet; - + det=octdet+cdet+findet; return(det); }; -bool fileexists(char *filename){ +bool fileexists(const char *filename) +{ struct stat tmp; int result=stat(filename,&tmp); if (result>=0) return(true); - + return(false); }; -void newFFTFREQS(FFTFREQS *f,int size){ +void newFFTFREQS(FFTFREQS *f,int size) +{ f->c=new REALTYPE[size]; f->s=new REALTYPE[size]; - for (int i=0;ic[i]=0.0;f->s[i]=0.0; + for (int i=0;ic[i]=0.0; + f->s[i]=0.0; }; }; -void deleteFFTFREQS(FFTFREQS *f){ +void deleteFFTFREQS(FFTFREQS *f) +{ delete[] f->c; delete[] f->s; f->c=f->s=NULL; diff --git a/plugins/zynaddsubfx/src/Misc/Util.h b/plugins/zynaddsubfx/src/Misc/Util.h index 6bb8fded4..66c313b13 100644 --- a/plugins/zynaddsubfx/src/Misc/Util.h +++ b/plugins/zynaddsubfx/src/Misc/Util.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Util.h - Miscellaneous functions Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -32,12 +32,12 @@ //Velocity Sensing function extern REALTYPE VelF(REALTYPE velocity,unsigned char scaling); -bool fileexists(char *filename); +bool fileexists(const char *filename); #define N_DETUNE_TYPES 4 //the number of detune types extern REALTYPE getdetune(unsigned char type,unsigned short int coarsedetune,unsigned short int finedetune); -extern REALTYPE *denormalkillbuf;//the buffer to add noise in order to avoid denormalisation +extern REALTYPE *denormalkillbuf;/** #include #include +#include #include +#include +#include #include "../globals.h" #include "Util.h" +using namespace std; + int xml_k=0; char tabs[STACKSIZE+2]; -const char *XMLwrapper_whitespace_callback(mxml_node_t *node,int where){ +const char *XMLwrapper_whitespace_callback(mxml_node_t *node,int where) +{ const char *name=node->value.element.name; if ((where==MXML_WS_BEFORE_OPEN)&&(!strcmp(name,"?xml"))) return(NULL); if ((where==MXML_WS_BEFORE_CLOSE)&&(!strcmp(name,"string"))) return(NULL); if ((where==MXML_WS_BEFORE_OPEN)||(where==MXML_WS_BEFORE_CLOSE)) { -/* const char *tmp=node->value.element.name; - if (tmp!=NULL) { - if ((strstr(tmp,"par")!=tmp)&&(strstr(tmp,"string")!=tmp)) { - printf("%s ",tmp); - if (where==MXML_WS_BEFORE_OPEN) xml_k++; - if (where==MXML_WS_BEFORE_CLOSE) xml_k--; - if (xml_k>=STACKSIZE) xml_k=STACKSIZE-1; - if (xml_k<0) xml_k=0; - printf("%d\n",xml_k); - printf("\n"); - }; - - }; - int i=0; - for (i=1;ivalue.element.name; + if (tmp!=NULL) { + if ((strstr(tmp,"par")!=tmp)&&(strstr(tmp,"string")!=tmp)) { + printf("%s ",tmp); + if (where==MXML_WS_BEFORE_OPEN) xml_k++; + if (where==MXML_WS_BEFORE_CLOSE) xml_k--; + if (xml_k>=STACKSIZE) xml_k=STACKSIZE-1; + if (xml_k<0) xml_k=0; + printf("%d\n",xml_k); + printf("\n"); + }; + + }; + int i=0; + for (i=1;i"); if ((start==NULL)||(end==NULL)||(start>end)) { - delete []xmldata; - return(false); + delete []xmldata; + return(false); }; end+=strlen(""); - end[0]='\0'; - + end[0]='\0'; + tree=mxmlNewElement(MXML_NO_PARENT,"?xml"); node=root=mxmlLoadString(tree,xmldata,MXML_OPAQUE_CALLBACK); if (root==NULL) { - delete []xmldata; - mxmlDelete(tree); - node=root=tree=NULL; - return(false); + delete []xmldata; + mxmlDelete(tree); + node=root=tree=NULL; + return(false); }; root=mxmlFindElement(tree,tree,"INFORMATION",NULL,NULL,MXML_DESCEND); push(root); - if (root==NULL){ - delete []xmldata; - mxmlDelete(tree); - node=root=tree=NULL; - return(false); + if (root==NULL) { + delete []xmldata; + mxmlDelete(tree); + node=root=tree=NULL; + return(false); }; - + information.PADsynth_used=getparbool("PADsynth_used",false); exitbranch(); @@ -162,33 +173,29 @@ bool XMLwrapper::checkfileinformation(const char *filename){ /* SAVE XML members */ -int XMLwrapper::saveXMLfile(const char *filename){ +int XMLwrapper::saveXMLfile(const string &filename) +{ char *xmldata=getXMLdata(); if (xmldata==NULL) return(-2); int compression=config.cfg.GzipCompression; - - int fnsize=strlen(filename)+100; - char *filenamenew=new char [fnsize]; - snprintf(filenamenew,fnsize,"%s",filename); - - int result=dosavefile(filenamenew,compression,xmldata); - - delete []filenamenew; - free(xmldata); + int result=dosavefile(filename.c_str(),compression,xmldata); + + free(xmldata); return(result); }; -char *XMLwrapper::getXMLdata(){ +char *XMLwrapper::getXMLdata() +{ xml_k=0; ZERO(tabs,STACKSIZE+2); - + mxml_node_t *oldnode=node; - + node=info; //Info storing addparbool("PADsynth_used",information.PADsynth_used); - + node=oldnode; char *xmldata=mxmlSaveAllocString(tree,XMLwrapper_whitespace_callback); @@ -196,62 +203,70 @@ char *XMLwrapper::getXMLdata(){ }; -int XMLwrapper::dosavefile(const char *filename,int compression,const char *xmldata){ - if (compression==0){ - FILE *file; - file=fopen(filename,"w"); - if (file==NULL) return(-1); - fputs(xmldata,file); - fclose(file); +int XMLwrapper::dosavefile(const char *filename,int compression,const char *xmldata) +{ + if (compression==0) { + FILE *file; + file=fopen(filename,"w"); + if (file==NULL) return(-1); + fputs(xmldata,file); + fclose(file); } else { - if (compression>9) compression=9; - if (compression<1) compression=1; - char options[10]; - snprintf(options,10,"wb%d",compression); + if (compression>9) compression=9; + if (compression<1) compression=1; + char options[10]; + snprintf(options,10,"wb%d",compression); - gzFile gzfile; - gzfile=gzopen(filename,options); - if (gzfile==NULL) return(-1); - gzputs(gzfile,xmldata); - gzclose(gzfile); + gzFile gzfile; + gzfile=gzopen(filename,options); + if (gzfile==NULL) return(-1); + gzputs(gzfile,xmldata); + gzclose(gzfile); }; - + return(0); }; -void XMLwrapper::addpar(const char *name,int val){ - addparams2("par","name",name,"value",int2str(val)); +void XMLwrapper::addpar(const string &name,int val) +{ + addparams2("par","name",name.c_str(),"value",int2str(val)); }; -void XMLwrapper::addparreal(const char *name,REALTYPE val){ - addparams2("par_real","name",name,"value",real2str(val)); +void XMLwrapper::addparreal(const string &name,REALTYPE val) +{ + addparams2("par_real","name",name.c_str(),"value",real2str(val)); }; -void XMLwrapper::addparbool(const char *name,int val){ - if (val!=0) addparams2("par_bool","name",name,"value","yes"); - else addparams2("par_bool","name",name,"value","no"); +void XMLwrapper::addparbool(const string &name,int val) +{ + if (val!=0) addparams2("par_bool","name",name.c_str(),"value","yes"); + else addparams2("par_bool","name",name.c_str(),"value","no"); }; -void XMLwrapper::addparstr(const char *name,const char *val){ +void XMLwrapper::addparstr(const string &name,const string &val) +{ mxml_node_t *element=mxmlNewElement(node,"string"); - mxmlElementSetAttr(element,"name",name); - mxmlNewText(element,0,val); + mxmlElementSetAttr(element,"name",name.c_str()); + mxmlNewText(element,0,val.c_str()); }; -void XMLwrapper::beginbranch(const char *name){ +void XMLwrapper::beginbranch(const string &name) +{ push(node); - node=addparams0(name); + node=addparams0(name.c_str()); }; -void XMLwrapper::beginbranch(const char *name,int id){ +void XMLwrapper::beginbranch(const string &name,int id) +{ push(node); - node=addparams1(name,"id",int2str(id)); + node=addparams1(name.c_str(),"id",int2str(id)); }; -void XMLwrapper::endbranch(){ +void XMLwrapper::endbranch() +{ node=pop(); }; @@ -259,7 +274,8 @@ void XMLwrapper::endbranch(){ /* LOAD XML members */ -int XMLwrapper::loadXMLfile(const char *filename){ +int XMLwrapper::loadXMLfile(const string &filename) +{ if (tree!=NULL) mxmlDelete(tree); tree=NULL; @@ -268,16 +284,16 @@ int XMLwrapper::loadXMLfile(const char *filename){ stackpos=0; - const char *xmldata=doloadfile(filename); + const char *xmldata=doloadfile(filename.c_str()); if (xmldata==NULL) return(-1);//the file could not be loaded or uncompressed - + root=tree=mxmlLoadString(NULL,xmldata,MXML_OPAQUE_CALLBACK); delete []xmldata; if (tree==NULL) return(-2);//this is not XML - - + + node=root=mxmlFindElement(tree,tree,"ZynAddSubFX-data",NULL,NULL,MXML_DESCEND); if (root==NULL) return(-3);//the XML doesnt embbed zynaddsubfx data push(root); @@ -289,51 +305,39 @@ int XMLwrapper::loadXMLfile(const char *filename){ }; -char *XMLwrapper::doloadfile(const char *filename){ - char *xmldata=NULL; - int filesize=-1; - - //try get filesize as gzip data (first) - gzFile gzfile=gzopen(filename,"rb"); - if (gzfile!=NULL){//this is a gzip file - // first check it's size - while(!gzeof(gzfile)) { - gzseek (gzfile,1024*1024,SEEK_CUR); - if (gztell(gzfile)>10000000) { - gzclose(gzfile); - goto notgzip;//the file is too big - }; - }; - filesize=gztell(gzfile); +char *XMLwrapper::doloadfile(const string &filename) +{ + char * xmldata = NULL; + gzFile gzfile = gzopen(filename.c_str(),"rb"); - //rewind the file and load the data - xmldata=new char[filesize+1]; - ZERO(xmldata,filesize+1); + if (gzfile != NULL) {//The possibly compressed file opened - gzrewind(gzfile); - gzread(gzfile,xmldata,filesize); - - gzclose(gzfile); - return (xmldata); - } else {//this is not a gzip file - notgzip: - FILE *file=fopen(filename,"rb"); - if (file==NULL) return(NULL); - fseek(file,0,SEEK_END); - filesize=ftell(file); + stringstream strBuf; //reading stream + const int bufSize = 500; //fetch size + char fetchBuf[bufSize+1];//fetch buffer + int read = 0; //chars read in last fetch - xmldata=new char [filesize+1]; - ZERO(xmldata,filesize+1); - - rewind(file); - fread(xmldata,filesize,1,file); - - fclose(file); - return(xmldata); - }; -}; + fetchBuf[bufSize] = 0;//force null termination -bool XMLwrapper::putXMLdata(const char *xmldata){ + while(bufSize == (read = gzread(gzfile, fetchBuf, bufSize))) + strBuf << fetchBuf; + + fetchBuf[read] = 0;//Truncate last partial read + strBuf << fetchBuf; + + gzclose(gzfile); + + //Place data in output format + string tmp = strBuf.str(); + xmldata = new char[tmp.size()+1]; + strncpy(xmldata, tmp.c_str(), tmp.size()+1); + } + + return xmldata; +} + +bool XMLwrapper::putXMLdata(const char *xmldata) +{ if (tree!=NULL) mxmlDelete(tree); tree=NULL; @@ -343,11 +347,11 @@ bool XMLwrapper::putXMLdata(const char *xmldata){ stackpos=0; if (xmldata==NULL) return (false); - + root=tree=mxmlLoadString(NULL,xmldata,MXML_OPAQUE_CALLBACK); if (tree==NULL) return(false); - + node=root=mxmlFindElement(tree,tree,"ZynAddSubFX-data",NULL,NULL,MXML_DESCEND); if (root==NULL) return (false);; push(root); @@ -357,17 +361,19 @@ bool XMLwrapper::putXMLdata(const char *xmldata){ -int XMLwrapper::enterbranch(const char *name){ - node=mxmlFindElement(peek(),peek(),name,NULL,NULL,MXML_DESCEND_FIRST); +int XMLwrapper::enterbranch(const string &name) +{ + node=mxmlFindElement(peek(),peek(),name.c_str(),NULL,NULL,MXML_DESCEND_FIRST); if (node==NULL) return(0); push(node); return(1); }; -int XMLwrapper::enterbranch(const char *name,int id){ +int XMLwrapper::enterbranch(const string &name,int id) +{ snprintf(tmpstr,TMPSTR_SIZE,"%d",id); - node=mxmlFindElement(peek(),peek(),name,"id",tmpstr,MXML_DESCEND_FIRST); + node=mxmlFindElement(peek(),peek(),name.c_str(),"id",tmpstr,MXML_DESCEND_FIRST); if (node==NULL) return(0); push(node); @@ -375,142 +381,157 @@ int XMLwrapper::enterbranch(const char *name,int id){ }; -void XMLwrapper::exitbranch(){ +void XMLwrapper::exitbranch() +{ + /**@bug Does not set the current node correctly*/ pop(); }; -int XMLwrapper::getbranchid(int min, int max){ +int XMLwrapper::getbranchid(int min, int max) +{ int id=str2int(mxmlElementGetAttr(node,"id")); if ((min==0)&&(max==0)) return(id); - + if (idmax) id=max; + else if (id>max) id=max; return(id); }; -int XMLwrapper::getpar(const char *name,int defaultpar,int min,int max){ - node=mxmlFindElement(peek(),peek(),"par","name",name,MXML_DESCEND_FIRST); +int XMLwrapper::getpar(const string &name,int defaultpar,int min,int max) +{ + node=mxmlFindElement(peek(),peek(),"par","name",name.c_str(),MXML_DESCEND_FIRST); if (node==NULL) return(defaultpar); const char *strval=mxmlElementGetAttr(node,"value"); if (strval==NULL) return(defaultpar); - + int val=str2int(strval); if (valmax) val=max; - + else if (val>max) val=max; + return(val); }; -int XMLwrapper::getpar127(const char *name,int defaultpar){ +int XMLwrapper::getpar127(const string &name,int defaultpar) +{ return(getpar(name,defaultpar,0,127)); }; -int XMLwrapper::getparbool(const char *name,int defaultpar){ - node=mxmlFindElement(peek(),peek(),"par_bool","name",name,MXML_DESCEND_FIRST); +int XMLwrapper::getparbool(const string &name,int defaultpar) +{ + node=mxmlFindElement(peek(),peek(),"par_bool","name",name.c_str(),MXML_DESCEND_FIRST); if (node==NULL) return(defaultpar); const char *strval=mxmlElementGetAttr(node,"value"); if (strval==NULL) return(defaultpar); - + if ((strval[0]=='Y')||(strval[0]=='y')) return(1); - else return(0); + else return(0); }; -void XMLwrapper::getparstr(const char *name,char *par,int maxstrlen){ +void XMLwrapper::getparstr(const string &name,char *par,int maxstrlen) +{ ZERO(par,maxstrlen); - node=mxmlFindElement(peek(),peek(),"string","name",name,MXML_DESCEND_FIRST); - + node=mxmlFindElement(peek(),peek(),"string","name",name.c_str(),MXML_DESCEND_FIRST); + if (node==NULL) return; if (node->child==NULL) return; if (node->child->type!=MXML_OPAQUE) return; - + snprintf(par,maxstrlen,"%s",node->child->value.element.name); - + }; -REALTYPE XMLwrapper::getparreal(const char *name,REALTYPE defaultpar){ +REALTYPE XMLwrapper::getparreal(const char *name,REALTYPE defaultpar) +{ node=mxmlFindElement(peek(),peek(),"par_real","name",name,MXML_DESCEND_FIRST); if (node==NULL) return(defaultpar); const char *strval=mxmlElementGetAttr(node,"value"); if (strval==NULL) return(defaultpar); - + return(str2real(strval)); }; -REALTYPE XMLwrapper::getparreal(const char *name,REALTYPE defaultpar,REALTYPE min,REALTYPE max){ +REALTYPE XMLwrapper::getparreal(const char *name,REALTYPE defaultpar,REALTYPE min,REALTYPE max) +{ REALTYPE result=getparreal(name,defaultpar); - + if (resultmax) result=max; + else if (result>max) result=max; return(result); }; /** Private members **/ -char *XMLwrapper::int2str(int x){ +char *XMLwrapper::int2str(int x) +{ snprintf(tmpstr,TMPSTR_SIZE,"%d",x); return(tmpstr); }; -char *XMLwrapper::real2str(REALTYPE x){ +char *XMLwrapper::real2str(REALTYPE x) +{ snprintf(tmpstr,TMPSTR_SIZE,"%g",x); return(tmpstr); }; -int XMLwrapper::str2int(const char *str){ +int XMLwrapper::str2int(const char *str) +{ if (str==NULL) return(0); int result=strtol(str,NULL,10); return(result); }; -REALTYPE XMLwrapper::str2real(const char *str){ +REALTYPE XMLwrapper::str2real(const char *str) +{ if (str==NULL) return(0.0); REALTYPE result=strtod(str,NULL); return(result); }; -mxml_node_t *XMLwrapper::addparams0(const char *name){ +mxml_node_t *XMLwrapper::addparams0(const char *name) +{ mxml_node_t *element=mxmlNewElement(node,name); return(element); }; -mxml_node_t *XMLwrapper::addparams1(const char *name,const char *par1,const char *val1){ +mxml_node_t *XMLwrapper::addparams1(const char *name,const char *par1,const char *val1) +{ mxml_node_t *element=mxmlNewElement(node,name); mxmlElementSetAttr(element,par1,val1); return(element); }; -mxml_node_t *XMLwrapper::addparams2(const char *name,const char *par1,const char *val1,const char *par2, const char *val2){ +mxml_node_t *XMLwrapper::addparams2(const char *name,const char *par1,const char *val1,const char *par2, const char *val2) +{ mxml_node_t *element=mxmlNewElement(node,name); mxmlElementSetAttr(element,par1,val1); mxmlElementSetAttr(element,par2,val2); return(element); }; - - - -void XMLwrapper::push(mxml_node_t *node){ +void XMLwrapper::push(mxml_node_t *node) +{ if (stackpos>=STACKSIZE-1) { - printf("BUG!: XMLwrapper::push() - full parentstack\n"); - return; + cerr << "BUG!: XMLwrapper::push() - full parentstack" << endl; + return; }; stackpos++; parentstack[stackpos]=node; - + // printf("push %d - %s\n",stackpos,node->value.element.name); - + }; -mxml_node_t *XMLwrapper::pop(){ +mxml_node_t *XMLwrapper::pop() +{ if (stackpos<=0) { - printf("BUG!: XMLwrapper::pop() - empty parentstack\n"); - return (root); + cerr << "BUG!: XMLwrapper::pop() - empty parentstack" << endl; + return (root); }; mxml_node_t *node=parentstack[stackpos]; parentstack[stackpos]=NULL; @@ -521,10 +542,11 @@ mxml_node_t *XMLwrapper::pop(){ return(node); }; -mxml_node_t *XMLwrapper::peek(){ +mxml_node_t *XMLwrapper::peek() +{ if (stackpos<=0) { - printf("BUG!: XMLwrapper::peek() - empty parentstack\n"); - return (root); + cerr << "BUG!: XMLwrapper::peek() - empty parentstack" << endl; + return (root); }; return(parentstack[stackpos]); }; diff --git a/plugins/zynaddsubfx/src/Misc/XMLwrapper.h b/plugins/zynaddsubfx/src/Misc/XMLwrapper.h index 7346e0c88..ccf875de6 100644 --- a/plugins/zynaddsubfx/src/Misc/XMLwrapper.h +++ b/plugins/zynaddsubfx/src/Misc/XMLwrapper.h @@ -1,12 +1,14 @@ /* ZynAddSubFX - a software synthesizer - - XML.h - XML wrapper + + XMLwrapper.h - XML wrapper Copyright (C) 2003-2005 Nasca Octavian Paul + Copyright (C) 2009-2009 Mark McCurry Author: Nasca Octavian Paul + Mark McCurry This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -20,7 +22,8 @@ */ -#include +#include +#include #ifndef REALTYPE #define REALTYPE float #endif @@ -33,143 +36,282 @@ //the maxim tree depth #define STACKSIZE 100 -class XMLwrapper{ - public: - XMLwrapper(); - ~XMLwrapper(); - - /********************************/ - /* SAVE to XML */ - /********************************/ +/**Mxml wrapper*/ +class XMLwrapper +{ +public: + /** + * Constructor. + * Will Construct the object and fill in top level branch + * */ + XMLwrapper(); - //returns 0 if ok or -1 if the file cannot be saved - int saveXMLfile(const char *filename); + /**Destructor*/ + ~XMLwrapper(); - //returns the new allocated string that contains the XML data (used for clipboard) - //the string is NULL terminated - char *getXMLdata(); - - //add simple parameter (name and value) - void addpar(const char *name,int val); - void addparreal(const char *name,REALTYPE val); - - //add boolean parameter (name and boolean value) - //if the value is 0 => "yes", else "no" - void addparbool(const char *name,int val); + /** + * Saves the XML to a file. + * @param filename the name of the destination file. + * @returns 0 if ok or -1 if the file cannot be saved. + */ + int saveXMLfile(const std::string &filename); - //add string parameter (name and string) - void addparstr(const char *name,const char *val); + /** + * Return XML tree as a string. + * Note: The string must be freed with free() to deallocate + * @returns a newly allocated NULL terminated string of the XML data. + */ + char *getXMLdata(); - //add a branch - void beginbranch(const char *name); - void beginbranch(const char *name, int id); + /** + * Add simple parameter. + * @param name The name of the mXML node. + * @param val The string value of the mXml node + */ + void addpar(const std::string &name,int val); - //this must be called after each branch (nodes that contains child nodes) - void endbranch(); + /** + * Adds a realtype parameter. + * @param name The name of the mXML node. + * @param val The REALTYPE value of the node. + */ + void addparreal(const std::string &name,REALTYPE val); - /********************************/ - /* LOAD from XML */ - /********************************/ - - //returns 0 if ok or -1 if the file cannot be loaded - int loadXMLfile(const char *filename); + /** + * Add boolean parameter. + * \todo Fix this reverse boolean logic. + * @param name The name of the mXML node. + * @param val The boolean value of the node (0->"yes";else->"no"). + */ + void addparbool(const std::string &name,int val); - //used by the clipboard - bool putXMLdata(const char *xmldata); - - //enter into the branch - //returns 1 if is ok, or 0 otherwise - int enterbranch(const char *name); + /** + * Add string parameter. + * @param name The name of the mXML node. + * @param val The string value of the node. + */ + void addparstr(const std::string &name,const std::string &val); - - //enter into the branch with id - //returns 1 if is ok, or 0 otherwise - int enterbranch(const char *name, int id); + /** + * Create a new branch. + * @param name Name of new branch + * @see void endbranch() + */ + void beginbranch(const std::string &name); + /** + * Create a new branch. + * @param name Name of new branch + * @param id "id" value of branch + * @see void endbranch() + */ + void beginbranch(const std::string &name, int id); - //exits from a branch - void exitbranch(); - - //get the the branch_id and limits it between the min and max - //if min==max==0, it will not limit it - //if there isn't any id, will return min - //this must be called only imediately after enterbranch() - int getbranchid(int min, int max); + /**Closes new branches. + * This must be called to exit each branch created by beginbranch( ). + * @see void beginbranch(const std::string &name) + * @see void beginbranch(const std::string &name, int id) + */ + void endbranch(); - //it returns the parameter and limits it between min and max - //if min==max==0, it will not limit it - //if no parameter will be here, the defaultpar will be returned - int getpar(const char *name,int defaultpar,int min,int max); + /** + * Loads file into XMLwrapper. + * @param filename file to be loaded + * @returns 0 if ok or -1 if the file cannot be loaded + */ + int loadXMLfile(const std::string &filename); - //the same as getpar, but the limits are 0 and 127 - int getpar127(const char *name,int defaultpar); - - int getparbool(const char *name,int defaultpar); + /** + * Loads string into XMLwrapper. + * @param xmldata NULL terminated string of XML data. + * @returns true if successful. + */ + bool putXMLdata(const char *xmldata); - void getparstr(const char *name,char *par,int maxstrlen); - REALTYPE getparreal(const char *name,REALTYPE defaultpar); - REALTYPE getparreal(const char *name,REALTYPE defaultpar,REALTYPE min,REALTYPE max); + /** + * Enters the branch. + * @param name Name of branch. + * @returns 1 if is ok, or 0 otherwise. + */ + int enterbranch(const std::string &name); - bool minimal;//false if all parameters will be stored (used only for clipboard) - - struct { - bool PADsynth_used; - }information; - - //opens a file and parse only the "information" data on it - //returns "true" if all went ok or "false" on errors - bool checkfileinformation(const char *filename); - - private: - - int dosavefile(const char *filename,int compression,const char *xmldata); - char *doloadfile(const char *filename); + /** + * Enter into the branch \c name with id \c id. + * @param name Name of branch. + * @param id Value of branch's "id". + * @returns 1 if is ok, or 0 otherwise. + */ + int enterbranch(const std::string &name, int id); - - mxml_node_t *tree;//all xml data - mxml_node_t *root;//xml data used by zynaddsubfx - mxml_node_t *node;//current node - mxml_node_t *info;//this node is used to store the information about the data - - //adds params like this: - // - //returns the node - mxml_node_t *addparams0(const char *name); + /**Exits from a branch*/ + void exitbranch(); - //adds params like this: - // - //returns the node - mxml_node_t *addparams1(const char *name,const char *par1,const char *val1); + /**Get the the branch_id and limits it between the min and max. + * if min==max==0, it will not limit it + * if there isn't any id, will return min + * this must be called only imediately after enterbranch() + */ + int getbranchid(int min, int max); - //adds params like this: - // - //returns the node - mxml_node_t *addparams2(const char *name,const char *par1,const char *val1,const char *par2, const char *val2); - - char *int2str(int x); - char *real2str(REALTYPE x); - - int str2int(const char *str); - REALTYPE str2real(const char *str); - - char tmpstr[TMPSTR_SIZE]; - - - //this is used to store the parents - mxml_node_t *parentstack[STACKSIZE]; - int stackpos; + /** + * Returns the integer value stored in node name. + * It returns the integer value between the limits min and max. + * If min==max==0, then the value will not be limited. + * If there is no location named name, then defaultpar will be returned. + * @param name The parameter name. + * @param defaultpar The default value if the real value is not found. + * @param min The minimum return value. + * @param max The maximum return value. + */ + int getpar(const std::string &name,int defaultpar,int min,int max); - - void push(mxml_node_t *node); - mxml_node_t *pop(); - mxml_node_t *peek(); + /** + * Returns the integer value stored in the node with range [0,127]. + * @param name The parameter name. + * @param defaultpar The default value if the real value is not found. + */ + int getpar127(const std::string &name,int defaultpar); + + /** + * Returns the boolean value stored in the node. + * @param name The parameter name. + * @param defaultpar The default value if the real value is not found. + */ + int getparbool(const std::string &name,int defaultpar); + + /** + * Get the string value stored in the node. + * @param name The parameter name. + * @param par Pointer to destination string + * @param maxstrlen Max string length for destination + */ + void getparstr(const std::string &name,char *par,int maxstrlen); + + /** + * Returns the real value stored in the node. + * @param name The parameter name. + * @param defaultpar The default value if the real value is not found. + */ + REALTYPE getparreal(const char *name,REALTYPE defaultpar); + + /** + * Returns the real value stored in the node. + * @param name The parameter name. + * @param defaultpar The default value if the real value is not found. + * @param min The minimum value + * @param max The maximum value + */ + REALTYPE getparreal(const char *name,REALTYPE defaultpar,REALTYPE min,REALTYPE max); + + bool minimal;/**. + * @returns The node + */ + mxml_node_t *addparams0(const char *name); + + /** + * Adds params like this: + * . + * @returns The node + */ + mxml_node_t *addparams1(const char *name,const char *par1,const char *val1); + + /** + * Adds params like this: + * . + * @returns the node + */ + mxml_node_t *addparams2(const char *name,const char *par1,const char *val1,const char *par2, const char *val2); + + /** + * Convert integer to string + * @param x integer input + * @returns string output + */ + char *int2str(int x); + + /** + * Convert integer to string + * @param x integer input + * @returns string output + */ + char *real2str(REALTYPE x); + + /** + * Convert string to int + * @param str string input + * @returns integer output + */ + int str2int(const char *str); + + /** + * Convert string to realtype + * @param x integer input + * @returns string output + */ + REALTYPE str2real(const char *str); + + /**Temporary string for various uses*/ + char tmpstr[TMPSTR_SIZE]; + + + /**this is used to store the parents. + * @todo Use the stack class provided by C++*/ + mxml_node_t *parentstack[STACKSIZE]; + int stackpos;/** -#include "DSSIaudiooutput.h" - -static LADSPA_Descriptor *tsLDescriptor = NULL; -static DSSI_Descriptor *tsDDescriptor = NULL; - -typedef struct { - LADSPA_Data *outl; - LADSPA_Data *outr; -// note_data data[MIDI_NOTES]; -// float omega[MIDI_NOTES]; -} TS; - - -static void cleanupTS(LADSPA_Handle instance){ - free(instance); -} -static void connectPortTS(LADSPA_Handle instance, unsigned long port, - LADSPA_Data * data){ - TS *plugin; - plugin = (TS *) instance; - switch (port) { - case 0: - plugin->outl = data; - break; - case 1: - plugin->outr = data; - break; - } -} - -const LADSPA_Descriptor *ladspa_descriptor(unsigned long index){ - switch (index) { - case 0: - return tsLDescriptor; - default: - return NULL; - } -} - -const DSSI_Descriptor *dssi_descriptor(unsigned long index){ -// FILE *a=fopen("/tmp/zzzzz11z","w"); -// fprintf(a,"aaaaaaaaaaa TEST\n"); -// fclose(a); - switch (index) { - case 0: - return tsDDescriptor; - default: - return NULL; - } -} - -static LADSPA_Handle instantiateTS(const LADSPA_Descriptor * descriptor, - unsigned long s_rate) -{ - - TS *plugin_data = (TS *) malloc(sizeof(TS)); -/* for (i=0; iomega[i] = M_PI * 2.0 / (double)s_rate * - pow(2.0, (i-69.0) / 12.0); - } -*/ - return (LADSPA_Handle) plugin_data; -} - -static void activateTS(LADSPA_Handle instance) -{ - TS *plugin_data = (TS *) instance; - -// for (i=0; idata[i].active = 0; -// } -} - - -static void runTS(LADSPA_Handle instance, unsigned long sample_count, - snd_seq_event_t *events, unsigned long event_count){ - TS *plugin_data = (TS *) instance; -// LADSPA_Data *const output = plugin_data->output; -// LADSPA_Data freq = *(plugin_data->freq); -// LADSPA_Data vol = *(plugin_data->vol); -// note_data *data = plugin_data->data; - unsigned long pos; - unsigned long event_pos; - unsigned long note; - -/* if (freq < 1.0) { - freq = 440.0f; - } - if (vol < 0.000001) { - vol = 1.0f; - } - - if (event_count > 0) { - printf("trivial_synth: have %ld events\n", event_count); - } - - for (pos = 0, event_pos = 0; pos < sample_count; pos++) { - - while (event_pos < event_count - && pos == events[event_pos].time.tick) { - - printf("trivial_synth: event type %d\n", events[event_pos].type); - - if (events[event_pos].type == SND_SEQ_EVENT_NOTEON) { - data[events[event_pos].data.note.note].amp = - events[event_pos].data.note.velocity / 512.0f; - data[events[event_pos].data.note.note]. - active = events[event_pos].data.note.velocity > 0; - data[events[event_pos].data.note.note]. - phase = 0.0; - } else if (events[event_pos].type == SND_SEQ_EVENT_NOTEOFF) { - data[events[event_pos].data.note.note]. - active = 0; - } - event_pos++; - } - - output[pos] = 0.0f; - for (note = 0; note < MIDI_NOTES; note++) { - if (data[note].active) { - output[pos] += sin(data[note].phase) * data[note].amp * vol; - data[note].phase += plugin_data->omega[note] * freq; - if (data[note].phase > M_PI * 2.0) { - data[note].phase -= M_PI * 2.0; - } - } - } - } - */ -} - - -static void runTSWrapper(LADSPA_Handle instance, - unsigned long sample_count){ - runTS(instance, sample_count, NULL, 0); -} - -int getControllerTS(LADSPA_Handle instance, unsigned long port){ - return -1; -} - -void _init(){ - char **port_names; - LADSPA_PortDescriptor *port_descriptors; - LADSPA_PortRangeHint *port_range_hints; - - FILE *a=fopen("/tmp/zzzzzz","w"); - fprintf(a,"aaaaaaaaaaa TEST\n"); - fclose(a); - - - tsLDescriptor = (LADSPA_Descriptor *) malloc(sizeof(LADSPA_Descriptor)); - if (tsLDescriptor) { - tsLDescriptor->UniqueID = 100; - tsLDescriptor->Label = "ZASF"; - tsLDescriptor->Properties = 0; - tsLDescriptor->Name = "ZynAddSubFX"; - tsLDescriptor->Maker = "Nasca Octavian Paul "; - tsLDescriptor->Copyright = "GNU General Public License v.2"; - tsLDescriptor->PortCount = 2; - - port_descriptors = (LADSPA_PortDescriptor *) - calloc(tsLDescriptor->PortCount, sizeof - (LADSPA_PortDescriptor)); - tsLDescriptor->PortDescriptors = - (const LADSPA_PortDescriptor *) port_descriptors; - - port_range_hints = (LADSPA_PortRangeHint *) - calloc(tsLDescriptor->PortCount, sizeof - (LADSPA_PortRangeHint)); - tsLDescriptor->PortRangeHints = - (const LADSPA_PortRangeHint *) port_range_hints; - - port_names = (char **) calloc(tsLDescriptor->PortCount, sizeof(char *)); - tsLDescriptor->PortNames = (const char **) port_names; - - port_descriptors[0] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO; - port_names[0] = "Output L"; - port_range_hints[0].HintDescriptor = 0; - port_descriptors[1] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO; - port_names[1] = "Output R"; - port_range_hints[1].HintDescriptor = 0; - - tsLDescriptor->activate = activateTS; - tsLDescriptor->cleanup = cleanupTS; - tsLDescriptor->connect_port = connectPortTS; - tsLDescriptor->deactivate = NULL; - tsLDescriptor->instantiate = instantiateTS; - tsLDescriptor->run = runTSWrapper; - tsLDescriptor->run_adding = NULL; - tsLDescriptor->set_run_adding_gain = NULL; - } - - tsDDescriptor = (DSSI_Descriptor *) malloc(sizeof(DSSI_Descriptor)); - if (tsDDescriptor) { - tsDDescriptor->DSSI_API_Version = 1; - tsDDescriptor->LADSPA_Plugin = tsLDescriptor; - tsDDescriptor->configure = NULL; - tsDDescriptor->get_program = NULL; - tsDDescriptor->get_midi_controller_for_port = getControllerTS; - tsDDescriptor->select_program = NULL; - tsDDescriptor->run_synth = runTS; - tsDDescriptor->run_synth_adding = NULL; - tsDDescriptor->run_multiple_synths = NULL; - tsDDescriptor->run_multiple_synths_adding = NULL; - } - -}; - -void _fini(){ -}; - - - - - - - -//the constructor and the destructor are defined in main.C -/* -void VSTSynth::process (float **inputs, float **outputs, long sampleframes){ - float *outl=outputs[0]; - float *outr=outputs[1]; - pthread_mutex_lock(&vmaster->mutex); - vmaster->GetAudioOutSamples(sampleframes,(int) getSampleRate(),outl,outr); - pthread_mutex_unlock(&vmaster->mutex); -}; - -void VSTSynth::processReplacing (float **inputs, float **outputs, long sampleframes){ - process(inputs,outputs,sampleframes); -}; - -long int VSTSynth::canDo(char *txt){ - if (strcmp(txt,"receiveVstEvents")==0) return (1); - if (strcmp(txt,"receiveVstMidiEvent")==0) return (1); - return(-1); -}; - -bool VSTSynth::getVendorString(char *txt){ - strcpy(txt,"Nasca O. Paul"); - return(true); -}; - -bool VSTSynth::getProductString(char *txt){ - strcpy(txt,"ZynAddSubFX"); - return(true); -}; - -void VSTSynth::resume(){ - wantEvents(); -}; - -*/ diff --git a/plugins/zynaddsubfx/src/Output/DSSIaudiooutput.cpp b/plugins/zynaddsubfx/src/Output/DSSIaudiooutput.cpp new file mode 100644 index 000000000..7137abc9d --- /dev/null +++ b/plugins/zynaddsubfx/src/Output/DSSIaudiooutput.cpp @@ -0,0 +1,288 @@ +/* + ZynAddSubFX - a software synthesizer + + DSSIaudiooutput.C - Audio functions for DSSI + Copyright (C) 2002 Nasca Octavian Paul + Author: Nasca Octavian Paul + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +//this file contains code used from trivial_synth.c from +//the DSSI (published by Steve Harris under public domain) as a template +//the code is incomplete +#include +#include "DSSIaudiooutput.h" + +static LADSPA_Descriptor *tsLDescriptor = NULL; +static DSSI_Descriptor *tsDDescriptor = NULL; + +typedef struct { + LADSPA_Data *outl; + LADSPA_Data *outr; +// note_data data[MIDI_NOTES]; +// float omega[MIDI_NOTES]; +} TS; + + +static void cleanupTS(LADSPA_Handle instance) +{ + free(instance); +} +static void connectPortTS(LADSPA_Handle instance, unsigned long port, + LADSPA_Data * data) +{ + TS *plugin; + plugin = (TS *) instance; + switch (port) { + case 0: + plugin->outl = data; + break; + case 1: + plugin->outr = data; + break; + } +} + +const LADSPA_Descriptor *ladspa_descriptor(unsigned long index) +{ + switch (index) { + case 0: + return tsLDescriptor; + default: + return NULL; + } +} + +const DSSI_Descriptor *dssi_descriptor(unsigned long index) +{ +// FILE *a=fopen("/tmp/zzzzz11z","w"); +// fprintf(a,"aaaaaaaaaaa TEST\n"); +// fclose(a); + switch (index) { + case 0: + return tsDDescriptor; + default: + return NULL; + } +} + +static LADSPA_Handle instantiateTS(const LADSPA_Descriptor * descriptor, + unsigned long s_rate) +{ + + TS *plugin_data = (TS *) malloc(sizeof(TS)); + /* for (i=0; iomega[i] = M_PI * 2.0 / (double)s_rate * + pow(2.0, (i-69.0) / 12.0); + } + */ + return (LADSPA_Handle) plugin_data; +} + +static void activateTS(LADSPA_Handle instance) +{ + TS *plugin_data = (TS *) instance; + +// for (i=0; idata[i].active = 0; +// } +} + + +static void runTS(LADSPA_Handle instance, unsigned long sample_count, + snd_seq_event_t *events, unsigned long event_count) +{ + TS *plugin_data = (TS *) instance; +// LADSPA_Data *const output = plugin_data->output; +// LADSPA_Data freq = *(plugin_data->freq); +// LADSPA_Data vol = *(plugin_data->vol); +// note_data *data = plugin_data->data; + unsigned long pos; + unsigned long event_pos; + unsigned long note; + + /* if (freq < 1.0) { + freq = 440.0f; + } + if (vol < 0.000001) { + vol = 1.0f; + } + + if (event_count > 0) { + printf("trivial_synth: have %ld events\n", event_count); + } + + for (pos = 0, event_pos = 0; pos < sample_count; pos++) { + + while (event_pos < event_count + && pos == events[event_pos].time.tick) { + + printf("trivial_synth: event type %d\n", events[event_pos].type); + + if (events[event_pos].type == SND_SEQ_EVENT_NOTEON) { + data[events[event_pos].data.note.note].amp = + events[event_pos].data.note.velocity / 512.0f; + data[events[event_pos].data.note.note]. + active = events[event_pos].data.note.velocity > 0; + data[events[event_pos].data.note.note]. + phase = 0.0; + } else if (events[event_pos].type == SND_SEQ_EVENT_NOTEOFF) { + data[events[event_pos].data.note.note]. + active = 0; + } + event_pos++; + } + + output[pos] = 0.0f; + for (note = 0; note < MIDI_NOTES; note++) { + if (data[note].active) { + output[pos] += sin(data[note].phase) * data[note].amp * vol; + data[note].phase += plugin_data->omega[note] * freq; + if (data[note].phase > M_PI * 2.0) { + data[note].phase -= M_PI * 2.0; + } + } + } + } + */ +} + + +static void runTSWrapper(LADSPA_Handle instance, + unsigned long sample_count) +{ + runTS(instance, sample_count, NULL, 0); +} + +int getControllerTS(LADSPA_Handle instance, unsigned long port) +{ + return -1; +} + +void _init() +{ + char **port_names; + LADSPA_PortDescriptor *port_descriptors; + LADSPA_PortRangeHint *port_range_hints; + + FILE *a=fopen("/tmp/zzzzzz","w"); + fprintf(a,"aaaaaaaaaaa TEST\n"); + fclose(a); + + + tsLDescriptor = (LADSPA_Descriptor *) malloc(sizeof(LADSPA_Descriptor)); + if (tsLDescriptor) { + tsLDescriptor->UniqueID = 100; + tsLDescriptor->Label = "ZASF"; + tsLDescriptor->Properties = 0; + tsLDescriptor->Name = "ZynAddSubFX"; + tsLDescriptor->Maker = "Nasca Octavian Paul "; + tsLDescriptor->Copyright = "GNU General Public License v.2"; + tsLDescriptor->PortCount = 2; + + port_descriptors = (LADSPA_PortDescriptor *) + calloc(tsLDescriptor->PortCount, sizeof + (LADSPA_PortDescriptor)); + tsLDescriptor->PortDescriptors = + (const LADSPA_PortDescriptor *) port_descriptors; + + port_range_hints = (LADSPA_PortRangeHint *) + calloc(tsLDescriptor->PortCount, sizeof + (LADSPA_PortRangeHint)); + tsLDescriptor->PortRangeHints = + (const LADSPA_PortRangeHint *) port_range_hints; + + port_names = (char **) calloc(tsLDescriptor->PortCount, sizeof(char *)); + tsLDescriptor->PortNames = (const char **) port_names; + + port_descriptors[0] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO; + port_names[0] = "Output L"; + port_range_hints[0].HintDescriptor = 0; + port_descriptors[1] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO; + port_names[1] = "Output R"; + port_range_hints[1].HintDescriptor = 0; + + tsLDescriptor->activate = activateTS; + tsLDescriptor->cleanup = cleanupTS; + tsLDescriptor->connect_port = connectPortTS; + tsLDescriptor->deactivate = NULL; + tsLDescriptor->instantiate = instantiateTS; + tsLDescriptor->run = runTSWrapper; + tsLDescriptor->run_adding = NULL; + tsLDescriptor->set_run_adding_gain = NULL; + } + + tsDDescriptor = (DSSI_Descriptor *) malloc(sizeof(DSSI_Descriptor)); + if (tsDDescriptor) { + tsDDescriptor->DSSI_API_Version = 1; + tsDDescriptor->LADSPA_Plugin = tsLDescriptor; + tsDDescriptor->configure = NULL; + tsDDescriptor->get_program = NULL; + tsDDescriptor->get_midi_controller_for_port = getControllerTS; + tsDDescriptor->select_program = NULL; + tsDDescriptor->run_synth = runTS; + tsDDescriptor->run_synth_adding = NULL; + tsDDescriptor->run_multiple_synths = NULL; + tsDDescriptor->run_multiple_synths_adding = NULL; + } + +}; + +void _fini() +{ +}; + + + + + + + +//the constructor and the destructor are defined in main.C +/* +void VSTSynth::process (float **inputs, float **outputs, long sampleframes){ + float *outl=outputs[0]; + float *outr=outputs[1]; + pthread_mutex_lock(&vmaster->mutex); + vmaster->GetAudioOutSamples(sampleframes,(int) getSampleRate(),outl,outr); + pthread_mutex_unlock(&vmaster->mutex); +}; + +void VSTSynth::processReplacing (float **inputs, float **outputs, long sampleframes){ + process(inputs,outputs,sampleframes); +}; + +long int VSTSynth::canDo(char *txt){ + if (strcmp(txt,"receiveVstEvents")==0) return (1); + if (strcmp(txt,"receiveVstMidiEvent")==0) return (1); + return(-1); +}; + +bool VSTSynth::getVendorString(char *txt){ + strcpy(txt,"Nasca O. Paul"); + return(true); +}; + +bool VSTSynth::getProductString(char *txt){ + strcpy(txt,"ZynAddSubFX"); + return(true); +}; + +void VSTSynth::resume(){ + wantEvents(); +}; + +*/ diff --git a/plugins/zynaddsubfx/src/Output/DSSIaudiooutput.h b/plugins/zynaddsubfx/src/Output/DSSIaudiooutput.h index fb93c40c5..6ca808fbf 100644 --- a/plugins/zynaddsubfx/src/Output/DSSIaudiooutput.h +++ b/plugins/zynaddsubfx/src/Output/DSSIaudiooutput.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + VSTaudiooutput.h - Audio output for VST Copyright (C) 2002 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -36,7 +36,7 @@ class VSTSynth:public AudioEffectX{ public: VSTSynth (audioMasterCallback audioMaster); ~VSTSynth(); - + virtual void process (float **inputs, float **outputs, long sampleframes); virtual void processReplacing (float **inputs, float **outputs, long sampleframes); virtual long processEvents(VstEvents *events);//this is used for Midi input @@ -44,9 +44,9 @@ class VSTSynth:public AudioEffectX{ virtual bool getVendorString(char *txt); virtual bool getProductString(char *txt); virtual void resume(); - + virtual long getChunk(void** data,bool isPreset=false); - virtual void setChunk(void *data,long size,bool isPreset=false); + virtual void setChunk(void *data,long size,bool isPreset=false); MasterUI *ui; int Pexitprogram; diff --git a/plugins/zynaddsubfx/src/Output/JACK_RTaudiooutput.C b/plugins/zynaddsubfx/src/Output/JACK_RTaudiooutput.cpp similarity index 53% rename from plugins/zynaddsubfx/src/Output/JACK_RTaudiooutput.C rename to plugins/zynaddsubfx/src/Output/JACK_RTaudiooutput.cpp index 90af1975d..ca568e08b 100644 --- a/plugins/zynaddsubfx/src/Output/JACK_RTaudiooutput.C +++ b/plugins/zynaddsubfx/src/Output/JACK_RTaudiooutput.cpp @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + JACKaudiooutput.C - Audio output for JACK Copyright (C) 2002 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -26,7 +26,8 @@ #include -extern "C" { +extern "C" +{ #include }; #include "JACKaudiooutput.h" @@ -50,89 +51,92 @@ pthread_mutex_t zyn_thread_lock=PTHREAD_MUTEX_INITIALIZER; pthread_t bthr; -bool JACKaudiooutputinit(Master *master_){ +bool JACKaudiooutputinit(Master *master_) +{ jackmaster=master_; jackclient=0; char tmpstr[100]; jackoutl=new REALTYPE [SOUND_BUFFER_SIZE]; jackoutr=new REALTYPE [SOUND_BUFFER_SIZE]; - + int rbbufsize=SOUND_BUFFER_SIZE*sizeof (REALTYPE)*2*2; printf("%d\n",rbbufsize); rb=jack_ringbuffer_create(rbbufsize); for (int i=0;ibuf[i]=0.0; - for (int i=0;i<15;i++){ - if (i!=0) snprintf(tmpstr,100,"ZynAddSubFX_%d",i); - else snprintf(tmpstr,100,"ZynAddSubFX"); - jackclient=jack_client_new(tmpstr); - if (jackclient!=0) break; + for (int i=0;i<15;i++) { + if (i!=0) snprintf(tmpstr,100,"ZynAddSubFX_%d",i); + else snprintf(tmpstr,100,"ZynAddSubFX"); + jackclient=jack_client_new(tmpstr); + if (jackclient!=0) break; }; if (jackclient==0) { - fprintf(stderr,"\nERROR: Cannot make a jack client (possible reasons: JACK server is not running or jackd is launched by root and zynaddsubfx by another user.).\n\n\n"); - return(false); + fprintf(stderr,"\nERROR: Cannot make a jack client (possible reasons: JACK server is not running or jackd is launched by root and zynaddsubfx by another user.).\n\n\n"); + return(false); }; fprintf(stderr,"Internal SampleRate = %d\nJack Output SampleRate= %d\n",SAMPLE_RATE,jack_get_sample_rate(jackclient)); - if ((unsigned int)jack_get_sample_rate(jackclient)!=(unsigned int) SAMPLE_RATE) - fprintf(stderr,"It is recomanded that the both samplerates to be equal.\n"); - - jack_set_process_callback(jackclient,jackprocess,0); - jack_set_sample_rate_callback(jackclient,jacksrate,0); - jack_on_shutdown(jackclient,jackshutdown,0); - - outport_left=jack_port_register(jackclient,"out_1", - JACK_DEFAULT_AUDIO_TYPE,JackPortIsOutput|JackPortIsTerminal,0); - outport_right=jack_port_register(jackclient,"out_2", - JACK_DEFAULT_AUDIO_TYPE,JackPortIsOutput|JackPortIsTerminal,0); + if ((unsigned int)jack_get_sample_rate(jackclient)!=(unsigned int) SAMPLE_RATE) + fprintf(stderr,"It is recomanded that the both samplerates to be equal.\n"); - if (jack_activate(jackclient)){ - fprintf(stderr,"Cannot activate jack client\n"); - return(false); + jack_set_process_callback(jackclient,jackprocess,0); + jack_set_sample_rate_callback(jackclient,jacksrate,0); + jack_on_shutdown(jackclient,jackshutdown,0); + + outport_left=jack_port_register(jackclient,"out_1", + JACK_DEFAULT_AUDIO_TYPE,JackPortIsOutput|JackPortIsTerminal,0); + outport_right=jack_port_register(jackclient,"out_2", + JACK_DEFAULT_AUDIO_TYPE,JackPortIsOutput|JackPortIsTerminal,0); + + if (jack_activate(jackclient)) { + fprintf(stderr,"Cannot activate jack client\n"); + return(false); }; pthread_create(&bthr,NULL,thread_blocked,NULL); - + /* jack_connect(jackclient,jack_port_name(outport_left),"alsa_pcm:out_1"); jack_connect(jackclient,jack_port_name(outport_right),"alsa_pcm:out_2"); */ - - return(true); + + return(true); }; -void *thread_blocked(void *arg){ +void *thread_blocked(void *arg) +{ int datasize=SOUND_BUFFER_SIZE*sizeof (REALTYPE); //try to get realtime sched_param sc; sc.sched_priority=50; int err=sched_setscheduler(0,SCHED_FIFO,&sc); - + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL); pthread_mutex_lock(&zyn_thread_lock); - while (jackfinish==0){ - while (jack_ringbuffer_write_space(rb)>=datasize){ - pthread_mutex_lock(&jackmaster->mutex); - jackmaster->GetAudioOutSamples(SOUND_BUFFER_SIZE,jack_get_sample_rate(jackclient),jackoutl,jackoutr); - pthread_mutex_unlock(&jackmaster->mutex); - - jack_ringbuffer_write(rb, (char *) jackoutl,datasize); - jack_ringbuffer_write(rb, (char *) jackoutr,datasize); - }; - pthread_cond_wait(&more_data,&zyn_thread_lock); + while (jackfinish==0) { + while (jack_ringbuffer_write_space(rb)>=datasize) { + pthread_mutex_lock(&jackmaster->mutex); + jackmaster->GetAudioOutSamples(SOUND_BUFFER_SIZE,jack_get_sample_rate(jackclient),jackoutl,jackoutr); + pthread_mutex_unlock(&jackmaster->mutex); + + jack_ringbuffer_write(rb, (char *) jackoutl,datasize); + jack_ringbuffer_write(rb, (char *) jackoutr,datasize); + }; + pthread_cond_wait(&more_data,&zyn_thread_lock); }; pthread_mutex_unlock(&zyn_thread_lock); - + return(0); }; -int jackprocess(jack_nframes_t nframes,void *arg){ +int jackprocess(jack_nframes_t nframes,void *arg) +{ jack_default_audio_sample_t *outl=(jack_default_audio_sample_t *) jack_port_get_buffer (outport_left, nframes); jack_default_audio_sample_t *outr=(jack_default_audio_sample_t *) jack_port_get_buffer (outport_right, nframes); @@ -141,42 +145,44 @@ int jackprocess(jack_nframes_t nframes,void *arg){ int data_read=0; - if (jack_ringbuffer_read_space(rb)>=(2*incoming_datasize)){ - if (datasize>incoming_datasize){ - data_read=0; - while (data_read < datasize){ - jack_ringbuffer_read(rb, (char *) outl+data_read,datasize); - jack_ringbuffer_read(rb, (char *) outr+data_read,datasize); - data_read+=incoming_datasize; - }; - } else if (datasize==incoming_datasize){ - jack_ringbuffer_read(rb, (char *) outl,datasize); - jack_ringbuffer_read(rb, (char *) outr,datasize); - } else { - }; + if (jack_ringbuffer_read_space(rb)>=(2*incoming_datasize)) { + if (datasize>incoming_datasize) { + data_read=0; + while (data_read < datasize) { + jack_ringbuffer_read(rb, (char *) outl+data_read,datasize); + jack_ringbuffer_read(rb, (char *) outr+data_read,datasize); + data_read+=incoming_datasize; + }; + } else if (datasize==incoming_datasize) { + jack_ringbuffer_read(rb, (char *) outl,datasize); + jack_ringbuffer_read(rb, (char *) outr,datasize); + } else { + }; } else {//the ringbuffer is empty or there are too small amount of samples in it - for (int i=0;i=datasize){ - jack_ringbuffer_read(rb, (char *) outl,datasize); - jack_ringbuffer_read(rb, (char *) outr,datasize); - } else {//the ringbuffer is empty or there are too small amount of samples in it - for (int i=0;i=datasize){ + jack_ringbuffer_read(rb, (char *) outl,datasize); + jack_ringbuffer_read(rb, (char *) outr,datasize); + } else {//the ringbuffer is empty or there are too small amount of samples in it + for (int i=0;i -#include -#include "JACKaudiooutput.h" - -Master *jackmaster; -jack_client_t *jackclient; -char jackname[100]; -jack_port_t *outport_left,*outport_right,*midi_inport; - -int jackprocess(jack_nframes_t nframes,void *arg); -int jacksrate(jack_nframes_t nframes,void *arg); -void jackshutdown(void *arg); - -bool JACKaudiooutputinit(Master *master_){ - jackmaster=master_; - jackclient=0; - - for (int i=0;i<15;i++){ - if (i!=0) snprintf(jackname,100,"ZynAddSubFX_%d",i); - else snprintf(jackname,100,"ZynAddSubFX"); - jackclient=jack_client_new(jackname); - if (jackclient!=0) break; - }; - - if (jackclient==0) { - fprintf(stderr,"\nERROR: Cannot make a jack client (possible reasons: JACK server is not running or jackd is launched by root and zynaddsubfx by another user.).\n"); - return(false); - }; - - fprintf(stderr,"Internal SampleRate = %d\nJack Output SampleRate= %d\n",SAMPLE_RATE,jack_get_sample_rate(jackclient)); - if ((unsigned int)jack_get_sample_rate(jackclient)!=(unsigned int) SAMPLE_RATE) - fprintf(stderr,"It is recomanded that the both samplerates to be equal.\n"); - - jack_set_process_callback(jackclient,jackprocess,0); - jack_set_sample_rate_callback(jackclient,jacksrate,0); - jack_on_shutdown(jackclient,jackshutdown,0); - - outport_left=jack_port_register(jackclient,"out_1", - JACK_DEFAULT_AUDIO_TYPE,JackPortIsOutput|JackPortIsTerminal,0); - outport_right=jack_port_register(jackclient,"out_2", - JACK_DEFAULT_AUDIO_TYPE,JackPortIsOutput|JackPortIsTerminal,0); - midi_inport=jack_port_register(jackclient,"midi_input", - JACK_DEFAULT_MIDI_TYPE,JackPortIsInput|JackPortIsTerminal,0); - - if (jack_activate(jackclient)){ - fprintf(stderr,"Cannot activate jack client\n"); - return(false); - }; - - /* - jack_connect(jackclient,jack_port_name(outport_left),"alsa_pcm:out_1"); - jack_connect(jackclient,jack_port_name(outport_right),"alsa_pcm:out_2"); - */ - return(true); -}; - -int jackprocess(jack_nframes_t nframes,void *arg){ - jack_default_audio_sample_t *outl=(jack_default_audio_sample_t *) jack_port_get_buffer (outport_left, nframes); - jack_default_audio_sample_t *outr=(jack_default_audio_sample_t *) jack_port_get_buffer (outport_right, nframes); - - if (!pthread_mutex_trylock(&jackmaster->mutex)) { - JACKhandlemidi(nframes); - jackmaster->GetAudioOutSamples(nframes,jack_get_sample_rate(jackclient),outl,outr); - pthread_mutex_unlock(&jackmaster->mutex); - } - else { - memset(outl, 0, sizeof(jack_default_audio_sample_t) * nframes); - memset(outr, 0, sizeof(jack_default_audio_sample_t) * nframes); - } - - return(0); -}; - -void JACKfinish(){ - jack_client_close(jackclient); -}; - -int jacksrate(jack_nframes_t nframes,void *arg){ - - return(0); -}; - -void jackshutdown(void *arg){ -}; - - -void JACKhandlemidi(unsigned long frames) { - - // We must have the master mutex before we run this function - - // XXX This is really nasty, not only do we lose the sample accuracy of - // JACK MIDI, but any accuracy at all below the buffer size - - void* midi_buf = jack_port_get_buffer(midi_inport, frames); - jack_midi_event_t jack_midi_event; - jack_nframes_t event_index = 0; - jack_nframes_t event_count = - jack_midi_port_get_info(midi_buf, frames)->event_count; - unsigned char* midi_data; - unsigned char type, chan; - - while (event_index < event_count) { - - jack_midi_event_get(&jack_midi_event, midi_buf, event_index, frames); - midi_data = jack_midi_event.buffer; - type = midi_data[0] & 0xF0; - chan = midi_data[0] & 0x0F; - - switch (type) { - - case 0x80: /* note-off */ - jackmaster->NoteOff(chan, midi_data[1]); - break; - - case 0x90: /* note-on */ - jackmaster->NoteOn(chan, midi_data[1], midi_data[2]); - break; - - case 0xB0: /* controller */ - jackmaster->SetController(chan, midi_data[1], midi_data[2]); - break; - - case 0xE0: /* pitch bend */ - jackmaster->SetController(chan, C_pitchwheel, - ((midi_data[2] << 7) | midi_data[1])); - break; - - /* XXX TODO: handle MSB/LSB controllers and RPNs and NRPNs */ - } - - event_index++; - } - -} - - -const char* JACKgetname() { - if (jackclient != NULL) - return jackname; - return NULL; -} diff --git a/plugins/zynaddsubfx/src/Output/JACKaudiooutput.cpp b/plugins/zynaddsubfx/src/Output/JACKaudiooutput.cpp new file mode 100644 index 000000000..82f97369d --- /dev/null +++ b/plugins/zynaddsubfx/src/Output/JACKaudiooutput.cpp @@ -0,0 +1,163 @@ +/* + ZynAddSubFX - a software synthesizer + + JACKaudiooutput.C - Audio output for JACK + Copyright (C) 2002 Nasca Octavian Paul + Author: Nasca Octavian Paul + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include +#include +#include "JACKaudiooutput.h" + +Master *jackmaster; +jack_client_t *jackclient; +char jackname[100]; +jack_port_t *outport_left,*outport_right,*midi_inport; + +int jackprocess(jack_nframes_t nframes,void *arg); +int jacksrate(jack_nframes_t nframes,void *arg); +void jackshutdown(void *arg); + +bool JACKaudiooutputinit(Master *master_) +{ + jackmaster=master_; + jackclient=0; + + for (int i=0;i<15;i++) { + if (i!=0) snprintf(jackname,100,"ZynAddSubFX_%d",i); + else snprintf(jackname,100,"ZynAddSubFX"); + jackclient=jack_client_new(jackname); + if (jackclient!=0) break; + }; + + if (jackclient==0) { + fprintf(stderr,"\nERROR: Cannot make a jack client (possible reasons: JACK server is not running or jackd is launched by root and zynaddsubfx by another user.).\n"); + return(false); + }; + + fprintf(stderr,"Internal SampleRate = %d\nJack Output SampleRate= %d\n",SAMPLE_RATE,jack_get_sample_rate(jackclient)); + if ((unsigned int)jack_get_sample_rate(jackclient)!=(unsigned int) SAMPLE_RATE) + fprintf(stderr,"It is recomanded that the both samplerates to be equal.\n"); + + jack_set_process_callback(jackclient,jackprocess,0); + jack_set_sample_rate_callback(jackclient,jacksrate,0); + jack_on_shutdown(jackclient,jackshutdown,0); + + outport_left=jack_port_register(jackclient,"out_1", + JACK_DEFAULT_AUDIO_TYPE,JackPortIsOutput|JackPortIsTerminal,0); + outport_right=jack_port_register(jackclient,"out_2", + JACK_DEFAULT_AUDIO_TYPE,JackPortIsOutput|JackPortIsTerminal,0); + midi_inport=jack_port_register(jackclient,"midi_input", + JACK_DEFAULT_MIDI_TYPE,JackPortIsInput|JackPortIsTerminal,0); + + if (jack_activate(jackclient)) { + fprintf(stderr,"Cannot activate jack client\n"); + return(false); + }; + + /* + jack_connect(jackclient,jack_port_name(outport_left),"alsa_pcm:out_1"); + jack_connect(jackclient,jack_port_name(outport_right),"alsa_pcm:out_2"); + */ + return(true); +}; + +int jackprocess(jack_nframes_t nframes,void *arg) +{ + jack_default_audio_sample_t *outl=(jack_default_audio_sample_t *) jack_port_get_buffer (outport_left, nframes); + jack_default_audio_sample_t *outr=(jack_default_audio_sample_t *) jack_port_get_buffer (outport_right, nframes); + + if (!pthread_mutex_trylock(&jackmaster->mutex)) { + JACKhandlemidi(nframes); + jackmaster->GetAudioOutSamples(nframes,jack_get_sample_rate(jackclient),outl,outr); + pthread_mutex_unlock(&jackmaster->mutex); + } else { + memset(outl, 0, sizeof(jack_default_audio_sample_t) * nframes); + memset(outr, 0, sizeof(jack_default_audio_sample_t) * nframes); + } + + return(0); +}; + +void JACKfinish() +{ + jack_client_close(jackclient); +}; + +int jacksrate(jack_nframes_t nframes,void *arg) +{ + + return(0); +}; + +void jackshutdown(void *arg) +{ +}; + + +void JACKhandlemidi(unsigned long frames) +{ + + // We must have the master mutex before we run this function + + // XXX This is really nasty, not only do we lose the sample accuracy of + // JACK MIDI, but any accuracy at all below the buffer size + + void* midi_buf = jack_port_get_buffer(midi_inport, frames); + jack_midi_event_t jack_midi_event; + jack_nframes_t event_index = 0; + unsigned char* midi_data; + unsigned char type, chan; + + while (jack_midi_event_get(&jack_midi_event,midi_buf, event_index++) == 0) { + midi_data = jack_midi_event.buffer; + type = midi_data[0] & 0xF0; + chan = midi_data[0] & 0x0F; + + switch (type) { + + case 0x80: /* note-off */ + jackmaster->NoteOff(chan, midi_data[1]); + break; + + case 0x90: /* note-on */ + jackmaster->NoteOn(chan, midi_data[1], midi_data[2]); + break; + + case 0xB0: /* controller */ + jackmaster->SetController(chan, midi_data[1], midi_data[2]); + break; + + case 0xE0: /* pitch bend */ + jackmaster->SetController(chan, C_pitchwheel, + ((midi_data[2] << 7) | midi_data[1])); + break; + + /* XXX TODO: handle MSB/LSB controllers and RPNs and NRPNs */ + } + } + +} + + +const char* JACKgetname() +{ + if (jackclient != NULL) + return jackname; + return NULL; +} diff --git a/plugins/zynaddsubfx/src/Output/JACKaudiooutput.h b/plugins/zynaddsubfx/src/Output/JACKaudiooutput.h index 6b3f3360f..7061f8c16 100644 --- a/plugins/zynaddsubfx/src/Output/JACKaudiooutput.h +++ b/plugins/zynaddsubfx/src/Output/JACKaudiooutput.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + JACKaudiooutput.h - Audio output for JACK Copyright (C) 2002 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, diff --git a/plugins/zynaddsubfx/src/Output/OSSaudiooutput.C b/plugins/zynaddsubfx/src/Output/OSSaudiooutput.cpp similarity index 78% rename from plugins/zynaddsubfx/src/Output/OSSaudiooutput.C rename to plugins/zynaddsubfx/src/Output/OSSaudiooutput.cpp index aea0b444e..d10d32c96 100644 --- a/plugins/zynaddsubfx/src/Output/OSSaudiooutput.C +++ b/plugins/zynaddsubfx/src/Output/OSSaudiooutput.cpp @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + OSSaudiooutput.C - Audio output for Open Sound System Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -27,25 +27,30 @@ #include #include #include +#include #include "OSSaudiooutput.h" #include "../Misc/Util.h" +#include "../globals.h" +using namespace std; -OSSaudiooutput::OSSaudiooutput(){ +OSSaudiooutput::OSSaudiooutput() +{ int i; int snd_bitsize=16; snd_fragment=0x00080009;//fragment size (?) snd_stereo=1;//stereo snd_format=AFMT_S16_LE; snd_samplerate=SAMPLE_RATE; - + smps=new short int[SOUND_BUFFER_SIZE*2]; for (i=0;i1.0) l=1.0; - if (r<-1.0) r=-1.0; else if (r>1.0) r=1.0; - - smps[i*2]=(short int) (l*32767.0); - smps[i*2+1]=(short int) (r*32767.0); + for (i=0;i1.0) l=1.0; + if (r<-1.0) r=-1.0; + else if (r>1.0) r=1.0; + + smps[i*2]=(short int) (l*32767.0); + smps[i*2+1]=(short int) (r*32767.0); }; write(snd_handle,smps,SOUND_BUFFER_SIZE*4);// *2 because is 16 bit, again * 2 because is stereo }; -OSSaudiooutput::~OSSaudiooutput(){ +OSSaudiooutput::~OSSaudiooutput() +{ close(snd_handle); delete [] smps; }; diff --git a/plugins/zynaddsubfx/src/Output/OSSaudiooutput.h b/plugins/zynaddsubfx/src/Output/OSSaudiooutput.h index 43d47aa6f..3f130e084 100644 --- a/plugins/zynaddsubfx/src/Output/OSSaudiooutput.h +++ b/plugins/zynaddsubfx/src/Output/OSSaudiooutput.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + OSSaudiooutput.h - Audio output for Open Sound System Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -23,25 +23,25 @@ #ifndef OSS_AUDIO_OUTPUT_H #define OSS_AUDIO_OUTPUT_H - -#include #include "../globals.h" -class OSSaudiooutput{ - public: - OSSaudiooutput(); - ~OSSaudiooutput(); - //the out is [-1.0 .. 1.0] - /* smp_left[] and smp_right[] has the size of SOUND_BUFFER_SIZE */ - void OSSout(REALTYPE *smp_left,REALTYPE *smp_right); - private: - int snd_handle; - int snd_fragment; - int snd_stereo; - int snd_format; - int snd_samplerate; - - short int *smps;//Samples to be sent to soundcard +class OSSaudiooutput +{ +public: + OSSaudiooutput(); + ~OSSaudiooutput(); + + //the out is [-1.0 .. 1.0] + /* smp_left[] and smp_right[] has the size of SOUND_BUFFER_SIZE */ + void OSSout(REALTYPE *smp_left,REALTYPE *smp_right); +private: + int snd_handle; + int snd_fragment; + int snd_stereo; + int snd_format; + int snd_samplerate; + + short int *smps;//Samples to be sent to soundcard }; #endif diff --git a/plugins/zynaddsubfx/src/Output/PAaudiooutput.C b/plugins/zynaddsubfx/src/Output/PAaudiooutput.cpp similarity index 74% rename from plugins/zynaddsubfx/src/Output/PAaudiooutput.C rename to plugins/zynaddsubfx/src/Output/PAaudiooutput.cpp index 6c5b9dc78..161153ffd 100644 --- a/plugins/zynaddsubfx/src/Output/PAaudiooutput.C +++ b/plugins/zynaddsubfx/src/Output/PAaudiooutput.cpp @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + PAaudiooutput.C - Audio output for PortAudio Copyright (C) 2002 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -27,30 +27,32 @@ PaStream *stream; REALTYPE *outl,*outr; int PAprocess(void *inputBuffer,void *outputBuffer, - unsigned long framesPerBuffer, - PaTimestamp outTime,void *userData){ + unsigned long framesPerBuffer, + PaTimestamp outTime,void *userData) +{ if (framesPerBuffer!=SOUND_BUFFER_SIZE) { - fprintf(stderr,"Bug: PAudioOutput::PAprocess SOUND_BUFFER_SIZE!=framesPerBuffer"); + fprintf(stderr,"Bug: PAudioOutput::PAprocess SOUND_BUFFER_SIZE!=framesPerBuffer"); fprintf(stderr,"%d %d\n",framesPerBuffer,SOUND_BUFFER_SIZE); }; pthread_mutex_lock(&PAmaster->mutex); - PAmaster->GetAudioOutSamples(SOUND_BUFFER_SIZE,SAMPLE_RATE,outl,outr); + PAmaster->GetAudioOutSamples(SOUND_BUFFER_SIZE,SAMPLE_RATE,outl,outr); pthread_mutex_unlock(&PAmaster->mutex); float *out=(float *)outputBuffer; - for (int i=0;i=SOUND_BUFFER_SIZE) break;//this should never happens, except only when framesPerBuffer!>SOUND_BUFFER_SIZE - out[i*2]=outl[i]; - out[i*2+1]=outr[i]; + for (int i=0;i=SOUND_BUFFER_SIZE) break;//this should never happens, except only when framesPerBuffer!>SOUND_BUFFER_SIZE + out[i*2]=outl[i]; + out[i*2+1]=outr[i]; }; return(0); }; -void PAaudiooutputinit(Master *master_){ +void PAaudiooutputinit(Master *master_) +{ PAmaster=master_; outl=new REALTYPE [SOUND_BUFFER_SIZE]; outr=new REALTYPE [SOUND_BUFFER_SIZE]; @@ -59,7 +61,8 @@ void PAaudiooutputinit(Master *master_){ Pa_StartStream(stream); }; -void PAfinish(){ +void PAfinish() +{ Pa_StopStream(stream); delete (outl); delete (outr); diff --git a/plugins/zynaddsubfx/src/Output/PAaudiooutput.h b/plugins/zynaddsubfx/src/Output/PAaudiooutput.h index c416156ec..942011d57 100644 --- a/plugins/zynaddsubfx/src/Output/PAaudiooutput.h +++ b/plugins/zynaddsubfx/src/Output/PAaudiooutput.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + PAaudiooutput.h - Audio output for PortAudio Copyright (C) 2002 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, diff --git a/plugins/zynaddsubfx/src/Output/Recorder.C b/plugins/zynaddsubfx/src/Output/Recorder.cpp similarity index 54% rename from plugins/zynaddsubfx/src/Output/Recorder.C rename to plugins/zynaddsubfx/src/Output/Recorder.cpp index 3851f3faf..388ab7f74 100644 --- a/plugins/zynaddsubfx/src/Output/Recorder.C +++ b/plugins/zynaddsubfx/src/Output/Recorder.cpp @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Recorder.C - Records sound to a file Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -20,87 +20,85 @@ */ -#include -#include -#include - -#include #include -#include -#include -#include - #include "Recorder.h" -#include -Recorder::Recorder(){ +Recorder::Recorder() +{ recordbuf_16bit=new short int [SOUND_BUFFER_SIZE*2]; status=0; notetrigger=0; - for (int i=0;i32767) tmp=32767; - recordbuf_16bit[i*2]=tmp; +void Recorder::recordbuffer(REALTYPE *outl,REALTYPE *outr) +{ + int tmp; + if (status!=2) return; + for (int i=0;i32767) tmp=32767; + recordbuf_16bit[i*2]=tmp; - tmp=(int)(outr[i]*32767.0); - if (tmp<-32768) tmp=-32768; - if (tmp>32767) tmp=32767; - recordbuf_16bit[i*2+1]=tmp; - }; - wav.write(SOUND_BUFFER_SIZE,recordbuf_16bit); + tmp=(int)(outr[i]*32767.0); + if (tmp<-32768) tmp=-32768; + if (tmp>32767) tmp=32767; + recordbuf_16bit[i*2+1]=tmp; + }; + wav.write_stereo_samples(SOUND_BUFFER_SIZE,recordbuf_16bit); }; -void Recorder::triggernow(){ +void Recorder::triggernow() +{ if (status==2) notetrigger=1; }; diff --git a/plugins/zynaddsubfx/src/Output/Recorder.h b/plugins/zynaddsubfx/src/Output/Recorder.h index cb089c0d8..059f7108f 100644 --- a/plugins/zynaddsubfx/src/Output/Recorder.h +++ b/plugins/zynaddsubfx/src/Output/Recorder.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Recorder.h - Records sound to a file Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -22,32 +22,35 @@ #ifndef RECORDER_H #define RECORDER_H - +#include #include "../globals.h" #include "WAVaudiooutput.h" -class Recorder{ - public: - Recorder(); - ~Recorder(); - int preparefile(char *filename_,int overwrite);//returns 1 if the file exists - void start(); - void stop(); - void pause(); - int recording(); - void triggernow(); - void recordbuffer(REALTYPE *outl,REALTYPE *outr); - - /* Status: - 0 - not ready(no file selected), - 1 - ready - 2 - recording */ - int status; - - private: - WAVaudiooutput wav; - short int *recordbuf_16bit; - int notetrigger; +/**Records sound to a file*/ +class Recorder +{ +public: + + Recorder(); + ~Recorder(); + int preparefile(std::string filename_,int overwrite);//returns 1 if the file exists + void start(); + void stop(); + void pause(); + int recording(); + void triggernow(); + void recordbuffer(REALTYPE *outl,REALTYPE *outr); + + /** Status: + * 0 - not ready(no file selected), + * 1 - ready + * 2 - recording */ + int status; + +private: + WAVaudiooutput wav; + short int *recordbuf_16bit; + int notetrigger; }; #endif diff --git a/plugins/zynaddsubfx/src/Output/VSTaudiooutput.C b/plugins/zynaddsubfx/src/Output/VSTaudiooutput.cpp similarity index 70% rename from plugins/zynaddsubfx/src/Output/VSTaudiooutput.C rename to plugins/zynaddsubfx/src/Output/VSTaudiooutput.cpp index 9d564cad1..6441ab092 100644 --- a/plugins/zynaddsubfx/src/Output/VSTaudiooutput.C +++ b/plugins/zynaddsubfx/src/Output/VSTaudiooutput.cpp @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + VSTaudiooutput.C - Audio output for VST Copyright (C) 2002 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -24,36 +24,42 @@ //the constructor and the destructor are defined in main.C -void VSTSynth::process (float **inputs, float **outputs, long sampleframes){ +void VSTSynth::process (float **inputs, float **outputs, long sampleframes) +{ float *outl=outputs[0]; float *outr=outputs[1]; pthread_mutex_lock(&vmaster->mutex); - vmaster->GetAudioOutSamples(sampleframes,(int) getSampleRate(),outl,outr); + vmaster->GetAudioOutSamples(sampleframes,(int) getSampleRate(),outl,outr); pthread_mutex_unlock(&vmaster->mutex); }; -void VSTSynth::processReplacing (float **inputs, float **outputs, long sampleframes){ +void VSTSynth::processReplacing (float **inputs, float **outputs, long sampleframes) +{ process(inputs,outputs,sampleframes); }; -long int VSTSynth::canDo(char *txt){ - if (strcmp(txt,"receiveVstEvents")==0) return (1); - if (strcmp(txt,"receiveVstMidiEvent")==0) return (1); - return(-1); +long int VSTSynth::canDo(char *txt) +{ + if (strcmp(txt,"receiveVstEvents")==0) return (1); + if (strcmp(txt,"receiveVstMidiEvent")==0) return (1); + return(-1); }; -bool VSTSynth::getVendorString(char *txt){ - strcpy(txt,"Nasca O. Paul"); - return(true); +bool VSTSynth::getVendorString(char *txt) +{ + strcpy(txt,"Nasca O. Paul"); + return(true); }; -bool VSTSynth::getProductString(char *txt){ - strcpy(txt,"ZynAddSubFX"); - return(true); +bool VSTSynth::getProductString(char *txt) +{ + strcpy(txt,"ZynAddSubFX"); + return(true); }; -void VSTSynth::resume(){ - wantEvents(); +void VSTSynth::resume() +{ + wantEvents(); }; diff --git a/plugins/zynaddsubfx/src/Output/VSTaudiooutput.h b/plugins/zynaddsubfx/src/Output/VSTaudiooutput.h index 0a027968e..116f33004 100644 --- a/plugins/zynaddsubfx/src/Output/VSTaudiooutput.h +++ b/plugins/zynaddsubfx/src/Output/VSTaudiooutput.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + VSTaudiooutput.h - Audio output for VST Copyright (C) 2002 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -30,27 +30,28 @@ #include "../../../vstsdk2/source/common/audioeffectx.h" -class VSTSynth:public AudioEffectX{ - public: - VSTSynth (audioMasterCallback audioMaster); - ~VSTSynth(); - - virtual void process (float **inputs, float **outputs, long sampleframes); - virtual void processReplacing (float **inputs, float **outputs, long sampleframes); - virtual long processEvents(VstEvents *events);//this is used for Midi input - virtual long int canDo(char *txt); - virtual bool getVendorString(char *txt); - virtual bool getProductString(char *txt); - virtual void resume(); - - virtual long getChunk(void** data,bool isPreset=false); - virtual long setChunk(void *data,long size,bool isPreset=false); +class VSTSynth:public AudioEffectX +{ +public: + VSTSynth (audioMasterCallback audioMaster); + ~VSTSynth(); - MasterUI *ui; - int Pexitprogram; + virtual void process (float **inputs, float **outputs, long sampleframes); + virtual void processReplacing (float **inputs, float **outputs, long sampleframes); + virtual long processEvents(VstEvents *events);//this is used for Midi input + virtual long int canDo(char *txt); + virtual bool getVendorString(char *txt); + virtual bool getProductString(char *txt); + virtual void resume(); - Master *vmaster; - pthread_t thr; + virtual long getChunk(void** data,bool isPreset=false); + virtual long setChunk(void *data,long size,bool isPreset=false); + + MasterUI *ui; + int Pexitprogram; + + Master *vmaster; + pthread_t thr; }; #endif diff --git a/plugins/zynaddsubfx/src/Output/WAVaudiooutput.C b/plugins/zynaddsubfx/src/Output/WAVaudiooutput.C deleted file mode 100644 index d305b54ad..000000000 --- a/plugins/zynaddsubfx/src/Output/WAVaudiooutput.C +++ /dev/null @@ -1,85 +0,0 @@ -/* - Copyright (C) 2006 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License (version 2) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include -#include -#include "WAVaudiooutput.h" -using namespace std; - -WAVaudiooutput::WAVaudiooutput(){ - file=NULL; - sampleswritten=0; - samplerate=44100; -}; - -WAVaudiooutput::~WAVaudiooutput(){ - close(); -}; - -bool WAVaudiooutput::newfile(string filename,int samplerate,int channels){ - close();//inchide un posibil fisier existent - file=fopen(filename.c_str(),"w"); - if (!file) return false; - this->samplerate=samplerate; - this->channels=channels; - sampleswritten=0; - char tmp[44]; - fwrite(tmp,1,44,file); - return(true); -}; - -void WAVaudiooutput::close(){ - if (file){ - unsigned int chunksize; - rewind(file); - - fwrite("RIFF",4,1,file); - chunksize=sampleswritten*4+36; - fwrite(&chunksize,4,1,file); - - fwrite("WAVEfmt ",8,1,file); - chunksize=16; - fwrite(&chunksize,4,1,file); - unsigned short int formattag=1;//uncompresed wave - fwrite(&formattag,2,1,file); - unsigned short int nchannels=channels;//stereo - fwrite(&nchannels,2,1,file); - unsigned int samplerate_=samplerate;//samplerate - fwrite(&samplerate_,4,1,file); - unsigned int bytespersec=samplerate*2*channels;//bytes/sec - fwrite(&bytespersec,4,1,file); - unsigned short int blockalign=2*channels;//2 channels * 16 bits/8 - fwrite(&blockalign,2,1,file); - unsigned short int bitspersample=16; - fwrite(&bitspersample,2,1,file); - - fwrite("data",4,1,file); - chunksize=sampleswritten*blockalign; - fwrite(&chunksize,4,1,file); - - fclose(file); - file=NULL; - }; -}; - -void WAVaudiooutput::write(int nsmps,short int *smps){ - if (!file) return; - fwrite(smps,nsmps,4,file); - sampleswritten+=nsmps; -}; - diff --git a/plugins/zynaddsubfx/src/Output/WAVaudiooutput.cpp b/plugins/zynaddsubfx/src/Output/WAVaudiooutput.cpp new file mode 100644 index 000000000..fc03243c4 --- /dev/null +++ b/plugins/zynaddsubfx/src/Output/WAVaudiooutput.cpp @@ -0,0 +1,99 @@ +/* + Copyright (C) 2006 Nasca Octavian Paul + Author: Nasca Octavian Paul + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include "WAVaudiooutput.h" +using namespace std; + +WAVaudiooutput::WAVaudiooutput() +{ + file=NULL; + sampleswritten=0; + samplerate=44100; +}; + +WAVaudiooutput::~WAVaudiooutput() +{ + close(); +}; + +bool WAVaudiooutput::newfile(string filename,int samplerate,int channels) +{ + /**\todo Move this into the Constructor*/ + close();//inchide un posibil fisier existent + file=fopen(filename.c_str(),"w"); + if (!file) return false; + this->samplerate=samplerate; + this->channels=channels; + sampleswritten=0; + char tmp[44]; + fwrite(tmp,1,44,file); + return(true); +}; + +void WAVaudiooutput::close() +{ + if (file) { + unsigned int chunksize; + rewind(file); + + fwrite("RIFF",4,1,file); + chunksize=sampleswritten*4+36; + fwrite(&chunksize,4,1,file); + + fwrite("WAVEfmt ",8,1,file); + chunksize=16; + fwrite(&chunksize,4,1,file); + unsigned short int formattag=1;//uncompresed wave + fwrite(&formattag,2,1,file); + unsigned short int nchannels=channels;//stereo + fwrite(&nchannels,2,1,file); + unsigned int samplerate_=samplerate;//samplerate + fwrite(&samplerate_,4,1,file); + unsigned int bytespersec=samplerate*2*channels;//bytes/sec + fwrite(&bytespersec,4,1,file); + unsigned short int blockalign=2*channels;//2 channels * 16 bits/8 + fwrite(&blockalign,2,1,file); + unsigned short int bitspersample=16; + fwrite(&bitspersample,2,1,file); + + fwrite("data",4,1,file); + chunksize=sampleswritten*blockalign; + fwrite(&chunksize,4,1,file); + + fclose(file); + file=NULL; + } +}; + +void WAVaudiooutput::write_stereo_samples(int nsmps,short int *smps) +{ + if (!file) return; + fwrite(smps,nsmps,4,file); + sampleswritten+=nsmps; +}; + +void WAVaudiooutput::write_mono_samples(int nsmps,short int *smps) +{ + if (!file) return; + fwrite(smps,nsmps,2,file); + sampleswritten+=nsmps; +}; + + diff --git a/plugins/zynaddsubfx/src/Output/WAVaudiooutput.h b/plugins/zynaddsubfx/src/Output/WAVaudiooutput.h index 2ae2539f3..54abae8fd 100644 --- a/plugins/zynaddsubfx/src/Output/WAVaudiooutput.h +++ b/plugins/zynaddsubfx/src/Output/WAVaudiooutput.h @@ -4,7 +4,7 @@ Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -20,22 +20,23 @@ #ifndef WAVOUTPUT_H #define WAVOUTPUT_H #include -#include -class WAVaudiooutput{ - public: - WAVaudiooutput(); - ~WAVaudiooutput(); - - bool newfile(std::string filename,int samplerate,int channels); - void close(); +class WAVaudiooutput +{ +public: + WAVaudiooutput(); + ~WAVaudiooutput(); - void write(int nsmps, short int *smps); - - private: - int sampleswritten; - int samplerate; - int channels; - FILE *file; + bool newfile(std::string filename,int samplerate,int channels); + void close(); + + void write_mono_samples(int nsmps, short int *smps); + void write_stereo_samples(int nsmps, short int *smps); + +private: + int sampleswritten; + int samplerate; + int channels; + FILE *file; }; #endif diff --git a/plugins/zynaddsubfx/src/Params/ADnoteParameters.C b/plugins/zynaddsubfx/src/Params/ADnoteParameters.C deleted file mode 100644 index c8ea7ef4f..000000000 --- a/plugins/zynaddsubfx/src/Params/ADnoteParameters.C +++ /dev/null @@ -1,637 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - ADnoteParameters.C - Parameters for ADnote (ADsynth) - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include -#include - -#include "ADnoteParameters.h" - -ADnoteParameters::ADnoteParameters(FFTwrapper *fft_):Presets(){ - setpresettype("Padsyth"); - fft=fft_; - - GlobalPar.FreqEnvelope=new EnvelopeParams(0,0); - GlobalPar.FreqEnvelope->ASRinit(64,50,64,60); - GlobalPar.FreqLfo=new LFOParams(70,0,64,0,0,0,0,0); - - GlobalPar.AmpEnvelope=new EnvelopeParams(64,1); - GlobalPar.AmpEnvelope->ADSRinit_dB(0,40,127,25); - GlobalPar.AmpLfo=new LFOParams(80,0,64,0,0,0,0,1); - - GlobalPar.GlobalFilter=new FilterParams(2,94,40); - GlobalPar.FilterEnvelope=new EnvelopeParams(0,1); - GlobalPar.FilterEnvelope->ADSRinit_filter(64,40,64,70,60,64); - GlobalPar.FilterLfo=new LFOParams(80,0,64,0,0,0,0,2); - GlobalPar.Reson=new Resonance(); - - for (int nvoice=0;nvoicedefaults(); - GlobalPar.FreqLfo->defaults(); - GlobalPar.PBandwidth=64; - - /* Amplitude Global Parameters */ - GlobalPar.PVolume=90; - GlobalPar.PPanning=64;//center - GlobalPar.PAmpVelocityScaleFunction=64; - GlobalPar.AmpEnvelope->defaults(); - GlobalPar.AmpLfo->defaults(); - GlobalPar.PPunchStrength=0; - GlobalPar.PPunchTime=60; - GlobalPar.PPunchStretch=64; - GlobalPar.PPunchVelocitySensing=72; - GlobalPar.Hrandgrouping=0; - - /* Filter Global Parameters*/ - GlobalPar.PFilterVelocityScale=64; - GlobalPar.PFilterVelocityScaleFunction=64; - GlobalPar.GlobalFilter->defaults(); - GlobalPar.FilterEnvelope->defaults(); - GlobalPar.FilterLfo->defaults(); - GlobalPar.Reson->defaults(); - - - for (int nvoice=0;nvoicedefaults(); - VoicePar[nvoice].FMSmp->defaults(); - - VoicePar[nvoice].AmpEnvelope->defaults(); - VoicePar[nvoice].AmpLfo->defaults(); - - VoicePar[nvoice].FreqEnvelope->defaults(); - VoicePar[nvoice].FreqLfo->defaults(); - - VoicePar[nvoice].VoiceFilter->defaults(); - VoicePar[nvoice].FilterEnvelope->defaults(); - VoicePar[nvoice].FilterLfo->defaults(); - - VoicePar[nvoice].FMFreqEnvelope->defaults(); - VoicePar[nvoice].FMAmpEnvelope->defaults(); -}; - - - -/* - * Init the voice parameters - */ -void ADnoteParameters::EnableVoice(int nvoice){ - VoicePar[nvoice].OscilSmp=new OscilGen(fft,GlobalPar.Reson); - VoicePar[nvoice].FMSmp=new OscilGen(fft,NULL); - - VoicePar[nvoice].AmpEnvelope=new EnvelopeParams(64,1); - VoicePar[nvoice].AmpEnvelope->ADSRinit_dB(0,100,127,100); - VoicePar[nvoice].AmpLfo=new LFOParams(90,32,64,0,0,30,0,1); - - VoicePar[nvoice].FreqEnvelope=new EnvelopeParams(0,0); - VoicePar[nvoice].FreqEnvelope->ASRinit(30,40,64,60); - VoicePar[nvoice].FreqLfo=new LFOParams(50,40,0,0,0,0,0,0); - - VoicePar[nvoice].VoiceFilter=new FilterParams(2,50,60); - VoicePar[nvoice].FilterEnvelope=new EnvelopeParams(0,0); - VoicePar[nvoice].FilterEnvelope->ADSRinit_filter(90,70,40,70,10,40); - VoicePar[nvoice].FilterLfo=new LFOParams(50,20,64,0,0,0,0,2); - - VoicePar[nvoice].FMFreqEnvelope=new EnvelopeParams(0,0); - VoicePar[nvoice].FMFreqEnvelope->ASRinit(20,90,40,80); - VoicePar[nvoice].FMAmpEnvelope=new EnvelopeParams(64,1); - VoicePar[nvoice].FMAmpEnvelope->ADSRinit(80,90,127,100); -}; - -/* - * Get the Multiplier of the fine detunes of the voices - */ -REALTYPE ADnoteParameters::getBandwidthDetuneMultiplier(){ - REALTYPE bw=(GlobalPar.PBandwidth-64.0)/64.0; - bw=pow(2.0,bw*pow(fabs(bw),0.2)*5.0); - - return(bw); -}; - - -/* - * Kill the voice - */ -void ADnoteParameters::KillVoice(int nvoice){ - delete (VoicePar[nvoice].OscilSmp); - delete (VoicePar[nvoice].FMSmp); - - delete (VoicePar[nvoice].AmpEnvelope); - delete (VoicePar[nvoice].AmpLfo); - - delete (VoicePar[nvoice].FreqEnvelope); - delete (VoicePar[nvoice].FreqLfo); - - delete (VoicePar[nvoice].VoiceFilter); - delete (VoicePar[nvoice].FilterEnvelope); - delete (VoicePar[nvoice].FilterLfo); - - delete (VoicePar[nvoice].FMFreqEnvelope); - delete (VoicePar[nvoice].FMAmpEnvelope); -}; - -ADnoteParameters::~ADnoteParameters(){ - delete(GlobalPar.FreqEnvelope); - delete(GlobalPar.FreqLfo); - delete(GlobalPar.AmpEnvelope); - delete(GlobalPar.AmpLfo); - delete(GlobalPar.GlobalFilter); - delete(GlobalPar.FilterEnvelope); - delete(GlobalPar.FilterLfo); - delete(GlobalPar.Reson); - - for (int nvoice=0;nvoice=NUM_VOICES) return; - - int oscilused=0,fmoscilused=0;//if the oscil or fmoscil are used by another voice - - for (int i=0;iaddparbool("enabled",VoicePar[nvoice].Enabled); - if (((VoicePar[nvoice].Enabled==0)&&(oscilused==0)&&(fmoscilused==0))&&(xml->minimal)) return; - - xml->addpar("type",VoicePar[nvoice].Type); - xml->addpar("delay",VoicePar[nvoice].PDelay); - xml->addparbool("resonance",VoicePar[nvoice].Presonance); - - xml->addpar("ext_oscil",VoicePar[nvoice].Pextoscil); - xml->addpar("ext_fm_oscil",VoicePar[nvoice].PextFMoscil); - - xml->addpar("oscil_phase",VoicePar[nvoice].Poscilphase); - xml->addpar("oscil_fm_phase",VoicePar[nvoice].PFMoscilphase); - - xml->addparbool("filter_enabled",VoicePar[nvoice].PFilterEnabled); - xml->addparbool("filter_bypass",VoicePar[nvoice].Pfilterbypass); - - xml->addpar("fm_enabled",VoicePar[nvoice].PFMEnabled); - - xml->beginbranch("OSCIL"); - VoicePar[nvoice].OscilSmp->add2XML(xml); - xml->endbranch(); - - - xml->beginbranch("AMPLITUDE_PARAMETERS"); - xml->addpar("panning",VoicePar[nvoice].PPanning); - xml->addpar("volume",VoicePar[nvoice].PVolume); - xml->addparbool("volume_minus",VoicePar[nvoice].PVolumeminus); - xml->addpar("velocity_sensing",VoicePar[nvoice].PAmpVelocityScaleFunction); - - xml->addparbool("amp_envelope_enabled",VoicePar[nvoice].PAmpEnvelopeEnabled); - if ((VoicePar[nvoice].PAmpEnvelopeEnabled!=0)||(!xml->minimal)){ - xml->beginbranch("AMPLITUDE_ENVELOPE"); - VoicePar[nvoice].AmpEnvelope->add2XML(xml); - xml->endbranch(); - }; - xml->addparbool("amp_lfo_enabled",VoicePar[nvoice].PAmpLfoEnabled); - if ((VoicePar[nvoice].PAmpLfoEnabled!=0)||(!xml->minimal)){ - xml->beginbranch("AMPLITUDE_LFO"); - VoicePar[nvoice].AmpLfo->add2XML(xml); - xml->endbranch(); - }; - xml->endbranch(); - - xml->beginbranch("FREQUENCY_PARAMETERS"); - xml->addparbool("fixed_freq",VoicePar[nvoice].Pfixedfreq); - xml->addpar("fixed_freq_et",VoicePar[nvoice].PfixedfreqET); - xml->addpar("detune",VoicePar[nvoice].PDetune); - xml->addpar("coarse_detune",VoicePar[nvoice].PCoarseDetune); - xml->addpar("detune_type",VoicePar[nvoice].PDetuneType); - - xml->addparbool("freq_envelope_enabled",VoicePar[nvoice].PFreqEnvelopeEnabled); - if ((VoicePar[nvoice].PFreqEnvelopeEnabled!=0)||(!xml->minimal)){ - xml->beginbranch("FREQUENCY_ENVELOPE"); - VoicePar[nvoice].FreqEnvelope->add2XML(xml); - xml->endbranch(); - }; - xml->addparbool("freq_lfo_enabled",VoicePar[nvoice].PFreqLfoEnabled); - if ((VoicePar[nvoice].PFreqLfoEnabled!=0)||(!xml->minimal)){ - xml->beginbranch("FREQUENCY_LFO"); - VoicePar[nvoice].FreqLfo->add2XML(xml); - xml->endbranch(); - }; - xml->endbranch(); - - - if ((VoicePar[nvoice].PFilterEnabled!=0)||(!xml->minimal)){ - xml->beginbranch("FILTER_PARAMETERS"); - xml->beginbranch("FILTER"); - VoicePar[nvoice].VoiceFilter->add2XML(xml); - xml->endbranch(); - - xml->addparbool("filter_envelope_enabled",VoicePar[nvoice].PFilterEnvelopeEnabled); - if ((VoicePar[nvoice].PFilterEnvelopeEnabled!=0)||(!xml->minimal)){ - xml->beginbranch("FILTER_ENVELOPE"); - VoicePar[nvoice].FilterEnvelope->add2XML(xml); - xml->endbranch(); - }; - - xml->addparbool("filter_lfo_enabled",VoicePar[nvoice].PFilterLfoEnabled); - if ((VoicePar[nvoice].PFilterLfoEnabled!=0)||(!xml->minimal)){ - xml->beginbranch("FILTER_LFO"); - VoicePar[nvoice].FilterLfo->add2XML(xml); - xml->endbranch(); - }; - xml->endbranch(); - }; - - if ((VoicePar[nvoice].PFMEnabled!=0)||(fmoscilused!=0)||(!xml->minimal)){ - xml->beginbranch("FM_PARAMETERS"); - xml->addpar("input_voice",VoicePar[nvoice].PFMVoice); - - xml->addpar("volume",VoicePar[nvoice].PFMVolume); - xml->addpar("volume_damp",VoicePar[nvoice].PFMVolumeDamp); - xml->addpar("velocity_sensing",VoicePar[nvoice].PFMVelocityScaleFunction); - - xml->addparbool("amp_envelope_enabled",VoicePar[nvoice].PFMAmpEnvelopeEnabled); - if ((VoicePar[nvoice].PFMAmpEnvelopeEnabled!=0)||(!xml->minimal)){ - xml->beginbranch("AMPLITUDE_ENVELOPE"); - VoicePar[nvoice].FMAmpEnvelope->add2XML(xml); - xml->endbranch(); - }; - xml->beginbranch("MODULATOR"); - xml->addpar("detune",VoicePar[nvoice].PFMDetune); - xml->addpar("coarse_detune",VoicePar[nvoice].PFMCoarseDetune); - xml->addpar("detune_type",VoicePar[nvoice].PFMDetuneType); - - xml->addparbool("freq_envelope_enabled",VoicePar[nvoice].PFMFreqEnvelopeEnabled); - if ((VoicePar[nvoice].PFMFreqEnvelopeEnabled!=0)||(!xml->minimal)){ - xml->beginbranch("FREQUENCY_ENVELOPE"); - VoicePar[nvoice].FMFreqEnvelope->add2XML(xml); - xml->endbranch(); - }; - - xml->beginbranch("OSCIL"); - VoicePar[nvoice].FMSmp->add2XML(xml); - xml->endbranch(); - - xml->endbranch(); - xml->endbranch(); - }; -}; - - -void ADnoteParameters::add2XML(XMLwrapper *xml){ - xml->addparbool("stereo",GlobalPar.PStereo); - - xml->beginbranch("AMPLITUDE_PARAMETERS"); - xml->addpar("volume",GlobalPar.PVolume); - xml->addpar("panning",GlobalPar.PPanning); - xml->addpar("velocity_sensing",GlobalPar.PAmpVelocityScaleFunction); - xml->addpar("punch_strength",GlobalPar.PPunchStrength); - xml->addpar("punch_time",GlobalPar.PPunchTime); - xml->addpar("punch_stretch",GlobalPar.PPunchStretch); - xml->addpar("punch_velocity_sensing",GlobalPar.PPunchVelocitySensing); - xml->addpar("harmonic_randomness_grouping",GlobalPar.Hrandgrouping); - - xml->beginbranch("AMPLITUDE_ENVELOPE"); - GlobalPar.AmpEnvelope->add2XML(xml); - xml->endbranch(); - - xml->beginbranch("AMPLITUDE_LFO"); - GlobalPar.AmpLfo->add2XML(xml); - xml->endbranch(); - xml->endbranch(); - - xml->beginbranch("FREQUENCY_PARAMETERS"); - xml->addpar("detune",GlobalPar.PDetune); - - xml->addpar("coarse_detune",GlobalPar.PCoarseDetune); - xml->addpar("detune_type",GlobalPar.PDetuneType); - - xml->addpar("bandwidth",GlobalPar.PBandwidth); - - xml->beginbranch("FREQUENCY_ENVELOPE"); - GlobalPar.FreqEnvelope->add2XML(xml); - xml->endbranch(); - - xml->beginbranch("FREQUENCY_LFO"); - GlobalPar.FreqLfo->add2XML(xml); - xml->endbranch(); - xml->endbranch(); - - - xml->beginbranch("FILTER_PARAMETERS"); - xml->addpar("velocity_sensing_amplitude",GlobalPar.PFilterVelocityScale); - xml->addpar("velocity_sensing",GlobalPar.PFilterVelocityScaleFunction); - - xml->beginbranch("FILTER"); - GlobalPar.GlobalFilter->add2XML(xml); - xml->endbranch(); - - xml->beginbranch("FILTER_ENVELOPE"); - GlobalPar.FilterEnvelope->add2XML(xml); - xml->endbranch(); - - xml->beginbranch("FILTER_LFO"); - GlobalPar.FilterLfo->add2XML(xml); - xml->endbranch(); - xml->endbranch(); - - xml->beginbranch("RESONANCE"); - GlobalPar.Reson->add2XML(xml); - xml->endbranch(); - - for (int nvoice=0;nvoicebeginbranch("VOICE",nvoice); - add2XMLsection(xml,nvoice); - xml->endbranch(); - }; -}; - - -void ADnoteParameters::getfromXML(XMLwrapper *xml){ - GlobalPar.PStereo=xml->getparbool("stereo",GlobalPar.PStereo); - - if (xml->enterbranch("AMPLITUDE_PARAMETERS")){ - GlobalPar.PVolume=xml->getpar127("volume",GlobalPar.PVolume); - GlobalPar.PPanning=xml->getpar127("panning",GlobalPar.PPanning); - GlobalPar.PAmpVelocityScaleFunction=xml->getpar127("velocity_sensing",GlobalPar.PAmpVelocityScaleFunction); - - GlobalPar.PPunchStrength=xml->getpar127("punch_strength",GlobalPar.PPunchStrength); - GlobalPar.PPunchTime=xml->getpar127("punch_time",GlobalPar.PPunchTime); - GlobalPar.PPunchStretch=xml->getpar127("punch_stretch",GlobalPar.PPunchStretch); - GlobalPar.PPunchVelocitySensing=xml->getpar127("punch_velocity_sensing",GlobalPar.PPunchVelocitySensing); - GlobalPar.Hrandgrouping=xml->getpar127("harmonic_randomness_grouping",GlobalPar.Hrandgrouping); - - if (xml->enterbranch("AMPLITUDE_ENVELOPE")){ - GlobalPar.AmpEnvelope->getfromXML(xml); - xml->exitbranch(); - }; - - if (xml->enterbranch("AMPLITUDE_LFO")){ - GlobalPar.AmpLfo->getfromXML(xml); - xml->exitbranch(); - }; - - xml->exitbranch(); - }; - - if (xml->enterbranch("FREQUENCY_PARAMETERS")){ - GlobalPar.PDetune=xml->getpar("detune",GlobalPar.PDetune,0,16383); - GlobalPar.PCoarseDetune=xml->getpar("coarse_detune",GlobalPar.PCoarseDetune,0,16383); - GlobalPar.PDetuneType=xml->getpar127("detune_type",GlobalPar.PDetuneType); - - GlobalPar.PBandwidth=xml->getpar127("bandwidth",GlobalPar.PBandwidth); - - xml->enterbranch("FREQUENCY_ENVELOPE"); - GlobalPar.FreqEnvelope->getfromXML(xml); - xml->exitbranch(); - - xml->enterbranch("FREQUENCY_LFO"); - GlobalPar.FreqLfo->getfromXML(xml); - xml->exitbranch(); - - xml->exitbranch(); - }; - - - if (xml->enterbranch("FILTER_PARAMETERS")){ - GlobalPar.PFilterVelocityScale=xml->getpar127("velocity_sensing_amplitude",GlobalPar.PFilterVelocityScale); - GlobalPar.PFilterVelocityScaleFunction=xml->getpar127("velocity_sensing",GlobalPar.PFilterVelocityScaleFunction); - - xml->enterbranch("FILTER"); - GlobalPar.GlobalFilter->getfromXML(xml); - xml->exitbranch(); - - xml->enterbranch("FILTER_ENVELOPE"); - GlobalPar.FilterEnvelope->getfromXML(xml); - xml->exitbranch(); - - xml->enterbranch("FILTER_LFO"); - GlobalPar.FilterLfo->getfromXML(xml); - xml->exitbranch(); - xml->exitbranch(); - }; - - if (xml->enterbranch("RESONANCE")){ - GlobalPar.Reson->getfromXML(xml); - xml->exitbranch(); - }; - - for (int nvoice=0;nvoiceenterbranch("VOICE",nvoice)==0) continue; - getfromXMLsection(xml,nvoice); - xml->exitbranch(); - }; - - -}; - -void ADnoteParameters::getfromXMLsection(XMLwrapper *xml,int n){ - int nvoice=n; - if (nvoice>=NUM_VOICES) return; - - VoicePar[nvoice].Enabled=xml->getparbool("enabled",0); - - VoicePar[nvoice].Type=xml->getpar127("type",VoicePar[nvoice].Type); - VoicePar[nvoice].PDelay=xml->getpar127("delay",VoicePar[nvoice].PDelay); - VoicePar[nvoice].Presonance=xml->getparbool("resonance",VoicePar[nvoice].Presonance); - - VoicePar[nvoice].Pextoscil=xml->getpar("ext_oscil",-1,-1,nvoice-1); - VoicePar[nvoice].PextFMoscil=xml->getpar("ext_fm_oscil",-1,-1,nvoice-1); - - VoicePar[nvoice].Poscilphase=xml->getpar127("oscil_phase",VoicePar[nvoice].Poscilphase); - VoicePar[nvoice].PFMoscilphase=xml->getpar127("oscil_fm_phase",VoicePar[nvoice].PFMoscilphase); - - VoicePar[nvoice].PFilterEnabled=xml->getparbool("filter_enabled",VoicePar[nvoice].PFilterEnabled); - VoicePar[nvoice].Pfilterbypass=xml->getparbool("filter_bypass",VoicePar[nvoice].Pfilterbypass); - - VoicePar[nvoice].PFMEnabled=xml->getpar127("fm_enabled",VoicePar[nvoice].PFMEnabled); - - if (xml->enterbranch("OSCIL")){ - VoicePar[nvoice].OscilSmp->getfromXML(xml); - xml->exitbranch(); - }; - - - if (xml->enterbranch("AMPLITUDE_PARAMETERS")){ - VoicePar[nvoice].PPanning=xml->getpar127("panning",VoicePar[nvoice].PPanning); - VoicePar[nvoice].PVolume=xml->getpar127("volume",VoicePar[nvoice].PVolume); - VoicePar[nvoice].PVolumeminus=xml->getparbool("volume_minus",VoicePar[nvoice].PVolumeminus); - VoicePar[nvoice].PAmpVelocityScaleFunction=xml->getpar127("velocity_sensing",VoicePar[nvoice].PAmpVelocityScaleFunction); - - VoicePar[nvoice].PAmpEnvelopeEnabled=xml->getparbool("amp_envelope_enabled",VoicePar[nvoice].PAmpEnvelopeEnabled); - if (xml->enterbranch("AMPLITUDE_ENVELOPE")){ - VoicePar[nvoice].AmpEnvelope->getfromXML(xml); - xml->exitbranch(); - }; - - VoicePar[nvoice].PAmpLfoEnabled=xml->getparbool("amp_lfo_enabled",VoicePar[nvoice].PAmpLfoEnabled); - if (xml->enterbranch("AMPLITUDE_LFO")){ - VoicePar[nvoice].AmpLfo->getfromXML(xml); - xml->exitbranch(); - }; - xml->exitbranch(); - }; - - if (xml->enterbranch("FREQUENCY_PARAMETERS")){ - VoicePar[nvoice].Pfixedfreq=xml->getparbool("fixed_freq",VoicePar[nvoice].Pfixedfreq); - VoicePar[nvoice].PfixedfreqET=xml->getpar127("fixed_freq_et",VoicePar[nvoice].PfixedfreqET); - - - VoicePar[nvoice].PDetune=xml->getpar("detune",VoicePar[nvoice].PDetune,0,16383); - - VoicePar[nvoice].PCoarseDetune=xml->getpar("coarse_detune",VoicePar[nvoice].PCoarseDetune,0,16383); - VoicePar[nvoice].PDetuneType=xml->getpar127("detune_type",VoicePar[nvoice].PDetuneType); - - VoicePar[nvoice].PFreqEnvelopeEnabled=xml->getparbool("freq_envelope_enabled",VoicePar[nvoice].PFreqEnvelopeEnabled); - if (xml->enterbranch("FREQUENCY_ENVELOPE")){ - VoicePar[nvoice].FreqEnvelope->getfromXML(xml); - xml->exitbranch(); - }; - - VoicePar[nvoice].PFreqLfoEnabled=xml->getparbool("freq_lfo_enabled",VoicePar[nvoice].PFreqLfoEnabled); - if (xml->enterbranch("FREQUENCY_LFO")){ - VoicePar[nvoice].FreqLfo->getfromXML(xml); - xml->exitbranch(); - }; - xml->exitbranch(); - }; - - if (xml->enterbranch("FILTER_PARAMETERS")){ - if (xml->enterbranch("FILTER")){ - VoicePar[nvoice].VoiceFilter->getfromXML(xml); - xml->exitbranch(); - }; - - VoicePar[nvoice].PFilterEnvelopeEnabled=xml->getparbool("filter_envelope_enabled",VoicePar[nvoice].PFilterEnvelopeEnabled); - if (xml->enterbranch("FILTER_ENVELOPE")){ - VoicePar[nvoice].FilterEnvelope->getfromXML(xml); - xml->exitbranch(); - }; - - VoicePar[nvoice].PFilterLfoEnabled=xml->getparbool("filter_lfo_enabled",VoicePar[nvoice].PFilterLfoEnabled); - if (xml->enterbranch("FILTER_LFO")){ - VoicePar[nvoice].FilterLfo->getfromXML(xml); - xml->exitbranch(); - }; - xml->exitbranch(); - }; - - if (xml->enterbranch("FM_PARAMETERS")){ - VoicePar[nvoice].PFMVoice=xml->getpar("input_voice",VoicePar[nvoice].PFMVoice,-1,nvoice-1); - - VoicePar[nvoice].PFMVolume=xml->getpar127("volume",VoicePar[nvoice].PFMVolume); - VoicePar[nvoice].PFMVolumeDamp=xml->getpar127("volume_damp",VoicePar[nvoice].PFMVolumeDamp); - VoicePar[nvoice].PFMVelocityScaleFunction=xml->getpar127("velocity_sensing",VoicePar[nvoice].PFMVelocityScaleFunction); - - VoicePar[nvoice].PFMAmpEnvelopeEnabled=xml->getparbool("amp_envelope_enabled",VoicePar[nvoice].PFMAmpEnvelopeEnabled); - if (xml->enterbranch("AMPLITUDE_ENVELOPE")){ - VoicePar[nvoice].FMAmpEnvelope->getfromXML(xml); - xml->exitbranch(); - }; - - if (xml->enterbranch("MODULATOR")){ - VoicePar[nvoice].PFMDetune=xml->getpar("detune",VoicePar[nvoice].PFMDetune,0,16383); - VoicePar[nvoice].PFMCoarseDetune=xml->getpar("coarse_detune",VoicePar[nvoice].PFMCoarseDetune,0,16383); - VoicePar[nvoice].PFMDetuneType=xml->getpar127("detune_type",VoicePar[nvoice].PFMDetuneType); - - VoicePar[nvoice].PFMFreqEnvelopeEnabled=xml->getparbool("freq_envelope_enabled",VoicePar[nvoice].PFMFreqEnvelopeEnabled); - if (xml->enterbranch("FREQUENCY_ENVELOPE")){ - VoicePar[nvoice].FMFreqEnvelope->getfromXML(xml); - xml->exitbranch(); - }; - - if (xml->enterbranch("OSCIL")){ - VoicePar[nvoice].FMSmp->getfromXML(xml); - xml->exitbranch(); - }; - - xml->exitbranch(); - }; - xml->exitbranch(); - }; -}; - - diff --git a/plugins/zynaddsubfx/src/Params/ADnoteParameters.cpp b/plugins/zynaddsubfx/src/Params/ADnoteParameters.cpp new file mode 100644 index 000000000..5fb6ce797 --- /dev/null +++ b/plugins/zynaddsubfx/src/Params/ADnoteParameters.cpp @@ -0,0 +1,648 @@ +/* + ZynAddSubFX - a software synthesizer + + ADnoteParameters.C - Parameters for ADnote (ADsynth) + Copyright (C) 2002-2005 Nasca Octavian Paul + Author: Nasca Octavian Paul + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include +#include +#include + +#include "ADnoteParameters.h" + +ADnoteParameters::ADnoteParameters(FFTwrapper *fft_):Presets() +{ + setpresettype("Padsyth"); + fft=fft_; + + GlobalPar.FreqEnvelope=new EnvelopeParams(0,0); + GlobalPar.FreqEnvelope->ASRinit(64,50,64,60); + GlobalPar.FreqLfo=new LFOParams(70,0,64,0,0,0,0,0); + + GlobalPar.AmpEnvelope=new EnvelopeParams(64,1); + GlobalPar.AmpEnvelope->ADSRinit_dB(0,40,127,25); + GlobalPar.AmpLfo=new LFOParams(80,0,64,0,0,0,0,1); + + GlobalPar.GlobalFilter=new FilterParams(2,94,40); + GlobalPar.FilterEnvelope=new EnvelopeParams(0,1); + GlobalPar.FilterEnvelope->ADSRinit_filter(64,40,64,70,60,64); + GlobalPar.FilterLfo=new LFOParams(80,0,64,0,0,0,0,2); + GlobalPar.Reson=new Resonance(); + + for (int nvoice=0;nvoicedefaults(); + GlobalPar.FreqLfo->defaults(); + GlobalPar.PBandwidth=64; + + /* Amplitude Global Parameters */ + GlobalPar.PVolume=90; + GlobalPar.PPanning=64;//center + GlobalPar.PAmpVelocityScaleFunction=64; + GlobalPar.AmpEnvelope->defaults(); + GlobalPar.AmpLfo->defaults(); + GlobalPar.PPunchStrength=0; + GlobalPar.PPunchTime=60; + GlobalPar.PPunchStretch=64; + GlobalPar.PPunchVelocitySensing=72; + GlobalPar.Hrandgrouping=0; + + /* Filter Global Parameters*/ + GlobalPar.PFilterVelocityScale=64; + GlobalPar.PFilterVelocityScaleFunction=64; + GlobalPar.GlobalFilter->defaults(); + GlobalPar.FilterEnvelope->defaults(); + GlobalPar.FilterLfo->defaults(); + GlobalPar.Reson->defaults(); + + + for (int nvoice=0;nvoicedefaults(); + VoicePar[nvoice].FMSmp->defaults(); + + VoicePar[nvoice].AmpEnvelope->defaults(); + VoicePar[nvoice].AmpLfo->defaults(); + + VoicePar[nvoice].FreqEnvelope->defaults(); + VoicePar[nvoice].FreqLfo->defaults(); + + VoicePar[nvoice].VoiceFilter->defaults(); + VoicePar[nvoice].FilterEnvelope->defaults(); + VoicePar[nvoice].FilterLfo->defaults(); + + VoicePar[nvoice].FMFreqEnvelope->defaults(); + VoicePar[nvoice].FMAmpEnvelope->defaults(); +}; + + + +/* + * Init the voice parameters + */ +void ADnoteParameters::EnableVoice(int nvoice) +{ + VoicePar[nvoice].OscilSmp=new OscilGen(fft,GlobalPar.Reson); + VoicePar[nvoice].FMSmp=new OscilGen(fft,NULL); + + VoicePar[nvoice].AmpEnvelope=new EnvelopeParams(64,1); + VoicePar[nvoice].AmpEnvelope->ADSRinit_dB(0,100,127,100); + VoicePar[nvoice].AmpLfo=new LFOParams(90,32,64,0,0,30,0,1); + + VoicePar[nvoice].FreqEnvelope=new EnvelopeParams(0,0); + VoicePar[nvoice].FreqEnvelope->ASRinit(30,40,64,60); + VoicePar[nvoice].FreqLfo=new LFOParams(50,40,0,0,0,0,0,0); + + VoicePar[nvoice].VoiceFilter=new FilterParams(2,50,60); + VoicePar[nvoice].FilterEnvelope=new EnvelopeParams(0,0); + VoicePar[nvoice].FilterEnvelope->ADSRinit_filter(90,70,40,70,10,40); + VoicePar[nvoice].FilterLfo=new LFOParams(50,20,64,0,0,0,0,2); + + VoicePar[nvoice].FMFreqEnvelope=new EnvelopeParams(0,0); + VoicePar[nvoice].FMFreqEnvelope->ASRinit(20,90,40,80); + VoicePar[nvoice].FMAmpEnvelope=new EnvelopeParams(64,1); + VoicePar[nvoice].FMAmpEnvelope->ADSRinit(80,90,127,100); +}; + +/* + * Get the Multiplier of the fine detunes of the voices + */ +REALTYPE ADnoteParameters::getBandwidthDetuneMultiplier() +{ + REALTYPE bw=(GlobalPar.PBandwidth-64.0)/64.0; + bw=pow(2.0,bw*pow(fabs(bw),0.2)*5.0); + + return(bw); +}; + + +/* + * Kill the voice + */ +void ADnoteParameters::KillVoice(int nvoice) +{ + delete (VoicePar[nvoice].OscilSmp); + delete (VoicePar[nvoice].FMSmp); + + delete (VoicePar[nvoice].AmpEnvelope); + delete (VoicePar[nvoice].AmpLfo); + + delete (VoicePar[nvoice].FreqEnvelope); + delete (VoicePar[nvoice].FreqLfo); + + delete (VoicePar[nvoice].VoiceFilter); + delete (VoicePar[nvoice].FilterEnvelope); + delete (VoicePar[nvoice].FilterLfo); + + delete (VoicePar[nvoice].FMFreqEnvelope); + delete (VoicePar[nvoice].FMAmpEnvelope); +}; + +ADnoteParameters::~ADnoteParameters() +{ + delete(GlobalPar.FreqEnvelope); + delete(GlobalPar.FreqLfo); + delete(GlobalPar.AmpEnvelope); + delete(GlobalPar.AmpLfo); + delete(GlobalPar.GlobalFilter); + delete(GlobalPar.FilterEnvelope); + delete(GlobalPar.FilterLfo); + delete(GlobalPar.Reson); + + for (int nvoice=0;nvoice=NUM_VOICES) return; + + int oscilused=0,fmoscilused=0;//if the oscil or fmoscil are used by another voice + + for (int i=0;iaddparbool("enabled",VoicePar[nvoice].Enabled); + if (((VoicePar[nvoice].Enabled==0)&&(oscilused==0)&&(fmoscilused==0))&&(xml->minimal)) return; + + xml->addpar("type",VoicePar[nvoice].Type); + xml->addpar("delay",VoicePar[nvoice].PDelay); + xml->addparbool("resonance",VoicePar[nvoice].Presonance); + + xml->addpar("ext_oscil",VoicePar[nvoice].Pextoscil); + xml->addpar("ext_fm_oscil",VoicePar[nvoice].PextFMoscil); + + xml->addpar("oscil_phase",VoicePar[nvoice].Poscilphase); + xml->addpar("oscil_fm_phase",VoicePar[nvoice].PFMoscilphase); + + xml->addparbool("filter_enabled",VoicePar[nvoice].PFilterEnabled); + xml->addparbool("filter_bypass",VoicePar[nvoice].Pfilterbypass); + + xml->addpar("fm_enabled",VoicePar[nvoice].PFMEnabled); + + xml->beginbranch("OSCIL"); + VoicePar[nvoice].OscilSmp->add2XML(xml); + xml->endbranch(); + + + xml->beginbranch("AMPLITUDE_PARAMETERS"); + xml->addpar("panning",VoicePar[nvoice].PPanning); + xml->addpar("volume",VoicePar[nvoice].PVolume); + xml->addparbool("volume_minus",VoicePar[nvoice].PVolumeminus); + xml->addpar("velocity_sensing",VoicePar[nvoice].PAmpVelocityScaleFunction); + + xml->addparbool("amp_envelope_enabled",VoicePar[nvoice].PAmpEnvelopeEnabled); + if ((VoicePar[nvoice].PAmpEnvelopeEnabled!=0)||(!xml->minimal)) { + xml->beginbranch("AMPLITUDE_ENVELOPE"); + VoicePar[nvoice].AmpEnvelope->add2XML(xml); + xml->endbranch(); + }; + xml->addparbool("amp_lfo_enabled",VoicePar[nvoice].PAmpLfoEnabled); + if ((VoicePar[nvoice].PAmpLfoEnabled!=0)||(!xml->minimal)) { + xml->beginbranch("AMPLITUDE_LFO"); + VoicePar[nvoice].AmpLfo->add2XML(xml); + xml->endbranch(); + }; + xml->endbranch(); + + xml->beginbranch("FREQUENCY_PARAMETERS"); + xml->addparbool("fixed_freq",VoicePar[nvoice].Pfixedfreq); + xml->addpar("fixed_freq_et",VoicePar[nvoice].PfixedfreqET); + xml->addpar("detune",VoicePar[nvoice].PDetune); + xml->addpar("coarse_detune",VoicePar[nvoice].PCoarseDetune); + xml->addpar("detune_type",VoicePar[nvoice].PDetuneType); + + xml->addparbool("freq_envelope_enabled",VoicePar[nvoice].PFreqEnvelopeEnabled); + if ((VoicePar[nvoice].PFreqEnvelopeEnabled!=0)||(!xml->minimal)) { + xml->beginbranch("FREQUENCY_ENVELOPE"); + VoicePar[nvoice].FreqEnvelope->add2XML(xml); + xml->endbranch(); + }; + xml->addparbool("freq_lfo_enabled",VoicePar[nvoice].PFreqLfoEnabled); + if ((VoicePar[nvoice].PFreqLfoEnabled!=0)||(!xml->minimal)) { + xml->beginbranch("FREQUENCY_LFO"); + VoicePar[nvoice].FreqLfo->add2XML(xml); + xml->endbranch(); + }; + xml->endbranch(); + + + if ((VoicePar[nvoice].PFilterEnabled!=0)||(!xml->minimal)) { + xml->beginbranch("FILTER_PARAMETERS"); + xml->beginbranch("FILTER"); + VoicePar[nvoice].VoiceFilter->add2XML(xml); + xml->endbranch(); + + xml->addparbool("filter_envelope_enabled",VoicePar[nvoice].PFilterEnvelopeEnabled); + if ((VoicePar[nvoice].PFilterEnvelopeEnabled!=0)||(!xml->minimal)) { + xml->beginbranch("FILTER_ENVELOPE"); + VoicePar[nvoice].FilterEnvelope->add2XML(xml); + xml->endbranch(); + }; + + xml->addparbool("filter_lfo_enabled",VoicePar[nvoice].PFilterLfoEnabled); + if ((VoicePar[nvoice].PFilterLfoEnabled!=0)||(!xml->minimal)) { + xml->beginbranch("FILTER_LFO"); + VoicePar[nvoice].FilterLfo->add2XML(xml); + xml->endbranch(); + }; + xml->endbranch(); + }; + + if ((VoicePar[nvoice].PFMEnabled!=0)||(fmoscilused!=0)||(!xml->minimal)) { + xml->beginbranch("FM_PARAMETERS"); + xml->addpar("input_voice",VoicePar[nvoice].PFMVoice); + + xml->addpar("volume",VoicePar[nvoice].PFMVolume); + xml->addpar("volume_damp",VoicePar[nvoice].PFMVolumeDamp); + xml->addpar("velocity_sensing",VoicePar[nvoice].PFMVelocityScaleFunction); + + xml->addparbool("amp_envelope_enabled",VoicePar[nvoice].PFMAmpEnvelopeEnabled); + if ((VoicePar[nvoice].PFMAmpEnvelopeEnabled!=0)||(!xml->minimal)) { + xml->beginbranch("AMPLITUDE_ENVELOPE"); + VoicePar[nvoice].FMAmpEnvelope->add2XML(xml); + xml->endbranch(); + }; + xml->beginbranch("MODULATOR"); + xml->addpar("detune",VoicePar[nvoice].PFMDetune); + xml->addpar("coarse_detune",VoicePar[nvoice].PFMCoarseDetune); + xml->addpar("detune_type",VoicePar[nvoice].PFMDetuneType); + + xml->addparbool("freq_envelope_enabled",VoicePar[nvoice].PFMFreqEnvelopeEnabled); + if ((VoicePar[nvoice].PFMFreqEnvelopeEnabled!=0)||(!xml->minimal)) { + xml->beginbranch("FREQUENCY_ENVELOPE"); + VoicePar[nvoice].FMFreqEnvelope->add2XML(xml); + xml->endbranch(); + }; + + xml->beginbranch("OSCIL"); + VoicePar[nvoice].FMSmp->add2XML(xml); + xml->endbranch(); + + xml->endbranch(); + xml->endbranch(); + }; +}; + + +void ADnoteParameters::add2XML(XMLwrapper *xml) +{ + xml->addparbool("stereo",GlobalPar.PStereo); + + xml->beginbranch("AMPLITUDE_PARAMETERS"); + xml->addpar("volume",GlobalPar.PVolume); + xml->addpar("panning",GlobalPar.PPanning); + xml->addpar("velocity_sensing",GlobalPar.PAmpVelocityScaleFunction); + xml->addpar("punch_strength",GlobalPar.PPunchStrength); + xml->addpar("punch_time",GlobalPar.PPunchTime); + xml->addpar("punch_stretch",GlobalPar.PPunchStretch); + xml->addpar("punch_velocity_sensing",GlobalPar.PPunchVelocitySensing); + xml->addpar("harmonic_randomness_grouping",GlobalPar.Hrandgrouping); + + xml->beginbranch("AMPLITUDE_ENVELOPE"); + GlobalPar.AmpEnvelope->add2XML(xml); + xml->endbranch(); + + xml->beginbranch("AMPLITUDE_LFO"); + GlobalPar.AmpLfo->add2XML(xml); + xml->endbranch(); + xml->endbranch(); + + xml->beginbranch("FREQUENCY_PARAMETERS"); + xml->addpar("detune",GlobalPar.PDetune); + + xml->addpar("coarse_detune",GlobalPar.PCoarseDetune); + xml->addpar("detune_type",GlobalPar.PDetuneType); + + xml->addpar("bandwidth",GlobalPar.PBandwidth); + + xml->beginbranch("FREQUENCY_ENVELOPE"); + GlobalPar.FreqEnvelope->add2XML(xml); + xml->endbranch(); + + xml->beginbranch("FREQUENCY_LFO"); + GlobalPar.FreqLfo->add2XML(xml); + xml->endbranch(); + xml->endbranch(); + + + xml->beginbranch("FILTER_PARAMETERS"); + xml->addpar("velocity_sensing_amplitude",GlobalPar.PFilterVelocityScale); + xml->addpar("velocity_sensing",GlobalPar.PFilterVelocityScaleFunction); + + xml->beginbranch("FILTER"); + GlobalPar.GlobalFilter->add2XML(xml); + xml->endbranch(); + + xml->beginbranch("FILTER_ENVELOPE"); + GlobalPar.FilterEnvelope->add2XML(xml); + xml->endbranch(); + + xml->beginbranch("FILTER_LFO"); + GlobalPar.FilterLfo->add2XML(xml); + xml->endbranch(); + xml->endbranch(); + + xml->beginbranch("RESONANCE"); + GlobalPar.Reson->add2XML(xml); + xml->endbranch(); + + for (int nvoice=0;nvoicebeginbranch("VOICE",nvoice); + add2XMLsection(xml,nvoice); + xml->endbranch(); + }; +}; + + +void ADnoteParameters::getfromXML(XMLwrapper *xml) +{ + GlobalPar.PStereo=xml->getparbool("stereo",GlobalPar.PStereo); + + if (xml->enterbranch("AMPLITUDE_PARAMETERS")) { + GlobalPar.PVolume=xml->getpar127("volume",GlobalPar.PVolume); + GlobalPar.PPanning=xml->getpar127("panning",GlobalPar.PPanning); + GlobalPar.PAmpVelocityScaleFunction=xml->getpar127("velocity_sensing",GlobalPar.PAmpVelocityScaleFunction); + + GlobalPar.PPunchStrength=xml->getpar127("punch_strength",GlobalPar.PPunchStrength); + GlobalPar.PPunchTime=xml->getpar127("punch_time",GlobalPar.PPunchTime); + GlobalPar.PPunchStretch=xml->getpar127("punch_stretch",GlobalPar.PPunchStretch); + GlobalPar.PPunchVelocitySensing=xml->getpar127("punch_velocity_sensing",GlobalPar.PPunchVelocitySensing); + GlobalPar.Hrandgrouping=xml->getpar127("harmonic_randomness_grouping",GlobalPar.Hrandgrouping); + + if (xml->enterbranch("AMPLITUDE_ENVELOPE")) { + GlobalPar.AmpEnvelope->getfromXML(xml); + xml->exitbranch(); + }; + + if (xml->enterbranch("AMPLITUDE_LFO")) { + GlobalPar.AmpLfo->getfromXML(xml); + xml->exitbranch(); + }; + + xml->exitbranch(); + }; + + if (xml->enterbranch("FREQUENCY_PARAMETERS")) { + GlobalPar.PDetune=xml->getpar("detune",GlobalPar.PDetune,0,16383); + GlobalPar.PCoarseDetune=xml->getpar("coarse_detune",GlobalPar.PCoarseDetune,0,16383); + GlobalPar.PDetuneType=xml->getpar127("detune_type",GlobalPar.PDetuneType); + + GlobalPar.PBandwidth=xml->getpar127("bandwidth",GlobalPar.PBandwidth); + + xml->enterbranch("FREQUENCY_ENVELOPE"); + GlobalPar.FreqEnvelope->getfromXML(xml); + xml->exitbranch(); + + xml->enterbranch("FREQUENCY_LFO"); + GlobalPar.FreqLfo->getfromXML(xml); + xml->exitbranch(); + + xml->exitbranch(); + }; + + + if (xml->enterbranch("FILTER_PARAMETERS")) { + GlobalPar.PFilterVelocityScale=xml->getpar127("velocity_sensing_amplitude",GlobalPar.PFilterVelocityScale); + GlobalPar.PFilterVelocityScaleFunction=xml->getpar127("velocity_sensing",GlobalPar.PFilterVelocityScaleFunction); + + xml->enterbranch("FILTER"); + GlobalPar.GlobalFilter->getfromXML(xml); + xml->exitbranch(); + + xml->enterbranch("FILTER_ENVELOPE"); + GlobalPar.FilterEnvelope->getfromXML(xml); + xml->exitbranch(); + + xml->enterbranch("FILTER_LFO"); + GlobalPar.FilterLfo->getfromXML(xml); + xml->exitbranch(); + xml->exitbranch(); + }; + + if (xml->enterbranch("RESONANCE")) { + GlobalPar.Reson->getfromXML(xml); + xml->exitbranch(); + }; + + for (int nvoice=0;nvoiceenterbranch("VOICE",nvoice)==0) continue; + getfromXMLsection(xml,nvoice); + xml->exitbranch(); + }; + + +}; + +void ADnoteParameters::getfromXMLsection(XMLwrapper *xml,int n) +{ + int nvoice=n; + if (nvoice>=NUM_VOICES) return; + + VoicePar[nvoice].Enabled=xml->getparbool("enabled",0); + + VoicePar[nvoice].Type=xml->getpar127("type",VoicePar[nvoice].Type); + VoicePar[nvoice].PDelay=xml->getpar127("delay",VoicePar[nvoice].PDelay); + VoicePar[nvoice].Presonance=xml->getparbool("resonance",VoicePar[nvoice].Presonance); + + VoicePar[nvoice].Pextoscil=xml->getpar("ext_oscil",-1,-1,nvoice-1); + VoicePar[nvoice].PextFMoscil=xml->getpar("ext_fm_oscil",-1,-1,nvoice-1); + + VoicePar[nvoice].Poscilphase=xml->getpar127("oscil_phase",VoicePar[nvoice].Poscilphase); + VoicePar[nvoice].PFMoscilphase=xml->getpar127("oscil_fm_phase",VoicePar[nvoice].PFMoscilphase); + + VoicePar[nvoice].PFilterEnabled=xml->getparbool("filter_enabled",VoicePar[nvoice].PFilterEnabled); + VoicePar[nvoice].Pfilterbypass=xml->getparbool("filter_bypass",VoicePar[nvoice].Pfilterbypass); + + VoicePar[nvoice].PFMEnabled=xml->getpar127("fm_enabled",VoicePar[nvoice].PFMEnabled); + + if (xml->enterbranch("OSCIL")) { + VoicePar[nvoice].OscilSmp->getfromXML(xml); + xml->exitbranch(); + }; + + + if (xml->enterbranch("AMPLITUDE_PARAMETERS")) { + VoicePar[nvoice].PPanning=xml->getpar127("panning",VoicePar[nvoice].PPanning); + VoicePar[nvoice].PVolume=xml->getpar127("volume",VoicePar[nvoice].PVolume); + VoicePar[nvoice].PVolumeminus=xml->getparbool("volume_minus",VoicePar[nvoice].PVolumeminus); + VoicePar[nvoice].PAmpVelocityScaleFunction=xml->getpar127("velocity_sensing",VoicePar[nvoice].PAmpVelocityScaleFunction); + + VoicePar[nvoice].PAmpEnvelopeEnabled=xml->getparbool("amp_envelope_enabled",VoicePar[nvoice].PAmpEnvelopeEnabled); + if (xml->enterbranch("AMPLITUDE_ENVELOPE")) { + VoicePar[nvoice].AmpEnvelope->getfromXML(xml); + xml->exitbranch(); + }; + + VoicePar[nvoice].PAmpLfoEnabled=xml->getparbool("amp_lfo_enabled",VoicePar[nvoice].PAmpLfoEnabled); + if (xml->enterbranch("AMPLITUDE_LFO")) { + VoicePar[nvoice].AmpLfo->getfromXML(xml); + xml->exitbranch(); + }; + xml->exitbranch(); + }; + + if (xml->enterbranch("FREQUENCY_PARAMETERS")) { + VoicePar[nvoice].Pfixedfreq=xml->getparbool("fixed_freq",VoicePar[nvoice].Pfixedfreq); + VoicePar[nvoice].PfixedfreqET=xml->getpar127("fixed_freq_et",VoicePar[nvoice].PfixedfreqET); + + + VoicePar[nvoice].PDetune=xml->getpar("detune",VoicePar[nvoice].PDetune,0,16383); + + VoicePar[nvoice].PCoarseDetune=xml->getpar("coarse_detune",VoicePar[nvoice].PCoarseDetune,0,16383); + VoicePar[nvoice].PDetuneType=xml->getpar127("detune_type",VoicePar[nvoice].PDetuneType); + + VoicePar[nvoice].PFreqEnvelopeEnabled=xml->getparbool("freq_envelope_enabled",VoicePar[nvoice].PFreqEnvelopeEnabled); + if (xml->enterbranch("FREQUENCY_ENVELOPE")) { + VoicePar[nvoice].FreqEnvelope->getfromXML(xml); + xml->exitbranch(); + }; + + VoicePar[nvoice].PFreqLfoEnabled=xml->getparbool("freq_lfo_enabled",VoicePar[nvoice].PFreqLfoEnabled); + if (xml->enterbranch("FREQUENCY_LFO")) { + VoicePar[nvoice].FreqLfo->getfromXML(xml); + xml->exitbranch(); + }; + xml->exitbranch(); + }; + + if (xml->enterbranch("FILTER_PARAMETERS")) { + if (xml->enterbranch("FILTER")) { + VoicePar[nvoice].VoiceFilter->getfromXML(xml); + xml->exitbranch(); + }; + + VoicePar[nvoice].PFilterEnvelopeEnabled=xml->getparbool("filter_envelope_enabled",VoicePar[nvoice].PFilterEnvelopeEnabled); + if (xml->enterbranch("FILTER_ENVELOPE")) { + VoicePar[nvoice].FilterEnvelope->getfromXML(xml); + xml->exitbranch(); + }; + + VoicePar[nvoice].PFilterLfoEnabled=xml->getparbool("filter_lfo_enabled",VoicePar[nvoice].PFilterLfoEnabled); + if (xml->enterbranch("FILTER_LFO")) { + VoicePar[nvoice].FilterLfo->getfromXML(xml); + xml->exitbranch(); + }; + xml->exitbranch(); + }; + + if (xml->enterbranch("FM_PARAMETERS")) { + VoicePar[nvoice].PFMVoice=xml->getpar("input_voice",VoicePar[nvoice].PFMVoice,-1,nvoice-1); + + VoicePar[nvoice].PFMVolume=xml->getpar127("volume",VoicePar[nvoice].PFMVolume); + VoicePar[nvoice].PFMVolumeDamp=xml->getpar127("volume_damp",VoicePar[nvoice].PFMVolumeDamp); + VoicePar[nvoice].PFMVelocityScaleFunction=xml->getpar127("velocity_sensing",VoicePar[nvoice].PFMVelocityScaleFunction); + + VoicePar[nvoice].PFMAmpEnvelopeEnabled=xml->getparbool("amp_envelope_enabled",VoicePar[nvoice].PFMAmpEnvelopeEnabled); + if (xml->enterbranch("AMPLITUDE_ENVELOPE")) { + VoicePar[nvoice].FMAmpEnvelope->getfromXML(xml); + xml->exitbranch(); + }; + + if (xml->enterbranch("MODULATOR")) { + VoicePar[nvoice].PFMDetune=xml->getpar("detune",VoicePar[nvoice].PFMDetune,0,16383); + VoicePar[nvoice].PFMCoarseDetune=xml->getpar("coarse_detune",VoicePar[nvoice].PFMCoarseDetune,0,16383); + VoicePar[nvoice].PFMDetuneType=xml->getpar127("detune_type",VoicePar[nvoice].PFMDetuneType); + + VoicePar[nvoice].PFMFreqEnvelopeEnabled=xml->getparbool("freq_envelope_enabled",VoicePar[nvoice].PFMFreqEnvelopeEnabled); + if (xml->enterbranch("FREQUENCY_ENVELOPE")) { + VoicePar[nvoice].FMFreqEnvelope->getfromXML(xml); + xml->exitbranch(); + }; + + if (xml->enterbranch("OSCIL")) { + VoicePar[nvoice].FMSmp->getfromXML(xml); + xml->exitbranch(); + }; + + xml->exitbranch(); + }; + xml->exitbranch(); + }; +}; + + diff --git a/plugins/zynaddsubfx/src/Params/ADnoteParameters.h b/plugins/zynaddsubfx/src/Params/ADnoteParameters.h index c1c765a07..8b35f92c4 100644 --- a/plugins/zynaddsubfx/src/Params/ADnoteParameters.h +++ b/plugins/zynaddsubfx/src/Params/ADnoteParameters.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + ADnoteParameters.h - Parameters for ADnote (ADsynth) Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -35,248 +35,249 @@ #include "../DSP/FFTwrapper.h" #include "Presets.h" - enum FMTYPE{NONE,MORPH,RING_MOD,PHASE_MOD,FREQ_MOD,PITCH_MOD}; - - /*****************************************************************/ - /* GLOBAL PARAMETERS */ - /*****************************************************************/ +enum FMTYPE {NONE,MORPH,RING_MOD,PHASE_MOD,FREQ_MOD,PITCH_MOD}; - struct ADnoteGlobalParam{ - - /* The instrument type - MONO/STEREO - If the mode is MONO, the panning of voices are not used - Stereo=1, Mono=0. */ - - unsigned char PStereo; - - - /****************************************** - * FREQUENCY GLOBAL PARAMETERS * - ******************************************/ - unsigned short int PDetune;//fine detune - unsigned short int PCoarseDetune;//coarse detune+octave - unsigned char PDetuneType;//detune type - - unsigned char PBandwidth;//how much the relative fine detunes of the voices are changed +/*****************************************************************/ +/* GLOBAL PARAMETERS */ +/*****************************************************************/ - EnvelopeParams *FreqEnvelope; //Frequency Envelope - - LFOParams *FreqLfo;//Frequency LFO +struct ADnoteGlobalParam { - /******************************************** - * AMPLITUDE GLOBAL PARAMETERS * - ********************************************/ + /* The instrument type - MONO/STEREO + If the mode is MONO, the panning of voices are not used + Stereo=1, Mono=0. */ - /* Panning - 0 - random - 1 - left - 64 - center - 127 - right */ - unsigned char PPanning; - - unsigned char PVolume; - - unsigned char PAmpVelocityScaleFunction; - - EnvelopeParams *AmpEnvelope; - - LFOParams *AmpLfo; - - unsigned char PPunchStrength,PPunchTime,PPunchStretch,PPunchVelocitySensing; - - /****************************************** - * FILTER GLOBAL PARAMETERS * - ******************************************/ - FilterParams *GlobalFilter; - - // filter velocity sensing - unsigned char PFilterVelocityScale; - - // filter velocity sensing - unsigned char PFilterVelocityScaleFunction; - - EnvelopeParams *FilterEnvelope; - - LFOParams *FilterLfo; - - // RESONANCE - Resonance *Reson; - - //how the randomness is applied to the harmonics on more voices using the same oscillator - unsigned char Hrandgrouping; - }; + unsigned char PStereo; - - /***********************************************************/ - /* VOICE PARAMETERS */ - /***********************************************************/ - struct ADnoteVoiceParam{ + /****************************************** + * FREQUENCY GLOBAL PARAMETERS * + ******************************************/ + unsigned short int PDetune;//fine detune + unsigned short int PCoarseDetune;//coarse detune+octave + unsigned char PDetuneType;//detune type - /* If the voice is enabled */ - unsigned char Enabled; + unsigned char PBandwidth;//how much the relative fine detunes of the voices are changed - /* Type of the voice (0=Sound,1=Noise)*/ - unsigned char Type; - - /* Voice Delay */ - unsigned char PDelay; + EnvelopeParams *FreqEnvelope; //Frequency Envelope - /* If the resonance is enabled for this voice */ - unsigned char Presonance; - - // What external oscil should I use, -1 for internal OscilSmp&FMSmp - short int Pextoscil,PextFMoscil; - // it is not allowed that the externoscil,externFMoscil => current voice + LFOParams *FreqLfo;//Frequency LFO - // oscillator phases - unsigned char Poscilphase,PFMoscilphase; + /******************************************** + * AMPLITUDE GLOBAL PARAMETERS * + ********************************************/ - // filter bypass - unsigned char Pfilterbypass; + /* Panning - 0 - random + 1 - left + 64 - center + 127 - right */ + unsigned char PPanning; - /* Voice oscillator */ - OscilGen *OscilSmp; + unsigned char PVolume; - /********************************** - * FREQUENCY PARAMETERS * - **********************************/ + unsigned char PAmpVelocityScaleFunction; - /* If the base frequency is fixed to 440 Hz*/ - unsigned char Pfixedfreq; - - /* Equal temperate (this is used only if the Pfixedfreq is enabled) - If this parameter is 0, the frequency is fixed (to 440 Hz); - if this parameter is 64, 1 MIDI halftone -> 1 frequency halftone */ - unsigned char PfixedfreqET; + EnvelopeParams *AmpEnvelope; - /* Fine detune */ - unsigned short int PDetune; + LFOParams *AmpLfo; - /* Coarse detune + octave */ - unsigned short int PCoarseDetune; + unsigned char PPunchStrength,PPunchTime,PPunchStretch,PPunchVelocitySensing; - /* Detune type */ - unsigned char PDetuneType; - - /* Frequency Envelope */ - unsigned char PFreqEnvelopeEnabled; - EnvelopeParams *FreqEnvelope; + /****************************************** + * FILTER GLOBAL PARAMETERS * + ******************************************/ + FilterParams *GlobalFilter; - /* Frequency LFO */ - unsigned char PFreqLfoEnabled; - LFOParams *FreqLfo; - + // filter velocity sensing + unsigned char PFilterVelocityScale; - /*************************** - * AMPLITUDE PARAMETERS * - ***************************/ + // filter velocity sensing + unsigned char PFilterVelocityScaleFunction; - /* Panning 0 - random - 1 - left - 64 - center - 127 - right - The Panning is ignored if the instrument is mono */ - unsigned char PPanning; + EnvelopeParams *FilterEnvelope; - /* Voice Volume */ - unsigned char PVolume; - - /* If the Volume negative */ - unsigned char PVolumeminus; + LFOParams *FilterLfo; - /* Velocity sensing */ - unsigned char PAmpVelocityScaleFunction; + // RESONANCE + Resonance *Reson; - /* Amplitude Envelope */ - unsigned char PAmpEnvelopeEnabled; - EnvelopeParams *AmpEnvelope; - - /* Amplitude LFO */ - unsigned char PAmpLfoEnabled; - LFOParams *AmpLfo; + //how the randomness is applied to the harmonics on more voices using the same oscillator + unsigned char Hrandgrouping; +}; - /************************* - * FILTER PARAMETERS * - *************************/ - - /* Voice Filter */ - unsigned char PFilterEnabled; - FilterParams *VoiceFilter; - - /* Filter Envelope */ - unsigned char PFilterEnvelopeEnabled; - EnvelopeParams *FilterEnvelope; - - /* LFO Envelope */ - unsigned char PFilterLfoEnabled; - LFOParams *FilterLfo; +/***********************************************************/ +/* VOICE PARAMETERS */ +/***********************************************************/ +struct ADnoteVoiceParam { - /**************************** - * MODULLATOR PARAMETERS * - ****************************/ + /** If the voice is enabled */ + unsigned char Enabled; - /* Modullator Parameters (0=off,1=Morph,2=RM,3=PM,4=FM.. */ - unsigned char PFMEnabled; - - /* Voice that I use as modullator instead of FMSmp. - It is -1 if I use FMSmp(default). - It maynot be equal or bigger than current voice */ - short int PFMVoice; - - /* Modullator oscillator */ - OscilGen *FMSmp; + /** Type of the voice (0=Sound,1=Noise)*/ + unsigned char Type; - /* Modullator Volume */ - unsigned char PFMVolume; + /** Voice Delay */ + unsigned char PDelay; - /* Modullator damping at higher frequencies */ - unsigned char PFMVolumeDamp; + /** If the resonance is enabled for this voice */ + unsigned char Presonance; - /* Modullator Velocity Sensing */ - unsigned char PFMVelocityScaleFunction; + // What external oscil should I use, -1 for internal OscilSmp&FMSmp + short int Pextoscil,PextFMoscil; + // it is not allowed that the externoscil,externFMoscil => current voice - /* Fine Detune of the Modullator*/ - unsigned short int PFMDetune; + // oscillator phases + unsigned char Poscilphase,PFMoscilphase; - /* Coarse Detune of the Modullator */ - unsigned short int PFMCoarseDetune; + // filter bypass + unsigned char Pfilterbypass; - /* The detune type */ - unsigned char PFMDetuneType; - - /* Frequency Envelope of the Modullator */ - unsigned char PFMFreqEnvelopeEnabled; - EnvelopeParams *FMFreqEnvelope; + /** Voice oscillator */ + OscilGen *OscilSmp; - /* Frequency Envelope of the Modullator */ - unsigned char PFMAmpEnvelopeEnabled; - EnvelopeParams *FMAmpEnvelope; - }; + /********************************** + * FREQUENCY PARAMETERS * + **********************************/ -class ADnoteParameters:public Presets{ - public: - ADnoteParameters(FFTwrapper *fft_); - ~ADnoteParameters(); + /** If the base frequency is fixed to 440 Hz*/ + unsigned char Pfixedfreq; - ADnoteGlobalParam GlobalPar; - ADnoteVoiceParam VoicePar[NUM_VOICES]; + /* Equal temperate (this is used only if the Pfixedfreq is enabled) + If this parameter is 0, the frequency is fixed (to 440 Hz); + if this parameter is 64, 1 MIDI halftone -> 1 frequency halftone */ + unsigned char PfixedfreqET; - void defaults(); - void add2XML(XMLwrapper *xml); - void getfromXML(XMLwrapper *xml); + /** Fine detune */ + unsigned short int PDetune; - REALTYPE getBandwidthDetuneMultiplier(); - private: - void defaults(int n);//n is the nvoice + /** Coarse detune + octave */ + unsigned short int PCoarseDetune; - void EnableVoice(int nvoice); - void KillVoice(int nvoice); - FFTwrapper *fft; + /** Detune type */ + unsigned char PDetuneType; - void add2XMLsection(XMLwrapper *xml,int n); - void getfromXMLsection(XMLwrapper *xml,int n); + /* Frequency Envelope */ + unsigned char PFreqEnvelopeEnabled; + EnvelopeParams *FreqEnvelope; + + /* Frequency LFO */ + unsigned char PFreqLfoEnabled; + LFOParams *FreqLfo; + + + /*************************** + * AMPLITUDE PARAMETERS * + ***************************/ + + /* Panning 0 - random + 1 - left + 64 - center + 127 - right + The Panning is ignored if the instrument is mono */ + unsigned char PPanning; + + /* Voice Volume */ + unsigned char PVolume; + + /* If the Volume negative */ + unsigned char PVolumeminus; + + /* Velocity sensing */ + unsigned char PAmpVelocityScaleFunction; + + /* Amplitude Envelope */ + unsigned char PAmpEnvelopeEnabled; + EnvelopeParams *AmpEnvelope; + + /* Amplitude LFO */ + unsigned char PAmpLfoEnabled; + LFOParams *AmpLfo; + + + + /************************* + * FILTER PARAMETERS * + *************************/ + + /* Voice Filter */ + unsigned char PFilterEnabled; + FilterParams *VoiceFilter; + + /* Filter Envelope */ + unsigned char PFilterEnvelopeEnabled; + EnvelopeParams *FilterEnvelope; + + /* LFO Envelope */ + unsigned char PFilterLfoEnabled; + LFOParams *FilterLfo; + + /**************************** + * MODULLATOR PARAMETERS * + ****************************/ + + /* Modullator Parameters (0=off,1=Morph,2=RM,3=PM,4=FM.. */ + unsigned char PFMEnabled; + + /* Voice that I use as modullator instead of FMSmp. + It is -1 if I use FMSmp(default). + It maynot be equal or bigger than current voice */ + short int PFMVoice; + + /* Modullator oscillator */ + OscilGen *FMSmp; + + /* Modullator Volume */ + unsigned char PFMVolume; + + /* Modullator damping at higher frequencies */ + unsigned char PFMVolumeDamp; + + /* Modullator Velocity Sensing */ + unsigned char PFMVelocityScaleFunction; + + /* Fine Detune of the Modullator*/ + unsigned short int PFMDetune; + + /* Coarse Detune of the Modullator */ + unsigned short int PFMCoarseDetune; + + /* The detune type */ + unsigned char PFMDetuneType; + + /* Frequency Envelope of the Modullator */ + unsigned char PFMFreqEnvelopeEnabled; + EnvelopeParams *FMFreqEnvelope; + + /* Frequency Envelope of the Modullator */ + unsigned char PFMAmpEnvelopeEnabled; + EnvelopeParams *FMAmpEnvelope; +}; + +class ADnoteParameters:public Presets +{ +public: + ADnoteParameters(FFTwrapper *fft_); + ~ADnoteParameters(); + + ADnoteGlobalParam GlobalPar; + ADnoteVoiceParam VoicePar[NUM_VOICES]; + + void defaults(); + void add2XML(XMLwrapper *xml); + void getfromXML(XMLwrapper *xml); + + REALTYPE getBandwidthDetuneMultiplier(); +private: + void defaults(int n);//n is the nvoice + + void EnableVoice(int nvoice); + void KillVoice(int nvoice); + FFTwrapper *fft; + + void add2XMLsection(XMLwrapper *xml,int n); + void getfromXMLsection(XMLwrapper *xml,int n); }; #endif diff --git a/plugins/zynaddsubfx/src/Params/CMakeLists.txt b/plugins/zynaddsubfx/src/Params/CMakeLists.txt new file mode 100644 index 000000000..5ad77a4f2 --- /dev/null +++ b/plugins/zynaddsubfx/src/Params/CMakeLists.txt @@ -0,0 +1,18 @@ +set(zynaddsubfx_params_SRCS + ADnoteParameters.cpp + Controller.cpp + EnvelopeParams.cpp + FilterParams.cpp + LFOParams.cpp + PADnoteParameters.cpp + Presets.cpp + PresetsStore.cpp + SUBnoteParameters.cpp + +) + +add_library(zynaddsubfx_params STATIC + ${zynaddsubfx_params_SRCS} + ) + +target_link_libraries(zynaddsubfx_params)# ${ASOUND_LIBRARY}) diff --git a/plugins/zynaddsubfx/src/Params/Controller.C b/plugins/zynaddsubfx/src/Params/Controller.cpp similarity index 64% rename from plugins/zynaddsubfx/src/Params/Controller.C rename to plugins/zynaddsubfx/src/Params/Controller.cpp index 754541510..2388dd4b6 100644 --- a/plugins/zynaddsubfx/src/Params/Controller.C +++ b/plugins/zynaddsubfx/src/Params/Controller.cpp @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Controller.C - (Midi) Controllers implementation Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -24,15 +24,18 @@ #include #include -Controller::Controller(){ +Controller::Controller() +{ defaults(); resetall(); }; -Controller::~Controller(){ +Controller::~Controller() +{ }; -void Controller::defaults(){ +void Controller::defaults() +{ setpitchwheelbendrange(200);//2 halftones expression.receive=1; panning.depth=64; @@ -43,12 +46,15 @@ void Controller::defaults(){ modwheel.depth=80; modwheel.exponential=0; fmamp.receive=1; - volume.receive=0; + volume.receive=1; sustain.receive=1; NRPN.receive=1; portamento.portamento=0; portamento.used=0; + portamento.proportional=0; + portamento.propRate=80; + portamento.propDepth=90; portamento.receive=1; portamento.time=64; portamento.updowntimestretch=64; @@ -63,7 +69,8 @@ void Controller::defaults(){ }; -void Controller::resetall(){ +void Controller::resetall() +{ setpitchwheel(0);//center setexpression(127); setpanning(64); @@ -76,7 +83,7 @@ void Controller::resetall(){ setsustain(0); setresonancecenter(64); setresonancebw(64); - + //reset the NRPN NRPN.parhi=-1; NRPN.parlo=-1; @@ -84,7 +91,8 @@ void Controller::resetall(){ NRPN.vallo=-1; }; -void Controller::setpitchwheel(int value){ +void Controller::setpitchwheel(int value) +{ pitchwheel.data=value; REALTYPE cents=value/8192.0; cents*=pitchwheel.bendrange; @@ -92,106 +100,130 @@ void Controller::setpitchwheel(int value){ //fprintf(stderr,"%ld %ld -> %.3f\n",pitchwheel.bendrange,pitchwheel.data,pitchwheel.relfreq);fflush(stderr); }; -void Controller::setpitchwheelbendrange(unsigned short int value){ +void Controller::setpitchwheelbendrange(unsigned short int value) +{ pitchwheel.bendrange=value; }; -void Controller::setexpression(int value){ +void Controller::setexpression(int value) +{ expression.data=value; if (expression.receive!=0) expression.relvolume=value/127.0; - else expression.relvolume=1.0; + else expression.relvolume=1.0; }; -void Controller::setpanning(int value){ +void Controller::setpanning(int value) +{ panning.data=value; panning.pan=(value/128.0-0.5)*(panning.depth/64.0); }; -void Controller::setfiltercutoff(int value){ +void Controller::setfiltercutoff(int value) +{ filtercutoff.data=value; filtercutoff.relfreq=(value-64.0)*filtercutoff.depth/4096.0*3.321928;//3.3219..=ln2(10) }; -void Controller::setfilterq(int value){ +void Controller::setfilterq(int value) +{ filterq.data=value; filterq.relq=pow(30.0,(value-64.0)/64.0*(filterq.depth/64.0)); }; -void Controller::setbandwidth(int value){ +void Controller::setbandwidth(int value) +{ bandwidth.data=value; if (bandwidth.exponential==0) { - REALTYPE tmp=pow(25.0,pow(bandwidth.depth/127.0,1.5))-1.0; - if ((value<64)&&(bandwidth.depth>=64)) tmp=1.0; - bandwidth.relbw=(value/64.0-1.0)*tmp+1.0; - if (bandwidth.relbw<0.01) bandwidth.relbw=0.01; + REALTYPE tmp=pow(25.0,pow(bandwidth.depth/127.0,1.5))-1.0; + if ((value<64)&&(bandwidth.depth>=64)) tmp=1.0; + bandwidth.relbw=(value/64.0-1.0)*tmp+1.0; + if (bandwidth.relbw<0.01) bandwidth.relbw=0.01; } else { - bandwidth.relbw=pow(25.0,(value-64.0)/64.0*(bandwidth.depth/64.0)); + bandwidth.relbw=pow(25.0,(value-64.0)/64.0*(bandwidth.depth/64.0)); }; }; -void Controller::setmodwheel(int value){ +void Controller::setmodwheel(int value) +{ modwheel.data=value; if (modwheel.exponential==0) { - REALTYPE tmp=pow(25.0,pow(modwheel.depth/127.0,1.5)*2.0)/25.0; - if ((value<64)&&(modwheel.depth>=64)) tmp=1.0; - modwheel.relmod=(value/64.0-1.0)*tmp+1.0; - if (modwheel.relmod<0.0) modwheel.relmod=0.0; - } else modwheel.relmod=pow(25.0,(value-64.0)/64.0*(modwheel.depth/80.0)); + REALTYPE tmp=pow(25.0,pow(modwheel.depth/127.0,1.5)*2.0)/25.0; + if ((value<64)&&(modwheel.depth>=64)) tmp=1.0; + modwheel.relmod=(value/64.0-1.0)*tmp+1.0; + if (modwheel.relmod<0.0) modwheel.relmod=0.0; + } else modwheel.relmod=pow(25.0,(value-64.0)/64.0*(modwheel.depth/80.0)); }; -void Controller::setfmamp(int value){ +void Controller::setfmamp(int value) +{ fmamp.data=value; fmamp.relamp=value/127.0; if (fmamp.receive!=0) fmamp.relamp=value/127.0; - else fmamp.relamp=1.0; + else fmamp.relamp=1.0; }; -void Controller::setvolume(int value){ +void Controller::setvolume(int value) +{ volume.data=value; if (volume.receive!=0) volume.volume=pow(0.1,(127-value)/127.0*2.0); - else volume.volume=1.0; + else volume.volume=1.0; }; -void Controller::setsustain(int value){ +void Controller::setsustain(int value) +{ sustain.data=value; if (sustain.receive!=0) sustain.sustain=((value<64) ? 0 : 1 ); - else sustain.sustain=0; + else sustain.sustain=0; }; -void Controller::setportamento(int value){ +void Controller::setportamento(int value) +{ portamento.data=value; if (portamento.receive!=0) portamento.portamento=((value<64) ? 0 : 1 ); }; -// I added a third argument to pass legato status, -// when legatoflag is true it means "there's a legato in progress". -int Controller::initportamento(REALTYPE oldfreq,REALTYPE newfreq,bool legatoflag){ +int Controller::initportamento(REALTYPE oldfreq,REALTYPE newfreq,bool legatoflag) +{ portamento.x=0.0; - if (legatoflag){ // Legato in progress - if (portamento.portamento==0) return(0); + if (legatoflag) { // Legato in progress + if (portamento.portamento==0) return(0); } else { // No legato, do the original if...return - if ((portamento.used!=0) || (portamento.portamento==0)) return(0); + if ((portamento.used!=0) || (portamento.portamento==0)) return(0); }; REALTYPE portamentotime=pow(100.0,portamento.time/127.0)/50.0;//portamento time in seconds - - if ((portamento.updowntimestretch>=64)&&(newfreqoldfreq)){ - if (portamento.updowntimestretch==0) return(0); - portamentotime*=pow(0.1,(64.0-portamento.updowntimestretch)/64.0); - }; + if (portamento.proportional) { + //If there is a min(float,float) and a max(float,float) then they + //could be used here + //Linear functors could also make this nicer + if(oldfreq > newfreq) //2 is the center of propRate + portamentotime *= pow(oldfreq/newfreq/(portamento.propRate/127.0*3+.05), + (portamento.propDepth/127.0*1.6+.2)); + else //1 is the center of propDepth + portamentotime *= pow(newfreq/oldfreq/(portamento.propRate/127.0*3+.05), + (portamento.propDepth/127.0*1.6+.2)); + } + + if ((portamento.updowntimestretch>=64)&&(newfreqoldfreq)) { + if (portamento.updowntimestretch==0) return(0); + portamentotime*=pow(0.1,(64.0-portamento.updowntimestretch)/64.0); + }; + + //printf("%f->%f : Time %f\n",oldfreq,newfreq,portamentotime); + portamento.dx=SOUND_BUFFER_SIZE/(portamentotime*SAMPLE_RATE); portamento.origfreqrap=oldfreq/newfreq; - - REALTYPE tmprap=( (portamento.origfreqrap>1.0) ? - (portamento.origfreqrap) : - (1.0/portamento.origfreqrap) ); - + + REALTYPE tmprap=( (portamento.origfreqrap>1.0) ? + (portamento.origfreqrap) : + (1.0/portamento.origfreqrap) ); + REALTYPE thresholdrap=pow(2.0,portamento.pitchthresh/12.0); if ((portamento.pitchthreshtype==0) && (tmprap-0.00001>thresholdrap) ) return(0); if ((portamento.pitchthreshtype==1) && (tmprap+0.000011.0) { - portamento.x=1.0; - portamento.used=0; + portamento.x=1.0; + portamento.used=0; }; portamento.freqrap=(1.0-portamento.x)*portamento.origfreqrap+portamento.x; }; -void Controller::setresonancecenter(int value){ +void Controller::setresonancecenter(int value) +{ resonancecenter.data=value; resonancecenter.relcenter=pow(3.0,(value-64.0)/64.0*(resonancecenter.depth/64.0)); }; -void Controller::setresonancebw(int value){ +void Controller::setresonancebw(int value) +{ resonancebandwidth.data=value; resonancebandwidth.relbw=pow(1.5,(value-64.0)/64.0*(resonancebandwidth.depth/127.0)); }; //Returns 0 if there is NRPN or 1 if there is not -int Controller::getnrpn(int *parhi, int *parlo, int *valhi, int *vallo){ +int Controller::getnrpn(int *parhi, int *parlo, int *valhi, int *vallo) +{ if (NRPN.receive==0) return(1); - if ((NRPN.parhi<0)||(NRPN.parlo<0)||(NRPN.valhi<0)||(NRPN.vallo<0)) - return(1); - + if ((NRPN.parhi<0)||(NRPN.parlo<0)||(NRPN.valhi<0)||(NRPN.vallo<0)) + return(1); + *parhi=NRPN.parhi; *parlo=NRPN.parlo; *valhi=NRPN.valhi; @@ -237,24 +273,32 @@ int Controller::getnrpn(int *parhi, int *parlo, int *valhi, int *vallo){ }; -void Controller::setparameternumber(unsigned int type,int value){ - switch(type){ - case C_nrpnhi:NRPN.parhi=value; - NRPN.valhi=-1;NRPN.vallo=-1;//clear the values - break; - case C_nrpnlo:NRPN.parlo=value; - NRPN.valhi=-1;NRPN.vallo=-1;//clear the values - break; - case C_dataentryhi:if ((NRPN.parhi>=0)&&(NRPN.parlo>=0)) NRPN.valhi=value; - break; - case C_dataentrylo:if ((NRPN.parhi>=0)&&(NRPN.parlo>=0)) NRPN.vallo=value; - break; +void Controller::setparameternumber(unsigned int type,int value) +{ + switch (type) { + case C_nrpnhi: + NRPN.parhi=value; + NRPN.valhi=-1; + NRPN.vallo=-1;//clear the values + break; + case C_nrpnlo: + NRPN.parlo=value; + NRPN.valhi=-1; + NRPN.vallo=-1;//clear the values + break; + case C_dataentryhi: + if ((NRPN.parhi>=0)&&(NRPN.parlo>=0)) NRPN.valhi=value; + break; + case C_dataentrylo: + if ((NRPN.parhi>=0)&&(NRPN.parlo>=0)) NRPN.vallo=value; + break; }; }; -void Controller::add2XML(XMLwrapper *xml){ +void Controller::add2XML(XMLwrapper *xml) +{ xml->addpar("pitchwheel_bendrange",pitchwheel.bendrange); xml->addparbool("expression_receive",expression.receive); @@ -274,12 +318,16 @@ void Controller::add2XML(XMLwrapper *xml){ xml->addpar("portamento_pitchthreshtype",portamento.pitchthreshtype); xml->addpar("portamento_portamento",portamento.portamento); xml->addpar("portamento_updowntimestretch",portamento.updowntimestretch); + xml->addpar("portamento_proportional",portamento.proportional); + xml->addpar("portamento_proprate",portamento.propRate); + xml->addpar("portamento_propdepth",portamento.propDepth); xml->addpar("resonance_center_depth",resonancecenter.depth); xml->addpar("resonance_bandwidth_depth",resonancebandwidth.depth); }; -void Controller::getfromXML(XMLwrapper *xml){ +void Controller::getfromXML(XMLwrapper *xml) +{ pitchwheel.bendrange=xml->getpar("pitchwheel_bendrange",pitchwheel.bendrange,-6400,6400); expression.receive=xml->getparbool("expression_receive",expression.receive); @@ -299,6 +347,10 @@ void Controller::getfromXML(XMLwrapper *xml){ portamento.pitchthreshtype=xml->getpar127("portamento_pitchthreshtype",portamento.pitchthreshtype); portamento.portamento=xml->getpar127("portamento_portamento",portamento.portamento); portamento.updowntimestretch=xml->getpar127("portamento_updowntimestretch",portamento.updowntimestretch); + portamento.proportional=xml->getpar127("portamento_proportional",portamento.proportional); + portamento.propRate=xml->getpar127("portamento_proprate",portamento.propRate); + portamento.propDepth=xml->getpar127("portamento_propdepth",portamento.propDepth); + resonancecenter.depth=xml->getpar127("resonance_center_depth",resonancecenter.depth); resonancebandwidth.depth=xml->getpar127("resonance_bandwidth_depth",resonancebandwidth.depth); diff --git a/plugins/zynaddsubfx/src/Params/Controller.h b/plugins/zynaddsubfx/src/Params/Controller.h index cdf629781..3e5ededac 100644 --- a/plugins/zynaddsubfx/src/Params/Controller.h +++ b/plugins/zynaddsubfx/src/Params/Controller.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Controller.h - (Midi) Controllers implementation Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -27,153 +27,195 @@ #include "../globals.h" #include "../Misc/XMLwrapper.h" -class Controller{ - public: - Controller(); - ~Controller(); - void resetall(); +/**(Midi) Controllers implementation*/ +class Controller +{ +public: + Controller(); + ~Controller(); + void resetall(); - void add2XML(XMLwrapper *xml); - void defaults(); - void getfromXML(XMLwrapper *xml); + void add2XML(XMLwrapper *xml); + void defaults(); + void getfromXML(XMLwrapper *xml); //Controllers functions - void setpitchwheel(int value); - void setpitchwheelbendrange(unsigned short int value); - void setexpression(int value); - void setpanning(int value); - void setfiltercutoff(int value); - void setfilterq(int value); - void setbandwidth(int value); - void setmodwheel(int value); - void setfmamp(int value); - void setvolume(int value); - void setsustain(int value); - void setportamento(int value); - void setresonancecenter(int value); - void setresonancebw(int value); + void setpitchwheel(int value); + void setpitchwheelbendrange(unsigned short int value); + void setexpression(int value); + void setpanning(int value); + void setfiltercutoff(int value); + void setfilterq(int value); + void setbandwidth(int value); + void setmodwheel(int value); + void setfmamp(int value); + void setvolume(int value); + void setsustain(int value); + /**Enable or disable portamento + * @param value 0-127 MIDI value (greater than 64 enables)*/ + void setportamento(int value); + void setresonancecenter(int value); + void setresonancebw(int value); - void setparameternumber(unsigned int type,int value);//used for RPN and NRPN's - int getnrpn(int *parhi, int *parlo, int *valhi, int *vallo); + void setparameternumber(unsigned int type,int value);//used for RPN and NRPN's + int getnrpn(int *parhi, int *parlo, int *valhi, int *vallo); - int initportamento(REALTYPE oldfreq,REALTYPE newfreq,bool legatoflag);//returns 1 if the portamento's conditions are true, else return 0 - void updateportamento(); //update portamento values + /** + * Initialize a portamento + * + * @param oldfreq Starting frequency of the portamento (Hz) + * @param newfreq Ending frequency of the portamento (Hz) + * @param legatoflag true when legato is in progress, false otherwise + * @returns 1 if properly initialized, 0 otherwise*/ + int initportamento(REALTYPE oldfreq,REALTYPE newfreq,bool legatoflag); + /**Update portamento's freqrap to next value based upon dx*/ + void updateportamento(); - // Controllers values + // Controllers values struct {//Pitch Wheel - int data; - short int bendrange;//bendrange is in cents - REALTYPE relfreq;//the relative frequency (default is 1.0) + int data; + short int bendrange;//bendrange is in cents + REALTYPE relfreq;//the relative frequency (default is 1.0) } pitchwheel; - - struct{//Expression - int data; - REALTYPE relvolume; - unsigned char receive; + + struct {//Expression + int data; + REALTYPE relvolume; + unsigned char receive; } expression; - struct{//Panning - int data; - REALTYPE pan; - unsigned char depth; + struct {//Panning + int data; + REALTYPE pan; + unsigned char depth; } panning; - - struct{//Filter cutoff - int data; - REALTYPE relfreq; - unsigned char depth; + + struct {//Filter cutoff + int data; + REALTYPE relfreq; + unsigned char depth; } filtercutoff; - struct{//Filter Q - int data; - REALTYPE relq; - unsigned char depth; + struct {//Filter Q + int data; + REALTYPE relq; + unsigned char depth; } filterq; - struct{//Bandwidth - int data; - REALTYPE relbw; - unsigned char depth; - unsigned char exponential; + struct {//Bandwidth + int data; + REALTYPE relbw; + unsigned char depth; + unsigned char exponential; } bandwidth; struct {//Modulation Wheel - int data; - REALTYPE relmod; - unsigned char depth; - unsigned char exponential; + int data; + REALTYPE relmod; + unsigned char depth; + unsigned char exponential; } modwheel; - struct{//FM amplitude - int data; - REALTYPE relamp; - unsigned char receive; + struct {//FM amplitude + int data; + REALTYPE relamp; + unsigned char receive; } fmamp; - struct{//Volume - int data; - REALTYPE volume; - unsigned char receive; + struct {//Volume + int data; + REALTYPE volume; + unsigned char receive; } volume; - struct{//Sustain - int data,sustain; - unsigned char receive; + struct {//Sustain + int data,sustain; + unsigned char receive; } sustain; - struct{//Portamento - //parameters - int data; - unsigned char portamento; - - //pitchthresh is the threshold of enabling protamento - //pitchthreshtype -> enable the portamento only below(0)/above(1) the threshold - unsigned char receive,time,pitchthresh,pitchthreshtype; + struct {/** #include "EnvelopeParams.h" -EnvelopeParams::EnvelopeParams(unsigned char Penvstretch_,unsigned char Pforcedrelease_):Presets(){ +EnvelopeParams::EnvelopeParams(unsigned char Penvstretch_,unsigned char Pforcedrelease_):Presets() +{ int i; - - PA_dt=10;PD_dt=10;PR_dt=10;PA_val=64;PD_val=64;PS_val=64;PR_val=64; - - for (i=0;iaddparbool("free_mode",Pfreemode); +void EnvelopeParams::add2XML(XMLwrapper *xml) +{ + xml->addparbool("free_mode",Pfreemode); xml->addpar("env_points",Penvpoints); xml->addpar("env_sustain",Penvsustain); xml->addpar("env_stretch",Penvstretch); @@ -156,20 +217,21 @@ void EnvelopeParams::add2XML(XMLwrapper *xml){ xml->addpar("S_val",PS_val); xml->addpar("R_val",PR_val); - if ((Pfreemode!=0)||(!xml->minimal)){ - for (int i=0;ibeginbranch("POINT",i); - if (i!=0) xml->addpar("dt",Penvdt[i]); - xml->addpar("val",Penvval[i]); - xml->endbranch(); - }; + if ((Pfreemode!=0)||(!xml->minimal)) { + for (int i=0;ibeginbranch("POINT",i); + if (i!=0) xml->addpar("dt",Penvdt[i]); + xml->addpar("val",Penvval[i]); + xml->endbranch(); + }; }; }; -void EnvelopeParams::getfromXML(XMLwrapper *xml){ - Pfreemode=xml->getparbool("free_mode",Pfreemode); +void EnvelopeParams::getfromXML(XMLwrapper *xml) +{ + Pfreemode=xml->getparbool("free_mode",Pfreemode); Penvpoints=xml->getpar127("env_points",Penvpoints); Penvsustain=xml->getpar127("env_sustain",Penvsustain); Penvstretch=xml->getpar127("env_stretch",Penvstretch); @@ -184,18 +246,19 @@ void EnvelopeParams::getfromXML(XMLwrapper *xml){ PS_val=xml->getpar127("S_val",PS_val); PR_val=xml->getpar127("R_val",PR_val); - for (int i=0;ienterbranch("POINT",i)==0) continue; - if (i!=0) Penvdt[i]=xml->getpar127("dt",Penvdt[i]); - Penvval[i]=xml->getpar127("val",Penvval[i]); - xml->exitbranch(); + if (i!=0) Penvdt[i]=xml->getpar127("dt",Penvdt[i]); + Penvval[i]=xml->getpar127("val",Penvval[i]); + xml->exitbranch(); }; - + if (!Pfreemode) converttofree(); }; -void EnvelopeParams::defaults(){ +void EnvelopeParams::defaults() +{ Penvstretch=Denvstretch; Pforcedrelease=Dforcedrelease; Plinearenvelope=Dlinearenvelope; @@ -210,7 +273,8 @@ void EnvelopeParams::defaults(){ converttofree(); }; -void EnvelopeParams::store2defaults(){ +void EnvelopeParams::store2defaults() +{ Denvstretch=Penvstretch; Dforcedrelease=Pforcedrelease; Dlinearenvelope=Plinearenvelope; @@ -223,5 +287,3 @@ void EnvelopeParams::store2defaults(){ DR_val=PR_val; }; - - diff --git a/plugins/zynaddsubfx/src/Params/EnvelopeParams.h b/plugins/zynaddsubfx/src/Params/EnvelopeParams.h index 5267356b1..d7d44c859 100644 --- a/plugins/zynaddsubfx/src/Params/EnvelopeParams.h +++ b/plugins/zynaddsubfx/src/Params/EnvelopeParams.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + EnvelopeParams.h - Parameters for Envelope Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -30,57 +30,57 @@ #define MAX_ENVELOPE_POINTS 40 #define MIN_ENVELOPE_DB -40 -class EnvelopeParams:public Presets{ - public: - EnvelopeParams(unsigned char Penvstretch_,unsigned char Pforcedrelease_); - ~EnvelopeParams(); - void ADSRinit(char A_dt,char D_dt,char S_val,char R_dt); - void ADSRinit_dB(char A_dt,char D_dt,char S_val,char R_dt); - void ASRinit(char A_val,char A_dt,char R_val,char R_dt); - void ADSRinit_filter(char A_val,char A_dt,char D_val,char D_dt,char R_dt,char R_val); - void ASRinit_bw(char A_val,char A_dt,char R_val,char R_dt); - void converttofree(); +class EnvelopeParams:public Presets +{ +public: + EnvelopeParams(unsigned char Penvstretch_,unsigned char Pforcedrelease_); + ~EnvelopeParams(); + void ADSRinit(char A_dt,char D_dt,char S_val,char R_dt); + void ADSRinit_dB(char A_dt,char D_dt,char S_val,char R_dt); + void ASRinit(char A_val,char A_dt,char R_val,char R_dt); + void ADSRinit_filter(char A_val,char A_dt,char D_val,char D_dt,char R_dt,char R_val); + void ASRinit_bw(char A_val,char A_dt,char R_val,char R_dt); + void converttofree(); - void add2XML(XMLwrapper *xml); - void defaults(); - void getfromXML(XMLwrapper *xml); + void add2XML(XMLwrapper *xml); + void defaults(); + void getfromXML(XMLwrapper *xml); - REALTYPE getdt(char i); + REALTYPE getdt(char i); - /* Parametrii MIDI */ - unsigned char Pfreemode;//1 daca este in modul free sau 0 daca este in mod ADSR,ASR,... - unsigned char Penvpoints; - unsigned char Penvsustain;//127 pentru dezactivat - unsigned char Penvdt[MAX_ENVELOPE_POINTS]; - unsigned char Penvval[MAX_ENVELOPE_POINTS]; - unsigned char Penvstretch;//64=normal stretch (piano-like), 0=no stretch - unsigned char Pforcedrelease;//0 - OFF, 1 - ON - unsigned char Plinearenvelope;//if the amplitude envelope is linear - - unsigned char PA_dt,PD_dt,PR_dt, - PA_val,PD_val,PS_val,PR_val; + /* MIDI Parameters */ + unsigned char Pfreemode;//1 daca este in modul free sau 0 daca este in mod ADSR,ASR,... + unsigned char Penvpoints; + unsigned char Penvsustain;//127 pentru dezactivat + unsigned char Penvdt[MAX_ENVELOPE_POINTS]; + unsigned char Penvval[MAX_ENVELOPE_POINTS]; + unsigned char Penvstretch;//64=normal stretch (piano-like), 0=no stretch + unsigned char Pforcedrelease;//0 - OFF, 1 - ON + unsigned char Plinearenvelope;//if the amplitude envelope is linear + + unsigned char PA_dt,PD_dt,PR_dt, + PA_val,PD_val,PS_val,PR_val; - int Envmode;// 1 for ADSR parameters (linear amplitude) - // 2 for ADSR_dB parameters (dB amplitude) - // 3 for ASR parameters (frequency LFO) - // 4 for ADSR_filter parameters (filter parameters) - // 5 for ASR_bw parameters (bandwidth parameters) + int Envmode;// 1 for ADSR parameters (linear amplitude) + // 2 for ADSR_dB parameters (dB amplitude) + // 3 for ASR parameters (frequency LFO) + // 4 for ADSR_filter parameters (filter parameters) + // 5 for ASR_bw parameters (bandwidth parameters) - private: - void store2defaults(); +private: + void store2defaults(); - /* Default parameters */ - unsigned char Denvstretch; - unsigned char Dforcedrelease; - unsigned char Dlinearenvelope; - unsigned char DA_dt,DD_dt,DR_dt, - DA_val,DD_val,DS_val,DR_val; + /* Default parameters */ + unsigned char Denvstretch; + unsigned char Dforcedrelease; + unsigned char Dlinearenvelope; + unsigned char DA_dt,DD_dt,DR_dt, + DA_val,DD_val,DS_val,DR_val; }; - #endif diff --git a/plugins/zynaddsubfx/src/Params/FilterParams.C b/plugins/zynaddsubfx/src/Params/FilterParams.C deleted file mode 100644 index f1402939b..000000000 --- a/plugins/zynaddsubfx/src/Params/FilterParams.C +++ /dev/null @@ -1,344 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - FilterParams.C - Parameters for filter - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include -#include -#include "FilterParams.h" - -FilterParams::FilterParams(unsigned char Ptype_,unsigned char Pfreq_,unsigned char Pq_):Presets(){ - setpresettype("Pfilter"); - Dtype=Ptype_; - Dfreq=Pfreq_; - Dq=Pq_; - - changed=false; - defaults(); -}; - -FilterParams::~FilterParams(){ -}; - - -void FilterParams::defaults(){ - Ptype=Dtype; - Pfreq=Dfreq; - Pq=Dq; - - Pstages=0; - Pfreqtrack=64; - Pgain=64; - Pcategory=0; - - Pnumformants=3; - Pformantslowness=64; - for (int j=0;jPtype; - Pfreq=pars->Pfreq; - Pq=pars->Pq; - - Pstages=pars->Pstages; - Pfreqtrack=pars->Pfreqtrack; - Pgain=pars->Pgain; - Pcategory=pars->Pcategory; - - Pnumformants=pars->Pnumformants; - Pformantslowness=pars->Pformantslowness; - for (int j=0;jPvowels[j].formants[i].freq; - Pvowels[j].formants[i].q=pars->Pvowels[j].formants[i].q; - Pvowels[j].formants[i].amp=pars->Pvowels[j].formants[i].amp; - }; - }; - - Psequencesize=pars->Psequencesize; - for (int i=0;iPsequence[i].nvowel; - - Psequencestretch=pars->Psequencestretch; - Psequencereversed=pars->Psequencereversed; - Pcenterfreq=pars->Pcenterfreq; - Poctavesfreq=pars->Poctavesfreq; - Pvowelclearness=pars->Pvowelclearness; -}; - - -/* - * Parameter control - */ -REALTYPE FilterParams::getfreq(){ - return((Pfreq/64.0-1.0)*5.0); -}; - -REALTYPE FilterParams::getq(){ - return(exp(pow((REALTYPE) Pq/127.0,2)*log(1000.0))-0.9); -}; -REALTYPE FilterParams::getfreqtracking(REALTYPE notefreq){ - return(log(notefreq/440.0)*(Pfreqtrack-64.0)/(64.0*LOG_2)); -}; - -REALTYPE FilterParams::getgain(){ - return((Pgain/64.0-1.0)*30.0);//-30..30dB -}; - -/* - * Get the center frequency of the formant's graph - */ -REALTYPE FilterParams::getcenterfreq(){ - return(10000.0*pow(10,-(1.0-Pcenterfreq/127.0)*2.0)); -}; - -/* - * Get the number of octave that the formant functions applies to - */ -REALTYPE FilterParams::getoctavesfreq(){ - return(0.25+10.0*Poctavesfreq/127.0); -}; - -/* - * Get the frequency from x, where x is [0..1] - */ -REALTYPE FilterParams::getfreqx(REALTYPE x){ - if (x>1.0) x=1.0; - REALTYPE octf=pow(2.0,getoctavesfreq()); - return(getcenterfreq()/sqrt(octf)*pow(octf,x)); -}; - -/* - * Get the x coordinate from frequency (used by the UI) - */ -REALTYPE FilterParams::getfreqpos(REALTYPE freq){ - return((log(freq)-log(getfreqx(0.0)))/log(2.0)/getoctavesfreq()); -}; - - -/* - * Get the freq. response of the formant filter - */ -void FilterParams::formantfilterH(int nvowel,int nfreqs,REALTYPE *freqs){ - REALTYPE c[3],d[3]; - REALTYPE filter_freq,filter_q,filter_amp; - REALTYPE omega,sn,cs,alpha; - - for (int i=0;i0) filter_q=(filter_q>1.0 ? pow(filter_q,1.0/(Pstages+1)) : filter_q); - - filter_amp=getformantamp(Pvowels[nvowel].formants[nformant].amp); - - - if (filter_freq<=(SAMPLE_RATE/2-100.0)){ - omega=2*PI*filter_freq/SAMPLE_RATE; - sn=sin(omega); - cs=cos(omega); - alpha=sn/(2*filter_q); - REALTYPE tmp=1+alpha; - c[0]=alpha/tmp*sqrt(filter_q+1); - c[1]=0; - c[2]=-alpha/tmp*sqrt(filter_q+1); - d[1]=-2*cs/tmp*(-1); - d[2]=(1-alpha)/tmp*(-1); - } else continue; - - - for (int i=0;iSAMPLE_RATE/2) { - for (int tmp=i;tmp0.000000001) freqs[i]=rap2dB(freqs[i])+getgain(); - else freqs[i]=-90.0; - }; - -}; - -/* - * Transforms a parameter to the real value - */ -REALTYPE FilterParams::getformantfreq(unsigned char freq){ - REALTYPE result=getfreqx(freq/127.0); - return(result); -}; - -REALTYPE FilterParams::getformantamp(unsigned char amp){ - REALTYPE result=pow(0.1,(1.0-amp/127.0)*4.0); - return(result); -}; - -REALTYPE FilterParams::getformantq(unsigned char q){ - //temp - REALTYPE result=pow(25.0,(q-32.0)/64.0); - return(result); -}; - - - -void FilterParams::add2XMLsection(XMLwrapper *xml,int n){ - int nvowel=n; - for (int nformant=0;nformantbeginbranch("FORMANT",nformant); - xml->addpar("freq",Pvowels[nvowel].formants[nformant].freq); - xml->addpar("amp",Pvowels[nvowel].formants[nformant].amp); - xml->addpar("q",Pvowels[nvowel].formants[nformant].q); - xml->endbranch(); - }; -}; - -void FilterParams::add2XML(XMLwrapper *xml){ - //filter parameters - xml->addpar("category",Pcategory); - xml->addpar("type",Ptype); - xml->addpar("freq",Pfreq); - xml->addpar("q",Pq); - xml->addpar("stages",Pstages); - xml->addpar("freq_track",Pfreqtrack); - xml->addpar("gain",Pgain); - - //formant filter parameters - if ((Pcategory==1)||(!xml->minimal)){ - xml->beginbranch("FORMANT_FILTER"); - xml->addpar("num_formants",Pnumformants); - xml->addpar("formant_slowness",Pformantslowness); - xml->addpar("vowel_clearness",Pvowelclearness); - xml->addpar("center_freq",Pcenterfreq); - xml->addpar("octaves_freq",Poctavesfreq); - for (int nvowel=0;nvowelbeginbranch("VOWEL",nvowel); - add2XMLsection(xml,nvowel); - xml->endbranch(); - }; - xml->addpar("sequence_size",Psequencesize); - xml->addpar("sequence_stretch",Psequencestretch); - xml->addparbool("sequence_reversed",Psequencereversed); - for (int nseq=0;nseqbeginbranch("SEQUENCE_POS",nseq); - xml->addpar("vowel_id",Psequence[nseq].nvowel); - xml->endbranch(); - }; - xml->endbranch(); - }; -}; - - -void FilterParams::getfromXMLsection(XMLwrapper *xml,int n){ - int nvowel=n; - for (int nformant=0;nformantenterbranch("FORMANT",nformant)==0) continue; - Pvowels[nvowel].formants[nformant].freq=xml->getpar127("freq",Pvowels[nvowel].formants[nformant].freq); - Pvowels[nvowel].formants[nformant].amp=xml->getpar127("amp",Pvowels[nvowel].formants[nformant].amp); - Pvowels[nvowel].formants[nformant].q=xml->getpar127("q",Pvowels[nvowel].formants[nformant].q); - xml->exitbranch(); - }; -}; - -void FilterParams::getfromXML(XMLwrapper *xml){ - //filter parameters - Pcategory=xml->getpar127("category",Pcategory); - Ptype=xml->getpar127("type",Ptype); - Pfreq=xml->getpar127("freq",Pfreq); - Pq=xml->getpar127("q",Pq); - Pstages=xml->getpar127("stages",Pstages); - Pfreqtrack=xml->getpar127("freq_track",Pfreqtrack); - Pgain=xml->getpar127("gain",Pgain); - - //formant filter parameters - if(xml->enterbranch("FORMANT_FILTER")){ - Pnumformants=xml->getpar127("num_formants",Pnumformants); - Pformantslowness=xml->getpar127("formant_slowness",Pformantslowness); - Pvowelclearness=xml->getpar127("vowel_clearness",Pvowelclearness); - Pcenterfreq=xml->getpar127("center_freq",Pcenterfreq); - Poctavesfreq=xml->getpar127("octaves_freq",Poctavesfreq); - - for (int nvowel=0;nvowelenterbranch("VOWEL",nvowel)==0) continue; - getfromXMLsection(xml,nvowel); - xml->exitbranch(); - }; - Psequencesize=xml->getpar127("sequence_size",Psequencesize); - Psequencestretch=xml->getpar127("sequence_stretch",Psequencestretch); - Psequencereversed=xml->getparbool("sequence_reversed",Psequencereversed); - for (int nseq=0;nseqenterbranch("SEQUENCE_POS",nseq)==0) continue; - Psequence[nseq].nvowel=xml->getpar("vowel_id",Psequence[nseq].nvowel,0,FF_MAX_VOWELS-1); - xml->exitbranch(); - }; - xml->exitbranch(); - }; - -}; - diff --git a/plugins/zynaddsubfx/src/Params/FilterParams.cpp b/plugins/zynaddsubfx/src/Params/FilterParams.cpp new file mode 100644 index 000000000..861b6d313 --- /dev/null +++ b/plugins/zynaddsubfx/src/Params/FilterParams.cpp @@ -0,0 +1,366 @@ +/* + ZynAddSubFX - a software synthesizer + + FilterParams.C - Parameters for filter + Copyright (C) 2002-2005 Nasca Octavian Paul + Author: Nasca Octavian Paul + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include +#include +#include +#include "FilterParams.h" + +FilterParams::FilterParams(unsigned char Ptype_,unsigned char Pfreq_,unsigned char Pq_):Presets() +{ + setpresettype("Pfilter"); + Dtype=Ptype_; + Dfreq=Pfreq_; + Dq=Pq_; + + changed=false; + defaults(); +}; + +FilterParams::~FilterParams() +{ +}; + + +void FilterParams::defaults() +{ + Ptype=Dtype; + Pfreq=Dfreq; + Pq=Dq; + + Pstages=0; + Pfreqtrack=64; + Pgain=64; + Pcategory=0; + + Pnumformants=3; + Pformantslowness=64; + for (int j=0;jPtype; + Pfreq=pars->Pfreq; + Pq=pars->Pq; + + Pstages=pars->Pstages; + Pfreqtrack=pars->Pfreqtrack; + Pgain=pars->Pgain; + Pcategory=pars->Pcategory; + + Pnumformants=pars->Pnumformants; + Pformantslowness=pars->Pformantslowness; + for (int j=0;jPvowels[j].formants[i].freq; + Pvowels[j].formants[i].q=pars->Pvowels[j].formants[i].q; + Pvowels[j].formants[i].amp=pars->Pvowels[j].formants[i].amp; + }; + }; + + Psequencesize=pars->Psequencesize; + for (int i=0;iPsequence[i].nvowel; + + Psequencestretch=pars->Psequencestretch; + Psequencereversed=pars->Psequencereversed; + Pcenterfreq=pars->Pcenterfreq; + Poctavesfreq=pars->Poctavesfreq; + Pvowelclearness=pars->Pvowelclearness; +}; + + +/* + * Parameter control + */ +REALTYPE FilterParams::getfreq() +{ + return((Pfreq/64.0-1.0)*5.0); +}; + +REALTYPE FilterParams::getq() +{ + return(exp(pow((REALTYPE) Pq/127.0,2)*log(1000.0))-0.9); +}; +REALTYPE FilterParams::getfreqtracking(REALTYPE notefreq) +{ + return(log(notefreq/440.0)*(Pfreqtrack-64.0)/(64.0*LOG_2)); +}; + +REALTYPE FilterParams::getgain() +{ + return((Pgain/64.0-1.0)*30.0);//-30..30dB +}; + +/* + * Get the center frequency of the formant's graph + */ +REALTYPE FilterParams::getcenterfreq() +{ + return(10000.0*pow(10,-(1.0-Pcenterfreq/127.0)*2.0)); +}; + +/* + * Get the number of octave that the formant functions applies to + */ +REALTYPE FilterParams::getoctavesfreq() +{ + return(0.25+10.0*Poctavesfreq/127.0); +}; + +/* + * Get the frequency from x, where x is [0..1] + */ +REALTYPE FilterParams::getfreqx(REALTYPE x) +{ + if (x>1.0) x=1.0; + REALTYPE octf=pow(2.0,getoctavesfreq()); + return(getcenterfreq()/sqrt(octf)*pow(octf,x)); +}; + +/* + * Get the x coordinate from frequency (used by the UI) + */ +REALTYPE FilterParams::getfreqpos(REALTYPE freq) +{ + return((log(freq)-log(getfreqx(0.0)))/log(2.0)/getoctavesfreq()); +}; + + +/* + * Get the freq. response of the formant filter + */ +void FilterParams::formantfilterH(int nvowel,int nfreqs,REALTYPE *freqs) +{ + REALTYPE c[3],d[3]; + REALTYPE filter_freq,filter_q,filter_amp; + REALTYPE omega,sn,cs,alpha; + + for (int i=0;i0) filter_q=(filter_q>1.0 ? pow(filter_q,1.0/(Pstages+1)) : filter_q); + + filter_amp=getformantamp(Pvowels[nvowel].formants[nformant].amp); + + + if (filter_freq<=(SAMPLE_RATE/2-100.0)) { + omega=2*PI*filter_freq/SAMPLE_RATE; + sn=sin(omega); + cs=cos(omega); + alpha=sn/(2*filter_q); + REALTYPE tmp=1+alpha; + c[0]=alpha/tmp*sqrt(filter_q+1); + c[1]=0; + c[2]=-alpha/tmp*sqrt(filter_q+1); + d[1]=-2*cs/tmp*(-1); + d[2]=(1-alpha)/tmp*(-1); + } else continue; + + + for (int i=0;iSAMPLE_RATE/2) { + for (int tmp=i;tmp0.000000001) freqs[i]=rap2dB(freqs[i])+getgain(); + else freqs[i]=-90.0; + }; + +}; + +/* + * Transforms a parameter to the real value + */ +REALTYPE FilterParams::getformantfreq(unsigned char freq) +{ + REALTYPE result=getfreqx(freq/127.0); + return(result); +}; + +REALTYPE FilterParams::getformantamp(unsigned char amp) +{ + REALTYPE result=pow(0.1,(1.0-amp/127.0)*4.0); + return(result); +}; + +REALTYPE FilterParams::getformantq(unsigned char q) +{ + //temp + REALTYPE result=pow(25.0,(q-32.0)/64.0); + return(result); +}; + + + +void FilterParams::add2XMLsection(XMLwrapper *xml,int n) +{ + int nvowel=n; + for (int nformant=0;nformantbeginbranch("FORMANT",nformant); + xml->addpar("freq",Pvowels[nvowel].formants[nformant].freq); + xml->addpar("amp",Pvowels[nvowel].formants[nformant].amp); + xml->addpar("q",Pvowels[nvowel].formants[nformant].q); + xml->endbranch(); + }; +}; + +void FilterParams::add2XML(XMLwrapper *xml) +{ + //filter parameters + xml->addpar("category",Pcategory); + xml->addpar("type",Ptype); + xml->addpar("freq",Pfreq); + xml->addpar("q",Pq); + xml->addpar("stages",Pstages); + xml->addpar("freq_track",Pfreqtrack); + xml->addpar("gain",Pgain); + + //formant filter parameters + if ((Pcategory==1)||(!xml->minimal)) { + xml->beginbranch("FORMANT_FILTER"); + xml->addpar("num_formants",Pnumformants); + xml->addpar("formant_slowness",Pformantslowness); + xml->addpar("vowel_clearness",Pvowelclearness); + xml->addpar("center_freq",Pcenterfreq); + xml->addpar("octaves_freq",Poctavesfreq); + for (int nvowel=0;nvowelbeginbranch("VOWEL",nvowel); + add2XMLsection(xml,nvowel); + xml->endbranch(); + }; + xml->addpar("sequence_size",Psequencesize); + xml->addpar("sequence_stretch",Psequencestretch); + xml->addparbool("sequence_reversed",Psequencereversed); + for (int nseq=0;nseqbeginbranch("SEQUENCE_POS",nseq); + xml->addpar("vowel_id",Psequence[nseq].nvowel); + xml->endbranch(); + }; + xml->endbranch(); + }; +}; + + +void FilterParams::getfromXMLsection(XMLwrapper *xml,int n) +{ + int nvowel=n; + for (int nformant=0;nformantenterbranch("FORMANT",nformant)==0) continue; + Pvowels[nvowel].formants[nformant].freq=xml->getpar127("freq",Pvowels[nvowel].formants[nformant].freq); + Pvowels[nvowel].formants[nformant].amp=xml->getpar127("amp",Pvowels[nvowel].formants[nformant].amp); + Pvowels[nvowel].formants[nformant].q=xml->getpar127("q",Pvowels[nvowel].formants[nformant].q); + xml->exitbranch(); + }; +}; + +void FilterParams::getfromXML(XMLwrapper *xml) +{ + //filter parameters + Pcategory=xml->getpar127("category",Pcategory); + Ptype=xml->getpar127("type",Ptype); + Pfreq=xml->getpar127("freq",Pfreq); + Pq=xml->getpar127("q",Pq); + Pstages=xml->getpar127("stages",Pstages); + Pfreqtrack=xml->getpar127("freq_track",Pfreqtrack); + Pgain=xml->getpar127("gain",Pgain); + + //formant filter parameters + if (xml->enterbranch("FORMANT_FILTER")) { + Pnumformants=xml->getpar127("num_formants",Pnumformants); + Pformantslowness=xml->getpar127("formant_slowness",Pformantslowness); + Pvowelclearness=xml->getpar127("vowel_clearness",Pvowelclearness); + Pcenterfreq=xml->getpar127("center_freq",Pcenterfreq); + Poctavesfreq=xml->getpar127("octaves_freq",Poctavesfreq); + + for (int nvowel=0;nvowelenterbranch("VOWEL",nvowel)==0) continue; + getfromXMLsection(xml,nvowel); + xml->exitbranch(); + }; + Psequencesize=xml->getpar127("sequence_size",Psequencesize); + Psequencestretch=xml->getpar127("sequence_stretch",Psequencestretch); + Psequencereversed=xml->getparbool("sequence_reversed",Psequencereversed); + for (int nseq=0;nseqenterbranch("SEQUENCE_POS",nseq)==0) continue; + Psequence[nseq].nvowel=xml->getpar("vowel_id",Psequence[nseq].nvowel,0,FF_MAX_VOWELS-1); + xml->exitbranch(); + }; + xml->exitbranch(); + }; + +}; + diff --git a/plugins/zynaddsubfx/src/Params/FilterParams.h b/plugins/zynaddsubfx/src/Params/FilterParams.h index bf3e06804..89c8b46ad 100644 --- a/plugins/zynaddsubfx/src/Params/FilterParams.h +++ b/plugins/zynaddsubfx/src/Params/FilterParams.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + FilterParams.h - Parameters for filter Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -27,73 +27,74 @@ #include "../Misc/XMLwrapper.h" #include "Presets.h" -class FilterParams:public Presets{ - public: - FilterParams(unsigned char Ptype_,unsigned char Pfreq,unsigned char Pq_); - ~FilterParams(); +class FilterParams:public Presets +{ +public: + FilterParams(unsigned char Ptype_,unsigned char Pfreq,unsigned char Pq_); + ~FilterParams(); - void add2XML(XMLwrapper *xml); - void add2XMLsection(XMLwrapper *xml,int n); - void defaults(); - void getfromXML(XMLwrapper *xml); - void getfromXMLsection(XMLwrapper *xml,int n); + void add2XML(XMLwrapper *xml); + void add2XMLsection(XMLwrapper *xml,int n); + void defaults(); + void getfromXML(XMLwrapper *xml); + void getfromXMLsection(XMLwrapper *xml,int n); - void getfromFilterParams(FilterParams *pars); + void getfromFilterParams(FilterParams *pars); - REALTYPE getfreq(); - REALTYPE getq(); - REALTYPE getfreqtracking(REALTYPE notefreq); - REALTYPE getgain(); - - unsigned char Pcategory;//Filter category (Analog/Formant/StVar) - unsigned char Ptype;// Filter type (for analog lpf,hpf,bpf..) - unsigned char Pfreq;// Frequency (64-central frequency) - unsigned char Pq; // Q parameters (resonance or bandwidth) - unsigned char Pstages; //filter stages+1 - unsigned char Pfreqtrack;//how the filter frequency is changing according the note frequency - unsigned char Pgain;//filter's output gain - - //Formant filter parameters - unsigned char Pnumformants;//how many formants are used - unsigned char Pformantslowness;//how slow varies the formants - unsigned char Pvowelclearness;//how vowels are kept clean (how much try to avoid "mixed" vowels) - unsigned char Pcenterfreq,Poctavesfreq;//the center frequency of the res. func., and the number of octaves + REALTYPE getfreq(); + REALTYPE getq(); + REALTYPE getfreqtracking(REALTYPE notefreq); + REALTYPE getgain(); - struct { - struct { - unsigned char freq,amp,q;//frequency,amplitude,Q - }formants[FF_MAX_FORMANTS]; - }Pvowels[FF_MAX_VOWELS]; - - - unsigned char Psequencesize;//how many vowels are in the sequence - unsigned char Psequencestretch;//how the sequence is stretched (how the input from filter envelopes/LFOs/etc. is "stretched") - unsigned char Psequencereversed;//if the input from filter envelopes/LFOs/etc. is reversed(negated) - struct { - unsigned char nvowel;//the vowel from the position - } Psequence[FF_MAX_SEQUENCE]; + unsigned char Pcategory;//Filter category (Analog/Formant/StVar) + unsigned char Ptype;// Filter type (for analog lpf,hpf,bpf..) + unsigned char Pfreq;// Frequency (64-central frequency) + unsigned char Pq; // Q parameters (resonance or bandwidth) + unsigned char Pstages; //filter stages+1 + unsigned char Pfreqtrack;//how the filter frequency is changing according the note frequency + unsigned char Pgain;//filter's output gain - REALTYPE getcenterfreq(); - REALTYPE getoctavesfreq(); - REALTYPE getfreqpos(REALTYPE freq); - REALTYPE getfreqx(REALTYPE x); - - void formantfilterH(int nvowel,int nfreqs,REALTYPE *freqs);//used by UI - - REALTYPE getformantfreq(unsigned char freq); - REALTYPE getformantamp(unsigned char amp); - REALTYPE getformantq(unsigned char q); + //Formant filter parameters + unsigned char Pnumformants;//how many formants are used + unsigned char Pformantslowness;//how slow varies the formants + unsigned char Pvowelclearness;//how vowels are kept clean (how much try to avoid "mixed" vowels) + unsigned char Pcenterfreq,Poctavesfreq;//the center frequency of the res. func., and the number of octaves - bool changed; - - private: - void defaults(int n); - - //stored default parameters - unsigned char Dtype; - unsigned char Dfreq; - unsigned char Dq; + struct { + struct { + unsigned char freq,amp,q;//frequency,amplitude,Q + }formants[FF_MAX_FORMANTS]; + }Pvowels[FF_MAX_VOWELS]; + + + unsigned char Psequencesize;//how many vowels are in the sequence + unsigned char Psequencestretch;//how the sequence is stretched (how the input from filter envelopes/LFOs/etc. is "stretched") + unsigned char Psequencereversed;//if the input from filter envelopes/LFOs/etc. is reversed(negated) + struct { + unsigned char nvowel;//the vowel from the position + } Psequence[FF_MAX_SEQUENCE]; + + REALTYPE getcenterfreq(); + REALTYPE getoctavesfreq(); + REALTYPE getfreqpos(REALTYPE freq); + REALTYPE getfreqx(REALTYPE x); + + void formantfilterH(int nvowel,int nfreqs,REALTYPE *freqs);//used by UI + + REALTYPE getformantfreq(unsigned char freq); + REALTYPE getformantamp(unsigned char amp); + REALTYPE getformantq(unsigned char q); + + bool changed; + +private: + void defaults(int n); + + //stored default parameters + unsigned char Dtype; + unsigned char Dfreq; + unsigned char Dq; }; #endif diff --git a/plugins/zynaddsubfx/src/Params/LFOParams.C b/plugins/zynaddsubfx/src/Params/LFOParams.cpp similarity index 85% rename from plugins/zynaddsubfx/src/Params/LFOParams.C rename to plugins/zynaddsubfx/src/Params/LFOParams.cpp index a074c2835..a124c5937 100644 --- a/plugins/zynaddsubfx/src/Params/LFOParams.C +++ b/plugins/zynaddsubfx/src/Params/LFOParams.cpp @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + LFOParams.C - Parameters for LFO Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -27,14 +27,18 @@ int LFOParams::time; -LFOParams::LFOParams(char Pfreq_,char Pintensity_,char Pstartphase_, char PLFOtype_,char Prandomness_, char Pdelay_,char Pcontinous_,char fel_):Presets(){ - switch(fel_) { - case 0:setpresettype("Plfofrequency"); - break; - case 1:setpresettype("Plfoamplitude"); - break; - case 2:setpresettype("Plfofilter"); - break; +LFOParams::LFOParams(char Pfreq_,char Pintensity_,char Pstartphase_, char PLFOtype_,char Prandomness_, char Pdelay_,char Pcontinous_,char fel_):Presets() +{ + switch (fel_) { + case 0: + setpresettype("Plfofrequency"); + break; + case 1: + setpresettype("Plfoamplitude"); + break; + case 2: + setpresettype("Plfofilter"); + break; }; Dfreq=Pfreq_; Dintensity=Pintensity_; @@ -45,14 +49,16 @@ LFOParams::LFOParams(char Pfreq_,char Pintensity_,char Pstartphase_, char PLFOty Dcontinous=Pcontinous_; fel=fel_; time=0; - + defaults(); }; -LFOParams::~LFOParams(){ +LFOParams::~LFOParams() +{ }; -void LFOParams::defaults(){ +void LFOParams::defaults() +{ Pfreq=Dfreq/127.0; Pintensity=Dintensity; Pstartphase=Dstartphase; @@ -65,7 +71,8 @@ void LFOParams::defaults(){ }; -void LFOParams::add2XML(XMLwrapper *xml){ +void LFOParams::add2XML(XMLwrapper *xml) +{ xml->addparreal("freq",Pfreq); xml->addpar("intensity",Pintensity); xml->addpar("start_phase",Pstartphase); @@ -77,7 +84,8 @@ void LFOParams::add2XML(XMLwrapper *xml){ xml->addparbool("continous",Pcontinous); }; -void LFOParams::getfromXML(XMLwrapper *xml){ +void LFOParams::getfromXML(XMLwrapper *xml) +{ Pfreq=xml->getparreal("freq",Pfreq,0.0,1.0); Pintensity=xml->getpar127("intensity",Pintensity); Pstartphase=xml->getpar127("start_phase",Pstartphase); diff --git a/plugins/zynaddsubfx/src/Params/LFOParams.h b/plugins/zynaddsubfx/src/Params/LFOParams.h index 35d74f135..a650d27f3 100644 --- a/plugins/zynaddsubfx/src/Params/LFOParams.h +++ b/plugins/zynaddsubfx/src/Params/LFOParams.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + LFOParams.h - Parameters for LFO Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -26,39 +26,40 @@ #include "../Misc/XMLwrapper.h" #include "Presets.h" -class LFOParams:public Presets{ - public: - LFOParams(char Pfreq_,char Pintensity_,char Pstartphase_, char PLFOtype_,char Prandomness_, char Pdelay_,char Pcontinous,char fel_); - ~LFOParams(); - - void add2XML(XMLwrapper *xml); - void defaults(); - void getfromXML(XMLwrapper *xml); - - /* Parametrii MIDI */ - REALTYPE Pfreq; // frequency - unsigned char Pintensity; // intensity - unsigned char Pstartphase;// start phase (0=random) - unsigned char PLFOtype; // LFO type (sin,triangle,square,ramp,...) - unsigned char Prandomness;// randomness (0=off) - unsigned char Pfreqrand; // frequency randomness (0=off) - unsigned char Pdelay; // delay (0=off) - unsigned char Pcontinous; // 1 if LFO is continous - unsigned char Pstretch; // how the LFO is "stretched" according the note frequency (64=no stretch) +class LFOParams:public Presets +{ +public: + LFOParams(char Pfreq_,char Pintensity_,char Pstartphase_, char PLFOtype_,char Prandomness_, char Pdelay_,char Pcontinous,char fel_); + ~LFOParams(); - int fel;//what kind is the LFO (0 - frequency, 1 - amplitude, 2 - filter) - static int time;//is used by Pcontinous parameter - private: - /* Default parameters */ - unsigned char Dfreq; - unsigned char Dintensity; - unsigned char Dstartphase; - unsigned char DLFOtype; - unsigned char Drandomness; - unsigned char Ddelay; - unsigned char Dcontinous; + void add2XML(XMLwrapper *xml); + void defaults(); + /**Loads the LFO from the xml*/ + void getfromXML(XMLwrapper *xml); + + /* MIDI Parameters*/ + REALTYPE Pfreq; /** -#include "PADnoteParameters.h" -#include "../Output/WAVaudiooutput.h" -using namespace std; - -PADnoteParameters::PADnoteParameters(FFTwrapper *fft_,pthread_mutex_t *mutex_):Presets(){ - setpresettype("Ppadsyth"); - - fft=fft_; - mutex=mutex_; - - resonance=new Resonance(); - oscilgen=new OscilGen(fft_,resonance); - oscilgen->ADvsPAD=true; - - FreqEnvelope=new EnvelopeParams(0,0); - FreqEnvelope->ASRinit(64,50,64,60); - FreqLfo=new LFOParams(70,0,64,0,0,0,0,0); - - AmpEnvelope=new EnvelopeParams(64,1); - AmpEnvelope->ADSRinit_dB(0,40,127,25); - AmpLfo=new LFOParams(80,0,64,0,0,0,0,1); - - GlobalFilter=new FilterParams(2,94,40); - FilterEnvelope=new EnvelopeParams(0,1); - FilterEnvelope->ADSRinit_filter(64,40,64,70,60,64); - FilterLfo=new LFOParams(80,0,64,0,0,0,0,2); - - for (int i=0;idefaults(); - oscilgen->defaults(); - - Phrpos.type=0; - Phrpos.par1=64; - Phrpos.par2=64; - Phrpos.par3=0; - - Pquality.samplesize=3; - Pquality.basenote=4; - Pquality.oct=3; - Pquality.smpoct=2; - - PStereo=1;//stereo - /* Frequency Global Parameters */ - Pfixedfreq=0; - PfixedfreqET=0; - PDetune=8192;//zero - PCoarseDetune=0; - PDetuneType=1; - FreqEnvelope->defaults(); - FreqLfo->defaults(); - - /* Amplitude Global Parameters */ - PVolume=90; - PPanning=64;//center - PAmpVelocityScaleFunction=64; - AmpEnvelope->defaults(); - AmpLfo->defaults(); - PPunchStrength=0; - PPunchTime=60; - PPunchStretch=64; - PPunchVelocitySensing=72; - - /* Filter Global Parameters*/ - PFilterVelocityScale=64; - PFilterVelocityScaleFunction=64; - GlobalFilter->defaults(); - FilterEnvelope->defaults(); - FilterLfo->defaults(); - - deletesamples(); -}; - -void PADnoteParameters::deletesample(int n){ - if ((n<0)||(n>=PAD_MAX_SAMPLES)) return; - if (sample[n].smp!=NULL){ - delete[]sample[n].smp; - sample[n].smp=NULL; - }; - sample[n].size=0; - sample[n].basefreq=440.0; -}; - -void PADnoteParameters::deletesamples(){ - for (int i=0;i1.0) { - x=1.0; - makezero=true; - }; - }; - - //compute the full profile or one half - switch(Php.onehalf){ - case 1:x=x*0.5+0.5; - break; - case 2:x=x*0.5; - break; - }; - - REALTYPE x_before_freq_mult=x; - - //do the frequency multiplier - x*=freqmult; - - //do the modulation of the profile - x+=sin(x_before_freq_mult*3.1415926*modfreq)*modpar1; - x=fmod(x+1000.0,1.0)*2.0-1.0; - - - //this is the base function of the profile - REALTYPE f; - switch (Php.base.type){ - case 1:f=exp(-(x*x)*basepar);if (f<0.4) f=0.0; else f=1.0; - break; - case 2:f=exp(-(fabs(x))*sqrt(basepar)); - break; - default:f=exp(-(x*x)*basepar); - break; - }; - if (makezero) f=0.0; - - REALTYPE amp=1.0; - origx=origx*2.0-1.0; - - //compute the amplitude multiplier - switch(Php.amp.type){ - case 1:amp=exp(-(origx*origx)*10.0*amppar1); - break; - case 2:amp=0.5*(1.0+cos(3.1415926*origx*sqrt(amppar1*4.0+1.0))); - break; - case 3:amp=1.0/(pow(origx*(amppar1*2.0+0.8),14.0)+1.0); - break; - }; - - //apply the amplitude multiplier - REALTYPE finalsmp=f; - if (Php.amp.type!=0){ - switch(Php.amp.mode){ - case 0:finalsmp=amp*(1.0-amppar2)+finalsmp*amppar2; - break; - case 1:finalsmp*=amp*(1.0-amppar2)+amppar2; - break; - case 2:finalsmp=finalsmp/(amp+pow(amppar2,4.0)*20.0+0.0001); - break; - case 3:finalsmp=amp/(finalsmp+pow(amppar2,4.0)*20.0+0.0001); - break; - }; - }; - - smp[i/supersample]+=finalsmp/supersample; - }; - - //normalize the profile (make the max. to be equal to 1.0) - REALTYPE max=0.0; - for (int i=0;imax) max=smp[i]; - }; - if (max<0.00001) max=1.0; - for (int i=0;i=4.0) break; - }; - - REALTYPE result=1.0-2.0*i/(REALTYPE) size; - return(result); -}; - -/* - * Compute the real bandwidth in cents and returns it - * Also, sets the bandwidth parameter - */ -REALTYPE PADnoteParameters::setPbandwidth(int Pbandwidth){ - this->Pbandwidth=Pbandwidth; - REALTYPE result=pow(Pbandwidth/1000.0,1.1); - result=pow(10.0,result*4.0)*0.25; - return(result); -}; - -/* - * Get the harmonic(overtone) position - */ -REALTYPE PADnoteParameters::getNhr(int n){ - REALTYPE result=1.0; - REALTYPE par1=pow(10.0,-(1.0-Phrpos.par1/255.0)*3.0); - REALTYPE par2=Phrpos.par2/255.0; - - REALTYPE n0=n-1.0; - REALTYPE tmp=0.0; - int thresh=0; - switch(Phrpos.type){ - case 1: - thresh=(int)(par2*par2*100.0)+1; - if (nget(harmonics,basefreq,false); - - //normalize - REALTYPE max=0.0; - for (int i=0;imax) max=harmonics[i]; - if (max<0.000001) max=1; - for (int i=0;iSAMPLE_RATE*0.49999) break; - if (realfreq<20.0) break; - if (harmonics[nh-1]<1e-4) continue; - - //compute the bandwidth of each harmonic - REALTYPE bandwidthcents=setPbandwidth(Pbandwidth); - REALTYPE bw=(pow(2.0,bandwidthcents/1200.0)-1.0)*basefreq/bwadjust; - REALTYPE power=1.0; - switch (Pbwscale){ - case 0: power=1.0;break; - case 1: power=0.0;break; - case 2: power=0.25;break; - case 3: power=0.5;break; - case 4: power=0.75;break; - case 5: power=1.5;break; - case 6: power=2.0;break; - case 7: power=-0.5;break; - }; - bw=bw*pow(realfreq/basefreq,power); - int ibw=(int)((bw/(SAMPLE_RATE*0.5)*size))+1; - - REALTYPE amp=harmonics[nh-1]; - if (resonance->Penabled) amp*=resonance->getfreqresponse(realfreq); - - if (ibw>profilesize){//if the bandwidth is larger than the profilesize - REALTYPE rap=sqrt((REALTYPE)profilesize/(REALTYPE)ibw); - int cfreq=(int) (realfreq/(SAMPLE_RATE*0.5)*size)-ibw/2; - for (int i=0;i=size) break; - spectrum[spfreq]+=amp*profile[src]*rap; - }; - }else{//if the bandwidth is smaller than the profilesize - REALTYPE rap=sqrt((REALTYPE)ibw/(REALTYPE)profilesize); - REALTYPE ibasefreq=realfreq/(SAMPLE_RATE*0.5)*size; - for (int i=0;i=size-1) break; - spectrum[spfreq]+=amp*profile[i]*rap*(1.0-fspfreq); - spectrum[spfreq+1]+=amp*profile[i]*rap*fspfreq; - }; - }; - }; -}; - -/* - * Generates the long spectrum for non-Bandwidth modes (only amplitudes are generated; phases will be random) - */ -void PADnoteParameters::generatespectrum_otherModes(REALTYPE *spectrum, int size,REALTYPE basefreq,REALTYPE *profile,int profilesize,REALTYPE bwadjust){ - for (int i=0;iget(harmonics,basefreq,false); - - //normalize - REALTYPE max=0.0; - for (int i=0;imax) max=harmonics[i]; - if (max<0.000001) max=1; - for (int i=0;iSAMPLE_RATE*0.49999) break; - if (realfreq<20.0) break; -// if (harmonics[nh-1]<1e-4) continue; - - - REALTYPE amp=harmonics[nh-1]; - if (resonance->Penabled) amp*=resonance->getfreqresponse(realfreq); - int cfreq=(int) (realfreq/(SAMPLE_RATE*0.5)*size); - - spectrum[cfreq]=amp+1e-9; - }; - - if (Pmode!=1){ - int old=0; - for (int k=1;k1e-10) || (k==(size-1)) ){ - int delta=k-old; - REALTYPE val1=spectrum[old]; - REALTYPE val2=spectrum[k]; - REALTYPE idelta=1.0/delta; - for (int i=0;ifreqs2smps(fftfreqs,newsample.smp);//that's all; here is the only ifft for the whole sample; no windows are used ;-) - - - //normalize(rms) - REALTYPE rms=0.0; - for (int i=0;iinformation.PADsynth_used=true; - - xml->addparbool("stereo",PStereo); - xml->addpar("mode",Pmode); - xml->addpar("bandwidth",Pbandwidth); - xml->addpar("bandwidth_scale",Pbwscale); - - xml->beginbranch("HARMONIC_PROFILE"); - xml->addpar("base_type",Php.base.type); - xml->addpar("base_par1",Php.base.par1); - xml->addpar("frequency_multiplier",Php.freqmult); - xml->addpar("modulator_par1",Php.modulator.par1); - xml->addpar("modulator_frequency",Php.modulator.freq); - xml->addpar("width",Php.width); - xml->addpar("amplitude_multiplier_type",Php.amp.type); - xml->addpar("amplitude_multiplier_mode",Php.amp.mode); - xml->addpar("amplitude_multiplier_par1",Php.amp.par1); - xml->addpar("amplitude_multiplier_par2",Php.amp.par2); - xml->addparbool("autoscale",Php.autoscale); - xml->addpar("one_half",Php.onehalf); - xml->endbranch(); - - xml->beginbranch("OSCIL"); - oscilgen->add2XML(xml); - xml->endbranch(); - - xml->beginbranch("RESONANCE"); - resonance->add2XML(xml); - xml->endbranch(); - - xml->beginbranch("HARMONIC_POSITION"); - xml->addpar("type",Phrpos.type); - xml->addpar("parameter1",Phrpos.par1); - xml->addpar("parameter2",Phrpos.par2); - xml->addpar("parameter3",Phrpos.par3); - xml->endbranch(); - - xml->beginbranch("SAMPLE_QUALITY"); - xml->addpar("samplesize",Pquality.samplesize); - xml->addpar("basenote",Pquality.basenote); - xml->addpar("octaves",Pquality.oct); - xml->addpar("samples_per_octave",Pquality.smpoct); - xml->endbranch(); - - xml->beginbranch("AMPLITUDE_PARAMETERS"); - xml->addpar("volume",PVolume); - xml->addpar("panning",PPanning); - xml->addpar("velocity_sensing",PAmpVelocityScaleFunction); - xml->addpar("punch_strength",PPunchStrength); - xml->addpar("punch_time",PPunchTime); - xml->addpar("punch_stretch",PPunchStretch); - xml->addpar("punch_velocity_sensing",PPunchVelocitySensing); - - xml->beginbranch("AMPLITUDE_ENVELOPE"); - AmpEnvelope->add2XML(xml); - xml->endbranch(); - - xml->beginbranch("AMPLITUDE_LFO"); - AmpLfo->add2XML(xml); - xml->endbranch(); - - xml->endbranch(); - - xml->beginbranch("FREQUENCY_PARAMETERS"); - xml->addpar("fixed_freq",Pfixedfreq); - xml->addpar("fixed_freq_et",PfixedfreqET); - xml->addpar("detune",PDetune); - xml->addpar("coarse_detune",PCoarseDetune); - xml->addpar("detune_type",PDetuneType); - - xml->beginbranch("FREQUENCY_ENVELOPE"); - FreqEnvelope->add2XML(xml); - xml->endbranch(); - - xml->beginbranch("FREQUENCY_LFO"); - FreqLfo->add2XML(xml); - xml->endbranch(); - xml->endbranch(); - - xml->beginbranch("FILTER_PARAMETERS"); - xml->addpar("velocity_sensing_amplitude",PFilterVelocityScale); - xml->addpar("velocity_sensing",PFilterVelocityScaleFunction); - - xml->beginbranch("FILTER"); - GlobalFilter->add2XML(xml); - xml->endbranch(); - - xml->beginbranch("FILTER_ENVELOPE"); - FilterEnvelope->add2XML(xml); - xml->endbranch(); - - xml->beginbranch("FILTER_LFO"); - FilterLfo->add2XML(xml); - xml->endbranch(); - xml->endbranch(); -}; - -void PADnoteParameters::getfromXML(XMLwrapper *xml){ - PStereo=xml->getparbool("stereo",PStereo); - Pmode=xml->getpar127("mode",0); - Pbandwidth=xml->getpar("bandwidth",Pbandwidth,0,1000); - Pbwscale=xml->getpar127("bandwidth_scale",Pbwscale); - - if (xml->enterbranch("HARMONIC_PROFILE")){ - Php.base.type=xml->getpar127("base_type",Php.base.type); - Php.base.par1=xml->getpar127("base_par1",Php.base.par1); - Php.freqmult=xml->getpar127("frequency_multiplier",Php.freqmult); - Php.modulator.par1=xml->getpar127("modulator_par1",Php.modulator.par1); - Php.modulator.freq=xml->getpar127("modulator_frequency",Php.modulator.freq); - Php.width=xml->getpar127("width",Php.width); - Php.amp.type=xml->getpar127("amplitude_multiplier_type",Php.amp.type); - Php.amp.mode=xml->getpar127("amplitude_multiplier_mode",Php.amp.mode); - Php.amp.par1=xml->getpar127("amplitude_multiplier_par1",Php.amp.par1); - Php.amp.par2=xml->getpar127("amplitude_multiplier_par2",Php.amp.par2); - Php.autoscale=xml->getparbool("autoscale",Php.autoscale); - Php.onehalf=xml->getpar127("one_half",Php.onehalf); - xml->exitbranch(); - }; - - if (xml->enterbranch("OSCIL")){ - oscilgen->getfromXML(xml); - xml->exitbranch(); - }; - - if (xml->enterbranch("RESONANCE")){ - resonance->getfromXML(xml); - xml->exitbranch(); - }; - - if (xml->enterbranch("HARMONIC_POSITION")){ - Phrpos.type=xml->getpar127("type",Phrpos.type); - Phrpos.par1=xml->getpar("parameter1",Phrpos.par1,0,255); - Phrpos.par2=xml->getpar("parameter2",Phrpos.par2,0,255); - Phrpos.par3=xml->getpar("parameter3",Phrpos.par3,0,255); - xml->exitbranch(); - }; - - if (xml->enterbranch("SAMPLE_QUALITY")){ - Pquality.samplesize=xml->getpar127("samplesize",Pquality.samplesize); - Pquality.basenote=xml->getpar127("basenote",Pquality.basenote); - Pquality.oct=xml->getpar127("octaves",Pquality.oct); - Pquality.smpoct=xml->getpar127("samples_per_octave",Pquality.smpoct); - xml->exitbranch(); - }; - - if (xml->enterbranch("AMPLITUDE_PARAMETERS")){ - PVolume=xml->getpar127("volume",PVolume); - PPanning=xml->getpar127("panning",PPanning); - PAmpVelocityScaleFunction=xml->getpar127("velocity_sensing",PAmpVelocityScaleFunction); - PPunchStrength=xml->getpar127("punch_strength",PPunchStrength); - PPunchTime=xml->getpar127("punch_time",PPunchTime); - PPunchStretch=xml->getpar127("punch_stretch",PPunchStretch); - PPunchVelocitySensing=xml->getpar127("punch_velocity_sensing",PPunchVelocitySensing); - - xml->enterbranch("AMPLITUDE_ENVELOPE"); - AmpEnvelope->getfromXML(xml); - xml->exitbranch(); - - xml->enterbranch("AMPLITUDE_LFO"); - AmpLfo->getfromXML(xml); - xml->exitbranch(); - - xml->exitbranch(); - }; - - if (xml->enterbranch("FREQUENCY_PARAMETERS")){ - Pfixedfreq=xml->getpar127("fixed_freq",Pfixedfreq); - PfixedfreqET=xml->getpar127("fixed_freq_et",PfixedfreqET); - PDetune=xml->getpar("detune",PDetune,0,16383); - PCoarseDetune=xml->getpar("coarse_detune",PCoarseDetune,0,16383); - PDetuneType=xml->getpar127("detune_type",PDetuneType); - - xml->enterbranch("FREQUENCY_ENVELOPE"); - FreqEnvelope->getfromXML(xml); - xml->exitbranch(); - - xml->enterbranch("FREQUENCY_LFO"); - FreqLfo->getfromXML(xml); - xml->exitbranch(); - xml->exitbranch(); - }; - - if (xml->enterbranch("FILTER_PARAMETERS")){ - PFilterVelocityScale=xml->getpar127("velocity_sensing_amplitude",PFilterVelocityScale); - PFilterVelocityScaleFunction=xml->getpar127("velocity_sensing",PFilterVelocityScaleFunction); - - xml->enterbranch("FILTER"); - GlobalFilter->getfromXML(xml); - xml->exitbranch(); - - xml->enterbranch("FILTER_ENVELOPE"); - FilterEnvelope->getfromXML(xml); - xml->exitbranch(); - - xml->enterbranch("FILTER_LFO"); - FilterLfo->getfromXML(xml); - xml->exitbranch(); - xml->exitbranch(); - }; -}; - - diff --git a/plugins/zynaddsubfx/src/Params/PADnoteParameters.cpp b/plugins/zynaddsubfx/src/Params/PADnoteParameters.cpp new file mode 100644 index 000000000..3143cb805 --- /dev/null +++ b/plugins/zynaddsubfx/src/Params/PADnoteParameters.cpp @@ -0,0 +1,806 @@ +/* + ZynAddSubFX - a software synthesizer + + PADnoteParameters.C - Parameters for PADnote (PADsynth) + Copyright (C) 2002-2005 Nasca Octavian Paul + Author: Nasca Octavian Paul + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ +#include +#include "PADnoteParameters.h" +#include "../Output/WAVaudiooutput.h" +using namespace std; + +PADnoteParameters::PADnoteParameters(FFTwrapper *fft_,pthread_mutex_t *mutex_):Presets() +{ + setpresettype("Ppadsyth"); + + fft=fft_; + mutex=mutex_; + + resonance=new Resonance(); + oscilgen=new OscilGen(fft_,resonance); + oscilgen->ADvsPAD=true; + + FreqEnvelope=new EnvelopeParams(0,0); + FreqEnvelope->ASRinit(64,50,64,60); + FreqLfo=new LFOParams(70,0,64,0,0,0,0,0); + + AmpEnvelope=new EnvelopeParams(64,1); + AmpEnvelope->ADSRinit_dB(0,40,127,25); + AmpLfo=new LFOParams(80,0,64,0,0,0,0,1); + + GlobalFilter=new FilterParams(2,94,40); + FilterEnvelope=new EnvelopeParams(0,1); + FilterEnvelope->ADSRinit_filter(64,40,64,70,60,64); + FilterLfo=new LFOParams(80,0,64,0,0,0,0,2); + + for (int i=0;idefaults(); + oscilgen->defaults(); + + Phrpos.type=0; + Phrpos.par1=64; + Phrpos.par2=64; + Phrpos.par3=0; + + Pquality.samplesize=3; + Pquality.basenote=4; + Pquality.oct=3; + Pquality.smpoct=2; + + PStereo=1;//stereo + /* Frequency Global Parameters */ + Pfixedfreq=0; + PfixedfreqET=0; + PDetune=8192;//zero + PCoarseDetune=0; + PDetuneType=1; + FreqEnvelope->defaults(); + FreqLfo->defaults(); + + /* Amplitude Global Parameters */ + PVolume=90; + PPanning=64;//center + PAmpVelocityScaleFunction=64; + AmpEnvelope->defaults(); + AmpLfo->defaults(); + PPunchStrength=0; + PPunchTime=60; + PPunchStretch=64; + PPunchVelocitySensing=72; + + /* Filter Global Parameters*/ + PFilterVelocityScale=64; + PFilterVelocityScaleFunction=64; + GlobalFilter->defaults(); + FilterEnvelope->defaults(); + FilterLfo->defaults(); + + deletesamples(); +}; + +void PADnoteParameters::deletesample(int n) +{ + if ((n<0)||(n>=PAD_MAX_SAMPLES)) return; + if (sample[n].smp!=NULL) { + delete[]sample[n].smp; + sample[n].smp=NULL; + }; + sample[n].size=0; + sample[n].basefreq=440.0; +}; + +void PADnoteParameters::deletesamples() +{ + for (int i=0;i1.0) { + x=1.0; + makezero=true; + }; + }; + + //compute the full profile or one half + switch (Php.onehalf) { + case 1: + x=x*0.5+0.5; + break; + case 2: + x=x*0.5; + break; + }; + + REALTYPE x_before_freq_mult=x; + + //do the frequency multiplier + x*=freqmult; + + //do the modulation of the profile + x+=sin(x_before_freq_mult*3.1415926*modfreq)*modpar1; + x=fmod(x+1000.0,1.0)*2.0-1.0; + + + //this is the base function of the profile + REALTYPE f; + switch (Php.base.type) { + case 1: + f=exp(-(x*x)*basepar); + if (f<0.4) f=0.0; + else f=1.0; + break; + case 2: + f=exp(-(fabs(x))*sqrt(basepar)); + break; + default: + f=exp(-(x*x)*basepar); + break; + }; + if (makezero) f=0.0; + + REALTYPE amp=1.0; + origx=origx*2.0-1.0; + + //compute the amplitude multiplier + switch (Php.amp.type) { + case 1: + amp=exp(-(origx*origx)*10.0*amppar1); + break; + case 2: + amp=0.5*(1.0+cos(3.1415926*origx*sqrt(amppar1*4.0+1.0))); + break; + case 3: + amp=1.0/(pow(origx*(amppar1*2.0+0.8),14.0)+1.0); + break; + }; + + //apply the amplitude multiplier + REALTYPE finalsmp=f; + if (Php.amp.type!=0) { + switch (Php.amp.mode) { + case 0: + finalsmp=amp*(1.0-amppar2)+finalsmp*amppar2; + break; + case 1: + finalsmp*=amp*(1.0-amppar2)+amppar2; + break; + case 2: + finalsmp=finalsmp/(amp+pow(amppar2,4.0)*20.0+0.0001); + break; + case 3: + finalsmp=amp/(finalsmp+pow(amppar2,4.0)*20.0+0.0001); + break; + }; + }; + + smp[i/supersample]+=finalsmp/supersample; + }; + + //normalize the profile (make the max. to be equal to 1.0) + REALTYPE max=0.0; + for (int i=0;imax) max=smp[i]; + }; + if (max<0.00001) max=1.0; + for (int i=0;i=4.0) break; + }; + + REALTYPE result=1.0-2.0*i/(REALTYPE) size; + return(result); +}; + +/* + * Compute the real bandwidth in cents and returns it + * Also, sets the bandwidth parameter + */ +REALTYPE PADnoteParameters::setPbandwidth(int Pbandwidth) +{ + this->Pbandwidth=Pbandwidth; + REALTYPE result=pow(Pbandwidth/1000.0,1.1); + result=pow(10.0,result*4.0)*0.25; + return(result); +}; + +/* + * Get the harmonic(overtone) position + */ +REALTYPE PADnoteParameters::getNhr(int n) +{ + REALTYPE result=1.0; + REALTYPE par1=pow(10.0,-(1.0-Phrpos.par1/255.0)*3.0); + REALTYPE par2=Phrpos.par2/255.0; + + REALTYPE n0=n-1.0; + REALTYPE tmp=0.0; + int thresh=0; + switch (Phrpos.type) { + case 1: + thresh=(int)(par2*par2*100.0)+1; + if (nget(harmonics,basefreq,false); + + //normalize + REALTYPE max=0.0; + for (int i=0;imax) max=harmonics[i]; + if (max<0.000001) max=1; + for (int i=0;iSAMPLE_RATE*0.49999) break; + if (realfreq<20.0) break; + if (harmonics[nh-1]<1e-4) continue; + + //compute the bandwidth of each harmonic + REALTYPE bandwidthcents=setPbandwidth(Pbandwidth); + REALTYPE bw=(pow(2.0,bandwidthcents/1200.0)-1.0)*basefreq/bwadjust; + REALTYPE power=1.0; + switch (Pbwscale) { + case 0: + power=1.0; + break; + case 1: + power=0.0; + break; + case 2: + power=0.25; + break; + case 3: + power=0.5; + break; + case 4: + power=0.75; + break; + case 5: + power=1.5; + break; + case 6: + power=2.0; + break; + case 7: + power=-0.5; + break; + }; + bw=bw*pow(realfreq/basefreq,power); + int ibw=(int)((bw/(SAMPLE_RATE*0.5)*size))+1; + + REALTYPE amp=harmonics[nh-1]; + if (resonance->Penabled) amp*=resonance->getfreqresponse(realfreq); + + if (ibw>profilesize) {//if the bandwidth is larger than the profilesize + REALTYPE rap=sqrt((REALTYPE)profilesize/(REALTYPE)ibw); + int cfreq=(int) (realfreq/(SAMPLE_RATE*0.5)*size)-ibw/2; + for (int i=0;i=size) break; + spectrum[spfreq]+=amp*profile[src]*rap; + }; + } else {//if the bandwidth is smaller than the profilesize + REALTYPE rap=sqrt((REALTYPE)ibw/(REALTYPE)profilesize); + REALTYPE ibasefreq=realfreq/(SAMPLE_RATE*0.5)*size; + for (int i=0;i=size-1) break; + spectrum[spfreq]+=amp*profile[i]*rap*(1.0-fspfreq); + spectrum[spfreq+1]+=amp*profile[i]*rap*fspfreq; + }; + }; + }; +}; + +/* + * Generates the long spectrum for non-Bandwidth modes (only amplitudes are generated; phases will be random) + */ +void PADnoteParameters::generatespectrum_otherModes(REALTYPE *spectrum, int size,REALTYPE basefreq,REALTYPE *profile,int profilesize,REALTYPE bwadjust) +{ + for (int i=0;iget(harmonics,basefreq,false); + + //normalize + REALTYPE max=0.0; + for (int i=0;imax) max=harmonics[i]; + if (max<0.000001) max=1; + for (int i=0;iSAMPLE_RATE*0.49999) break; + if (realfreq<20.0) break; +// if (harmonics[nh-1]<1e-4) continue; + + + REALTYPE amp=harmonics[nh-1]; + if (resonance->Penabled) amp*=resonance->getfreqresponse(realfreq); + int cfreq=(int) (realfreq/(SAMPLE_RATE*0.5)*size); + + spectrum[cfreq]=amp+1e-9; + }; + + if (Pmode!=1) { + int old=0; + for (int k=1;k1e-10) || (k==(size-1)) ) { + int delta=k-old; + REALTYPE val1=spectrum[old]; + REALTYPE val2=spectrum[k]; + REALTYPE idelta=1.0/delta; + for (int i=0;ifreqs2smps(fftfreqs,newsample.smp);//that's all; here is the only ifft for the whole sample; no windows are used ;-) + + + //normalize(rms) + REALTYPE rms=0.0; + for (int i=0;iinformation.PADsynth_used=true; + + xml->addparbool("stereo",PStereo); + xml->addpar("mode",Pmode); + xml->addpar("bandwidth",Pbandwidth); + xml->addpar("bandwidth_scale",Pbwscale); + + xml->beginbranch("HARMONIC_PROFILE"); + xml->addpar("base_type",Php.base.type); + xml->addpar("base_par1",Php.base.par1); + xml->addpar("frequency_multiplier",Php.freqmult); + xml->addpar("modulator_par1",Php.modulator.par1); + xml->addpar("modulator_frequency",Php.modulator.freq); + xml->addpar("width",Php.width); + xml->addpar("amplitude_multiplier_type",Php.amp.type); + xml->addpar("amplitude_multiplier_mode",Php.amp.mode); + xml->addpar("amplitude_multiplier_par1",Php.amp.par1); + xml->addpar("amplitude_multiplier_par2",Php.amp.par2); + xml->addparbool("autoscale",Php.autoscale); + xml->addpar("one_half",Php.onehalf); + xml->endbranch(); + + xml->beginbranch("OSCIL"); + oscilgen->add2XML(xml); + xml->endbranch(); + + xml->beginbranch("RESONANCE"); + resonance->add2XML(xml); + xml->endbranch(); + + xml->beginbranch("HARMONIC_POSITION"); + xml->addpar("type",Phrpos.type); + xml->addpar("parameter1",Phrpos.par1); + xml->addpar("parameter2",Phrpos.par2); + xml->addpar("parameter3",Phrpos.par3); + xml->endbranch(); + + xml->beginbranch("SAMPLE_QUALITY"); + xml->addpar("samplesize",Pquality.samplesize); + xml->addpar("basenote",Pquality.basenote); + xml->addpar("octaves",Pquality.oct); + xml->addpar("samples_per_octave",Pquality.smpoct); + xml->endbranch(); + + xml->beginbranch("AMPLITUDE_PARAMETERS"); + xml->addpar("volume",PVolume); + xml->addpar("panning",PPanning); + xml->addpar("velocity_sensing",PAmpVelocityScaleFunction); + xml->addpar("punch_strength",PPunchStrength); + xml->addpar("punch_time",PPunchTime); + xml->addpar("punch_stretch",PPunchStretch); + xml->addpar("punch_velocity_sensing",PPunchVelocitySensing); + + xml->beginbranch("AMPLITUDE_ENVELOPE"); + AmpEnvelope->add2XML(xml); + xml->endbranch(); + + xml->beginbranch("AMPLITUDE_LFO"); + AmpLfo->add2XML(xml); + xml->endbranch(); + + xml->endbranch(); + + xml->beginbranch("FREQUENCY_PARAMETERS"); + xml->addpar("fixed_freq",Pfixedfreq); + xml->addpar("fixed_freq_et",PfixedfreqET); + xml->addpar("detune",PDetune); + xml->addpar("coarse_detune",PCoarseDetune); + xml->addpar("detune_type",PDetuneType); + + xml->beginbranch("FREQUENCY_ENVELOPE"); + FreqEnvelope->add2XML(xml); + xml->endbranch(); + + xml->beginbranch("FREQUENCY_LFO"); + FreqLfo->add2XML(xml); + xml->endbranch(); + xml->endbranch(); + + xml->beginbranch("FILTER_PARAMETERS"); + xml->addpar("velocity_sensing_amplitude",PFilterVelocityScale); + xml->addpar("velocity_sensing",PFilterVelocityScaleFunction); + + xml->beginbranch("FILTER"); + GlobalFilter->add2XML(xml); + xml->endbranch(); + + xml->beginbranch("FILTER_ENVELOPE"); + FilterEnvelope->add2XML(xml); + xml->endbranch(); + + xml->beginbranch("FILTER_LFO"); + FilterLfo->add2XML(xml); + xml->endbranch(); + xml->endbranch(); +}; + +void PADnoteParameters::getfromXML(XMLwrapper *xml) +{ + PStereo=xml->getparbool("stereo",PStereo); + Pmode=xml->getpar127("mode",0); + Pbandwidth=xml->getpar("bandwidth",Pbandwidth,0,1000); + Pbwscale=xml->getpar127("bandwidth_scale",Pbwscale); + + if (xml->enterbranch("HARMONIC_PROFILE")) { + Php.base.type=xml->getpar127("base_type",Php.base.type); + Php.base.par1=xml->getpar127("base_par1",Php.base.par1); + Php.freqmult=xml->getpar127("frequency_multiplier",Php.freqmult); + Php.modulator.par1=xml->getpar127("modulator_par1",Php.modulator.par1); + Php.modulator.freq=xml->getpar127("modulator_frequency",Php.modulator.freq); + Php.width=xml->getpar127("width",Php.width); + Php.amp.type=xml->getpar127("amplitude_multiplier_type",Php.amp.type); + Php.amp.mode=xml->getpar127("amplitude_multiplier_mode",Php.amp.mode); + Php.amp.par1=xml->getpar127("amplitude_multiplier_par1",Php.amp.par1); + Php.amp.par2=xml->getpar127("amplitude_multiplier_par2",Php.amp.par2); + Php.autoscale=xml->getparbool("autoscale",Php.autoscale); + Php.onehalf=xml->getpar127("one_half",Php.onehalf); + xml->exitbranch(); + }; + + if (xml->enterbranch("OSCIL")) { + oscilgen->getfromXML(xml); + xml->exitbranch(); + }; + + if (xml->enterbranch("RESONANCE")) { + resonance->getfromXML(xml); + xml->exitbranch(); + }; + + if (xml->enterbranch("HARMONIC_POSITION")) { + Phrpos.type=xml->getpar127("type",Phrpos.type); + Phrpos.par1=xml->getpar("parameter1",Phrpos.par1,0,255); + Phrpos.par2=xml->getpar("parameter2",Phrpos.par2,0,255); + Phrpos.par3=xml->getpar("parameter3",Phrpos.par3,0,255); + xml->exitbranch(); + }; + + if (xml->enterbranch("SAMPLE_QUALITY")) { + Pquality.samplesize=xml->getpar127("samplesize",Pquality.samplesize); + Pquality.basenote=xml->getpar127("basenote",Pquality.basenote); + Pquality.oct=xml->getpar127("octaves",Pquality.oct); + Pquality.smpoct=xml->getpar127("samples_per_octave",Pquality.smpoct); + xml->exitbranch(); + }; + + if (xml->enterbranch("AMPLITUDE_PARAMETERS")) { + PVolume=xml->getpar127("volume",PVolume); + PPanning=xml->getpar127("panning",PPanning); + PAmpVelocityScaleFunction=xml->getpar127("velocity_sensing",PAmpVelocityScaleFunction); + PPunchStrength=xml->getpar127("punch_strength",PPunchStrength); + PPunchTime=xml->getpar127("punch_time",PPunchTime); + PPunchStretch=xml->getpar127("punch_stretch",PPunchStretch); + PPunchVelocitySensing=xml->getpar127("punch_velocity_sensing",PPunchVelocitySensing); + + xml->enterbranch("AMPLITUDE_ENVELOPE"); + AmpEnvelope->getfromXML(xml); + xml->exitbranch(); + + xml->enterbranch("AMPLITUDE_LFO"); + AmpLfo->getfromXML(xml); + xml->exitbranch(); + + xml->exitbranch(); + }; + + if (xml->enterbranch("FREQUENCY_PARAMETERS")) { + Pfixedfreq=xml->getpar127("fixed_freq",Pfixedfreq); + PfixedfreqET=xml->getpar127("fixed_freq_et",PfixedfreqET); + PDetune=xml->getpar("detune",PDetune,0,16383); + PCoarseDetune=xml->getpar("coarse_detune",PCoarseDetune,0,16383); + PDetuneType=xml->getpar127("detune_type",PDetuneType); + + xml->enterbranch("FREQUENCY_ENVELOPE"); + FreqEnvelope->getfromXML(xml); + xml->exitbranch(); + + xml->enterbranch("FREQUENCY_LFO"); + FreqLfo->getfromXML(xml); + xml->exitbranch(); + xml->exitbranch(); + }; + + if (xml->enterbranch("FILTER_PARAMETERS")) { + PFilterVelocityScale=xml->getpar127("velocity_sensing_amplitude",PFilterVelocityScale); + PFilterVelocityScaleFunction=xml->getpar127("velocity_sensing",PFilterVelocityScaleFunction); + + xml->enterbranch("FILTER"); + GlobalFilter->getfromXML(xml); + xml->exitbranch(); + + xml->enterbranch("FILTER_ENVELOPE"); + FilterEnvelope->getfromXML(xml); + xml->exitbranch(); + + xml->enterbranch("FILTER_LFO"); + FilterLfo->getfromXML(xml); + xml->exitbranch(); + xml->exitbranch(); + }; +}; + + diff --git a/plugins/zynaddsubfx/src/Params/PADnoteParameters.h b/plugins/zynaddsubfx/src/Params/PADnoteParameters.h index 4bfa4c4eb..eacd676c8 100644 --- a/plugins/zynaddsubfx/src/Params/PADnoteParameters.h +++ b/plugins/zynaddsubfx/src/Params/PADnoteParameters.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - - PADnoteParameters.h - Parameters for PADnote (PADsynth) + + PADnoteParameters.h - Parameters for PADnote (PADsynth) Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -36,132 +36,133 @@ #include "Presets.h" #include -class PADnoteParameters:public Presets{ - public: - PADnoteParameters(FFTwrapper *fft_,pthread_mutex_t *mutex_); - ~PADnoteParameters(); - - void defaults(); - void add2XML(XMLwrapper *xml); - void getfromXML(XMLwrapper *xml); - - //returns a value between 0.0-1.0 that represents the estimation perceived bandwidth - REALTYPE getprofile(REALTYPE *smp,int size); - - //parameters - - //the mode: 0 - bandwidth, 1 - discrete (bandwidth=0), 2 - continous - //the harmonic profile is used only on mode 0 - unsigned char Pmode; - - //Harmonic profile (the frequency distribution of a single harmonic) - struct { - struct{//base function - unsigned char type; - unsigned char par1; - }base; - unsigned char freqmult;//frequency multiplier of the distribution - struct{//the modulator of the distribution - unsigned char par1; - unsigned char freq; - }modulator; - - unsigned char width;//the width of the resulting function after the modulation - struct{//the amplitude multiplier of the harmonic profile - unsigned char mode; - unsigned char type; - unsigned char par1; - unsigned char par2; - }amp; - bool autoscale;//if the scale of the harmonic profile is computed automaticaly - unsigned char onehalf;//what part of the base function is used to make the distribution - }Php; +class PADnoteParameters:public Presets +{ +public: + PADnoteParameters(FFTwrapper *fft_,pthread_mutex_t *mutex_); + ~PADnoteParameters(); - - unsigned int Pbandwidth;//the values are from 0 to 1000 - unsigned char Pbwscale;//how the bandwidth is increased according to the harmonic's frequency - - struct{//where are positioned the harmonics (on integer multimplier or different places) - unsigned char type; - unsigned char par1,par2,par3;//0..255 - }Phrpos; + void defaults(); + void add2XML(XMLwrapper *xml); + void getfromXML(XMLwrapper *xml); - struct {//quality of the samples (how many samples, the length of them,etc.) - unsigned char samplesize; - unsigned char basenote,oct,smpoct; - } Pquality; - - //frequency parameters - //If the base frequency is fixed to 440 Hz - unsigned char Pfixedfreq; + //returns a value between 0.0-1.0 that represents the estimation perceived bandwidth + REALTYPE getprofile(REALTYPE *smp,int size); - /* Equal temperate (this is used only if the Pfixedfreq is enabled) - If this parameter is 0, the frequency is fixed (to 440 Hz); - if this parameter is 64, 1 MIDI halftone -> 1 frequency halftone */ - unsigned char PfixedfreqET; - unsigned short int PDetune;//fine detune - unsigned short int PCoarseDetune;//coarse detune+octave - unsigned char PDetuneType;//detune type + //parameters - EnvelopeParams *FreqEnvelope; //Frequency Envelope - LFOParams *FreqLfo;//Frequency LFO + //the mode: 0 - bandwidth, 1 - discrete (bandwidth=0), 2 - continous + //the harmonic profile is used only on mode 0 + unsigned char Pmode; - //Amplitude parameters - unsigned char PStereo; - /* Panning - 0 - random - 1 - left - 64 - center - 127 - right */ - unsigned char PPanning; + //Harmonic profile (the frequency distribution of a single harmonic) + struct { + struct {//base function + unsigned char type; + unsigned char par1; + }base; + unsigned char freqmult;//frequency multiplier of the distribution + struct {//the modulator of the distribution + unsigned char par1; + unsigned char freq; + }modulator; - unsigned char PVolume; - - unsigned char PAmpVelocityScaleFunction; - - EnvelopeParams *AmpEnvelope; - - LFOParams *AmpLfo; - - unsigned char PPunchStrength,PPunchTime,PPunchStretch,PPunchVelocitySensing; - - //Filter Parameters - FilterParams *GlobalFilter; - - // filter velocity sensing - unsigned char PFilterVelocityScale; - - // filter velocity sensing - unsigned char PFilterVelocityScaleFunction; - - EnvelopeParams *FilterEnvelope; - LFOParams *FilterLfo; - + unsigned char width;//the width of the resulting function after the modulation + struct {//the amplitude multiplier of the harmonic profile + unsigned char mode; + unsigned char type; + unsigned char par1; + unsigned char par2; + }amp; + bool autoscale;//if the scale of the harmonic profile is computed automaticaly + unsigned char onehalf;//what part of the base function is used to make the distribution + }Php; - - REALTYPE setPbandwidth(int Pbandwidth);//returns the BandWidth in cents - REALTYPE getNhr(int n);//gets the n-th overtone position relatively to N harmonic + unsigned int Pbandwidth;//the values are from 0 to 1000 + unsigned char Pbwscale;//how the bandwidth is increased according to the harmonic's frequency - void applyparameters(bool lockmutex); - void export2wav(std::string basefilename); + struct {//where are positioned the harmonics (on integer multimplier or different places) + unsigned char type; + unsigned char par1,par2,par3;//0..255 + }Phrpos; - OscilGen *oscilgen; - Resonance *resonance; - - struct{ - int size; - REALTYPE basefreq; - REALTYPE *smp; - }sample[PAD_MAX_SAMPLES],newsample; - - private: - void generatespectrum_bandwidthMode(REALTYPE *spectrum, int size,REALTYPE basefreq,REALTYPE *profile,int profilesize,REALTYPE bwadjust); - void generatespectrum_otherModes(REALTYPE *spectrum, int size,REALTYPE basefreq,REALTYPE *profile,int profilesize,REALTYPE bwadjust); - void deletesamples(); - void deletesample(int n); - - FFTwrapper *fft; - pthread_mutex_t *mutex; + struct {//quality of the samples (how many samples, the length of them,etc.) + unsigned char samplesize; + unsigned char basenote,oct,smpoct; + } Pquality; + + //frequency parameters + //If the base frequency is fixed to 440 Hz + unsigned char Pfixedfreq; + + /* Equal temperate (this is used only if the Pfixedfreq is enabled) + If this parameter is 0, the frequency is fixed (to 440 Hz); + if this parameter is 64, 1 MIDI halftone -> 1 frequency halftone */ + unsigned char PfixedfreqET; + unsigned short int PDetune;//fine detune + unsigned short int PCoarseDetune;//coarse detune+octave + unsigned char PDetuneType;//detune type + + EnvelopeParams *FreqEnvelope; //Frequency Envelope + LFOParams *FreqLfo;//Frequency LFO + + //Amplitude parameters + unsigned char PStereo; + /* Panning - 0 - random + 1 - left + 64 - center + 127 - right */ + unsigned char PPanning; + + unsigned char PVolume; + + unsigned char PAmpVelocityScaleFunction; + + EnvelopeParams *AmpEnvelope; + + LFOParams *AmpLfo; + + unsigned char PPunchStrength,PPunchTime,PPunchStretch,PPunchVelocitySensing; + + //Filter Parameters + FilterParams *GlobalFilter; + + // filter velocity sensing + unsigned char PFilterVelocityScale; + + // filter velocity sensing + unsigned char PFilterVelocityScaleFunction; + + EnvelopeParams *FilterEnvelope; + LFOParams *FilterLfo; + + + + + REALTYPE setPbandwidth(int Pbandwidth);//returns the BandWidth in cents + REALTYPE getNhr(int n);//gets the n-th overtone position relatively to N harmonic + + void applyparameters(bool lockmutex); + void export2wav(std::string basefilename); + + OscilGen *oscilgen; + Resonance *resonance; + + struct { + int size; + REALTYPE basefreq; + REALTYPE *smp; + }sample[PAD_MAX_SAMPLES],newsample; + +private: + void generatespectrum_bandwidthMode(REALTYPE *spectrum, int size,REALTYPE basefreq,REALTYPE *profile,int profilesize,REALTYPE bwadjust); + void generatespectrum_otherModes(REALTYPE *spectrum, int size,REALTYPE basefreq,REALTYPE *profile,int profilesize,REALTYPE bwadjust); + void deletesamples(); + void deletesample(int n); + + FFTwrapper *fft; + pthread_mutex_t *mutex; }; diff --git a/plugins/zynaddsubfx/src/Params/Presets.C b/plugins/zynaddsubfx/src/Params/Presets.cpp similarity index 62% rename from plugins/zynaddsubfx/src/Params/Presets.C rename to plugins/zynaddsubfx/src/Params/Presets.cpp index 8f45a93bf..40c78c24d 100644 --- a/plugins/zynaddsubfx/src/Params/Presets.C +++ b/plugins/zynaddsubfx/src/Params/Presets.cpp @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Presets.C - Presets and Clipboard management Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -24,89 +24,95 @@ #include -Presets::Presets(){ +Presets::Presets() +{ type[0]=0; nelement=-1; }; -Presets::~Presets(){ +Presets::~Presets() +{ }; -void Presets::setpresettype(const char *type){ +void Presets::setpresettype(const char *type) +{ strcpy(this->type,type); }; -void Presets::copy(const char *name){ +void Presets::copy(const char *name) +{ XMLwrapper *xml=new XMLwrapper(); - + //used only for the clipboard if (name==NULL) xml->minimal=false; - + char type[MAX_PRESETTYPE_SIZE]; strcpy(type,this->type); if (nelement!=-1) strcat(type,"n"); if (name==NULL) { - if (strstr(type,"Plfo")!=NULL) strcpy(type,"Plfo"); + if (strstr(type,"Plfo")!=NULL) strcpy(type,"Plfo"); }; xml->beginbranch(type); if (nelement==-1) add2XML(xml); - else add2XMLsection(xml,nelement); + else add2XMLsection(xml,nelement); xml->endbranch(); if (name==NULL) presetsstore.copyclipboard(xml,type); - else presetsstore.copypreset(xml,type,name); - + else presetsstore.copypreset(xml,type,name); + delete(xml); nelement=-1; }; -void Presets::paste(int npreset){ +void Presets::paste(int npreset) +{ char type[MAX_PRESETTYPE_SIZE]; strcpy(type,this->type); if (nelement!=-1) strcat(type,"n"); - if (npreset==0){ - if (strstr(type,"Plfo")!=NULL) strcpy(type,"Plfo"); + if (npreset==0) { + if (strstr(type,"Plfo")!=NULL) strcpy(type,"Plfo"); }; XMLwrapper *xml=new XMLwrapper(); - if (npreset==0){ - if (!checkclipboardtype()) { - nelement=-1; - delete(xml); - return; - }; - if (!presetsstore.pasteclipboard(xml)) { - delete(xml); - nelement=-1; - return; - }; + if (npreset==0) { + if (!checkclipboardtype()) { + nelement=-1; + delete(xml); + return; + }; + if (!presetsstore.pasteclipboard(xml)) { + delete(xml); + nelement=-1; + return; + }; } else { - if (!presetsstore.pastepreset(xml,npreset)) { - delete(xml); - nelement=-1; - return; - }; + if (!presetsstore.pastepreset(xml,npreset)) { + delete(xml); + nelement=-1; + return; + }; }; - + if (xml->enterbranch(type)==0) { - nelement=-1; - return; + nelement=-1; + return; + }; + if (nelement==-1) { + defaults(); + getfromXML(xml); + } else { + defaults(nelement); + getfromXMLsection(xml,nelement); }; - if (nelement==-1) { - defaults(); - getfromXML(xml); - } else { - defaults(nelement); - getfromXMLsection(xml,nelement); - }; xml->exitbranch(); - + delete(xml); nelement=-1; }; -bool Presets::checkclipboardtype(){ +bool Presets::checkclipboardtype() +{ char type[MAX_PRESETTYPE_SIZE]; strcpy(type,this->type); if (nelement!=-1) strcat(type,"n"); @@ -114,16 +120,19 @@ bool Presets::checkclipboardtype(){ return(presetsstore.checkclipboardtype(type)); }; -void Presets::setelement(int n){ +void Presets::setelement(int n) +{ nelement=n; }; -void Presets::rescanforpresets(){ +void Presets::rescanforpresets() +{ presetsstore.rescanforpresets(type); }; -void Presets::deletepreset(int npreset){ +void Presets::deletepreset(int npreset) +{ presetsstore.deletepreset(npreset); }; diff --git a/plugins/zynaddsubfx/src/Params/Presets.h b/plugins/zynaddsubfx/src/Params/Presets.h index 41211ccc2..4f4bf78a4 100644 --- a/plugins/zynaddsubfx/src/Params/Presets.h +++ b/plugins/zynaddsubfx/src/Params/Presets.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Presets.h - Presets and Clipboard management Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -27,31 +27,33 @@ #include "PresetsStore.h" -class Presets{ - public: - Presets(); - virtual ~Presets(); - - void copy(const char *name);//if name==NULL, the clipboard is used - void paste(int npreset);//npreset==0 for clipboard - bool checkclipboardtype(); - void deletepreset(int npreset); +/**Presets and Clipboard management*/ +class Presets +{ +public: + Presets(); + virtual ~Presets(); - char type[MAX_PRESETTYPE_SIZE]; - void setelement(int n); - - void rescanforpresets(); - - protected: - void setpresettype(const char *type); - private: - virtual void add2XML(XMLwrapper *xml)=0; - virtual void getfromXML(XMLwrapper *xml)=0; - virtual void defaults()=0; - virtual void add2XMLsection(XMLwrapper *xml,int n){}; - virtual void getfromXMLsection(XMLwrapper *xml,int n){}; - virtual void defaults(int n){}; - int nelement; + void copy(const char *name);/**getXMLdata(); }; -bool PresetsStore::pasteclipboard(XMLwrapper *xml){ +bool PresetsStore::pasteclipboard(XMLwrapper *xml) +{ if (clipboard.data!=NULL) xml->putXMLdata(clipboard.data); - else return(false); - return(true); + else return(false); + return(true); }; -bool PresetsStore::checkclipboardtype(char *type){ +bool PresetsStore::checkclipboardtype(char *type) +{ //makes LFO's compatible if ((strstr(type,"Plfo")!=NULL)&&(strstr(clipboard.type,"Plfo")!=NULL)) return(true); return(strcmp(type,clipboard.type)==0); }; //Presets management -void PresetsStore::clearpresets(){ - for (int i=0;iname)==NULL)||((p2->name)==NULL)) return(0); - + return(strcasecmp(p1->name,p2->name)<0); }; -void PresetsStore::rescanforpresets(char *type){ +void PresetsStore::rescanforpresets(char *type) +{ clearpresets(); int presetk=0; char ftype[MAX_STRING_SIZE]; snprintf(ftype,MAX_STRING_SIZE,".%s.xpz",type); - - for (int i=0;id_name; - if (strstr(filename,ftype)==NULL) continue; - - - presets[presetk].file=new char [MAX_STRING_SIZE]; - presets[presetk].name=new char [MAX_STRING_SIZE]; - char tmpc=dirname[strlen(dirname)-1]; - const char *tmps; - if ((tmpc=='/')||(tmpc=='\\')) tmps=""; - else tmps="/"; - snprintf(presets[presetk].file,MAX_STRING_SIZE,"%s%s%s",dirname,tmps,filename); - snprintf(presets[presetk].name,MAX_STRING_SIZE,"%s",filename); - char *tmp=strstr(presets[presetk].name,ftype); - if (tmp!=NULL) tmp[0]='\0'; - presetk++; if (presetk>=MAX_PRESETS) return; - }; + for (int i=0;id_name; + if (strstr(filename,ftype)==NULL) continue; - closedir(dir); + + presets[presetk].file=new char [MAX_STRING_SIZE]; + presets[presetk].name=new char [MAX_STRING_SIZE]; + char tmpc=dirname[strlen(dirname)-1]; + const char *tmps; + if ((tmpc=='/')||(tmpc=='\\')) tmps=""; + else tmps="/"; + snprintf(presets[presetk].file,MAX_STRING_SIZE,"%s%s%s",dirname,tmps,filename); + snprintf(presets[presetk].name,MAX_STRING_SIZE,"%s",filename); + + char *tmp=strstr(presets[presetk].name,ftype); + if (tmp!=NULL) tmp[0]='\0'; + presetk++; + if (presetk>=MAX_PRESETS) return; + }; + + closedir(dir); }; //sort the presets - for (int j=0;j='0')&&(c<='9')) continue; - if ((c>='A')&&(c<='Z')) continue; - if ((c>='a')&&(c<='z')) continue; - if ((c=='-')||(c==' ')) continue; - tmpfilename[i]='_'; + char c=tmpfilename[i]; + if ((c>='0')&&(c<='9')) continue; + if ((c>='A')&&(c<='Z')) continue; + if ((c>='a')&&(c<='z')) continue; + if ((c=='-')||(c==' ')) continue; + tmpfilename[i]='_'; }; - + const char *dirname=config.cfg.presetsDirList[0]; char tmpc=dirname[strlen(dirname)-1]; const char *tmps; @@ -160,11 +170,12 @@ void PresetsStore::copypreset(XMLwrapper *xml,char *type, const char *name){ else tmps="/"; snprintf(filename,MAX_STRING_SIZE,"%s%s%s.%s.xpz",dirname,tmps,name,type); - + xml->saveXMLfile(filename); }; -bool PresetsStore::pastepreset(XMLwrapper *xml, int npreset){ +bool PresetsStore::pastepreset(XMLwrapper *xml, int npreset) +{ npreset--; if (npreset>=MAX_PRESETS) return(false); char *filename=presets[npreset].file; @@ -173,7 +184,8 @@ bool PresetsStore::pastepreset(XMLwrapper *xml, int npreset){ return(result); }; -void PresetsStore::deletepreset(int npreset){ +void PresetsStore::deletepreset(int npreset) +{ npreset--; if (npreset>=MAX_PRESETS) return; char *filename=presets[npreset].file; diff --git a/plugins/zynaddsubfx/src/Params/PresetsStore.h b/plugins/zynaddsubfx/src/Params/PresetsStore.h index bbbecccc3..8ff602beb 100644 --- a/plugins/zynaddsubfx/src/Params/PresetsStore.h +++ b/plugins/zynaddsubfx/src/Params/PresetsStore.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + PresetsStore.C - Presets and Clipboard store Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -26,37 +26,38 @@ #define MAX_PRESETTYPE_SIZE 30 #define MAX_PRESETS 1000 -class PresetsStore{ - public: - PresetsStore(); - ~PresetsStore(); +class PresetsStore +{ +public: + PresetsStore(); + ~PresetsStore(); - //Clipboard stuff - void copyclipboard(XMLwrapper *xml,char *type); - bool pasteclipboard(XMLwrapper *xml); - bool checkclipboardtype(char *type); + //Clipboard stuff + void copyclipboard(XMLwrapper *xml,char *type); + bool pasteclipboard(XMLwrapper *xml); + bool checkclipboardtype(char *type); - //presets stuff - void copypreset(XMLwrapper *xml,char *type, const char *name); - bool pastepreset(XMLwrapper *xml, int npreset); - void deletepreset(int npreset); - - struct presetstruct{ - char *file; - char *name; - }; - presetstruct presets[MAX_PRESETS]; + //presets stuff + void copypreset(XMLwrapper *xml,char *type, const char *name); + bool pastepreset(XMLwrapper *xml, int npreset); + void deletepreset(int npreset); + + struct presetstruct { + char *file; + char *name; + }; + presetstruct presets[MAX_PRESETS]; + + void rescanforpresets(char *type); + +private: + struct { + char *data; + char type[MAX_PRESETTYPE_SIZE]; + } clipboard; + + void clearpresets(); - void rescanforpresets(char *type); - - private: - struct { - char *data; - char type[MAX_PRESETTYPE_SIZE]; - } clipboard; - - void clearpresets(); - }; extern PresetsStore presetsstore; diff --git a/plugins/zynaddsubfx/src/Params/SUBnoteParameters.C b/plugins/zynaddsubfx/src/Params/SUBnoteParameters.C deleted file mode 100644 index 2d387de46..000000000 --- a/plugins/zynaddsubfx/src/Params/SUBnoteParameters.C +++ /dev/null @@ -1,238 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - SUBnoteParameters.C - Parameters for SUBnote (SUBsynth) - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include "../globals.h" -#include "SUBnoteParameters.h" -#include - -SUBnoteParameters::SUBnoteParameters():Presets(){ - setpresettype("Psubsyth"); - AmpEnvelope=new EnvelopeParams(64,1); - AmpEnvelope->ADSRinit_dB(0,40,127,25); - FreqEnvelope=new EnvelopeParams(64,0); - FreqEnvelope->ASRinit(30,50,64,60); - BandWidthEnvelope=new EnvelopeParams(64,0); - BandWidthEnvelope->ASRinit_bw(100,70,64,60); - - GlobalFilter=new FilterParams(2,80,40); - GlobalFilterEnvelope=new EnvelopeParams(0,1); - GlobalFilterEnvelope->ADSRinit_filter(64,40,64,70,60,64); - - defaults(); -}; - - -void SUBnoteParameters::defaults(){ - PVolume=96; - PPanning=64; - PAmpVelocityScaleFunction=90; - - Pfixedfreq=0; - PfixedfreqET=0; - Pnumstages=2; - Pbandwidth=40; - Phmagtype=0; - Pbwscale=64; - Pstereo=1; - Pstart=1; - - PDetune=8192; - PCoarseDetune=0; - PDetuneType=1; - PFreqEnvelopeEnabled=0; - PBandWidthEnvelopeEnabled=0; - - for (int n=0;ndefaults(); - FreqEnvelope->defaults(); - BandWidthEnvelope->defaults(); - GlobalFilter->defaults(); - GlobalFilterEnvelope->defaults(); - -}; - - - -SUBnoteParameters::~SUBnoteParameters(){ - delete (AmpEnvelope); - delete (FreqEnvelope); - delete (BandWidthEnvelope); - delete (GlobalFilter); - delete (GlobalFilterEnvelope); -}; - - - - -void SUBnoteParameters::add2XML(XMLwrapper *xml){ - xml->addpar("num_stages",Pnumstages); - xml->addpar("harmonic_mag_type",Phmagtype); - xml->addpar("start",Pstart); - - xml->beginbranch("HARMONICS"); - for (int i=0;iminimal)) continue; - xml->beginbranch("HARMONIC",i); - xml->addpar("mag",Phmag[i]); - xml->addpar("relbw",Phrelbw[i]); - xml->endbranch(); - }; - xml->endbranch(); - - xml->beginbranch("AMPLITUDE_PARAMETERS"); - xml->addparbool("stereo",Pstereo); - xml->addpar("volume",PVolume); - xml->addpar("panning",PPanning); - xml->addpar("velocity_sensing",PAmpVelocityScaleFunction); - xml->beginbranch("AMPLITUDE_ENVELOPE"); - AmpEnvelope->add2XML(xml); - xml->endbranch(); - xml->endbranch(); - - xml->beginbranch("FREQUENCY_PARAMETERS"); - xml->addparbool("fixed_freq",Pfixedfreq); - xml->addpar("fixed_freq_et",PfixedfreqET); - - xml->addpar("detune",PDetune); - xml->addpar("coarse_detune",PCoarseDetune); - xml->addpar("detune_type",PDetuneType); - - xml->addpar("bandwidth",Pbandwidth); - xml->addpar("bandwidth_scale",Pbwscale); - - xml->addparbool("freq_envelope_enabled",PFreqEnvelopeEnabled); - if ((PFreqEnvelopeEnabled!=0)||(!xml->minimal)){ - xml->beginbranch("FREQUENCY_ENVELOPE"); - FreqEnvelope->add2XML(xml); - xml->endbranch(); - }; - - xml->addparbool("band_width_envelope_enabled",PBandWidthEnvelopeEnabled); - if ((PBandWidthEnvelopeEnabled!=0)||(!xml->minimal)){ - xml->beginbranch("BANDWIDTH_ENVELOPE"); - BandWidthEnvelope->add2XML(xml); - xml->endbranch(); - }; - xml->endbranch(); - - xml->beginbranch("FILTER_PARAMETERS"); - xml->addparbool("enabled",PGlobalFilterEnabled); - if ((PGlobalFilterEnabled!=0)||(!xml->minimal)){ - xml->beginbranch("FILTER"); - GlobalFilter->add2XML(xml); - xml->endbranch(); - - xml->addpar("filter_velocity_sensing",PGlobalFilterVelocityScaleFunction); - xml->addpar("filter_velocity_sensing_amplitude",PGlobalFilterVelocityScale); - - xml->beginbranch("FILTER_ENVELOPE"); - GlobalFilterEnvelope->add2XML(xml); - xml->endbranch(); - }; - xml->endbranch(); -}; - -void SUBnoteParameters::getfromXML(XMLwrapper *xml){ - Pnumstages=xml->getpar127("num_stages",Pnumstages); - Phmagtype=xml->getpar127("harmonic_mag_type",Phmagtype); - Pstart=xml->getpar127("start",Pstart); - - if (xml->enterbranch("HARMONICS")){ - Phmag[0]=0; - for (int i=0;ienterbranch("HARMONIC",i)==0) continue; - Phmag[i]=xml->getpar127("mag",Phmag[i]); - Phrelbw[i]=xml->getpar127("relbw",Phrelbw[i]); - xml->exitbranch(); - }; - xml->exitbranch(); - }; - - if (xml->enterbranch("AMPLITUDE_PARAMETERS")){ - Pstereo=xml->getparbool("stereo",Pstereo); - PVolume=xml->getpar127("volume",PVolume); - PPanning=xml->getpar127("panning",PPanning); - PAmpVelocityScaleFunction=xml->getpar127("velocity_sensing",PAmpVelocityScaleFunction); - if (xml->enterbranch("AMPLITUDE_ENVELOPE")){ - AmpEnvelope->getfromXML(xml); - xml->exitbranch(); - }; - xml->exitbranch(); - }; - - if (xml->enterbranch("FREQUENCY_PARAMETERS")){ - Pfixedfreq=xml->getparbool("fixed_freq",Pfixedfreq); - PfixedfreqET=xml->getpar127("fixed_freq_et",PfixedfreqET); - - PDetune=xml->getpar("detune",PDetune,0,16383); - PCoarseDetune=xml->getpar("coarse_detune",PCoarseDetune,0,16383); - PDetuneType=xml->getpar127("detune_type",PDetuneType); - - Pbandwidth=xml->getpar127("bandwidth",Pbandwidth); - Pbwscale=xml->getpar127("bandwidth_scale",Pbwscale); - - PFreqEnvelopeEnabled=xml->getparbool("freq_envelope_enabled",PFreqEnvelopeEnabled); - if (xml->enterbranch("FREQUENCY_ENVELOPE")){ - FreqEnvelope->getfromXML(xml); - xml->exitbranch(); - }; - - PBandWidthEnvelopeEnabled=xml->getparbool("band_width_envelope_enabled",PBandWidthEnvelopeEnabled); - if (xml->enterbranch("BANDWIDTH_ENVELOPE")){ - BandWidthEnvelope->getfromXML(xml); - xml->exitbranch(); - }; - - xml->exitbranch(); - }; - - if (xml->enterbranch("FILTER_PARAMETERS")){ - PGlobalFilterEnabled=xml->getparbool("enabled",PGlobalFilterEnabled); - if (xml->enterbranch("FILTER")){ - GlobalFilter->getfromXML(xml); - xml->exitbranch(); - }; - - PGlobalFilterVelocityScaleFunction=xml->getpar127("filter_velocity_sensing",PGlobalFilterVelocityScaleFunction); - PGlobalFilterVelocityScale=xml->getpar127("filter_velocity_sensing_amplitude",PGlobalFilterVelocityScale); - - if (xml->enterbranch("FILTER_ENVELOPE")){ - GlobalFilterEnvelope->getfromXML(xml); - xml->exitbranch(); - }; - - xml->exitbranch(); - }; -}; - - - - diff --git a/plugins/zynaddsubfx/src/Params/SUBnoteParameters.cpp b/plugins/zynaddsubfx/src/Params/SUBnoteParameters.cpp new file mode 100644 index 000000000..963af0911 --- /dev/null +++ b/plugins/zynaddsubfx/src/Params/SUBnoteParameters.cpp @@ -0,0 +1,243 @@ +/* + ZynAddSubFX - a software synthesizer + + SUBnoteParameters.C - Parameters for SUBnote (SUBsynth) + Copyright (C) 2002-2005 Nasca Octavian Paul + Author: Nasca Octavian Paul + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "../globals.h" +#include "SUBnoteParameters.h" +#include + +SUBnoteParameters::SUBnoteParameters():Presets() +{ + setpresettype("Psubsyth"); + AmpEnvelope=new EnvelopeParams(64,1); + AmpEnvelope->ADSRinit_dB(0,40,127,25); + FreqEnvelope=new EnvelopeParams(64,0); + FreqEnvelope->ASRinit(30,50,64,60); + BandWidthEnvelope=new EnvelopeParams(64,0); + BandWidthEnvelope->ASRinit_bw(100,70,64,60); + + GlobalFilter=new FilterParams(2,80,40); + GlobalFilterEnvelope=new EnvelopeParams(0,1); + GlobalFilterEnvelope->ADSRinit_filter(64,40,64,70,60,64); + + defaults(); +}; + + +void SUBnoteParameters::defaults() +{ + PVolume=96; + PPanning=64; + PAmpVelocityScaleFunction=90; + + Pfixedfreq=0; + PfixedfreqET=0; + Pnumstages=2; + Pbandwidth=40; + Phmagtype=0; + Pbwscale=64; + Pstereo=1; + Pstart=1; + + PDetune=8192; + PCoarseDetune=0; + PDetuneType=1; + PFreqEnvelopeEnabled=0; + PBandWidthEnvelopeEnabled=0; + + for (int n=0;ndefaults(); + FreqEnvelope->defaults(); + BandWidthEnvelope->defaults(); + GlobalFilter->defaults(); + GlobalFilterEnvelope->defaults(); + +}; + + + +SUBnoteParameters::~SUBnoteParameters() +{ + delete (AmpEnvelope); + delete (FreqEnvelope); + delete (BandWidthEnvelope); + delete (GlobalFilter); + delete (GlobalFilterEnvelope); +}; + + + + +void SUBnoteParameters::add2XML(XMLwrapper *xml) +{ + xml->addpar("num_stages",Pnumstages); + xml->addpar("harmonic_mag_type",Phmagtype); + xml->addpar("start",Pstart); + + xml->beginbranch("HARMONICS"); + for (int i=0;iminimal)) continue; + xml->beginbranch("HARMONIC",i); + xml->addpar("mag",Phmag[i]); + xml->addpar("relbw",Phrelbw[i]); + xml->endbranch(); + }; + xml->endbranch(); + + xml->beginbranch("AMPLITUDE_PARAMETERS"); + xml->addparbool("stereo",Pstereo); + xml->addpar("volume",PVolume); + xml->addpar("panning",PPanning); + xml->addpar("velocity_sensing",PAmpVelocityScaleFunction); + xml->beginbranch("AMPLITUDE_ENVELOPE"); + AmpEnvelope->add2XML(xml); + xml->endbranch(); + xml->endbranch(); + + xml->beginbranch("FREQUENCY_PARAMETERS"); + xml->addparbool("fixed_freq",Pfixedfreq); + xml->addpar("fixed_freq_et",PfixedfreqET); + + xml->addpar("detune",PDetune); + xml->addpar("coarse_detune",PCoarseDetune); + xml->addpar("detune_type",PDetuneType); + + xml->addpar("bandwidth",Pbandwidth); + xml->addpar("bandwidth_scale",Pbwscale); + + xml->addparbool("freq_envelope_enabled",PFreqEnvelopeEnabled); + if ((PFreqEnvelopeEnabled!=0)||(!xml->minimal)) { + xml->beginbranch("FREQUENCY_ENVELOPE"); + FreqEnvelope->add2XML(xml); + xml->endbranch(); + }; + + xml->addparbool("band_width_envelope_enabled",PBandWidthEnvelopeEnabled); + if ((PBandWidthEnvelopeEnabled!=0)||(!xml->minimal)) { + xml->beginbranch("BANDWIDTH_ENVELOPE"); + BandWidthEnvelope->add2XML(xml); + xml->endbranch(); + }; + xml->endbranch(); + + xml->beginbranch("FILTER_PARAMETERS"); + xml->addparbool("enabled",PGlobalFilterEnabled); + if ((PGlobalFilterEnabled!=0)||(!xml->minimal)) { + xml->beginbranch("FILTER"); + GlobalFilter->add2XML(xml); + xml->endbranch(); + + xml->addpar("filter_velocity_sensing",PGlobalFilterVelocityScaleFunction); + xml->addpar("filter_velocity_sensing_amplitude",PGlobalFilterVelocityScale); + + xml->beginbranch("FILTER_ENVELOPE"); + GlobalFilterEnvelope->add2XML(xml); + xml->endbranch(); + }; + xml->endbranch(); +}; + +void SUBnoteParameters::getfromXML(XMLwrapper *xml) +{ + Pnumstages=xml->getpar127("num_stages",Pnumstages); + Phmagtype=xml->getpar127("harmonic_mag_type",Phmagtype); + Pstart=xml->getpar127("start",Pstart); + + if (xml->enterbranch("HARMONICS")) { + Phmag[0]=0; + for (int i=0;ienterbranch("HARMONIC",i)==0) continue; + Phmag[i]=xml->getpar127("mag",Phmag[i]); + Phrelbw[i]=xml->getpar127("relbw",Phrelbw[i]); + xml->exitbranch(); + }; + xml->exitbranch(); + }; + + if (xml->enterbranch("AMPLITUDE_PARAMETERS")) { + Pstereo=xml->getparbool("stereo",Pstereo); + PVolume=xml->getpar127("volume",PVolume); + PPanning=xml->getpar127("panning",PPanning); + PAmpVelocityScaleFunction=xml->getpar127("velocity_sensing",PAmpVelocityScaleFunction); + if (xml->enterbranch("AMPLITUDE_ENVELOPE")) { + AmpEnvelope->getfromXML(xml); + xml->exitbranch(); + }; + xml->exitbranch(); + }; + + if (xml->enterbranch("FREQUENCY_PARAMETERS")) { + Pfixedfreq=xml->getparbool("fixed_freq",Pfixedfreq); + PfixedfreqET=xml->getpar127("fixed_freq_et",PfixedfreqET); + + PDetune=xml->getpar("detune",PDetune,0,16383); + PCoarseDetune=xml->getpar("coarse_detune",PCoarseDetune,0,16383); + PDetuneType=xml->getpar127("detune_type",PDetuneType); + + Pbandwidth=xml->getpar127("bandwidth",Pbandwidth); + Pbwscale=xml->getpar127("bandwidth_scale",Pbwscale); + + PFreqEnvelopeEnabled=xml->getparbool("freq_envelope_enabled",PFreqEnvelopeEnabled); + if (xml->enterbranch("FREQUENCY_ENVELOPE")) { + FreqEnvelope->getfromXML(xml); + xml->exitbranch(); + }; + + PBandWidthEnvelopeEnabled=xml->getparbool("band_width_envelope_enabled",PBandWidthEnvelopeEnabled); + if (xml->enterbranch("BANDWIDTH_ENVELOPE")) { + BandWidthEnvelope->getfromXML(xml); + xml->exitbranch(); + }; + + xml->exitbranch(); + }; + + if (xml->enterbranch("FILTER_PARAMETERS")) { + PGlobalFilterEnabled=xml->getparbool("enabled",PGlobalFilterEnabled); + if (xml->enterbranch("FILTER")) { + GlobalFilter->getfromXML(xml); + xml->exitbranch(); + }; + + PGlobalFilterVelocityScaleFunction=xml->getpar127("filter_velocity_sensing",PGlobalFilterVelocityScaleFunction); + PGlobalFilterVelocityScale=xml->getpar127("filter_velocity_sensing_amplitude",PGlobalFilterVelocityScale); + + if (xml->enterbranch("FILTER_ENVELOPE")) { + GlobalFilterEnvelope->getfromXML(xml); + xml->exitbranch(); + }; + + xml->exitbranch(); + }; +}; + + + + diff --git a/plugins/zynaddsubfx/src/Params/SUBnoteParameters.h b/plugins/zynaddsubfx/src/Params/SUBnoteParameters.h index 419fc25d6..a0ebd8fde 100644 --- a/plugins/zynaddsubfx/src/Params/SUBnoteParameters.h +++ b/plugins/zynaddsubfx/src/Params/SUBnoteParameters.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - - SUBnoteParameters.h - Parameters for SUBnote (SUBsynth) + + SUBnoteParameters.h - Parameters for SUBnote (SUBsynth) Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -29,74 +29,75 @@ #include "FilterParams.h" #include "Presets.h" -class SUBnoteParameters:public Presets{ - public: - SUBnoteParameters(); - ~SUBnoteParameters(); +class SUBnoteParameters:public Presets +{ +public: + SUBnoteParameters(); + ~SUBnoteParameters(); - void add2XML(XMLwrapper *xml); - void defaults(); - void getfromXML(XMLwrapper *xml); - - //Parameters - //AMPLITUDE PARAMETRERS - unsigned char Pstereo;//0 for mono,1 for stereo - unsigned char PVolume; - unsigned char PPanning; - unsigned char PAmpVelocityScaleFunction; - EnvelopeParams *AmpEnvelope; + void add2XML(XMLwrapper *xml); + void defaults(); + void getfromXML(XMLwrapper *xml); - //Frequency Parameters - unsigned short int PDetune; - unsigned short int PCoarseDetune; - unsigned char PDetuneType; - unsigned char PFreqEnvelopeEnabled; - EnvelopeParams *FreqEnvelope; - unsigned char PBandWidthEnvelopeEnabled; - EnvelopeParams *BandWidthEnvelope; - - //Filter Parameters (Global) - unsigned char PGlobalFilterEnabled; - FilterParams *GlobalFilter; - unsigned char PGlobalFilterVelocityScale; - unsigned char PGlobalFilterVelocityScaleFunction; - EnvelopeParams *GlobalFilterEnvelope; - - - //Other Parameters - - //If the base frequency is fixed to 440 Hz - unsigned char Pfixedfreq; + //Parameters + //AMPLITUDE PARAMETRERS + unsigned char Pstereo;//0 for mono,1 for stereo + unsigned char PVolume; + unsigned char PPanning; + unsigned char PAmpVelocityScaleFunction; + EnvelopeParams *AmpEnvelope; - /* Equal temperate (this is used only if the Pfixedfreq is enabled) - If this parameter is 0, the frequency is fixed (to 440 Hz); - if this parameter is 64, 1 MIDI halftone -> 1 frequency halftone */ - unsigned char PfixedfreqET; + //Frequency Parameters + unsigned short int PDetune; + unsigned short int PCoarseDetune; + unsigned char PDetuneType; + unsigned char PFreqEnvelopeEnabled; + EnvelopeParams *FreqEnvelope; + unsigned char PBandWidthEnvelopeEnabled; + EnvelopeParams *BandWidthEnvelope; - - //how many times the filters are applied - unsigned char Pnumstages; + //Filter Parameters (Global) + unsigned char PGlobalFilterEnabled; + FilterParams *GlobalFilter; + unsigned char PGlobalFilterVelocityScale; + unsigned char PGlobalFilterVelocityScaleFunction; + EnvelopeParams *GlobalFilterEnvelope; - //bandwidth - unsigned char Pbandwidth; - //How the magnitudes are computed (0=linear,1=-60dB,2=-60dB) - unsigned char Phmagtype; - - //Magnitudes - unsigned char Phmag[MAX_SUB_HARMONICS]; - - //Relative BandWidth ("64"=1.0) - unsigned char Phrelbw[MAX_SUB_HARMONICS]; + //Other Parameters - //how much the bandwidth is increased according to lower/higher frequency; 64-default - unsigned char Pbwscale; + //If the base frequency is fixed to 440 Hz + unsigned char Pfixedfreq; - //how the harmonics start("0"=0,"1"=random,"2"=1) - unsigned char Pstart; - - - private: + /* Equal temperate (this is used only if the Pfixedfreq is enabled) + If this parameter is 0, the frequency is fixed (to 440 Hz); + if this parameter is 64, 1 MIDI halftone -> 1 frequency halftone */ + unsigned char PfixedfreqET; + + + //how many times the filters are applied + unsigned char Pnumstages; + + //bandwidth + unsigned char Pbandwidth; + + //How the magnitudes are computed (0=linear,1=-60dB,2=-60dB) + unsigned char Phmagtype; + + //Magnitudes + unsigned char Phmag[MAX_SUB_HARMONICS]; + + //Relative BandWidth ("64"=1.0) + unsigned char Phrelbw[MAX_SUB_HARMONICS]; + + //how much the bandwidth is increased according to lower/higher frequency; 64-default + unsigned char Pbwscale; + + //how the harmonics start("0"=0,"1"=random,"2"=1) + unsigned char Pstart; + + +private: }; #endif diff --git a/plugins/zynaddsubfx/src/README.txt b/plugins/zynaddsubfx/src/README.txt index daadfc9fd..44740a7dc 100644 --- a/plugins/zynaddsubfx/src/README.txt +++ b/plugins/zynaddsubfx/src/README.txt @@ -1,9 +1,9 @@ ZynAddSubFX ----------- It is a realtime software synthesizer for Linux and Windows with many features. Please see the docs for details. -Copyright (c) 2002-2006 Nasca Octavian Paul and others contribuitors +Copyright (c) 2002-2009 Nasca Octavian Paul and others contributors e-mail: zynaddsubfx AT yahoo D0T com -ZynAddSubFX is free program and is distribuited WITH NO WARRANTY. It is licensed under GNU General Public License version 2 (and only version 2) - see the file COPYING. +ZynAddSubFX is free program and is distributed WITH NO WARRANTY. It is licensed under GNU General Public License version 2 (and only version 2) - see the file COPYING. --==## PLEASE SHARE YOUR INSTRUMENTS/MASTER SETTINGS ##==-- --==## MADE WITH ZynAddSubFX ##==-- @@ -28,14 +28,14 @@ Requirements: ------------- - a fast computer - Linux (tested with RedHat 7.2,7.3,etc.) or Windows - - FFTW 2.x.x (tested with fftw 2.0.5, 2.1.3) - necesary for + - FFTW 2.x.x or 3.x.x (tested with fftw 2.0.5, 2.1.3, and 3.1.3) - necessary for Fast Fourier computations - - MXML-2.2 library from http://www.easysw.com/~mike/mxml/ - - zlib library from http://www.zlib.org - this exists in most linux distributions + - MXML-2.5 library from www.minixml.org + - zlib library from http://www.zlib.org - this exists in most Linux distributions - (for Linux) OpenSoundSystem (OSS) (if you don't have ALSA, only) - (for Windows) pthreads, portaudio -Not requred, but recomanded: +Not required, but recommended: --------------------------- - FLTK 1.x.x (tested with fltk 1.1.0, 1.1.1, 1.1.2,etc.) @@ -49,8 +49,8 @@ Compilation: If you don't know how to compile, you may download binaries from Planet CCRMA (see above, on sites). First set what should sound input/ouput should use in Makefile.inc in src/ directory. Then "make" from the "src/" directory. Hope all goes right. If the compiler complains something about FFTwrapper.h and FFTW library headers(rfftw.h or fftw.h) please read the docs from DSP/FFTwrapper.h . - To compile the Spliter, run "compile.sh" from the "Spliter" directory. - To compile the Controller, run "compile.sh" from the "Controller" directory. + To compile the Spliter, run "make" from the "Spliter" directory. + To compile the Controller, run "make" from the "Controller" directory. Running on LINUX ---------------- @@ -59,9 +59,9 @@ Running on LINUX B) JACK (JACK Audio Connection Kit) *MIDI INPUT* - There are 2 possibilites of midi inputs (depends on what you have chosen in Makefile.inc to use - OSS or ALSA). - A) ALSA (Advenced Linux Sound Architecture) - 1) Launch zynaddsubfx + There are 2 possibilities of midi inputs (depends on what you have chosen in Makefile.inc to use - OSS or ALSA). + A) ALSA (Advanced Linux Sound Architecture) + 1) Launch ZynAddSubFX 2) ZynAddSubFX will make a virtual MIDI port. You can connect other midi devices (like a real MIDI keyboard, midi sequencers which supports ALSA or virtual keyboard - like vkeybd). To connect, use "aconnect" or "alsa-patch-bay"; usualy the port of ZynAddSubFX is 128:0 or 129:0. @@ -72,24 +72,24 @@ Running on LINUX B) OSS (Open Sound System) - 1) Launch zynaddsubfx - 2) Connect the midi keyboard + 1) Launch ZynAddSubFX + 2) Connect the MIDI keyboard As you have seen the OSS option needs a real midi keyboard. If you don't have it, you can download/install ALSA from www.alsa-project.org Running on WINDOWS ------------------ - If you launch zynaddsubfx.exe and nothing happens, you need pthreadGC.dll in the same directory (or windows directory). The dll files are distribuited with zynaddsubfx windows binaries. + If you launch zynaddsubfx.exe and nothing happens, you need pthreadGC.dll in the same directory (or windows directory). The dll files are distribuited with ZynAddSubFX windows binaries. It might be possible that the latency will be very high. If this happens, you have to set the environment variable PA_MIN_LATENCY_MSEC to a value that represents the latency in miliseconds. - Eg: (in autoexec.bat or launched before running zynaddsubfx) "set PA_MIN_LATENCY_MSEC=50" - Warning: if the value is too low, you might ecounter severe dropouts on zynaddsubfx. You'll have to set to a higher value and turn off automated background tasks (like virus scanners, email clients, etc.). - If you have more cards, you can select the desired card where you can play audio with the evironment variable "PA_RECOMMENDED_OUTPUT_DEVICE" + Eg: (in autoexec.bat or launched before running ZynAddSubFX) "set PA_MIN_LATENCY_MSEC=50" + Warning: if the value is too low, you might encounter severe dropouts on ZynAddSubFX. You'll have to set to a higher value and turn off automated background tasks (like virus scanners, email clients, etc.). + If you have more cards, you can select the desired card where you can play audio with the environment variable "PA_RECOMMENDED_OUTPUT_DEVICE" Eg: "set PA_RECOMMENDED_OUTPUT_DEVICE=1" A better way to set all of this, I will put on next versions. -Please send me instruments,banks,master settings,songs(midi+...xmz files) done with ZynAddSubFX. I'll apreciate this. +Please send me instruments,banks,master settings,songs(midi+...xmz files) done with ZynAddSubFX. I'll appreciate this. Have fun! :-) - +--The ZynAddSubFX team diff --git a/plugins/zynaddsubfx/src/Samples/AuSample.cpp b/plugins/zynaddsubfx/src/Samples/AuSample.cpp new file mode 100644 index 000000000..5d95390cf --- /dev/null +++ b/plugins/zynaddsubfx/src/Samples/AuSample.cpp @@ -0,0 +1,28 @@ +/* + ZynAddSubFX - a software synthesizer + + AuSample.h - Object for storing information on audio samples (for one channel) + Copyright (C) 2009-2009 Mark McCurry + Author: Mark McCurry + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include "AuSample.h" + +AuSample::AuSample(int length,REALTYPE fill) + : Sample(length,fill) {} + +AuSample::AuSample(int length,const REALTYPE *input) + : Sample(length,input) {} + diff --git a/plugins/zynaddsubfx/src/Samples/AuSample.h b/plugins/zynaddsubfx/src/Samples/AuSample.h new file mode 100644 index 000000000..f82166482 --- /dev/null +++ b/plugins/zynaddsubfx/src/Samples/AuSample.h @@ -0,0 +1,36 @@ +/* + ZynAddSubFX - a software synthesizer + + AuSample.h - Object for storing information on audio samples (for one channel) + Copyright (C) 2009-2009 Mark McCurry + Author: Mark McCurry + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#ifndef AUSAMPLE_H +#define AUSAMPLE_H + +#include "Sample.h" +#include "FqSample.h" + +class AuSample : public Sample +{ +public: + AuSample(int length,REALTYPE fill=0); + AuSample(int length,const REALTYPE *input); + FqSample getFqSample();/**\todo implement this*/ + +}; +#endif + diff --git a/plugins/zynaddsubfx/src/Samples/CMakeLists.txt b/plugins/zynaddsubfx/src/Samples/CMakeLists.txt new file mode 100644 index 000000000..2efd9e924 --- /dev/null +++ b/plugins/zynaddsubfx/src/Samples/CMakeLists.txt @@ -0,0 +1,13 @@ +set(zynaddsubfx_samples_SRCS + AuSample.cpp + FqSample.cpp + Sample.cpp +) + +add_library(zynaddsubfx_samples STATIC + ${zynaddsubfx_samples_SRCS} + ) + +target_link_libraries(zynaddsubfx_samples + zynaddsubfx_samples + ) diff --git a/plugins/zynaddsubfx/src/Samples/FqSample.cpp b/plugins/zynaddsubfx/src/Samples/FqSample.cpp new file mode 100644 index 000000000..888dd0c45 --- /dev/null +++ b/plugins/zynaddsubfx/src/Samples/FqSample.cpp @@ -0,0 +1,33 @@ +/* + ZynAddSubFX - a software synthesizer + + FqSample.C - Object for storing information on samples + Copyright (C) 2009-2009 Mark McCurry + Author: Mark McCurry + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include "FqSample.h" + +FqSample::FqSample(int length,REALTYPE fill) + :Sample(length,fill) +{} + +FqSample::FqSample(int length,const REALTYPE *input) + : Sample(length,input) +{} + +FqSample::~FqSample() +{} + diff --git a/plugins/zynaddsubfx/src/Samples/FqSample.h b/plugins/zynaddsubfx/src/Samples/FqSample.h new file mode 100644 index 000000000..f81abe20f --- /dev/null +++ b/plugins/zynaddsubfx/src/Samples/FqSample.h @@ -0,0 +1,37 @@ +/* + ZynAddSubFX - a software synthesizer + + FqSample.h - Object for storing information on samples + Copyright (C) 2009-2009 Mark McCurry + Author: Mark McCurry + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#ifndef MONOSAMPLE_H +#define MONOSAMPLE_H + +#include "FqSample.h" +#include "Sample.h" + +class FqSample : public Sample +{ +public: + FqSample(int length,REALTYPE fill=0); + FqSample(int length,const REALTYPE *input); + ~FqSample(); + //FqSample &operator=(const FqSample &smp); + //float *dontuse(){return buffer;}; +}; +#endif + diff --git a/plugins/zynaddsubfx/src/Samples/Sample.cpp b/plugins/zynaddsubfx/src/Samples/Sample.cpp new file mode 100644 index 000000000..c11bc6d56 --- /dev/null +++ b/plugins/zynaddsubfx/src/Samples/Sample.cpp @@ -0,0 +1,119 @@ +/* + ZynAddSubFX - a software synthesizer + + Sample.C - Object for storing information on samples + Copyright (C) 2009-2009 Mark McCurry + Author: Mark McCurry + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include +#include "Sample.h" + +/**\TODO start using pointer math here as these will be Frequency called + * functions throughout the code*/ +Sample::Sample(const Sample &smp) + : bufferSize(smp.bufferSize) +{ + buffer=new REALTYPE[bufferSize]; + for (int i=0;i0) { + buffer=new REALTYPE[length]; + for (int i=0;ibufferSize!=smp.bufferSize) + return false; + for(int i=0;ibuffer[i]!=smp.buffer[i]) + return false; + return true; +} + +REALTYPE Sample::max()const +{ + REALTYPE max=-1500;//a good low considering that samples should store values -1.0 to 1.0 + for(int i=0;imax) + max=buffer[i]; + return max; +} + +REALTYPE Sample::min()const +{ + REALTYPE min=1500;//a good high considering that samples should store values -1.0 to 1.0 + for(int i=0;imax) + max=fabs(buffer[i]); + return max; +} diff --git a/plugins/zynaddsubfx/src/Samples/Sample.h b/plugins/zynaddsubfx/src/Samples/Sample.h new file mode 100644 index 000000000..c46786d8b --- /dev/null +++ b/plugins/zynaddsubfx/src/Samples/Sample.h @@ -0,0 +1,70 @@ +/* + ZynAddSubFX - a software synthesizer + + Sample.h - Object for storing information on samples + Copyright (C) 2009-2009 Mark McCurry + Author: Mark McCurry + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#ifndef SAMPLE_H +#define SAMPLE_H +#include "../globals.h" +/** + * Base Class for Samples + */ +class Sample +{ +public: + Sample(const Sample &smp); + Sample(int length,REALTYPE fill=0); + Sample(int length,const REALTYPE *fill); + ~Sample(); + /**Fills the buffer with zeros*/ + void clear(); + /**States the size of the buffer + * @return the size of the buffer*/ + int size() const { + return bufferSize; + }; + /**Provides the indexing operator for non const Samples*/ + REALTYPE &operator[](int index) { + return *(buffer+index%bufferSize); + }; + /**Provides the indexing operator for const Samples*/ + const REALTYPE &operator[](int index)const { + return *(buffer+index%bufferSize); + }; + /**Provides the assignment operator*/ + void operator=(const Sample &smp); + /**Provides the == operator*/ + bool operator==(const Sample &smp)const; + /**Provides direct access to the buffer to allow for transition + * + * This method is like c_str() from the string class and should be used + * sparingly*/ + const REALTYPE *c_buf() { + return buffer; + }; + REALTYPE max()const; + REALTYPE min()const; + REALTYPE absMax()const; +private: + int bufferSize; + float *buffer; + + +}; +#endif + diff --git a/plugins/zynaddsubfx/src/Seq/CMakeLists.txt b/plugins/zynaddsubfx/src/Seq/CMakeLists.txt new file mode 100644 index 000000000..008c821e4 --- /dev/null +++ b/plugins/zynaddsubfx/src/Seq/CMakeLists.txt @@ -0,0 +1,11 @@ +set(zynaddsubfx_seq_SRCS + MIDIEvents.cpp + MIDIFile.cpp + Sequencer.cpp +) + +add_library(zynaddsubfx_seq STATIC + ${zynaddsubfx_seq_SRCS} + ) + +target_link_libraries(zynaddsubfx_seq) diff --git a/plugins/zynaddsubfx/src/Seq/MIDIEvents.C b/plugins/zynaddsubfx/src/Seq/MIDIEvents.cpp similarity index 78% rename from plugins/zynaddsubfx/src/Seq/MIDIEvents.C rename to plugins/zynaddsubfx/src/Seq/MIDIEvents.cpp index cc44b5711..42618c1ce 100644 --- a/plugins/zynaddsubfx/src/Seq/MIDIEvents.C +++ b/plugins/zynaddsubfx/src/Seq/MIDIEvents.cpp @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + MIDIEvents.C - It stores the midi events from midi file or sequencer Copyright (C) 2003-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -24,30 +24,34 @@ #include #include -MIDIEvents::MIDIEvents(){ +MIDIEvents::MIDIEvents() +{ }; -MIDIEvents::~MIDIEvents(){ +MIDIEvents::~MIDIEvents() +{ }; /************** Track stuff ***************/ -void MIDIEvents::writeevent(list *l,event *ev){ +void MIDIEvents::writeevent(list *l,event *ev) +{ listpos *tmp=new listpos; tmp->next=NULL; tmp->ev=*ev; if (l->current!=NULL) l->current->next=tmp; - else l->first=tmp; + else l->first=tmp; l->current=tmp; // printf("Wx%x ",(int) l->current); // printf("-> %d \n",l->current->ev.deltatime); l->size++; }; -void MIDIEvents::readevent(list *l,event *ev){ +void MIDIEvents::readevent(list *l,event *ev) +{ if (l->current==NULL) { - ev->type=-1; - return; + ev->type=-1; + return; }; *ev=l->current->ev; l->current=l->current->next; @@ -63,22 +67,25 @@ void MIDIEvents::readevent(list *l,event *ev){ }; -void MIDIEvents::rewindlist(list *l){ +void MIDIEvents::rewindlist(list *l) +{ l->current=l->first; }; -void MIDIEvents::deletelist(list *l){ +void MIDIEvents::deletelist(list *l) +{ l->current=l->first; if (l->current==NULL) return; - while (l->current->next!=NULL){ - listpos *tmp=l->current; - l->current=l->current->next; - delete(tmp); + while (l->current->next!=NULL) { + listpos *tmp=l->current; + l->current=l->current->next; + delete(tmp); }; deletelistreference(l); }; -void MIDIEvents::deletelistreference(list *l){ +void MIDIEvents::deletelistreference(list *l) +{ l->current=l->first=NULL; l->size=0; l->length=0.0; diff --git a/plugins/zynaddsubfx/src/Seq/MIDIEvents.h b/plugins/zynaddsubfx/src/Seq/MIDIEvents.h index 3c4b91bda..5b3b6f1e1 100644 --- a/plugins/zynaddsubfx/src/Seq/MIDIEvents.h +++ b/plugins/zynaddsubfx/src/Seq/MIDIEvents.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + MIDIEvents.h - It stores the midi events from midi file or sequencer Copyright (C) 2003-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -25,42 +25,46 @@ #include "../globals.h" #define NUM_MIDI_TRACKS NUM_MIDI_CHANNELS -class MIDIEvents{ +/**storage the midi events from midi file or sequencer + * \todo this looks quite like a remake of a linked list + * if it is, then it should be rewritten to use */ +class MIDIEvents +{ friend class MIDIFile; - public: - MIDIEvents(); - ~MIDIEvents(); +public: + MIDIEvents(); + ~MIDIEvents(); - protected: +protected: /* Events */ - struct event{ + struct event { int deltatime; - int channel;//on what midi channel is - int type,par1,par2;//type=1 for note, type=2 for controller, type=255 for time messages + int channel;//on what midi channel is + int type,par1,par2;//type=1 for note, type=2 for controller, type=255 for time messages } tmpevent; - struct listpos{ - event ev; + struct listpos { + event ev; struct listpos *next; }; - struct list{ - listpos *first,*current; - int size;//how many events are - double length;//in seconds + struct list { + listpos *first,*current; + int size;//how many events are + double length;//in seconds }; struct { - list track;//the stored track - list record;//the track being "recorded" from midi + list track;//the stored track + list record;//the track being "recorded" from midi } miditrack[NUM_MIDI_TRACKS]; - + void writeevent(list *l,event *ev); void readevent(list *l,event *ev); - + void rewindlist(list *l); void deletelist(list *l); void deletelistreference(list *l); }; - #endif + diff --git a/plugins/zynaddsubfx/src/Seq/MIDIFile.C b/plugins/zynaddsubfx/src/Seq/MIDIFile.cpp similarity index 66% rename from plugins/zynaddsubfx/src/Seq/MIDIFile.C rename to plugins/zynaddsubfx/src/Seq/MIDIFile.cpp index c9d1f9c08..61e748d3a 100644 --- a/plugins/zynaddsubfx/src/Seq/MIDIFile.C +++ b/plugins/zynaddsubfx/src/Seq/MIDIFile.cpp @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + MIDIFile.C - MIDI file loader Copyright (C) 2003-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -25,7 +25,8 @@ #include "MIDIFile.h" -MIDIFile::MIDIFile(){ +MIDIFile::MIDIFile() +{ midifile=NULL; midifilesize=0; midifilek=0; @@ -33,31 +34,33 @@ MIDIFile::MIDIFile(){ me=NULL; }; -MIDIFile::~MIDIFile(){ +MIDIFile::~MIDIFile() +{ clearmidifile(); }; -int MIDIFile::loadfile(char *filename){ +int MIDIFile::loadfile(const char *filename) +{ clearmidifile(); - + FILE *file=fopen(filename,"r"); if (file==NULL) return(-1); - + char header[4]; ZERO(header,4); fread(header,4,1,file); //test to see if this a midi file - if ((header[0]!='M')||(header[1]!='T')||(header[2]!='h')||(header[3]!='d')){ - fclose(file); - return(-1); + if ((header[0]!='M')||(header[1]!='T')||(header[2]!='h')||(header[3]!='d')) { + fclose(file); + return(-1); }; - + //get the filesize fseek(file,0,SEEK_END); midifilesize=ftell(file); rewind(file); - + midifile=new unsigned char[midifilesize]; ZERO(midifile,midifilesize); fread(midifile,midifilesize,1,file); @@ -65,12 +68,13 @@ int MIDIFile::loadfile(char *filename){ // for (int i=0;ime=me_; //read the header @@ -88,19 +92,19 @@ int MIDIFile::parsemidifile(MIDIEvents *me_){ int division=getint16(); printf("division %d\n",division); - if (division>=0){//delta time units in each a quater note + if (division>=0) {//delta time units in each a quater note // tick=???; } else {//SMPTE (frames/second and ticks/frame) - printf("ERROR:in MIDIFile.C::parsemidifile() - SMPTE not implemented yet."); - }; - + printf("ERROR:in MIDIFile.C::parsemidifile() - SMPTE not implemented yet."); + }; + if (ntracks>=NUM_MIDI_TRACKS) ntracks=NUM_MIDI_TRACKS-1; - - for (int n=0;nsize) return(-1); + if (midieof) return(-1); + + if ((midifilek-oldmidifilek)==size) break; + else if ((midifilek-oldmidifilek)>size) return(-1); // if (size!=6) return(-1);//header is always 6 bytes long }; @@ -212,40 +217,42 @@ int MIDIFile::parsetrack(int ntrack){ }; -void MIDIFile::parsenoteoff(char ntrack,char chan,unsigned int dt){ +void MIDIFile::parsenoteoff(char ntrack,char chan,unsigned int dt) +{ unsigned char note; note=getbyte(); - + unsigned char noteoff_velocity=getbyte();//unused by zynaddsubfx noteoff_velocity=0; if (chan>=NUM_MIDI_CHANNELS) return; - + me->tmpevent.deltatime=convertdt(dt); me->tmpevent.type=1; me->tmpevent.par1=note; me->tmpevent.par2=0; me->tmpevent.channel=chan; - + printf("Note off:%d \n",note); - - ///test + + ///test // ntrack=0; - + me->writeevent(&me->miditrack[(int)ntrack].record,&me->tmpevent); - + }; -void MIDIFile::parsenoteon(char ntrack,char chan,unsigned int dt){ +void MIDIFile::parsenoteon(char ntrack,char chan,unsigned int dt) +{ unsigned char note,vel; note=getbyte(); vel=getbyte(); - + // printf("ntrack=%d\n",ntrack); printf("[dt %d ] Note on:%d %d\n",dt,note,vel); - + if (chan>=NUM_MIDI_CHANNELS) return; - + me->tmpevent.deltatime=convertdt(dt); me->tmpevent.type=1; me->tmpevent.par1=note; @@ -253,52 +260,56 @@ void MIDIFile::parsenoteon(char ntrack,char chan,unsigned int dt){ me->tmpevent.channel=chan; me->writeevent(&me->miditrack[(int)ntrack].record,&me->tmpevent); - - + + }; -void MIDIFile::parsecontrolchange(char ntrack,char chan,unsigned int dt){ +void MIDIFile::parsecontrolchange(char ntrack,char chan,unsigned int dt) +{ unsigned char control,value; control=getbyte(); value=getbyte(); - + if (chan>=NUM_MIDI_CHANNELS) return; - + printf("[dt %d] Control change:%d %d\n",dt,control,value); - + me->tmpevent.deltatime=convertdt(dt); me->tmpevent.type=2; me->tmpevent.par1=control;//???????????? ma uit la Sequencer::recordnote() din varianele vechi de zyn me->tmpevent.par2=value; me->tmpevent.channel=chan; me->writeevent(&me->miditrack[(int)ntrack].record,&me->tmpevent); - + }; -void MIDIFile::parsepitchwheel(char ntrack,char chan, unsigned int dt){ +void MIDIFile::parsepitchwheel(char ntrack,char chan, unsigned int dt) +{ unsigned char valhi,vallo; vallo=getbyte(); valhi=getbyte(); - + if (chan>=NUM_MIDI_CHANNELS) return; - + int value=(int)valhi*128+vallo; - + printf("[dt %d] Pitch wheel:%d\n",dt,value); - + }; -void MIDIFile::parsemetaevent(unsigned char mtype,unsigned char mlength){ +void MIDIFile::parsemetaevent(unsigned char mtype,unsigned char mlength) +{ int oldmidifilek=midifilek; printf("meta-event type=0x%x length=%d\n",mtype,mlength); - + midifilek=oldmidifilek+mlength; - + }; -void MIDIFile::add_dt(char ntrack, unsigned int dt){ +void MIDIFile::add_dt(char ntrack, unsigned int dt) +{ me->tmpevent.deltatime=convertdt(dt); me->tmpevent.type=255; me->tmpevent.par1=0; @@ -308,7 +319,8 @@ void MIDIFile::add_dt(char ntrack, unsigned int dt){ }; -unsigned int MIDIFile::convertdt(unsigned int dt){ +unsigned int MIDIFile::convertdt(unsigned int dt) +{ double result=dt; printf("DT=%d\n",dt); @@ -316,7 +328,8 @@ unsigned int MIDIFile::convertdt(unsigned int dt){ }; -void MIDIFile::clearmidifile(){ +void MIDIFile::clearmidifile() +{ if (midifile!=NULL) delete(midifile); midifile=NULL; midifilesize=0; @@ -325,43 +338,48 @@ void MIDIFile::clearmidifile(){ data.tick=0.05; }; -unsigned char MIDIFile::getbyte(){ +unsigned char MIDIFile::getbyte() +{ if (midifilek>=midifilesize) { - midieof=true; - return(0); + midieof=true; + return(0); }; /// printf("(%d) ",midifile[midifilek]); return(midifile[midifilek++]); }; -unsigned char MIDIFile::peekbyte(){ +unsigned char MIDIFile::peekbyte() +{ if (midifilek>=midifilesize) { - midieof=true; - return(0); + midieof=true; + return(0); }; return(midifile[midifilek]); }; -unsigned int MIDIFile::getint32(){ +unsigned int MIDIFile::getint32() +{ unsigned int result=0; for (int i=0;i<4;i++) { - result=result*256+getbyte(); + result=result*256+getbyte(); }; if (midieof) result=0; return(result); }; -unsigned short int MIDIFile::getint16(){ +unsigned short int MIDIFile::getint16() +{ unsigned short int result=0; for (int i=0;i<2;i++) { - result=result*256+getbyte(); + result=result*256+getbyte(); }; if (midieof) result=0; return(result); }; -unsigned int MIDIFile::getvarint32(){ +unsigned int MIDIFile::getvarint32() +{ unsigned long result=0; unsigned char b; @@ -370,20 +388,21 @@ unsigned int MIDIFile::getvarint32(){ if ((result = getbyte()) & 0x80) { result &= 0x7f; do { - b=getbyte(); + b=getbyte(); result = (result << 7) + (b & 0x7f); - }while (b & 0x80); + } while (b & 0x80); } /// printf("[end - result= %d]\n",result); return result; }; -void MIDIFile::skipnbytes(int n){ +void MIDIFile::skipnbytes(int n) +{ midifilek+=n; - if (midifilek>=midifilesize){ - midifilek=midifilesize-1; - midieof=true; + if (midifilek>=midifilesize) { + midifilek=midifilesize-1; + midieof=true; }; }; diff --git a/plugins/zynaddsubfx/src/Seq/MIDIFile.h b/plugins/zynaddsubfx/src/Seq/MIDIFile.h index 8b300c13b..7f831589f 100644 --- a/plugins/zynaddsubfx/src/Seq/MIDIFile.h +++ b/plugins/zynaddsubfx/src/Seq/MIDIFile.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + MIDIFile.h - MIDI file loader Copyright (C) 2003-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -26,65 +26,70 @@ #include "../globals.h" #include "MIDIEvents.h" -class MIDIFile{ - public: - MIDIFile(); - ~MIDIFile(); - - //returns -1 if there is an error, otherwise 0 - int loadfile(char *filename); - - //returns -1 if there is an error, otherwise 0 - int parsemidifile(MIDIEvents *me_); - - private: - MIDIEvents *me; - - unsigned char *midifile; - int midifilesize,midifilek; - bool midieof; +/**MIDI file loader*/ +class MIDIFile +{ +public: + MIDIFile(); + ~MIDIFile(); - //returns -1 if there is an error, otherwise 0 - int parsetrack(int ntrack); - - void parsenoteoff(char ntrack,char chan,unsigned int dt); - void parsenoteon(char ntrack,char chan,unsigned int dt); - void parsecontrolchange(char ntrack,char chan,unsigned int dt); - void parsepitchwheel(char ntrack,char chan, unsigned int dt); - void parsemetaevent(unsigned char mtype,unsigned char mlength); + /**Loads the given file + * @param filename The name of the file to load + * @return -1 if there is an error, otherwise 0*/ + int loadfile(const char *filename); - void add_dt(char ntrack, unsigned int dt); - - void clearmidifile(); + //returns -1 if there is an error, otherwise 0 + int parsemidifile(MIDIEvents *me_); - //convert the delta-time to internal format - unsigned int convertdt(unsigned int dt); - - /* Low Level MIDIfile functions */ - - //get a byte from the midifile - unsigned char getbyte(); +private: + MIDIEvents *me; - //peek the current byte from the midifile - unsigned char peekbyte(); - - //get a set of 4 bytes from the midifile - unsigned int getint32(); - - //get a word of 2 bytes from the midifile - unsigned short int getint16(); + unsigned char *midifile; + int midifilesize,midifilek; + bool midieof; - //read a variable length quantity - unsigned int getvarint32(); + //returns -1 if there is an error, otherwise 0 + int parsetrack(int ntrack); - //skip some bytes - void skipnbytes(int n); + void parsenoteoff(char ntrack,char chan,unsigned int dt); + void parsenoteon(char ntrack,char chan,unsigned int dt); + void parsecontrolchange(char ntrack,char chan,unsigned int dt); + void parsepitchwheel(char ntrack,char chan, unsigned int dt); + void parsemetaevent(unsigned char mtype,unsigned char mlength); + + void add_dt(char ntrack, unsigned int dt); + + void clearmidifile(); + + //convert the delta-time to internal format + unsigned int convertdt(unsigned int dt); + + /* Low Level MIDIfile functions */ + + //get a byte from the midifile + unsigned char getbyte(); + + //peek the current byte from the midifile + unsigned char peekbyte(); + + //get a set of 4 bytes from the midifile + unsigned int getint32(); + + //get a word of 2 bytes from the midifile + unsigned short int getint16(); + + //read a variable length quantity + unsigned int getvarint32(); + + //skip some bytes + void skipnbytes(int n); + + struct { + double tick;//how many seconds one tick has + + }data; - struct { - double tick;//how many seconds one tick has - - }data; - }; #endif + diff --git a/plugins/zynaddsubfx/src/Seq/Sequencer.C b/plugins/zynaddsubfx/src/Seq/Sequencer.cpp similarity index 65% rename from plugins/zynaddsubfx/src/Seq/Sequencer.C rename to plugins/zynaddsubfx/src/Seq/Sequencer.cpp index 94d98b20b..d0a32f1c4 100644 --- a/plugins/zynaddsubfx/src/Seq/Sequencer.C +++ b/plugins/zynaddsubfx/src/Seq/Sequencer.cpp @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Sequencer.C - The Sequencer Copyright (C) 2003-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -31,70 +31,76 @@ -Sequencer::Sequencer(){ +Sequencer::Sequencer() +{ play=0; - for (int i=0;i1sec) sa elimin nota @@ -119,7 +125,7 @@ int Sequencer::getevent(char ntrack,int *midich, int *type,int *par1, int *par2) *par2=nextevent[(int)ntrack].ev.par2; *midich=nextevent[(int)ntrack].ev.channel; - + double dt=nextevent[(int)ntrack].ev.deltatime*0.0001*realplayspeed; printf("zzzzzzzzzzzzzz[%d] %d\n",ntrack,nextevent[(int)ntrack].ev.deltatime); nextevent[(int)ntrack].time+=dt; @@ -130,36 +136,40 @@ int Sequencer::getevent(char ntrack,int *midich, int *type,int *par1, int *par2) /************** Timer stuff ***************/ -void Sequencer::resettime(timestruct *t){ +void Sequencer::resettime(timestruct *t) +{ t->abs=0.0; t->rel=0.0; - + timeval tval; - + t->last=0.0; - #ifndef OS_WINDOWS - if (gettimeofday(&tval,NULL)==0) - t->last=tval.tv_sec+tval.tv_usec*0.000001; - #endif - +#ifndef OS_WINDOWS + if (gettimeofday(&tval,NULL)==0) + t->last=tval.tv_sec+tval.tv_usec*0.000001; +#endif + }; -void Sequencer::updatecounter(timestruct *t){ +void Sequencer::updatecounter(timestruct *t) +{ timeval tval; double current=0.0; - #ifndef OS_WINDOWS - if (gettimeofday(&tval,NULL)==0) - current=tval.tv_sec+tval.tv_usec*0.000001; - #endif - +#ifndef OS_WINDOWS + if (gettimeofday(&tval,NULL)==0) + current=tval.tv_sec+tval.tv_usec*0.000001; +#endif + t->rel=current - t->last; t->abs+=t->rel; t->last=current; - + // printf("%f %f %f\n",t->last,t->abs,t->rel); }; -void Sequencer::setplayspeed(int speed){ +void Sequencer::setplayspeed(int speed) +{ playspeed=speed; realplayspeed=pow(10.0,speed/128.0); }; + diff --git a/plugins/zynaddsubfx/src/Seq/Sequencer.h b/plugins/zynaddsubfx/src/Seq/Sequencer.h index 3236741a4..7798c9943 100644 --- a/plugins/zynaddsubfx/src/Seq/Sequencer.h +++ b/plugins/zynaddsubfx/src/Seq/Sequencer.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Sequencer.h - The Sequencer Copyright (C) 2003-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -26,59 +26,66 @@ #include "MIDIEvents.h" #include "MIDIFile.h" -class Sequencer:public MIDIEvents{ - public: - Sequencer(); - ~Sequencer(); - - //theese functions are called by the master and are ignored if the recorder/player are stopped - void recordnote(char chan, char note, char vel); - void recordcontroller(char chan,unsigned int type,int par); - - //this is only for player - //it returns 1 if this must be called at least once more - //it returns 0 if there are no more notes for the current time - //or -1 if there is no note - int getevent(char ntrack, int *midich,int *type,int *par1, int *par2); +/**The Sequencer + * \todo restructure some of this code*/ +class Sequencer:public MIDIEvents +{ +public: + /**Constructor*/ + Sequencer(); + /**Destructor*/ + ~Sequencer(); - //returns 0 if ok or -1 if there is a error loading file - int importmidifile(char *filename); - - void startplay(); - void stopplay(); - + //these functions are called by the master and are ignored if the recorder/player are stopped + void recordnote(char chan, char note, char vel); + void recordcontroller(char chan,unsigned int type,int par); - int play; - int playspeed;//viteza de rulare (0.1x-10x), 0=1.0x, 128=10x - void setplayspeed(int speed); - - private: - - MIDIFile midifile; + /**Gets an event \todo better description + * + * this is only for player + * @return 1 if this must be called at least once more + * 0 if there are no more notes for the current time + * -1 if there are no notes*/ + int getevent(char ntrack, int *midich,int *type,int *par1, int *par2); + + /**Imports a given midifile + * @return 0 if ok or -1 if there is a error loading file*/ + int importmidifile(const char *filename); + + void startplay(); + void stopplay(); + + + int play; + int playspeed;//viteza de rulare (0.1x-10x), 0=1.0x, 128=10x + void setplayspeed(int speed); + +private: + + MIDIFile midifile; /* Timer */ - struct timestruct{ - double abs;//the time from the begining of the track - double rel;//the time difference between the last and the current event - double last;//the time of the last event (absolute, since 1 Jan 1970) - //theese must be double, because the float's precision is too low - //and all theese represents the time in seconds + struct timestruct { + double abs;//the time from the begining of the track + double rel;//the time difference between the last and the current event + double last;//the time of the last event (absolute, since 1 Jan 1970) + //these must be double, because the float's precision is too low + //and all these represent the time in seconds } playtime[NUM_MIDI_TRACKS]; - + void resettime(timestruct *t); void updatecounter(timestruct *t);//this updates the timer values /* Player only*/ struct { - event ev; - double time; - } nextevent[NUM_MIDI_TRACKS]; - - double realplayspeed; - -}; + event ev; + double time; + } nextevent[NUM_MIDI_TRACKS]; + double realplayspeed; + +}; #endif diff --git a/plugins/zynaddsubfx/src/Synth/ADnote.C b/plugins/zynaddsubfx/src/Synth/ADnote.C deleted file mode 100644 index de569539d..000000000 --- a/plugins/zynaddsubfx/src/Synth/ADnote.C +++ /dev/null @@ -1,1271 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - ADnote.C - The "additive" synthesizer - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include -#include -#include - - -#include "../globals.h" -#include "../Misc/Util.h" -#include "ADnote.h" - - -ADnote::ADnote(ADnoteParameters *pars,Controller *ctl_,REALTYPE freq,REALTYPE velocity,int portamento_,int midinote_,bool besilent){ - ready=0; - - tmpwave=new REALTYPE [SOUND_BUFFER_SIZE]; - bypassl=new REALTYPE [SOUND_BUFFER_SIZE]; - bypassr=new REALTYPE [SOUND_BUFFER_SIZE]; - - // Initialise some legato-specific vars - Legato.msg=LM_Norm; - Legato.fade.length=(int)(SAMPLE_RATE*0.005);// 0.005 seems ok. - if (Legato.fade.length<1) Legato.fade.length=1;// (if something's fishy) - Legato.fade.step=(1.0/Legato.fade.length); - Legato.decounter=-10; - Legato.param.freq=freq; - Legato.param.vel=velocity; - Legato.param.portamento=portamento_; - Legato.param.midinote=midinote_; - Legato.silent=besilent; - - partparams=pars; - ctl=ctl_; - portamento=portamento_; - midinote=midinote_; - NoteEnabled=ON; - basefreq=freq; - if (velocity>1.0) velocity=1.0; - this->velocity=velocity; - time=0.0; - stereo=pars->GlobalPar.PStereo; - - NoteGlobalPar.Detune=getdetune(pars->GlobalPar.PDetuneType - ,pars->GlobalPar.PCoarseDetune,pars->GlobalPar.PDetune); - bandwidthDetuneMultiplier=pars->getBandwidthDetuneMultiplier(); - - if (pars->GlobalPar.PPanning==0) NoteGlobalPar.Panning=RND; - else NoteGlobalPar.Panning=pars->GlobalPar.PPanning/128.0; - - - NoteGlobalPar.FilterCenterPitch=pars->GlobalPar.GlobalFilter->getfreq()+//center freq - pars->GlobalPar.PFilterVelocityScale/127.0*6.0* //velocity sensing - (VelF(velocity,pars->GlobalPar.PFilterVelocityScaleFunction)-1); - - if (pars->GlobalPar.PPunchStrength!=0) { - NoteGlobalPar.Punch.Enabled=1; - NoteGlobalPar.Punch.t=1.0;//start from 1.0 and to 0.0 - NoteGlobalPar.Punch.initialvalue=( (pow(10,1.5*pars->GlobalPar.PPunchStrength/127.0)-1.0) - *VelF(velocity,pars->GlobalPar.PPunchVelocitySensing) ); - REALTYPE time=pow(10,3.0*pars->GlobalPar.PPunchTime/127.0)/10000.0;//0.1 .. 100 ms - REALTYPE stretch=pow(440.0/freq,pars->GlobalPar.PPunchStretch/64.0); - NoteGlobalPar.Punch.dt=1.0/(time*SAMPLE_RATE*stretch); - } else NoteGlobalPar.Punch.Enabled=0; - - for (int nvoice=0;nvoiceVoicePar[nvoice].OscilSmp->newrandseed(rand()); - NoteVoicePar[nvoice].OscilSmp=NULL; - NoteVoicePar[nvoice].FMSmp=NULL; - NoteVoicePar[nvoice].VoiceOut=NULL; - - NoteVoicePar[nvoice].FMVoice=-1; - - if (pars->VoicePar[nvoice].Enabled==0) { - NoteVoicePar[nvoice].Enabled=OFF; - continue; //the voice is disabled - }; - - NoteVoicePar[nvoice].Enabled=ON; - NoteVoicePar[nvoice].fixedfreq=pars->VoicePar[nvoice].Pfixedfreq; - NoteVoicePar[nvoice].fixedfreqET=pars->VoicePar[nvoice].PfixedfreqET; - - //use the Globalpars.detunetype if the detunetype is 0 - if (pars->VoicePar[nvoice].PDetuneType!=0){ - NoteVoicePar[nvoice].Detune=getdetune(pars->VoicePar[nvoice].PDetuneType - ,pars->VoicePar[nvoice].PCoarseDetune,8192);//coarse detune - NoteVoicePar[nvoice].FineDetune=getdetune(pars->VoicePar[nvoice].PDetuneType - ,0,pars->VoicePar[nvoice].PDetune);//fine detune - } else { - NoteVoicePar[nvoice].Detune=getdetune(pars->GlobalPar.PDetuneType - ,pars->VoicePar[nvoice].PCoarseDetune,8192);//coarse detune - NoteVoicePar[nvoice].FineDetune=getdetune(pars->GlobalPar.PDetuneType - ,0,pars->VoicePar[nvoice].PDetune);//fine detune - }; - if (pars->VoicePar[nvoice].PFMDetuneType!=0){ - NoteVoicePar[nvoice].FMDetune=getdetune(pars->VoicePar[nvoice].PFMDetuneType - ,pars->VoicePar[nvoice].PFMCoarseDetune,pars->VoicePar[nvoice].PFMDetune); - } else { - NoteVoicePar[nvoice].FMDetune=getdetune(pars->GlobalPar.PDetuneType - ,pars->VoicePar[nvoice].PFMCoarseDetune,pars->VoicePar[nvoice].PFMDetune); - }; - - oscposhi[nvoice]=0;oscposlo[nvoice]=0.0; - oscposhiFM[nvoice]=0;oscposloFM[nvoice]=0.0; - - NoteVoicePar[nvoice].OscilSmp=new REALTYPE[OSCIL_SIZE+OSCIL_SMP_EXTRA_SAMPLES];//the extra points contains the first point - - //Get the voice's oscil or external's voice oscil - int vc=nvoice; - if (pars->VoicePar[nvoice].Pextoscil!=-1) vc=pars->VoicePar[nvoice].Pextoscil; - if (!pars->GlobalPar.Hrandgrouping) pars->VoicePar[vc].OscilSmp->newrandseed(rand()); - oscposhi[nvoice]=pars->VoicePar[vc].OscilSmp->get(NoteVoicePar[nvoice].OscilSmp,getvoicebasefreq(nvoice), - pars->VoicePar[nvoice].Presonance); - - //I store the first elments to the last position for speedups - for (int i=0;iVoicePar[nvoice].Poscilphase-64.0)/128.0*OSCIL_SIZE+OSCIL_SIZE*4); - oscposhi[nvoice]%=OSCIL_SIZE; - - - NoteVoicePar[nvoice].FreqLfo=NULL; - NoteVoicePar[nvoice].FreqEnvelope=NULL; - - NoteVoicePar[nvoice].AmpLfo=NULL; - NoteVoicePar[nvoice].AmpEnvelope=NULL; - - NoteVoicePar[nvoice].VoiceFilter=NULL; - NoteVoicePar[nvoice].FilterEnvelope=NULL; - NoteVoicePar[nvoice].FilterLfo=NULL; - - NoteVoicePar[nvoice].FilterCenterPitch=pars->VoicePar[nvoice].VoiceFilter->getfreq(); - NoteVoicePar[nvoice].filterbypass=pars->VoicePar[nvoice].Pfilterbypass; - - switch(pars->VoicePar[nvoice].PFMEnabled){ - case 1:NoteVoicePar[nvoice].FMEnabled=MORPH;break; - case 2:NoteVoicePar[nvoice].FMEnabled=RING_MOD;break; - case 3:NoteVoicePar[nvoice].FMEnabled=PHASE_MOD;break; - case 4:NoteVoicePar[nvoice].FMEnabled=FREQ_MOD;break; - case 5:NoteVoicePar[nvoice].FMEnabled=PITCH_MOD;break; - default:NoteVoicePar[nvoice].FMEnabled=NONE; - }; - - NoteVoicePar[nvoice].FMVoice=pars->VoicePar[nvoice].PFMVoice; - NoteVoicePar[nvoice].FMFreqEnvelope=NULL; - NoteVoicePar[nvoice].FMAmpEnvelope=NULL; - - //Compute the Voice's modulator volume (incl. damping) - REALTYPE fmvoldamp=pow(440.0/getvoicebasefreq(nvoice),pars->VoicePar[nvoice].PFMVolumeDamp/64.0-1.0); - switch (NoteVoicePar[nvoice].FMEnabled){ - case PHASE_MOD:fmvoldamp=pow(440.0/getvoicebasefreq(nvoice),pars->VoicePar[nvoice].PFMVolumeDamp/64.0); - NoteVoicePar[nvoice].FMVolume=(exp(pars->VoicePar[nvoice].PFMVolume/127.0*FM_AMP_MULTIPLIER)-1.0)*fmvoldamp*4.0; - break; - case FREQ_MOD:NoteVoicePar[nvoice].FMVolume=(exp(pars->VoicePar[nvoice].PFMVolume/127.0*FM_AMP_MULTIPLIER)-1.0)*fmvoldamp*4.0; - break; - // case PITCH_MOD:NoteVoicePar[nvoice].FMVolume=(pars->VoicePar[nvoice].PFMVolume/127.0*8.0)*fmvoldamp;//??????????? - // break; - default:if (fmvoldamp>1.0) fmvoldamp=1.0; - NoteVoicePar[nvoice].FMVolume=pars->VoicePar[nvoice].PFMVolume/127.0*fmvoldamp; - }; - - //Voice's modulator velocity sensing - NoteVoicePar[nvoice].FMVolume*=VelF(velocity,partparams->VoicePar[nvoice].PFMVelocityScaleFunction); - - FMoldsmp[nvoice]=0.0;//this is for FM (integration) - - firsttick[nvoice]=1; - NoteVoicePar[nvoice].DelayTicks=(int)((exp(pars->VoicePar[nvoice].PDelay/127.0*log(50.0))-1.0)/SOUND_BUFFER_SIZE/10.0*SAMPLE_RATE); - }; - - initparameters(); - ready=1; -}; - - -// ADlegatonote: This function is (mostly) a copy of ADnote(...) and -// initparameters() stuck together with some lines removed so that it -// only alter the already playing note (to perform legato). It is -// possible I left stuff that is not required for this. -void ADnote::ADlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int midinote_, bool externcall){ - ADnoteParameters *pars=partparams; - //Controller *ctl_=ctl; - - // Manage legato stuff - if (externcall) Legato.msg=LM_Norm; - if (Legato.msg!=LM_CatchUp){ - Legato.lastfreq=Legato.param.freq; - Legato.param.freq=freq; - Legato.param.vel=velocity; - Legato.param.portamento=portamento_; - Legato.param.midinote=midinote_; - if (Legato.msg==LM_Norm){ - if (Legato.silent){ - Legato.fade.m=0.0; - Legato.msg=LM_FadeIn; - } else { - Legato.fade.m=1.0; - Legato.msg=LM_FadeOut; - return; - } - } - if (Legato.msg==LM_ToNorm) Legato.msg=LM_Norm; - } - - portamento=portamento_; - midinote=midinote_; - basefreq=freq; - - if (velocity>1.0) velocity=1.0; - this->velocity=velocity; - - NoteGlobalPar.Detune=getdetune(pars->GlobalPar.PDetuneType - ,pars->GlobalPar.PCoarseDetune,pars->GlobalPar.PDetune); - bandwidthDetuneMultiplier=pars->getBandwidthDetuneMultiplier(); - - if (pars->GlobalPar.PPanning==0) NoteGlobalPar.Panning=RND; - else NoteGlobalPar.Panning=pars->GlobalPar.PPanning/128.0; - - - NoteGlobalPar.FilterCenterPitch=pars->GlobalPar.GlobalFilter->getfreq()+//center freq - pars->GlobalPar.PFilterVelocityScale/127.0*6.0* //velocity sensing - (VelF(velocity,pars->GlobalPar.PFilterVelocityScaleFunction)-1); - - - for (int nvoice=0;nvoiceVoicePar[nvoice].Pfixedfreq; - NoteVoicePar[nvoice].fixedfreqET=pars->VoicePar[nvoice].PfixedfreqET; - - //use the Globalpars.detunetype if the detunetype is 0 - if (pars->VoicePar[nvoice].PDetuneType!=0){ - NoteVoicePar[nvoice].Detune=getdetune(pars->VoicePar[nvoice].PDetuneType - ,pars->VoicePar[nvoice].PCoarseDetune,8192);//coarse detune - NoteVoicePar[nvoice].FineDetune=getdetune(pars->VoicePar[nvoice].PDetuneType - ,0,pars->VoicePar[nvoice].PDetune);//fine detune - } else { - NoteVoicePar[nvoice].Detune=getdetune(pars->GlobalPar.PDetuneType - ,pars->VoicePar[nvoice].PCoarseDetune,8192);//coarse detune - NoteVoicePar[nvoice].FineDetune=getdetune(pars->GlobalPar.PDetuneType - ,0,pars->VoicePar[nvoice].PDetune);//fine detune - }; - if (pars->VoicePar[nvoice].PFMDetuneType!=0){ - NoteVoicePar[nvoice].FMDetune=getdetune(pars->VoicePar[nvoice].PFMDetuneType - ,pars->VoicePar[nvoice].PFMCoarseDetune,pars->VoicePar[nvoice].PFMDetune); - } else { - NoteVoicePar[nvoice].FMDetune=getdetune(pars->GlobalPar.PDetuneType - ,pars->VoicePar[nvoice].PFMCoarseDetune,pars->VoicePar[nvoice].PFMDetune); - }; - - //Get the voice's oscil or external's voice oscil - int vc=nvoice; - if (pars->VoicePar[nvoice].Pextoscil!=-1) vc=pars->VoicePar[nvoice].Pextoscil; - if (!pars->GlobalPar.Hrandgrouping) pars->VoicePar[vc].OscilSmp->newrandseed(rand()); - - ///oscposhi[nvoice]=pars->VoicePar[vc].OscilSmp->get(NoteVoicePar[nvoice].OscilSmp,getvoicebasefreq(nvoice),pars->VoicePar[nvoice].Presonance); - pars->VoicePar[vc].OscilSmp->get(NoteVoicePar[nvoice].OscilSmp,getvoicebasefreq(nvoice),pars->VoicePar[nvoice].Presonance);//(gf)Modif of the above line. - - //I store the first elments to the last position for speedups - for (int i=0;iVoicePar[nvoice].VoiceFilter->getfreq(); - NoteVoicePar[nvoice].filterbypass=pars->VoicePar[nvoice].Pfilterbypass; - - - NoteVoicePar[nvoice].FMVoice=pars->VoicePar[nvoice].PFMVoice; - - //Compute the Voice's modulator volume (incl. damping) - REALTYPE fmvoldamp=pow(440.0/getvoicebasefreq(nvoice),pars->VoicePar[nvoice].PFMVolumeDamp/64.0-1.0); - - switch (NoteVoicePar[nvoice].FMEnabled){ - case PHASE_MOD:fmvoldamp=pow(440.0/getvoicebasefreq(nvoice),pars->VoicePar[nvoice].PFMVolumeDamp/64.0); - NoteVoicePar[nvoice].FMVolume=(exp(pars->VoicePar[nvoice].PFMVolume/127.0*FM_AMP_MULTIPLIER)-1.0)*fmvoldamp*4.0; - break; - case FREQ_MOD:NoteVoicePar[nvoice].FMVolume=(exp(pars->VoicePar[nvoice].PFMVolume/127.0*FM_AMP_MULTIPLIER)-1.0)*fmvoldamp*4.0; - break; - // case PITCH_MOD:NoteVoicePar[nvoice].FMVolume=(pars->VoicePar[nvoice].PFMVolume/127.0*8.0)*fmvoldamp;//??????????? - // break; - default:if (fmvoldamp>1.0) fmvoldamp=1.0; - NoteVoicePar[nvoice].FMVolume=pars->VoicePar[nvoice].PFMVolume/127.0*fmvoldamp; - }; - - //Voice's modulator velocity sensing - NoteVoicePar[nvoice].FMVolume*=VelF(velocity,partparams->VoicePar[nvoice].PFMVelocityScaleFunction); - - NoteVoicePar[nvoice].DelayTicks=(int)((exp(pars->VoicePar[nvoice].PDelay/127.0*log(50.0))-1.0)/SOUND_BUFFER_SIZE/10.0*SAMPLE_RATE); - }; - - /// initparameters(); - - /////////////// - // Altered content of initparameters(): - - int nvoice,i,tmp[NUM_VOICES]; - - NoteGlobalPar.Volume=4.0*pow(0.1,3.0*(1.0-partparams->GlobalPar.PVolume/96.0))//-60 dB .. 0 dB - *VelF(velocity,partparams->GlobalPar.PAmpVelocityScaleFunction);//velocity sensing - - globalnewamplitude=NoteGlobalPar.Volume*NoteGlobalPar.AmpEnvelope->envout_dB()*NoteGlobalPar.AmpLfo->amplfoout(); - - NoteGlobalPar.FilterQ=partparams->GlobalPar.GlobalFilter->getq(); - NoteGlobalPar.FilterFreqTracking=partparams->GlobalPar.GlobalFilter->getfreqtracking(basefreq); - - // Forbids the Modulation Voice to be greater or equal than voice - for (i=0;i=i) NoteVoicePar[i].FMVoice=-1; - - // Voice Parameter init - for (nvoice=0;nvoiceVoicePar[nvoice].Type; - /* Voice Amplitude Parameters Init */ - NoteVoicePar[nvoice].Volume=pow(0.1,3.0*(1.0-partparams->VoicePar[nvoice].PVolume/127.0)) // -60 dB .. 0 dB - *VelF(velocity,partparams->VoicePar[nvoice].PAmpVelocityScaleFunction);//velocity - - if (partparams->VoicePar[nvoice].PVolumeminus!=0) NoteVoicePar[nvoice].Volume=-NoteVoicePar[nvoice].Volume; - - if (partparams->VoicePar[nvoice].PPanning==0) - NoteVoicePar[nvoice].Panning=RND;// random panning - else NoteVoicePar[nvoice].Panning=partparams->VoicePar[nvoice].PPanning/128.0; - - newamplitude[nvoice]=1.0; - if ((partparams->VoicePar[nvoice].PAmpEnvelopeEnabled!=0) - && (NoteVoicePar[nvoice].AmpEnvelope!=NULL)){ - newamplitude[nvoice]*=NoteVoicePar[nvoice].AmpEnvelope->envout_dB(); - }; - - if ((partparams->VoicePar[nvoice].PAmpLfoEnabled!=0) - && (NoteVoicePar[nvoice].AmpLfo!=NULL)){ - newamplitude[nvoice]*=NoteVoicePar[nvoice].AmpLfo->amplfoout(); - }; - - - NoteVoicePar[nvoice].FilterFreqTracking=partparams->VoicePar[nvoice].VoiceFilter->getfreqtracking(basefreq); - - /* Voice Modulation Parameters Init */ - if ((NoteVoicePar[nvoice].FMEnabled!=NONE)&&(NoteVoicePar[nvoice].FMVoice<0)){ - partparams->VoicePar[nvoice].FMSmp->newrandseed(rand()); - - //Perform Anti-aliasing only on MORPH or RING MODULATION - - int vc=nvoice; - if (partparams->VoicePar[nvoice].PextFMoscil!=-1) vc=partparams->VoicePar[nvoice].PextFMoscil; - - REALTYPE tmp=1.0; - if ((partparams->VoicePar[vc].FMSmp->Padaptiveharmonics!=0)|| - (NoteVoicePar[nvoice].FMEnabled==MORPH)|| - (NoteVoicePar[nvoice].FMEnabled==RING_MOD)){ - tmp=getFMvoicebasefreq(nvoice); - }; - if (!partparams->GlobalPar.Hrandgrouping) partparams->VoicePar[vc].FMSmp->newrandseed(rand()); - - ///oscposhiFM[nvoice]=(oscposhi[nvoice]+partparams->VoicePar[vc].FMSmp->get(NoteVoicePar[nvoice].FMSmp,tmp)) % OSCIL_SIZE; - // / oscposhi[nvoice]+partparams->VoicePar[vc].FMSmp->get(NoteVoicePar[nvoice].FMSmp,tmp); //(gf) Modif of the above line. - for (int i=0;iVoicePar[nvoice].PFMoscilphase-64.0)/128.0*OSCIL_SIZE+OSCIL_SIZE*4); - ///oscposhiFM[nvoice]%=OSCIL_SIZE; - }; - - FMnewamplitude[nvoice]=NoteVoicePar[nvoice].FMVolume*ctl->fmamp.relamp; - - if ((partparams->VoicePar[nvoice].PFMAmpEnvelopeEnabled!=0) - && (NoteVoicePar[nvoice].FMAmpEnvelope!=NULL)){ - FMnewamplitude[nvoice]*=NoteVoicePar[nvoice].FMAmpEnvelope->envout_dB(); - }; - }; - - for (nvoice=0;nvoiceGlobalPar.FreqEnvelope,basefreq); - NoteGlobalPar.FreqLfo=new LFO(partparams->GlobalPar.FreqLfo,basefreq); - - NoteGlobalPar.AmpEnvelope=new Envelope(partparams->GlobalPar.AmpEnvelope,basefreq); - NoteGlobalPar.AmpLfo=new LFO(partparams->GlobalPar.AmpLfo,basefreq); - - NoteGlobalPar.Volume=4.0*pow(0.1,3.0*(1.0-partparams->GlobalPar.PVolume/96.0))//-60 dB .. 0 dB - *VelF(velocity,partparams->GlobalPar.PAmpVelocityScaleFunction);//velocity sensing - - NoteGlobalPar.AmpEnvelope->envout_dB();//discard the first envelope output - globalnewamplitude=NoteGlobalPar.Volume*NoteGlobalPar.AmpEnvelope->envout_dB()*NoteGlobalPar.AmpLfo->amplfoout(); - - NoteGlobalPar.GlobalFilterL=new Filter(partparams->GlobalPar.GlobalFilter); - if (stereo!=0) NoteGlobalPar.GlobalFilterR=new Filter(partparams->GlobalPar.GlobalFilter); - - NoteGlobalPar.FilterEnvelope=new Envelope(partparams->GlobalPar.FilterEnvelope,basefreq); - NoteGlobalPar.FilterLfo=new LFO(partparams->GlobalPar.FilterLfo,basefreq); - NoteGlobalPar.FilterQ=partparams->GlobalPar.GlobalFilter->getq(); - NoteGlobalPar.FilterFreqTracking=partparams->GlobalPar.GlobalFilter->getfreqtracking(basefreq); - - // Forbids the Modulation Voice to be greater or equal than voice - for (i=0;i=i) NoteVoicePar[i].FMVoice=-1; - - // Voice Parameter init - for (nvoice=0;nvoiceVoicePar[nvoice].Type; - /* Voice Amplitude Parameters Init */ - NoteVoicePar[nvoice].Volume=pow(0.1,3.0*(1.0-partparams->VoicePar[nvoice].PVolume/127.0)) // -60 dB .. 0 dB - *VelF(velocity,partparams->VoicePar[nvoice].PAmpVelocityScaleFunction);//velocity - - if (partparams->VoicePar[nvoice].PVolumeminus!=0) NoteVoicePar[nvoice].Volume=-NoteVoicePar[nvoice].Volume; - - if (partparams->VoicePar[nvoice].PPanning==0) - NoteVoicePar[nvoice].Panning=RND;// random panning - else NoteVoicePar[nvoice].Panning=partparams->VoicePar[nvoice].PPanning/128.0; - - newamplitude[nvoice]=1.0; - if (partparams->VoicePar[nvoice].PAmpEnvelopeEnabled!=0) { - NoteVoicePar[nvoice].AmpEnvelope=new Envelope(partparams->VoicePar[nvoice].AmpEnvelope,basefreq); - NoteVoicePar[nvoice].AmpEnvelope->envout_dB();//discard the first envelope sample - newamplitude[nvoice]*=NoteVoicePar[nvoice].AmpEnvelope->envout_dB(); - }; - - if (partparams->VoicePar[nvoice].PAmpLfoEnabled!=0){ - NoteVoicePar[nvoice].AmpLfo=new LFO(partparams->VoicePar[nvoice].AmpLfo,basefreq); - newamplitude[nvoice]*=NoteVoicePar[nvoice].AmpLfo->amplfoout(); - }; - - /* Voice Frequency Parameters Init */ - if (partparams->VoicePar[nvoice].PFreqEnvelopeEnabled!=0) - NoteVoicePar[nvoice].FreqEnvelope=new Envelope(partparams->VoicePar[nvoice].FreqEnvelope,basefreq); - - if (partparams->VoicePar[nvoice].PFreqLfoEnabled!=0) NoteVoicePar[nvoice].FreqLfo=new LFO(partparams->VoicePar[nvoice].FreqLfo,basefreq); - - /* Voice Filter Parameters Init */ - if (partparams->VoicePar[nvoice].PFilterEnabled!=0){ - NoteVoicePar[nvoice].VoiceFilter=new Filter(partparams->VoicePar[nvoice].VoiceFilter); - }; - - if (partparams->VoicePar[nvoice].PFilterEnvelopeEnabled!=0) - NoteVoicePar[nvoice].FilterEnvelope=new Envelope(partparams->VoicePar[nvoice].FilterEnvelope,basefreq); - - if (partparams->VoicePar[nvoice].PFilterLfoEnabled!=0) - NoteVoicePar[nvoice].FilterLfo=new LFO(partparams->VoicePar[nvoice].FilterLfo,basefreq); - - NoteVoicePar[nvoice].FilterFreqTracking=partparams->VoicePar[nvoice].VoiceFilter->getfreqtracking(basefreq); - - /* Voice Modulation Parameters Init */ - if ((NoteVoicePar[nvoice].FMEnabled!=NONE)&&(NoteVoicePar[nvoice].FMVoice<0)){ - partparams->VoicePar[nvoice].FMSmp->newrandseed(rand()); - NoteVoicePar[nvoice].FMSmp=new REALTYPE[OSCIL_SIZE+OSCIL_SMP_EXTRA_SAMPLES]; - - //Perform Anti-aliasing only on MORPH or RING MODULATION - - int vc=nvoice; - if (partparams->VoicePar[nvoice].PextFMoscil!=-1) vc=partparams->VoicePar[nvoice].PextFMoscil; - - REALTYPE tmp=1.0; - if ((partparams->VoicePar[vc].FMSmp->Padaptiveharmonics!=0)|| - (NoteVoicePar[nvoice].FMEnabled==MORPH)|| - (NoteVoicePar[nvoice].FMEnabled==RING_MOD)){ - tmp=getFMvoicebasefreq(nvoice); - }; - if (!partparams->GlobalPar.Hrandgrouping) partparams->VoicePar[vc].FMSmp->newrandseed(rand()); - - oscposhiFM[nvoice]=(oscposhi[nvoice]+partparams->VoicePar[vc].FMSmp->get(NoteVoicePar[nvoice].FMSmp,tmp)) % OSCIL_SIZE; - for (int i=0;iVoicePar[nvoice].PFMoscilphase-64.0)/128.0*OSCIL_SIZE+OSCIL_SIZE*4); - oscposhiFM[nvoice]%=OSCIL_SIZE; - }; - - if (partparams->VoicePar[nvoice].PFMFreqEnvelopeEnabled!=0) - NoteVoicePar[nvoice].FMFreqEnvelope=new Envelope(partparams->VoicePar[nvoice].FMFreqEnvelope,basefreq); - - FMnewamplitude[nvoice]=NoteVoicePar[nvoice].FMVolume*ctl->fmamp.relamp; - - if (partparams->VoicePar[nvoice].PFMAmpEnvelopeEnabled!=0){ - NoteVoicePar[nvoice].FMAmpEnvelope=new Envelope(partparams->VoicePar[nvoice].FMAmpEnvelope,basefreq); - FMnewamplitude[nvoice]*=NoteVoicePar[nvoice].FMAmpEnvelope->envout_dB(); - }; - }; - - for (nvoice=0;nvoiceOSCIL_SIZE) speed=OSCIL_SIZE; - - F2I(speed,oscfreqhi[nvoice]); - oscfreqlo[nvoice]=speed-floor(speed); -}; - -/* - * Computes the frequency of an modullator oscillator - */ -void ADnote::setfreqFM(int nvoice,REALTYPE freq){ - REALTYPE speed; - freq=fabs(freq); - speed=freq*REALTYPE(OSCIL_SIZE)/(REALTYPE) SAMPLE_RATE; - if (speed>OSCIL_SIZE) speed=OSCIL_SIZE; - - F2I(speed,oscfreqhiFM[nvoice]); - oscfreqloFM[nvoice]=speed-floor(speed); -}; - -/* - * Get Voice base frequency - */ -REALTYPE ADnote::getvoicebasefreq(int nvoice){ - REALTYPE detune=NoteVoicePar[nvoice].Detune/100.0+ - NoteVoicePar[nvoice].FineDetune/100.0*ctl->bandwidth.relbw*bandwidthDetuneMultiplier+ - NoteGlobalPar.Detune/100.0; - - if (NoteVoicePar[nvoice].fixedfreq==0) return(this->basefreq*pow(2,detune/12.0)); - else {//the fixed freq is enabled - REALTYPE fixedfreq=440.0; - int fixedfreqET=NoteVoicePar[nvoice].fixedfreqET; - if (fixedfreqET!=0) {//if the frequency varies according the keyboard note - REALTYPE tmp=(midinote-69.0)/12.0*(pow(2.0,(fixedfreqET-1)/63.0)-1.0); - if (fixedfreqET<=64) fixedfreq*=pow(2.0,tmp); - else fixedfreq*=pow(3.0,tmp); - }; - return(fixedfreq*pow(2.0,detune/12.0)); - }; -}; - -/* - * Get Voice's Modullator base frequency - */ -REALTYPE ADnote::getFMvoicebasefreq(int nvoice){ - REALTYPE detune=NoteVoicePar[nvoice].FMDetune/100.0; - return(getvoicebasefreq(nvoice)*pow(2,detune/12.0)); -}; - -/* - * Computes all the parameters for each tick - */ -void ADnote::computecurrentparameters(){ - int nvoice; - REALTYPE voicefreq,voicepitch,filterpitch,filterfreq,FMfreq,FMrelativepitch,globalpitch,globalfilterpitch; - globalpitch=0.01*(NoteGlobalPar.FreqEnvelope->envout()+ - NoteGlobalPar.FreqLfo->lfoout()*ctl->modwheel.relmod); - globaloldamplitude=globalnewamplitude; - globalnewamplitude=NoteGlobalPar.Volume*NoteGlobalPar.AmpEnvelope->envout_dB()*NoteGlobalPar.AmpLfo->amplfoout(); - - globalfilterpitch=NoteGlobalPar.FilterEnvelope->envout()+NoteGlobalPar.FilterLfo->lfoout() - +NoteGlobalPar.FilterCenterPitch; - - REALTYPE tmpfilterfreq=globalfilterpitch+ctl->filtercutoff.relfreq - +NoteGlobalPar.FilterFreqTracking; - - tmpfilterfreq=NoteGlobalPar.GlobalFilterL->getrealfreq(tmpfilterfreq); - - REALTYPE globalfilterq=NoteGlobalPar.FilterQ*ctl->filterq.relq; - NoteGlobalPar.GlobalFilterL->setfreq_and_q(tmpfilterfreq,globalfilterq); - if (stereo!=0) NoteGlobalPar.GlobalFilterR->setfreq_and_q(tmpfilterfreq,globalfilterq); - - //compute the portamento, if it is used by this note - REALTYPE portamentofreqrap=1.0; - if (portamento!=0){//this voice use portamento - portamentofreqrap=ctl->portamento.freqrap; - if (ctl->portamento.used==0){//the portamento has finished - portamento=0;//this note is no longer "portamented" - }; - }; - - //compute parameters for all voices - for (nvoice=0;nvoice0) continue; - - /*******************/ - /* Voice Amplitude */ - /*******************/ - oldamplitude[nvoice]=newamplitude[nvoice]; - newamplitude[nvoice]=1.0; - - if (NoteVoicePar[nvoice].AmpEnvelope!=NULL) - newamplitude[nvoice]*=NoteVoicePar[nvoice].AmpEnvelope->envout_dB(); - - if (NoteVoicePar[nvoice].AmpLfo!=NULL) - newamplitude[nvoice]*=NoteVoicePar[nvoice].AmpLfo->amplfoout(); - - /****************/ - /* Voice Filter */ - /****************/ - if (NoteVoicePar[nvoice].VoiceFilter!=NULL){ - filterpitch=NoteVoicePar[nvoice].FilterCenterPitch; - - if (NoteVoicePar[nvoice].FilterEnvelope!=NULL) - filterpitch+=NoteVoicePar[nvoice].FilterEnvelope->envout(); - - if (NoteVoicePar[nvoice].FilterLfo!=NULL) - filterpitch+=NoteVoicePar[nvoice].FilterLfo->lfoout(); - - filterfreq=filterpitch+NoteVoicePar[nvoice].FilterFreqTracking; - filterfreq=NoteVoicePar[nvoice].VoiceFilter->getrealfreq(filterfreq); - - NoteVoicePar[nvoice].VoiceFilter->setfreq(filterfreq); - }; - - if (NoteVoicePar[nvoice].noisetype==0){//compute only if the voice isn't noise - - /*******************/ - /* Voice Frequency */ - /*******************/ - voicepitch=0.0; - if (NoteVoicePar[nvoice].FreqLfo!=NULL) - voicepitch+=NoteVoicePar[nvoice].FreqLfo->lfoout()/100.0 - *ctl->bandwidth.relbw; - - if (NoteVoicePar[nvoice].FreqEnvelope!=NULL) voicepitch+=NoteVoicePar[nvoice].FreqEnvelope->envout()/100.0; - voicefreq=getvoicebasefreq(nvoice)*pow(2,(voicepitch+globalpitch)/12.0);//Hz frequency - voicefreq*=ctl->pitchwheel.relfreq;//change the frequency by the controller - setfreq(nvoice,voicefreq*portamentofreqrap); - - /***************/ - /* Modulator */ - /***************/ - if (NoteVoicePar[nvoice].FMEnabled!=NONE){ - FMrelativepitch=NoteVoicePar[nvoice].FMDetune/100.0; - if (NoteVoicePar[nvoice].FMFreqEnvelope!=NULL) FMrelativepitch+=NoteVoicePar[nvoice].FMFreqEnvelope->envout()/100; - FMfreq=pow(2.0,FMrelativepitch/12.0)*voicefreq*portamentofreqrap; - setfreqFM(nvoice,FMfreq); - - FMoldamplitude[nvoice]=FMnewamplitude[nvoice]; - FMnewamplitude[nvoice]=NoteVoicePar[nvoice].FMVolume*ctl->fmamp.relamp; - if (NoteVoicePar[nvoice].FMAmpEnvelope!=NULL) - FMnewamplitude[nvoice]*=NoteVoicePar[nvoice].FMAmpEnvelope->envout_dB(); - }; - }; - - }; - time+=(REALTYPE)SOUND_BUFFER_SIZE/(REALTYPE)SAMPLE_RATE; -}; - - -/* - * Fadein in a way that removes clicks but keep sound "punchy" - */ -inline void ADnote::fadein(REALTYPE *smps){ - int zerocrossings=0; - for (int i=1;i0.0)) zerocrossings++;//this is only the possitive crossings - - REALTYPE tmp=(SOUND_BUFFER_SIZE-1.0)/(zerocrossings+1)/3.0; - if (tmp<8.0) tmp=8.0; - - int n; - F2I(tmp,n);//how many samples is the fade-in - if (n>SOUND_BUFFER_SIZE) n=SOUND_BUFFER_SIZE; - for (int i=0;i=1.0) { - poslo-=1.0; - poshi++; - }; - poshi+=oscfreqhi[nvoice]; - poshi&=OSCIL_SIZE-1; - }; - oscposhi[nvoice]=poshi; - oscposlo[nvoice]=poslo; -}; - - - -/* - * Computes the Oscillator (Without Modulation) - CubicInterpolation - * - The differences from the Linear are to little to deserve to be used. This is because I am using a large OSCIL_SIZE (>512) -inline void ADnote::ComputeVoiceOscillator_CubicInterpolation(int nvoice){ - int i,poshi; - REALTYPE poslo; - - poshi=oscposhi[nvoice]; - poslo=oscposlo[nvoice]; - REALTYPE *smps=NoteVoicePar[nvoice].OscilSmp; - REALTYPE xm1,x0,x1,x2,a,b,c; - for (i=0;i=1.0) { - poslo-=1.0; - poshi++; - }; - poshi+=oscfreqhi[nvoice]; - poshi&=OSCIL_SIZE-1; - }; - oscposhi[nvoice]=poshi; - oscposlo[nvoice]=poslo; -}; -*/ -/* - * Computes the Oscillator (Morphing) - */ -inline void ADnote::ComputeVoiceOscillatorMorph(int nvoice){ - int i; - REALTYPE amp; - ComputeVoiceOscillator_LinearInterpolation(nvoice); - if (FMnewamplitude[nvoice]>1.0) FMnewamplitude[nvoice]=1.0; - if (FMoldamplitude[nvoice]>1.0) FMoldamplitude[nvoice]=1.0; - - if (NoteVoicePar[nvoice].FMVoice>=0){ - //if I use VoiceOut[] as modullator - int FMVoice=NoteVoicePar[nvoice].FMVoice; - for (i=0;i=1.0) { - posloFM-=1.0; - poshiFM++; - }; - poshiFM+=oscfreqhiFM[nvoice]; - poshiFM&=OSCIL_SIZE-1; - }; - oscposhiFM[nvoice]=poshiFM; - oscposloFM[nvoice]=posloFM; - }; -}; - -/* - * Computes the Oscillator (Ring Modulation) - */ -inline void ADnote::ComputeVoiceOscillatorRingModulation(int nvoice){ - int i; - REALTYPE amp; - ComputeVoiceOscillator_LinearInterpolation(nvoice); - if (FMnewamplitude[nvoice]>1.0) FMnewamplitude[nvoice]=1.0; - if (FMoldamplitude[nvoice]>1.0) FMoldamplitude[nvoice]=1.0; - if (NoteVoicePar[nvoice].FMVoice>=0){ - // if I use VoiceOut[] as modullator - for (i=0;i=1.0) { - posloFM-=1.0; - poshiFM++; - }; - poshiFM+=oscfreqhiFM[nvoice]; - poshiFM&=OSCIL_SIZE-1; - }; - oscposhiFM[nvoice]=poshiFM; - oscposloFM[nvoice]=posloFM; - }; -}; - - - -/* - * Computes the Oscillator (Phase Modulation or Frequency Modulation) - */ -inline void ADnote::ComputeVoiceOscillatorFrequencyModulation(int nvoice,int FMmode){ - int carposhi; - int i,FMmodfreqhi; - REALTYPE FMmodfreqlo,carposlo; - - if (NoteVoicePar[nvoice].FMVoice>=0){ - //if I use VoiceOut[] as modulator - for (i=0;i=1.0) { - posloFM=fmod(posloFM,1.0); - poshiFM++; - }; - poshiFM+=oscfreqhiFM[nvoice]; - poshiFM&=OSCIL_SIZE-1; - }; - oscposhiFM[nvoice]=poshiFM; - oscposloFM[nvoice]=posloFM; - }; - // Amplitude interpolation - if (ABOVE_AMPLITUDE_THRESHOLD(FMoldamplitude[nvoice],FMnewamplitude[nvoice])){ - for (i=0;i=1.0) { - carposhi++; - carposlo=fmod(carposlo,1.0); - }; - carposhi&=(OSCIL_SIZE-1); - - tmpwave[i]=NoteVoicePar[nvoice].OscilSmp[carposhi]*(1.0-carposlo) - +NoteVoicePar[nvoice].OscilSmp[carposhi+1]*carposlo; - - oscposlo[nvoice]+=oscfreqlo[nvoice]; - if (oscposlo[nvoice]>=1.0) { - oscposlo[nvoice]=fmod(oscposlo[nvoice],1.0); - oscposhi[nvoice]++; - }; - - oscposhi[nvoice]+=oscfreqhi[nvoice]; - oscposhi[nvoice]&=OSCIL_SIZE-1; - }; -}; - - -/*Calculeaza Oscilatorul cu PITCH MODULATION*/ -inline void ADnote::ComputeVoiceOscillatorPitchModulation(int nvoice){ -//TODO -}; - -/* - * Computes the Noise - */ -inline void ADnote::ComputeVoiceNoise(int nvoice){ - for (int i=0;i0)) continue; - if (NoteVoicePar[nvoice].noisetype==0){//voice mode=sound - switch (NoteVoicePar[nvoice].FMEnabled){ - case MORPH:ComputeVoiceOscillatorMorph(nvoice);break; - case RING_MOD:ComputeVoiceOscillatorRingModulation(nvoice);break; - case PHASE_MOD:ComputeVoiceOscillatorFrequencyModulation(nvoice,0);break; - case FREQ_MOD:ComputeVoiceOscillatorFrequencyModulation(nvoice,1);break; - //case PITCH_MOD:ComputeVoiceOscillatorPitchModulation(nvoice);break; - default:ComputeVoiceOscillator_LinearInterpolation(nvoice); - //if (config.cfg.Interpolation) ComputeVoiceOscillator_CubicInterpolation(nvoice); - - }; - } else ComputeVoiceNoise(nvoice); - // Voice Processing - - // Amplitude - if (ABOVE_AMPLITUDE_THRESHOLD(oldamplitude[nvoice],newamplitude[nvoice])){ - int rest=SOUND_BUFFER_SIZE; - //test if the amplitude if raising and the difference is high - if ((newamplitude[nvoice]>oldamplitude[nvoice])&&((newamplitude[nvoice]-oldamplitude[nvoice])>0.25)){ - rest=10; - if (rest>SOUND_BUFFER_SIZE) rest=SOUND_BUFFER_SIZE; - for (int i=0;ifilterout(&tmpwave[0]); - - //check if the amplitude envelope is finished, if yes, the voice will be fadeout - if (NoteVoicePar[nvoice].AmpEnvelope!=NULL) { - if (NoteVoicePar[nvoice].AmpEnvelope->finished()!=0) - for (i=0;ifinished()!=0) KillVoice(nvoice); - }; - }; - - - //Processing Global parameters - NoteGlobalPar.GlobalFilterL->filterout(&outl[0]); - - if (stereo==0) { - for (i=0;ifilterout(&outr[0]); - - for (i=0;ifinished()!=0) { - for (i=0;irelasekey(); - if (NoteVoicePar[nvoice].FreqEnvelope!=NULL) NoteVoicePar[nvoice].FreqEnvelope->relasekey(); - if (NoteVoicePar[nvoice].FilterEnvelope!=NULL) NoteVoicePar[nvoice].FilterEnvelope->relasekey(); - if (NoteVoicePar[nvoice].FMFreqEnvelope!=NULL) NoteVoicePar[nvoice].FMFreqEnvelope->relasekey(); - if (NoteVoicePar[nvoice].FMAmpEnvelope!=NULL) NoteVoicePar[nvoice].FMAmpEnvelope->relasekey(); - }; - NoteGlobalPar.FreqEnvelope->relasekey(); - NoteGlobalPar.FilterEnvelope->relasekey(); - NoteGlobalPar.AmpEnvelope->relasekey(); - -}; - -/* - * Check if the note is finished - */ -int ADnote::finished(){ - if (NoteEnabled==ON) return(0); - else return(1); -}; - - - diff --git a/plugins/zynaddsubfx/src/Synth/ADnote.cpp b/plugins/zynaddsubfx/src/Synth/ADnote.cpp new file mode 100644 index 000000000..d6a0b7bdf --- /dev/null +++ b/plugins/zynaddsubfx/src/Synth/ADnote.cpp @@ -0,0 +1,1321 @@ +/* + ZynAddSubFX - a software synthesizer + + ADnote.C - The "additive" synthesizer + Copyright (C) 2002-2005 Nasca Octavian Paul + Author: Nasca Octavian Paul + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include + + +#include "../globals.h" +#include "../Misc/Util.h" +#include "ADnote.h" + + +ADnote::ADnote(ADnoteParameters *pars,Controller *ctl_,REALTYPE freq,REALTYPE velocity,int portamento_,int midinote_,bool besilent) +{ + ready=0; + + tmpwave=new REALTYPE [SOUND_BUFFER_SIZE]; + bypassl=new REALTYPE [SOUND_BUFFER_SIZE]; + bypassr=new REALTYPE [SOUND_BUFFER_SIZE]; + + // Initialise some legato-specific vars + Legato.msg=LM_Norm; + Legato.fade.length=(int)(SAMPLE_RATE*0.005);// 0.005 seems ok. + if (Legato.fade.length<1) Legato.fade.length=1;// (if something's fishy) + Legato.fade.step=(1.0/Legato.fade.length); + Legato.decounter=-10; + Legato.param.freq=freq; + Legato.param.vel=velocity; + Legato.param.portamento=portamento_; + Legato.param.midinote=midinote_; + Legato.silent=besilent; + + partparams=pars; + ctl=ctl_; + portamento=portamento_; + midinote=midinote_; + NoteEnabled=ON; + basefreq=freq; + if (velocity>1.0) velocity=1.0; + this->velocity=velocity; + time=0.0; + stereo=pars->GlobalPar.PStereo; + + NoteGlobalPar.Detune=getdetune(pars->GlobalPar.PDetuneType + ,pars->GlobalPar.PCoarseDetune,pars->GlobalPar.PDetune); + bandwidthDetuneMultiplier=pars->getBandwidthDetuneMultiplier(); + + if (pars->GlobalPar.PPanning==0) NoteGlobalPar.Panning=RND; + else NoteGlobalPar.Panning=pars->GlobalPar.PPanning/128.0; + + + NoteGlobalPar.FilterCenterPitch=pars->GlobalPar.GlobalFilter->getfreq()+//center freq + pars->GlobalPar.PFilterVelocityScale/127.0*6.0* //velocity sensing + (VelF(velocity,pars->GlobalPar.PFilterVelocityScaleFunction)-1); + + if (pars->GlobalPar.PPunchStrength!=0) { + NoteGlobalPar.Punch.Enabled=1; + NoteGlobalPar.Punch.t=1.0;//start from 1.0 and to 0.0 + NoteGlobalPar.Punch.initialvalue=( (pow(10,1.5*pars->GlobalPar.PPunchStrength/127.0)-1.0) + *VelF(velocity,pars->GlobalPar.PPunchVelocitySensing) ); + REALTYPE time=pow(10,3.0*pars->GlobalPar.PPunchTime/127.0)/10000.0;//0.1 .. 100 ms + REALTYPE stretch=pow(440.0/freq,pars->GlobalPar.PPunchStretch/64.0); + NoteGlobalPar.Punch.dt=1.0/(time*SAMPLE_RATE*stretch); + } else NoteGlobalPar.Punch.Enabled=0; + + for (int nvoice=0;nvoiceVoicePar[nvoice].OscilSmp->newrandseed(rand()); + NoteVoicePar[nvoice].OscilSmp=NULL; + NoteVoicePar[nvoice].FMSmp=NULL; + NoteVoicePar[nvoice].VoiceOut=NULL; + + NoteVoicePar[nvoice].FMVoice=-1; + + if (pars->VoicePar[nvoice].Enabled==0) { + NoteVoicePar[nvoice].Enabled=OFF; + continue; //the voice is disabled + }; + + NoteVoicePar[nvoice].Enabled=ON; + NoteVoicePar[nvoice].fixedfreq=pars->VoicePar[nvoice].Pfixedfreq; + NoteVoicePar[nvoice].fixedfreqET=pars->VoicePar[nvoice].PfixedfreqET; + + //use the Globalpars.detunetype if the detunetype is 0 + if (pars->VoicePar[nvoice].PDetuneType!=0) { + NoteVoicePar[nvoice].Detune=getdetune(pars->VoicePar[nvoice].PDetuneType + ,pars->VoicePar[nvoice].PCoarseDetune,8192);//coarse detune + NoteVoicePar[nvoice].FineDetune=getdetune(pars->VoicePar[nvoice].PDetuneType + ,0,pars->VoicePar[nvoice].PDetune);//fine detune + } else { + NoteVoicePar[nvoice].Detune=getdetune(pars->GlobalPar.PDetuneType + ,pars->VoicePar[nvoice].PCoarseDetune,8192);//coarse detune + NoteVoicePar[nvoice].FineDetune=getdetune(pars->GlobalPar.PDetuneType + ,0,pars->VoicePar[nvoice].PDetune);//fine detune + }; + if (pars->VoicePar[nvoice].PFMDetuneType!=0) { + NoteVoicePar[nvoice].FMDetune=getdetune(pars->VoicePar[nvoice].PFMDetuneType + ,pars->VoicePar[nvoice].PFMCoarseDetune,pars->VoicePar[nvoice].PFMDetune); + } else { + NoteVoicePar[nvoice].FMDetune=getdetune(pars->GlobalPar.PDetuneType + ,pars->VoicePar[nvoice].PFMCoarseDetune,pars->VoicePar[nvoice].PFMDetune); + }; + + oscposhi[nvoice]=0; + oscposlo[nvoice]=0.0; + oscposhiFM[nvoice]=0; + oscposloFM[nvoice]=0.0; + + NoteVoicePar[nvoice].OscilSmp=new REALTYPE[OSCIL_SIZE+OSCIL_SMP_EXTRA_SAMPLES];//the extra points contains the first point + + //Get the voice's oscil or external's voice oscil + int vc=nvoice; + if (pars->VoicePar[nvoice].Pextoscil!=-1) vc=pars->VoicePar[nvoice].Pextoscil; + if (!pars->GlobalPar.Hrandgrouping) pars->VoicePar[vc].OscilSmp->newrandseed(rand()); + oscposhi[nvoice]=pars->VoicePar[vc].OscilSmp->get(NoteVoicePar[nvoice].OscilSmp,getvoicebasefreq(nvoice), + pars->VoicePar[nvoice].Presonance); + + //I store the first elments to the last position for speedups + for (int i=0;iVoicePar[nvoice].Poscilphase-64.0)/128.0*OSCIL_SIZE+OSCIL_SIZE*4); + oscposhi[nvoice]%=OSCIL_SIZE; + + + NoteVoicePar[nvoice].FreqLfo=NULL; + NoteVoicePar[nvoice].FreqEnvelope=NULL; + + NoteVoicePar[nvoice].AmpLfo=NULL; + NoteVoicePar[nvoice].AmpEnvelope=NULL; + + NoteVoicePar[nvoice].VoiceFilter=NULL; + NoteVoicePar[nvoice].FilterEnvelope=NULL; + NoteVoicePar[nvoice].FilterLfo=NULL; + + NoteVoicePar[nvoice].FilterCenterPitch=pars->VoicePar[nvoice].VoiceFilter->getfreq(); + NoteVoicePar[nvoice].filterbypass=pars->VoicePar[nvoice].Pfilterbypass; + + switch (pars->VoicePar[nvoice].PFMEnabled) { + case 1: + NoteVoicePar[nvoice].FMEnabled=MORPH; + break; + case 2: + NoteVoicePar[nvoice].FMEnabled=RING_MOD; + break; + case 3: + NoteVoicePar[nvoice].FMEnabled=PHASE_MOD; + break; + case 4: + NoteVoicePar[nvoice].FMEnabled=FREQ_MOD; + break; + case 5: + NoteVoicePar[nvoice].FMEnabled=PITCH_MOD; + break; + default: + NoteVoicePar[nvoice].FMEnabled=NONE; + }; + + NoteVoicePar[nvoice].FMVoice=pars->VoicePar[nvoice].PFMVoice; + NoteVoicePar[nvoice].FMFreqEnvelope=NULL; + NoteVoicePar[nvoice].FMAmpEnvelope=NULL; + + //Compute the Voice's modulator volume (incl. damping) + REALTYPE fmvoldamp=pow(440.0/getvoicebasefreq(nvoice),pars->VoicePar[nvoice].PFMVolumeDamp/64.0-1.0); + switch (NoteVoicePar[nvoice].FMEnabled) { + case PHASE_MOD: + fmvoldamp=pow(440.0/getvoicebasefreq(nvoice),pars->VoicePar[nvoice].PFMVolumeDamp/64.0); + NoteVoicePar[nvoice].FMVolume=(exp(pars->VoicePar[nvoice].PFMVolume/127.0*FM_AMP_MULTIPLIER)-1.0)*fmvoldamp*4.0; + break; + case FREQ_MOD: + NoteVoicePar[nvoice].FMVolume=(exp(pars->VoicePar[nvoice].PFMVolume/127.0*FM_AMP_MULTIPLIER)-1.0)*fmvoldamp*4.0; + break; + // case PITCH_MOD:NoteVoicePar[nvoice].FMVolume=(pars->VoicePar[nvoice].PFMVolume/127.0*8.0)*fmvoldamp;//??????????? + // break; + default: + if (fmvoldamp>1.0) fmvoldamp=1.0; + NoteVoicePar[nvoice].FMVolume=pars->VoicePar[nvoice].PFMVolume/127.0*fmvoldamp; + }; + + //Voice's modulator velocity sensing + NoteVoicePar[nvoice].FMVolume*=VelF(velocity,partparams->VoicePar[nvoice].PFMVelocityScaleFunction); + + FMoldsmp[nvoice]=0.0;//this is for FM (integration) + + firsttick[nvoice]=1; + NoteVoicePar[nvoice].DelayTicks=(int)((exp(pars->VoicePar[nvoice].PDelay/127.0*log(50.0))-1.0)/SOUND_BUFFER_SIZE/10.0*SAMPLE_RATE); + }; + + initparameters(); + ready=1; +}; + + +// ADlegatonote: This function is (mostly) a copy of ADnote(...) and +// initparameters() stuck together with some lines removed so that it +// only alter the already playing note (to perform legato). It is +// possible I left stuff that is not required for this. +void ADnote::ADlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int midinote_, bool externcall) +{ + ADnoteParameters *pars=partparams; + //Controller *ctl_=ctl; + + // Manage legato stuff + if (externcall) Legato.msg=LM_Norm; + if (Legato.msg!=LM_CatchUp) { + Legato.lastfreq=Legato.param.freq; + Legato.param.freq=freq; + Legato.param.vel=velocity; + Legato.param.portamento=portamento_; + Legato.param.midinote=midinote_; + if (Legato.msg==LM_Norm) { + if (Legato.silent) { + Legato.fade.m=0.0; + Legato.msg=LM_FadeIn; + } else { + Legato.fade.m=1.0; + Legato.msg=LM_FadeOut; + return; + } + } + if (Legato.msg==LM_ToNorm) Legato.msg=LM_Norm; + } + + portamento=portamento_; + midinote=midinote_; + basefreq=freq; + + if (velocity>1.0) velocity=1.0; + this->velocity=velocity; + + NoteGlobalPar.Detune=getdetune(pars->GlobalPar.PDetuneType + ,pars->GlobalPar.PCoarseDetune,pars->GlobalPar.PDetune); + bandwidthDetuneMultiplier=pars->getBandwidthDetuneMultiplier(); + + if (pars->GlobalPar.PPanning==0) NoteGlobalPar.Panning=RND; + else NoteGlobalPar.Panning=pars->GlobalPar.PPanning/128.0; + + + NoteGlobalPar.FilterCenterPitch=pars->GlobalPar.GlobalFilter->getfreq()+//center freq + pars->GlobalPar.PFilterVelocityScale/127.0*6.0* //velocity sensing + (VelF(velocity,pars->GlobalPar.PFilterVelocityScaleFunction)-1); + + + for (int nvoice=0;nvoiceVoicePar[nvoice].Pfixedfreq; + NoteVoicePar[nvoice].fixedfreqET=pars->VoicePar[nvoice].PfixedfreqET; + + //use the Globalpars.detunetype if the detunetype is 0 + if (pars->VoicePar[nvoice].PDetuneType!=0) { + NoteVoicePar[nvoice].Detune=getdetune(pars->VoicePar[nvoice].PDetuneType + ,pars->VoicePar[nvoice].PCoarseDetune,8192);//coarse detune + NoteVoicePar[nvoice].FineDetune=getdetune(pars->VoicePar[nvoice].PDetuneType + ,0,pars->VoicePar[nvoice].PDetune);//fine detune + } else { + NoteVoicePar[nvoice].Detune=getdetune(pars->GlobalPar.PDetuneType + ,pars->VoicePar[nvoice].PCoarseDetune,8192);//coarse detune + NoteVoicePar[nvoice].FineDetune=getdetune(pars->GlobalPar.PDetuneType + ,0,pars->VoicePar[nvoice].PDetune);//fine detune + }; + if (pars->VoicePar[nvoice].PFMDetuneType!=0) { + NoteVoicePar[nvoice].FMDetune=getdetune(pars->VoicePar[nvoice].PFMDetuneType + ,pars->VoicePar[nvoice].PFMCoarseDetune,pars->VoicePar[nvoice].PFMDetune); + } else { + NoteVoicePar[nvoice].FMDetune=getdetune(pars->GlobalPar.PDetuneType + ,pars->VoicePar[nvoice].PFMCoarseDetune,pars->VoicePar[nvoice].PFMDetune); + }; + + //Get the voice's oscil or external's voice oscil + int vc=nvoice; + if (pars->VoicePar[nvoice].Pextoscil!=-1) vc=pars->VoicePar[nvoice].Pextoscil; + if (!pars->GlobalPar.Hrandgrouping) pars->VoicePar[vc].OscilSmp->newrandseed(rand()); + + ///oscposhi[nvoice]=pars->VoicePar[vc].OscilSmp->get(NoteVoicePar[nvoice].OscilSmp,getvoicebasefreq(nvoice),pars->VoicePar[nvoice].Presonance); + pars->VoicePar[vc].OscilSmp->get(NoteVoicePar[nvoice].OscilSmp,getvoicebasefreq(nvoice),pars->VoicePar[nvoice].Presonance);//(gf)Modif of the above line. + + //I store the first elments to the last position for speedups + for (int i=0;iVoicePar[nvoice].VoiceFilter->getfreq(); + NoteVoicePar[nvoice].filterbypass=pars->VoicePar[nvoice].Pfilterbypass; + + + NoteVoicePar[nvoice].FMVoice=pars->VoicePar[nvoice].PFMVoice; + + //Compute the Voice's modulator volume (incl. damping) + REALTYPE fmvoldamp=pow(440.0/getvoicebasefreq(nvoice),pars->VoicePar[nvoice].PFMVolumeDamp/64.0-1.0); + + switch (NoteVoicePar[nvoice].FMEnabled) { + case PHASE_MOD: + fmvoldamp=pow(440.0/getvoicebasefreq(nvoice),pars->VoicePar[nvoice].PFMVolumeDamp/64.0); + NoteVoicePar[nvoice].FMVolume=(exp(pars->VoicePar[nvoice].PFMVolume/127.0*FM_AMP_MULTIPLIER)-1.0)*fmvoldamp*4.0; + break; + case FREQ_MOD: + NoteVoicePar[nvoice].FMVolume=(exp(pars->VoicePar[nvoice].PFMVolume/127.0*FM_AMP_MULTIPLIER)-1.0)*fmvoldamp*4.0; + break; + // case PITCH_MOD:NoteVoicePar[nvoice].FMVolume=(pars->VoicePar[nvoice].PFMVolume/127.0*8.0)*fmvoldamp;//??????????? + // break; + default: + if (fmvoldamp>1.0) fmvoldamp=1.0; + NoteVoicePar[nvoice].FMVolume=pars->VoicePar[nvoice].PFMVolume/127.0*fmvoldamp; + }; + + //Voice's modulator velocity sensing + NoteVoicePar[nvoice].FMVolume*=VelF(velocity,partparams->VoicePar[nvoice].PFMVelocityScaleFunction); + + NoteVoicePar[nvoice].DelayTicks=(int)((exp(pars->VoicePar[nvoice].PDelay/127.0*log(50.0))-1.0)/SOUND_BUFFER_SIZE/10.0*SAMPLE_RATE); + }; + + /// initparameters(); + + /////////////// + // Altered content of initparameters(): + + int nvoice,i,tmp[NUM_VOICES]; + + NoteGlobalPar.Volume=4.0*pow(0.1,3.0*(1.0-partparams->GlobalPar.PVolume/96.0))//-60 dB .. 0 dB + *VelF(velocity,partparams->GlobalPar.PAmpVelocityScaleFunction);//velocity sensing + + globalnewamplitude=NoteGlobalPar.Volume*NoteGlobalPar.AmpEnvelope->envout_dB()*NoteGlobalPar.AmpLfo->amplfoout(); + + NoteGlobalPar.FilterQ=partparams->GlobalPar.GlobalFilter->getq(); + NoteGlobalPar.FilterFreqTracking=partparams->GlobalPar.GlobalFilter->getfreqtracking(basefreq); + + // Forbids the Modulation Voice to be greater or equal than voice + for (i=0;i=i) NoteVoicePar[i].FMVoice=-1; + + // Voice Parameter init + for (nvoice=0;nvoiceVoicePar[nvoice].Type; + /* Voice Amplitude Parameters Init */ + NoteVoicePar[nvoice].Volume=pow(0.1,3.0*(1.0-partparams->VoicePar[nvoice].PVolume/127.0)) // -60 dB .. 0 dB + *VelF(velocity,partparams->VoicePar[nvoice].PAmpVelocityScaleFunction);//velocity + + if (partparams->VoicePar[nvoice].PVolumeminus!=0) NoteVoicePar[nvoice].Volume=-NoteVoicePar[nvoice].Volume; + + if (partparams->VoicePar[nvoice].PPanning==0) + NoteVoicePar[nvoice].Panning=RND;// random panning + else NoteVoicePar[nvoice].Panning=partparams->VoicePar[nvoice].PPanning/128.0; + + newamplitude[nvoice]=1.0; + if ((partparams->VoicePar[nvoice].PAmpEnvelopeEnabled!=0) + && (NoteVoicePar[nvoice].AmpEnvelope!=NULL)) { + newamplitude[nvoice]*=NoteVoicePar[nvoice].AmpEnvelope->envout_dB(); + }; + + if ((partparams->VoicePar[nvoice].PAmpLfoEnabled!=0) + && (NoteVoicePar[nvoice].AmpLfo!=NULL)) { + newamplitude[nvoice]*=NoteVoicePar[nvoice].AmpLfo->amplfoout(); + }; + + + NoteVoicePar[nvoice].FilterFreqTracking=partparams->VoicePar[nvoice].VoiceFilter->getfreqtracking(basefreq); + + /* Voice Modulation Parameters Init */ + if ((NoteVoicePar[nvoice].FMEnabled!=NONE)&&(NoteVoicePar[nvoice].FMVoice<0)) { + partparams->VoicePar[nvoice].FMSmp->newrandseed(rand()); + + //Perform Anti-aliasing only on MORPH or RING MODULATION + + int vc=nvoice; + if (partparams->VoicePar[nvoice].PextFMoscil!=-1) vc=partparams->VoicePar[nvoice].PextFMoscil; + + REALTYPE tmp=1.0; + if ((partparams->VoicePar[vc].FMSmp->Padaptiveharmonics!=0)|| + (NoteVoicePar[nvoice].FMEnabled==MORPH)|| + (NoteVoicePar[nvoice].FMEnabled==RING_MOD)) { + tmp=getFMvoicebasefreq(nvoice); + }; + if (!partparams->GlobalPar.Hrandgrouping) partparams->VoicePar[vc].FMSmp->newrandseed(rand()); + + ///oscposhiFM[nvoice]=(oscposhi[nvoice]+partparams->VoicePar[vc].FMSmp->get(NoteVoicePar[nvoice].FMSmp,tmp)) % OSCIL_SIZE; + // / oscposhi[nvoice]+partparams->VoicePar[vc].FMSmp->get(NoteVoicePar[nvoice].FMSmp,tmp); //(gf) Modif of the above line. + for (int i=0;iVoicePar[nvoice].PFMoscilphase-64.0)/128.0*OSCIL_SIZE+OSCIL_SIZE*4); + ///oscposhiFM[nvoice]%=OSCIL_SIZE; + }; + + FMnewamplitude[nvoice]=NoteVoicePar[nvoice].FMVolume*ctl->fmamp.relamp; + + if ((partparams->VoicePar[nvoice].PFMAmpEnvelopeEnabled!=0) + && (NoteVoicePar[nvoice].FMAmpEnvelope!=NULL)) { + FMnewamplitude[nvoice]*=NoteVoicePar[nvoice].FMAmpEnvelope->envout_dB(); + }; + }; + + for (nvoice=0;nvoiceGlobalPar.FreqEnvelope,basefreq); + NoteGlobalPar.FreqLfo=new LFO(partparams->GlobalPar.FreqLfo,basefreq); + + NoteGlobalPar.AmpEnvelope=new Envelope(partparams->GlobalPar.AmpEnvelope,basefreq); + NoteGlobalPar.AmpLfo=new LFO(partparams->GlobalPar.AmpLfo,basefreq); + + NoteGlobalPar.Volume=4.0*pow(0.1,3.0*(1.0-partparams->GlobalPar.PVolume/96.0))//-60 dB .. 0 dB + *VelF(velocity,partparams->GlobalPar.PAmpVelocityScaleFunction);//velocity sensing + + NoteGlobalPar.AmpEnvelope->envout_dB();//discard the first envelope output + globalnewamplitude=NoteGlobalPar.Volume*NoteGlobalPar.AmpEnvelope->envout_dB()*NoteGlobalPar.AmpLfo->amplfoout(); + + NoteGlobalPar.GlobalFilterL=new Filter(partparams->GlobalPar.GlobalFilter); + if (stereo!=0) NoteGlobalPar.GlobalFilterR=new Filter(partparams->GlobalPar.GlobalFilter); + + NoteGlobalPar.FilterEnvelope=new Envelope(partparams->GlobalPar.FilterEnvelope,basefreq); + NoteGlobalPar.FilterLfo=new LFO(partparams->GlobalPar.FilterLfo,basefreq); + NoteGlobalPar.FilterQ=partparams->GlobalPar.GlobalFilter->getq(); + NoteGlobalPar.FilterFreqTracking=partparams->GlobalPar.GlobalFilter->getfreqtracking(basefreq); + + // Forbids the Modulation Voice to be greater or equal than voice + for (i=0;i=i) NoteVoicePar[i].FMVoice=-1; + + // Voice Parameter init + for (nvoice=0;nvoiceVoicePar[nvoice].Type; + /* Voice Amplitude Parameters Init */ + NoteVoicePar[nvoice].Volume=pow(0.1,3.0*(1.0-partparams->VoicePar[nvoice].PVolume/127.0)) // -60 dB .. 0 dB + *VelF(velocity,partparams->VoicePar[nvoice].PAmpVelocityScaleFunction);//velocity + + if (partparams->VoicePar[nvoice].PVolumeminus!=0) NoteVoicePar[nvoice].Volume=-NoteVoicePar[nvoice].Volume; + + if (partparams->VoicePar[nvoice].PPanning==0) + NoteVoicePar[nvoice].Panning=RND;// random panning + else NoteVoicePar[nvoice].Panning=partparams->VoicePar[nvoice].PPanning/128.0; + + newamplitude[nvoice]=1.0; + if (partparams->VoicePar[nvoice].PAmpEnvelopeEnabled!=0) { + NoteVoicePar[nvoice].AmpEnvelope=new Envelope(partparams->VoicePar[nvoice].AmpEnvelope,basefreq); + NoteVoicePar[nvoice].AmpEnvelope->envout_dB();//discard the first envelope sample + newamplitude[nvoice]*=NoteVoicePar[nvoice].AmpEnvelope->envout_dB(); + }; + + if (partparams->VoicePar[nvoice].PAmpLfoEnabled!=0) { + NoteVoicePar[nvoice].AmpLfo=new LFO(partparams->VoicePar[nvoice].AmpLfo,basefreq); + newamplitude[nvoice]*=NoteVoicePar[nvoice].AmpLfo->amplfoout(); + }; + + /* Voice Frequency Parameters Init */ + if (partparams->VoicePar[nvoice].PFreqEnvelopeEnabled!=0) + NoteVoicePar[nvoice].FreqEnvelope=new Envelope(partparams->VoicePar[nvoice].FreqEnvelope,basefreq); + + if (partparams->VoicePar[nvoice].PFreqLfoEnabled!=0) NoteVoicePar[nvoice].FreqLfo=new LFO(partparams->VoicePar[nvoice].FreqLfo,basefreq); + + /* Voice Filter Parameters Init */ + if (partparams->VoicePar[nvoice].PFilterEnabled!=0) { + NoteVoicePar[nvoice].VoiceFilter=new Filter(partparams->VoicePar[nvoice].VoiceFilter); + }; + + if (partparams->VoicePar[nvoice].PFilterEnvelopeEnabled!=0) + NoteVoicePar[nvoice].FilterEnvelope=new Envelope(partparams->VoicePar[nvoice].FilterEnvelope,basefreq); + + if (partparams->VoicePar[nvoice].PFilterLfoEnabled!=0) + NoteVoicePar[nvoice].FilterLfo=new LFO(partparams->VoicePar[nvoice].FilterLfo,basefreq); + + NoteVoicePar[nvoice].FilterFreqTracking=partparams->VoicePar[nvoice].VoiceFilter->getfreqtracking(basefreq); + + /* Voice Modulation Parameters Init */ + if ((NoteVoicePar[nvoice].FMEnabled!=NONE)&&(NoteVoicePar[nvoice].FMVoice<0)) { + partparams->VoicePar[nvoice].FMSmp->newrandseed(rand()); + NoteVoicePar[nvoice].FMSmp=new REALTYPE[OSCIL_SIZE+OSCIL_SMP_EXTRA_SAMPLES]; + + //Perform Anti-aliasing only on MORPH or RING MODULATION + + int vc=nvoice; + if (partparams->VoicePar[nvoice].PextFMoscil!=-1) vc=partparams->VoicePar[nvoice].PextFMoscil; + + REALTYPE tmp=1.0; + if ((partparams->VoicePar[vc].FMSmp->Padaptiveharmonics!=0)|| + (NoteVoicePar[nvoice].FMEnabled==MORPH)|| + (NoteVoicePar[nvoice].FMEnabled==RING_MOD)) { + tmp=getFMvoicebasefreq(nvoice); + }; + if (!partparams->GlobalPar.Hrandgrouping) partparams->VoicePar[vc].FMSmp->newrandseed(rand()); + + oscposhiFM[nvoice]=(oscposhi[nvoice]+partparams->VoicePar[vc].FMSmp->get(NoteVoicePar[nvoice].FMSmp,tmp)) % OSCIL_SIZE; + for (int i=0;iVoicePar[nvoice].PFMoscilphase-64.0)/128.0*OSCIL_SIZE+OSCIL_SIZE*4); + oscposhiFM[nvoice]%=OSCIL_SIZE; + }; + + if (partparams->VoicePar[nvoice].PFMFreqEnvelopeEnabled!=0) + NoteVoicePar[nvoice].FMFreqEnvelope=new Envelope(partparams->VoicePar[nvoice].FMFreqEnvelope,basefreq); + + FMnewamplitude[nvoice]=NoteVoicePar[nvoice].FMVolume*ctl->fmamp.relamp; + + if (partparams->VoicePar[nvoice].PFMAmpEnvelopeEnabled!=0) { + NoteVoicePar[nvoice].FMAmpEnvelope=new Envelope(partparams->VoicePar[nvoice].FMAmpEnvelope,basefreq); + FMnewamplitude[nvoice]*=NoteVoicePar[nvoice].FMAmpEnvelope->envout_dB(); + }; + }; + + for (nvoice=0;nvoiceOSCIL_SIZE) speed=OSCIL_SIZE; + + F2I(speed,oscfreqhi[nvoice]); + oscfreqlo[nvoice]=speed-floor(speed); +}; + +/* + * Computes the frequency of an modullator oscillator + */ +void ADnote::setfreqFM(int nvoice,REALTYPE freq) +{ + REALTYPE speed; + freq=fabs(freq); + speed=freq*REALTYPE(OSCIL_SIZE)/(REALTYPE) SAMPLE_RATE; + if (speed>OSCIL_SIZE) speed=OSCIL_SIZE; + + F2I(speed,oscfreqhiFM[nvoice]); + oscfreqloFM[nvoice]=speed-floor(speed); +}; + +/* + * Get Voice base frequency + */ +REALTYPE ADnote::getvoicebasefreq(int nvoice) +{ + REALTYPE detune=NoteVoicePar[nvoice].Detune/100.0+ + NoteVoicePar[nvoice].FineDetune/100.0*ctl->bandwidth.relbw*bandwidthDetuneMultiplier+ + NoteGlobalPar.Detune/100.0; + + if (NoteVoicePar[nvoice].fixedfreq==0) return(this->basefreq*pow(2,detune/12.0)); + else {//the fixed freq is enabled + REALTYPE fixedfreq=440.0; + int fixedfreqET=NoteVoicePar[nvoice].fixedfreqET; + if (fixedfreqET!=0) {//if the frequency varies according the keyboard note + REALTYPE tmp=(midinote-69.0)/12.0*(pow(2.0,(fixedfreqET-1)/63.0)-1.0); + if (fixedfreqET<=64) fixedfreq*=pow(2.0,tmp); + else fixedfreq*=pow(3.0,tmp); + }; + return(fixedfreq*pow(2.0,detune/12.0)); + }; +}; + +/* + * Get Voice's Modullator base frequency + */ +REALTYPE ADnote::getFMvoicebasefreq(int nvoice) +{ + REALTYPE detune=NoteVoicePar[nvoice].FMDetune/100.0; + return(getvoicebasefreq(nvoice)*pow(2,detune/12.0)); +}; + +/* + * Computes all the parameters for each tick + */ +void ADnote::computecurrentparameters() +{ + int nvoice; + REALTYPE voicefreq,voicepitch,filterpitch,filterfreq,FMfreq,FMrelativepitch,globalpitch,globalfilterpitch; + globalpitch=0.01*(NoteGlobalPar.FreqEnvelope->envout()+ + NoteGlobalPar.FreqLfo->lfoout()*ctl->modwheel.relmod); + globaloldamplitude=globalnewamplitude; + globalnewamplitude=NoteGlobalPar.Volume*NoteGlobalPar.AmpEnvelope->envout_dB()*NoteGlobalPar.AmpLfo->amplfoout(); + + globalfilterpitch=NoteGlobalPar.FilterEnvelope->envout()+NoteGlobalPar.FilterLfo->lfoout() + +NoteGlobalPar.FilterCenterPitch; + + REALTYPE tmpfilterfreq=globalfilterpitch+ctl->filtercutoff.relfreq + +NoteGlobalPar.FilterFreqTracking; + + tmpfilterfreq=NoteGlobalPar.GlobalFilterL->getrealfreq(tmpfilterfreq); + + REALTYPE globalfilterq=NoteGlobalPar.FilterQ*ctl->filterq.relq; + NoteGlobalPar.GlobalFilterL->setfreq_and_q(tmpfilterfreq,globalfilterq); + if (stereo!=0) NoteGlobalPar.GlobalFilterR->setfreq_and_q(tmpfilterfreq,globalfilterq); + + //compute the portamento, if it is used by this note + REALTYPE portamentofreqrap=1.0; + if (portamento!=0) {//this voice use portamento + portamentofreqrap=ctl->portamento.freqrap; + if (ctl->portamento.used==0) {//the portamento has finished + portamento=0;//this note is no longer "portamented" + }; + }; + + //compute parameters for all voices + for (nvoice=0;nvoice0) continue; + + /*******************/ + /* Voice Amplitude */ + /*******************/ + oldamplitude[nvoice]=newamplitude[nvoice]; + newamplitude[nvoice]=1.0; + + if (NoteVoicePar[nvoice].AmpEnvelope!=NULL) + newamplitude[nvoice]*=NoteVoicePar[nvoice].AmpEnvelope->envout_dB(); + + if (NoteVoicePar[nvoice].AmpLfo!=NULL) + newamplitude[nvoice]*=NoteVoicePar[nvoice].AmpLfo->amplfoout(); + + /****************/ + /* Voice Filter */ + /****************/ + if (NoteVoicePar[nvoice].VoiceFilter!=NULL) { + filterpitch=NoteVoicePar[nvoice].FilterCenterPitch; + + if (NoteVoicePar[nvoice].FilterEnvelope!=NULL) + filterpitch+=NoteVoicePar[nvoice].FilterEnvelope->envout(); + + if (NoteVoicePar[nvoice].FilterLfo!=NULL) + filterpitch+=NoteVoicePar[nvoice].FilterLfo->lfoout(); + + filterfreq=filterpitch+NoteVoicePar[nvoice].FilterFreqTracking; + filterfreq=NoteVoicePar[nvoice].VoiceFilter->getrealfreq(filterfreq); + + NoteVoicePar[nvoice].VoiceFilter->setfreq(filterfreq); + }; + + if (NoteVoicePar[nvoice].noisetype==0) {//compute only if the voice isn't noise + + /*******************/ + /* Voice Frequency */ + /*******************/ + voicepitch=0.0; + if (NoteVoicePar[nvoice].FreqLfo!=NULL) + voicepitch+=NoteVoicePar[nvoice].FreqLfo->lfoout()/100.0 + *ctl->bandwidth.relbw; + + if (NoteVoicePar[nvoice].FreqEnvelope!=NULL) voicepitch+=NoteVoicePar[nvoice].FreqEnvelope->envout()/100.0; + voicefreq=getvoicebasefreq(nvoice)*pow(2,(voicepitch+globalpitch)/12.0);//Hz frequency + voicefreq*=ctl->pitchwheel.relfreq;//change the frequency by the controller + setfreq(nvoice,voicefreq*portamentofreqrap); + + /***************/ + /* Modulator */ + /***************/ + if (NoteVoicePar[nvoice].FMEnabled!=NONE) { + FMrelativepitch=NoteVoicePar[nvoice].FMDetune/100.0; + if (NoteVoicePar[nvoice].FMFreqEnvelope!=NULL) FMrelativepitch+=NoteVoicePar[nvoice].FMFreqEnvelope->envout()/100; + FMfreq=pow(2.0,FMrelativepitch/12.0)*voicefreq*portamentofreqrap; + setfreqFM(nvoice,FMfreq); + + FMoldamplitude[nvoice]=FMnewamplitude[nvoice]; + FMnewamplitude[nvoice]=NoteVoicePar[nvoice].FMVolume*ctl->fmamp.relamp; + if (NoteVoicePar[nvoice].FMAmpEnvelope!=NULL) + FMnewamplitude[nvoice]*=NoteVoicePar[nvoice].FMAmpEnvelope->envout_dB(); + }; + }; + + }; + time+=(REALTYPE)SOUND_BUFFER_SIZE/(REALTYPE)SAMPLE_RATE; +}; + + +/* + * Fadein in a way that removes clicks but keep sound "punchy" + */ +inline void ADnote::fadein(REALTYPE *smps) +{ + int zerocrossings=0; + for (int i=1;i0.0)) zerocrossings++;//this is only the possitive crossings + + REALTYPE tmp=(SOUND_BUFFER_SIZE-1.0)/(zerocrossings+1)/3.0; + if (tmp<8.0) tmp=8.0; + + int n; + F2I(tmp,n);//how many samples is the fade-in + if (n>SOUND_BUFFER_SIZE) n=SOUND_BUFFER_SIZE; + for (int i=0;i=1.0) { + poslo-=1.0; + poshi++; + }; + poshi+=oscfreqhi[nvoice]; + poshi&=OSCIL_SIZE-1; + }; + oscposhi[nvoice]=poshi; + oscposlo[nvoice]=poslo; +}; + + + +/* + * Computes the Oscillator (Without Modulation) - CubicInterpolation + * + The differences from the Linear are to little to deserve to be used. This is because I am using a large OSCIL_SIZE (>512) +inline void ADnote::ComputeVoiceOscillator_CubicInterpolation(int nvoice){ + int i,poshi; + REALTYPE poslo; + + poshi=oscposhi[nvoice]; + poslo=oscposlo[nvoice]; + REALTYPE *smps=NoteVoicePar[nvoice].OscilSmp; + REALTYPE xm1,x0,x1,x2,a,b,c; + for (i=0;i=1.0) { + poslo-=1.0; + poshi++; + }; + poshi+=oscfreqhi[nvoice]; + poshi&=OSCIL_SIZE-1; + }; + oscposhi[nvoice]=poshi; + oscposlo[nvoice]=poslo; +}; +*/ +/* + * Computes the Oscillator (Morphing) + */ +inline void ADnote::ComputeVoiceOscillatorMorph(int nvoice) +{ + int i; + REALTYPE amp; + ComputeVoiceOscillator_LinearInterpolation(nvoice); + if (FMnewamplitude[nvoice]>1.0) FMnewamplitude[nvoice]=1.0; + if (FMoldamplitude[nvoice]>1.0) FMoldamplitude[nvoice]=1.0; + + if (NoteVoicePar[nvoice].FMVoice>=0) { + //if I use VoiceOut[] as modullator + int FMVoice=NoteVoicePar[nvoice].FMVoice; + for (i=0;i=1.0) { + posloFM-=1.0; + poshiFM++; + }; + poshiFM+=oscfreqhiFM[nvoice]; + poshiFM&=OSCIL_SIZE-1; + }; + oscposhiFM[nvoice]=poshiFM; + oscposloFM[nvoice]=posloFM; + }; +}; + +/* + * Computes the Oscillator (Ring Modulation) + */ +inline void ADnote::ComputeVoiceOscillatorRingModulation(int nvoice) +{ + int i; + REALTYPE amp; + ComputeVoiceOscillator_LinearInterpolation(nvoice); + if (FMnewamplitude[nvoice]>1.0) FMnewamplitude[nvoice]=1.0; + if (FMoldamplitude[nvoice]>1.0) FMoldamplitude[nvoice]=1.0; + if (NoteVoicePar[nvoice].FMVoice>=0) { + // if I use VoiceOut[] as modullator + for (i=0;i=1.0) { + posloFM-=1.0; + poshiFM++; + }; + poshiFM+=oscfreqhiFM[nvoice]; + poshiFM&=OSCIL_SIZE-1; + }; + oscposhiFM[nvoice]=poshiFM; + oscposloFM[nvoice]=posloFM; + }; +}; + + + +/* + * Computes the Oscillator (Phase Modulation or Frequency Modulation) + */ +inline void ADnote::ComputeVoiceOscillatorFrequencyModulation(int nvoice,int FMmode) +{ + int carposhi; + int i,FMmodfreqhi; + REALTYPE FMmodfreqlo,carposlo; + + if (NoteVoicePar[nvoice].FMVoice>=0) { + //if I use VoiceOut[] as modulator + for (i=0;i=1.0) { + posloFM=fmod(posloFM,1.0); + poshiFM++; + }; + poshiFM+=oscfreqhiFM[nvoice]; + poshiFM&=OSCIL_SIZE-1; + }; + oscposhiFM[nvoice]=poshiFM; + oscposloFM[nvoice]=posloFM; + }; + // Amplitude interpolation + if (ABOVE_AMPLITUDE_THRESHOLD(FMoldamplitude[nvoice],FMnewamplitude[nvoice])) { + for (i=0;i=1.0) { + carposhi++; + carposlo=fmod(carposlo,1.0); + }; + carposhi&=(OSCIL_SIZE-1); + + tmpwave[i]=NoteVoicePar[nvoice].OscilSmp[carposhi]*(1.0-carposlo) + +NoteVoicePar[nvoice].OscilSmp[carposhi+1]*carposlo; + + oscposlo[nvoice]+=oscfreqlo[nvoice]; + if (oscposlo[nvoice]>=1.0) { + oscposlo[nvoice]=fmod(oscposlo[nvoice],1.0); + oscposhi[nvoice]++; + }; + + oscposhi[nvoice]+=oscfreqhi[nvoice]; + oscposhi[nvoice]&=OSCIL_SIZE-1; + }; +}; + + +/*Calculeaza Oscilatorul cu PITCH MODULATION*/ +inline void ADnote::ComputeVoiceOscillatorPitchModulation(int nvoice) +{ +//TODO +}; + +/* + * Computes the Noise + */ +inline void ADnote::ComputeVoiceNoise(int nvoice) +{ + for (int i=0;i0)) continue; + if (NoteVoicePar[nvoice].noisetype==0) {//voice mode=sound + switch (NoteVoicePar[nvoice].FMEnabled) { + case MORPH: + ComputeVoiceOscillatorMorph(nvoice); + break; + case RING_MOD: + ComputeVoiceOscillatorRingModulation(nvoice); + break; + case PHASE_MOD: + ComputeVoiceOscillatorFrequencyModulation(nvoice,0); + break; + case FREQ_MOD: + ComputeVoiceOscillatorFrequencyModulation(nvoice,1); + break; + //case PITCH_MOD:ComputeVoiceOscillatorPitchModulation(nvoice);break; + default: + ComputeVoiceOscillator_LinearInterpolation(nvoice); + //if (config.cfg.Interpolation) ComputeVoiceOscillator_CubicInterpolation(nvoice); + + }; + } else ComputeVoiceNoise(nvoice); + // Voice Processing + + // Amplitude + if (ABOVE_AMPLITUDE_THRESHOLD(oldamplitude[nvoice],newamplitude[nvoice])) { + int rest=SOUND_BUFFER_SIZE; + //test if the amplitude if raising and the difference is high + if ((newamplitude[nvoice]>oldamplitude[nvoice])&&((newamplitude[nvoice]-oldamplitude[nvoice])>0.25)) { + rest=10; + if (rest>SOUND_BUFFER_SIZE) rest=SOUND_BUFFER_SIZE; + for (int i=0;ifilterout(&tmpwave[0]); + + //check if the amplitude envelope is finished, if yes, the voice will be fadeout + if (NoteVoicePar[nvoice].AmpEnvelope!=NULL) { + if (NoteVoicePar[nvoice].AmpEnvelope->finished()!=0) + for (i=0;ifinished()!=0) KillVoice(nvoice); + }; + }; + + + //Processing Global parameters + NoteGlobalPar.GlobalFilterL->filterout(&outl[0]); + + if (stereo==0) { + for (i=0;ifilterout(&outr[0]); + + for (i=0;ifinished()!=0) { + for (i=0;irelasekey(); + if (NoteVoicePar[nvoice].FreqEnvelope!=NULL) NoteVoicePar[nvoice].FreqEnvelope->relasekey(); + if (NoteVoicePar[nvoice].FilterEnvelope!=NULL) NoteVoicePar[nvoice].FilterEnvelope->relasekey(); + if (NoteVoicePar[nvoice].FMFreqEnvelope!=NULL) NoteVoicePar[nvoice].FMFreqEnvelope->relasekey(); + if (NoteVoicePar[nvoice].FMAmpEnvelope!=NULL) NoteVoicePar[nvoice].FMAmpEnvelope->relasekey(); + }; + NoteGlobalPar.FreqEnvelope->relasekey(); + NoteGlobalPar.FilterEnvelope->relasekey(); + NoteGlobalPar.AmpEnvelope->relasekey(); + +}; + +/* + * Check if the note is finished + */ +int ADnote::finished() +{ + if (NoteEnabled==ON) return(0); + else return(1); +}; + + + diff --git a/plugins/zynaddsubfx/src/Synth/ADnote.cxx b/plugins/zynaddsubfx/src/Synth/ADnote.cxx new file mode 100644 index 000000000..66c7f4d66 --- /dev/null +++ b/plugins/zynaddsubfx/src/Synth/ADnote.cxx @@ -0,0 +1,136 @@ +#include +#include +#include +#include "../Misc/Master.h" +#include "../Misc/Util.h" +#include "../Synth/ADnote.h" +#include "../Params/Presets.h" +#include "../globals.h" + +class AdNoteTest : public CxxTest::TestSuite +{ +public: + + ADnote *note; + Master *master; + Controller *controller; + unsigned char testnote; + + + float *outR,*outL; + + void setUp() { + + //First the sensible settings and variables that have to be set: + SOUND_BUFFER_SIZE = 256; + + outL=new float[SOUND_BUFFER_SIZE]; + for (int i=0;iloadXMLfile("src/Tests/guitar-adnote.xmz"); + TS_ASSERT(wrap->enterbranch("MASTER")); + TS_ASSERT(wrap->enterbranch("PART", 0)); + TS_ASSERT(wrap->enterbranch("INSTRUMENT")); + TS_ASSERT(wrap->enterbranch("INSTRUMENT_KIT")); + TS_ASSERT(wrap->enterbranch("INSTRUMENT_KIT_ITEM", 0)); + TS_ASSERT(wrap->enterbranch("ADD_SYNTH_PARAMETERS")); + defaultPreset->getfromXML(wrap); + //defaultPreset->defaults(); + + + + controller = new Controller(); + + //lets go with.... 50! as a nice note + testnote = 50; + REALTYPE freq = 440.0*pow(2.0,(testnote-69.0)/12.0); + + note = new ADnote(defaultPreset, controller, freq, 120, 0, testnote, false); + + } + + void willNoteBeRunButIsHereForLinkingReasonsHowsThisForCamelCaseEh() + { + master = new Master(); + } + + void tearDown() { + delete note; + deleteFFTFREQS(&OscilGen::outoscilFFTfreqs); + } + + void testDefaults() { + + TS_ASSERT(note->ready); + int sampleCount = 0; + +//#define WRITE_OUTPUT + +#ifdef WRITE_OUTPUT + ofstream file("adnoteout", ios::out); +#endif + note->noteout(outL, outR); +#ifdef WRITE_OUTPUT + for (int i = 0; i < SOUND_BUFFER_SIZE; ++i) { + file << outL[i] << std::endl; + } +#endif + sampleCount += SOUND_BUFFER_SIZE; + + TS_ASSERT_DELTA(outL[255], 0.1724, 0.0001); + + note->relasekey(); + + + note->noteout(outL, outR); + sampleCount += SOUND_BUFFER_SIZE; + TS_ASSERT_DELTA(outL[255], -0.1284, 0.0001); + + note->noteout(outL, outR); + sampleCount += SOUND_BUFFER_SIZE; + TS_ASSERT_DELTA(outL[255], -0.0206, 0.0001); + + note->noteout(outL, outR); + sampleCount += SOUND_BUFFER_SIZE; + TS_ASSERT_DELTA(outL[255], -0.1122, 0.0001); + + note->noteout(outL, outR); + sampleCount += SOUND_BUFFER_SIZE; + TS_ASSERT_DELTA(outL[255], 0.1707, 0.0001); + + while (!note->finished()) { + note->noteout(outL, outR); +#ifdef WRITE_OUTPUT + for (int i = 0; i < SOUND_BUFFER_SIZE; ++i) { + file << outL[i] << std::endl; + } +#endif + sampleCount += SOUND_BUFFER_SIZE; + } +#ifdef WRITE_OUTPUT + file.close(); +#endif + + TS_ASSERT_EQUALS(sampleCount, 9472); + + } +}; + diff --git a/plugins/zynaddsubfx/src/Synth/ADnote.h b/plugins/zynaddsubfx/src/Synth/ADnote.h index 8215b4035..1ec25832e 100644 --- a/plugins/zynaddsubfx/src/Synth/ADnote.h +++ b/plugins/zynaddsubfx/src/Synth/ADnote.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + ADnote.h - The "additive" synthesizer Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -32,51 +32,53 @@ //Globals -//FM amplitude tune +/**FM amplitude tune*/ #define FM_AMP_MULTIPLIER 14.71280603 #define OSCIL_SMP_EXTRA_SAMPLES 5 -class ADnote{ //ADDitive note - public: - ADnote(ADnoteParameters *pars,Controller *ctl_,REALTYPE freq,REALTYPE velocity,int portamento_,int midinote_,bool besilent);//(gf)Added the besilent parameter to tell it to start silent (if true). - ~ADnote(); +/**The "additive" synthesizer*/ +class ADnote //ADDitive note +{ +public: + ADnote(ADnoteParameters *pars,Controller *ctl_,REALTYPE freq,REALTYPE velocity,int portamento_,int midinote_,bool besilent);//(gf)Added the besilent parameter to tell it to start silent (if true). + ~ADnote(); - void ADlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int midinote_, bool externcall); + void ADlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int midinote_, bool externcall); - int noteout(REALTYPE *outl,REALTYPE *outr); - void relasekey(); - int finished(); + int noteout(REALTYPE *outl,REALTYPE *outr); + void relasekey(); + int finished(); - /*ready - this is 0 if it is not ready (the parameters has to be computed) - or other value if the parameters has been computed and if it is ready to output*/ - char ready; + /*ready - this is 0 if it is not ready (the parameters has to be computed) + or other value if the parameters has been computed and if it is ready to output*/ + char ready; - private: - - void setfreq(int nvoice,REALTYPE freq); - void setfreqFM(int nvoice,REALTYPE freq); - void computecurrentparameters(); - void initparameters(); - void KillVoice(int nvoice); - void KillNote(); - inline REALTYPE getvoicebasefreq(int nvoice); - inline REALTYPE getFMvoicebasefreq(int nvoice); - inline void ComputeVoiceOscillator_LinearInterpolation(int nvoice); - inline void ComputeVoiceOscillator_CubicInterpolation(int nvoice); - inline void ComputeVoiceOscillatorMorph(int nvoice); - inline void ComputeVoiceOscillatorRingModulation(int nvoice); - inline void ComputeVoiceOscillatorFrequencyModulation(int nvoice,int FMmode);//FMmode=0 for phase modulation, 1 for Frequency modulation -// inline void ComputeVoiceOscillatorFrequencyModulation(int nvoice); - inline void ComputeVoiceOscillatorPitchModulation(int nvoice); +private: - inline void ComputeVoiceNoise(int nvoice); + void setfreq(int nvoice,REALTYPE freq); + void setfreqFM(int nvoice,REALTYPE freq); + void computecurrentparameters(); + void initparameters(); + void KillVoice(int nvoice); + void KillNote(); + inline REALTYPE getvoicebasefreq(int nvoice); + inline REALTYPE getFMvoicebasefreq(int nvoice); + inline void ComputeVoiceOscillator_LinearInterpolation(int nvoice); + inline void ComputeVoiceOscillator_CubicInterpolation(int nvoice); + inline void ComputeVoiceOscillatorMorph(int nvoice); + inline void ComputeVoiceOscillatorRingModulation(int nvoice); + inline void ComputeVoiceOscillatorFrequencyModulation(int nvoice,int FMmode);//FMmode=0 for phase modulation, 1 for Frequency modulation + // inline void ComputeVoiceOscillatorFrequencyModulation(int nvoice); + inline void ComputeVoiceOscillatorPitchModulation(int nvoice); - inline void fadein(REALTYPE *smps); + inline void ComputeVoiceNoise(int nvoice); + + inline void fadein(REALTYPE *smps); - //GLOBALS + //GLOBALS ADnoteParameters *partparams; unsigned char stereo;//if the note is stereo (allows note Panning) int midinote; @@ -85,188 +87,188 @@ class ADnote{ //ADDitive note ONOFFTYPE NoteEnabled; Controller *ctl; - /*****************************************************************/ - /* GLOBAL PARAMETERS */ - /*****************************************************************/ + /*****************************************************************/ + /* GLOBAL PARAMETERS */ + /*****************************************************************/ - struct ADnoteGlobal{ - /****************************************** - * FREQUENCY GLOBAL PARAMETERS * - ******************************************/ - REALTYPE Detune;//cents + struct ADnoteGlobal { + /****************************************** + * FREQUENCY GLOBAL PARAMETERS * + ******************************************/ + REALTYPE Detune;//cents - Envelope *FreqEnvelope; - LFO *FreqLfo; + Envelope *FreqEnvelope; + LFO *FreqLfo; - /******************************************** - * AMPLITUDE GLOBAL PARAMETERS * - ********************************************/ - REALTYPE Volume;// [ 0 .. 1 ] + /******************************************** + * AMPLITUDE GLOBAL PARAMETERS * + ********************************************/ + REALTYPE Volume;// [ 0 .. 1 ] - REALTYPE Panning;// [ 0 .. 1 ] + REALTYPE Panning;// [ 0 .. 1 ] - Envelope *AmpEnvelope; - LFO *AmpLfo; - - struct { - int Enabled; - REALTYPE initialvalue,dt,t; - } Punch; + Envelope *AmpEnvelope; + LFO *AmpLfo; - /****************************************** - * FILTER GLOBAL PARAMETERS * - ******************************************/ - Filter *GlobalFilterL,*GlobalFilterR; + struct { + int Enabled; + REALTYPE initialvalue,dt,t; + } Punch; - REALTYPE FilterCenterPitch;//octaves - REALTYPE FilterQ; - REALTYPE FilterFreqTracking; - - Envelope *FilterEnvelope; - - LFO *FilterLfo; - } NoteGlobalPar; + /****************************************** + * FILTER GLOBAL PARAMETERS * + ******************************************/ + Filter *GlobalFilterL,*GlobalFilterR; + + REALTYPE FilterCenterPitch;//octaves + REALTYPE FilterQ; + REALTYPE FilterFreqTracking; + + Envelope *FilterEnvelope; + + LFO *FilterLfo; + } NoteGlobalPar; - - /***********************************************************/ - /* VOICE PARAMETERS */ - /***********************************************************/ - struct ADnoteVoice{ + + /***********************************************************/ + /* VOICE PARAMETERS */ + /***********************************************************/ + struct ADnoteVoice { /* If the voice is enabled */ - ONOFFTYPE Enabled; + ONOFFTYPE Enabled; - /* Voice Type (sound/noise)*/ - int noisetype; + /* Voice Type (sound/noise)*/ + int noisetype; - /* Filter Bypass */ - int filterbypass; - - /* Delay (ticks) */ - int DelayTicks; - - /* Waveform of the Voice */ - REALTYPE *OscilSmp; + /* Filter Bypass */ + int filterbypass; + + /* Delay (ticks) */ + int DelayTicks; + + /* Waveform of the Voice */ + REALTYPE *OscilSmp; /************************************ - * FREQUENCY PARAMETERS * - ************************************/ - int fixedfreq;//if the frequency is fixed to 440 Hz - int fixedfreqET;//if the "fixed" frequency varies according to the note (ET) + * FREQUENCY PARAMETERS * + ************************************/ + int fixedfreq;//if the frequency is fixed to 440 Hz + int fixedfreqET;//if the "fixed" frequency varies according to the note (ET) - // cents = basefreq*VoiceDetune - REALTYPE Detune,FineDetune; - - Envelope *FreqEnvelope; - LFO *FreqLfo; - + // cents = basefreq*VoiceDetune + REALTYPE Detune,FineDetune; - /*************************** - * AMPLITUDE PARAMETERS * - ***************************/ - - /* Panning 0.0=left, 0.5 - center, 1.0 = right */ - REALTYPE Panning; - REALTYPE Volume;// [-1.0 .. 1.0] - - Envelope *AmpEnvelope; - LFO *AmpLfo; - - /************************* - * FILTER PARAMETERS * - *************************/ - - Filter *VoiceFilter; - - REALTYPE FilterCenterPitch;/* Filter center Pitch*/ - REALTYPE FilterFreqTracking; - - Envelope *FilterEnvelope; - LFO *FilterLfo; + Envelope *FreqEnvelope; + LFO *FreqLfo; - /**************************** - * MODULLATOR PARAMETERS * - ****************************/ + /*************************** + * AMPLITUDE PARAMETERS * + ***************************/ - FMTYPE FMEnabled; + /* Panning 0.0=left, 0.5 - center, 1.0 = right */ + REALTYPE Panning; + REALTYPE Volume;// [-1.0 .. 1.0] - int FMVoice; + Envelope *AmpEnvelope; + LFO *AmpLfo; - // Voice Output used by other voices if use this as modullator - REALTYPE *VoiceOut; + /************************* + * FILTER PARAMETERS * + *************************/ - /* Wave of the Voice */ - REALTYPE *FMSmp; + Filter *VoiceFilter; - REALTYPE FMVolume; - REALTYPE FMDetune; //in cents - - Envelope *FMFreqEnvelope; - Envelope *FMAmpEnvelope; - } NoteVoicePar[NUM_VOICES]; + REALTYPE FilterCenterPitch;/* Filter center Pitch*/ + REALTYPE FilterFreqTracking; + + Envelope *FilterEnvelope; + LFO *FilterLfo; - /********************************************************/ - /* INTERNAL VALUES OF THE NOTE AND OF THE VOICES */ - /********************************************************/ + /**************************** + * MODULLATOR PARAMETERS * + ****************************/ + + FMTYPE FMEnabled; + + int FMVoice; + + // Voice Output used by other voices if use this as modullator + REALTYPE *VoiceOut; + + /* Wave of the Voice */ + REALTYPE *FMSmp; + + REALTYPE FMVolume; + REALTYPE FMDetune; //in cents + + Envelope *FMFreqEnvelope; + Envelope *FMAmpEnvelope; + } NoteVoicePar[NUM_VOICES]; + + + /********************************************************/ + /* INTERNAL VALUES OF THE NOTE AND OF THE VOICES */ + /********************************************************/ //time from the start of the note REALTYPE time; //fractional part (skip) - REALTYPE oscposlo[NUM_VOICES],oscfreqlo[NUM_VOICES]; + REALTYPE oscposlo[NUM_VOICES],oscfreqlo[NUM_VOICES]; //integer part (skip) int oscposhi[NUM_VOICES],oscfreqhi[NUM_VOICES]; //fractional part (skip) of the Modullator - REALTYPE oscposloFM[NUM_VOICES],oscfreqloFM[NUM_VOICES]; + REALTYPE oscposloFM[NUM_VOICES],oscfreqloFM[NUM_VOICES]; //integer part (skip) of the Modullator unsigned short int oscposhiFM[NUM_VOICES],oscfreqhiFM[NUM_VOICES]; //used to compute and interpolate the amplitudes of voices and modullators REALTYPE oldamplitude[NUM_VOICES], - newamplitude[NUM_VOICES], - FMoldamplitude[NUM_VOICES], - FMnewamplitude[NUM_VOICES]; + newamplitude[NUM_VOICES], + FMoldamplitude[NUM_VOICES], + FMnewamplitude[NUM_VOICES]; //used by Frequency Modulation (for integration) REALTYPE FMoldsmp[NUM_VOICES]; - + //temporary buffer REALTYPE *tmpwave; - + //Filter bypass samples REALTYPE *bypassl,*bypassr; - //interpolate the amplitudes + //interpolate the amplitudes REALTYPE globaloldamplitude,globalnewamplitude; - + //1 - if it is the fitst tick (used to fade in the sound) char firsttick[NUM_VOICES]; - - //1 if the note has portamento + + //1 if the note has portamento int portamento; - + //how the fine detunes are made bigger or smaller REALTYPE bandwidthDetuneMultiplier; // Legato vars struct { - bool silent; - REALTYPE lastfreq; - LegatoMsg msg; - int decounter; - struct { // Fade In/Out vars - int length; - REALTYPE m, step; - } fade; - struct { // Note parameters - REALTYPE freq, vel; - int portamento, midinote; - } param; + bool silent; + REALTYPE lastfreq; + LegatoMsg msg; + int decounter; + struct { // Fade In/Out vars + int length; + REALTYPE m, step; + } fade; + struct { // Note parameters + REALTYPE freq, vel; + int portamento, midinote; + } param; } Legato; }; diff --git a/plugins/zynaddsubfx/src/Synth/CMakeLists.txt b/plugins/zynaddsubfx/src/Synth/CMakeLists.txt new file mode 100644 index 000000000..19fa17aad --- /dev/null +++ b/plugins/zynaddsubfx/src/Synth/CMakeLists.txt @@ -0,0 +1,18 @@ +set(zynaddsubfx_synth_SRCS + ADnote.cpp + Envelope.cpp + LFO.cpp + OscilGen.cpp + PADnote.cpp + Resonance.cpp + SUBnote.cpp +) + +add_library(zynaddsubfx_synth STATIC + ${zynaddsubfx_synth_SRCS} + ) + +target_link_libraries(zynaddsubfx_synth) + +unit_test(adnote_test ADnote.cxx "") + diff --git a/plugins/zynaddsubfx/src/Synth/Envelope.C b/plugins/zynaddsubfx/src/Synth/Envelope.cpp similarity index 56% rename from plugins/zynaddsubfx/src/Synth/Envelope.C rename to plugins/zynaddsubfx/src/Synth/Envelope.cpp index 6337ab421..83450e31a 100644 --- a/plugins/zynaddsubfx/src/Synth/Envelope.C +++ b/plugins/zynaddsubfx/src/Synth/Envelope.cpp @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Envelope.C - Envelope implementation Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -23,7 +23,8 @@ #include #include "Envelope.h" -Envelope::Envelope(EnvelopeParams *envpars,REALTYPE basefreq){ +Envelope::Envelope(EnvelopeParams *envpars,REALTYPE basefreq) +{ int i; envpoints=envpars->Penvpoints; if (envpoints>MAX_ENVELOPE_POINTS) envpoints=MAX_ENVELOPE_POINTS; @@ -33,7 +34,7 @@ Envelope::Envelope(EnvelopeParams *envpars,REALTYPE basefreq){ linearenvelope=envpars->Plinearenvelope; if (envpars->Pfreemode==0) envpars->converttofree(); - + REALTYPE bufferdt=SOUND_BUFFER_SIZE/(REALTYPE)SAMPLE_RATE; int mode=envpars->Envmode; @@ -44,22 +45,27 @@ Envelope::Envelope(EnvelopeParams *envpars,REALTYPE basefreq){ for (i=0;igetdt(i)/1000.0*envstretch; - if (tmp>bufferdt) envdt[i]=bufferdt/tmp; - else envdt[i]=2.0;//any value larger than 1 + if (tmp>bufferdt) envdt[i]=bufferdt/tmp; + else envdt[i]=2.0;//any value larger than 1 + + switch (mode) { + case 2: + envval[i]=(1.0-envpars->Penvval[i]/127.0)*MIN_ENVELOPE_DB; + break; + case 3: + envval[i]=(pow(2,6.0*fabs(envpars->Penvval[i]-64.0)/64.0)-1.0)*100.0; + if (envpars->Penvval[i]<64) envval[i]=-envval[i]; + break; + case 4: + envval[i]=(envpars->Penvval[i]-64.0)/64.0*6.0;//6 octaves (filtru) + break; + case 5: + envval[i]=(envpars->Penvval[i]-64.0)/64.0*10; + break; + default: + envval[i]=envpars->Penvval[i]/127.0; + }; - switch (mode){ - case 2:envval[i]=(1.0-envpars->Penvval[i]/127.0)*MIN_ENVELOPE_DB; - break; - case 3:envval[i]=(pow(2,6.0*fabs(envpars->Penvval[i]-64.0)/64.0)-1.0)*100.0; - if (envpars->Penvval[i]<64) envval[i]=-envval[i]; - break; - case 4:envval[i]=(envpars->Penvval[i]-64.0)/64.0*6.0;//6 octaves (filtru) - break; - case 5:envval[i]=(envpars->Penvval[i]-64.0)/64.0*10; - break; - default:envval[i]=envpars->Penvval[i]/127.0; - }; - }; envdt[0]=1.0; @@ -72,14 +78,16 @@ Envelope::Envelope(EnvelopeParams *envpars,REALTYPE basefreq){ envoutval=0.0; }; -Envelope::~Envelope(){ +Envelope::~Envelope() +{ }; /* * Relase the key (note envelope) */ -void Envelope::relasekey(){ +void Envelope::relasekey() +{ if (keyreleased==1) return; keyreleased=1; if (forcedrelase!=0) t=0.0; @@ -88,78 +96,81 @@ void Envelope::relasekey(){ /* * Envelope Output */ -REALTYPE Envelope::envout(){ +REALTYPE Envelope::envout() +{ REALTYPE out; if (envfinish!=0) {//if the envelope is finished - envoutval=envval[envpoints-1]; - return(envoutval); + envoutval=envval[envpoints-1]; + return(envoutval); }; if ((currentpoint==envsustain+1)&&(keyreleased==0)) {//if it is sustaining now - envoutval=envval[envsustain]; - return(envoutval); + envoutval=envval[envsustain]; + return(envoutval); }; - if ((keyreleased!=0) && (forcedrelase!=0)){//do the forced release - + if ((keyreleased!=0) && (forcedrelase!=0)) {//do the forced release + int tmp=(envsustain<0) ? (envpoints-1):(envsustain+1);//if there is no sustain point, use the last point for release - if (envdt[tmp]<0.00000001) out=envval[tmp]; - else out=envoutval+(envval[tmp]-envoutval)*t; - t+=envdt[tmp]*envstretch; + if (envdt[tmp]<0.00000001) out=envval[tmp]; + else out=envoutval+(envval[tmp]-envoutval)*t; + t+=envdt[tmp]*envstretch; - if (t>=1.0) { - currentpoint=envsustain+2; - forcedrelase=0; - t=0.0; - inct=envdt[currentpoint]; - if ((currentpoint>=envpoints)||(envsustain<0)) envfinish=1; - }; - return(out); + if (t>=1.0) { + currentpoint=envsustain+2; + forcedrelase=0; + t=0.0; + inct=envdt[currentpoint]; + if ((currentpoint>=envpoints)||(envsustain<0)) envfinish=1; + }; + return(out); }; if (inct>=1.0) out=envval[currentpoint]; - else out=envval[currentpoint-1]+(envval[currentpoint]-envval[currentpoint-1])*t; + else out=envval[currentpoint-1]+(envval[currentpoint]-envval[currentpoint-1])*t; t+=inct; - if (t>=1.0){ - if (currentpoint>=envpoints-1) envfinish=1; - else currentpoint++; - t=0.0; - inct=envdt[currentpoint]; + if (t>=1.0) { + if (currentpoint>=envpoints-1) envfinish=1; + else currentpoint++; + t=0.0; + inct=envdt[currentpoint]; }; - envoutval=out; + envoutval=out; return (out); }; /* * Envelope Output (dB) */ -REALTYPE Envelope::envout_dB(){ +REALTYPE Envelope::envout_dB() +{ REALTYPE out; if (linearenvelope!=0) return (envout()); - + if ((currentpoint==1)&&((keyreleased==0)||(forcedrelase==0))) {//first point is always lineary interpolated - REALTYPE v1=dB2rap(envval[0]); - REALTYPE v2=dB2rap(envval[1]); - out=v1+(v2-v1)*t; - - t+=inct; - if (t>=1.0) { - t=0.0; - inct=envdt[2]; - currentpoint++; - out=v2; - }; - - if (out>0.001) envoutval=rap2dB(out); - else envoutval=-40.0; + REALTYPE v1=dB2rap(envval[0]); + REALTYPE v2=dB2rap(envval[1]); + out=v1+(v2-v1)*t; + + t+=inct; + if (t>=1.0) { + t=0.0; + inct=envdt[2]; + currentpoint++; + out=v2; + }; + + if (out>0.001) envoutval=rap2dB(out); + else envoutval=-40.0; } else out=dB2rap(envout()); return(out); }; -int Envelope::finished(){ +int Envelope::finished() +{ return(envfinish); }; diff --git a/plugins/zynaddsubfx/src/Synth/Envelope.h b/plugins/zynaddsubfx/src/Synth/Envelope.h index 4c2598ff4..60a17ed49 100644 --- a/plugins/zynaddsubfx/src/Synth/Envelope.h +++ b/plugins/zynaddsubfx/src/Synth/Envelope.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Envelope.h - Envelope implementation Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -27,32 +27,40 @@ #include "../globals.h" #include "../Params/EnvelopeParams.h" -class Envelope{ +/**Implementation of a general Envelope*/ +class Envelope +{ public: + + /**Constructor*/ Envelope(EnvelopeParams *envpars,REALTYPE basefreq); + /**Destructor*/ ~Envelope(); void relasekey(); REALTYPE envout(); REALTYPE envout_dB(); - int finished();//returns 1 if the envelope is finished + /**Determines the status of the Envelope + * + *\todo see if this can be changed to use a boolean + * @return returns 1 if the envelope is finished*/ + int finished(); private: int envpoints; int envsustain;//"-1" means disabled REALTYPE envdt[MAX_ENVELOPE_POINTS];//millisecons REALTYPE envval[MAX_ENVELOPE_POINTS];// [0.0 .. 1.0] - REALTYPE envstretch; + REALTYPE envstretch; int linearenvelope; int currentpoint; //current envelope point (starts from 1) int forcedrelase; - char keyreleased; //if the key was released - char envfinish; + char keyreleased; //if the key was released /** \todo figure out WHY IS THIS A CHAR*/ + char envfinish; /** \todo figure out WHY IS THIS A CHAR*/ REALTYPE t; // the time from the last point - REALTYPE inct;// the time increment + REALTYPE inct;// the time increment REALTYPE envoutval;//used to do the forced release }; #endif - diff --git a/plugins/zynaddsubfx/src/Synth/LFO.C b/plugins/zynaddsubfx/src/Synth/LFO.cpp similarity index 51% rename from plugins/zynaddsubfx/src/Synth/LFO.C rename to plugins/zynaddsubfx/src/Synth/LFO.cpp index 420158eac..3c1d9962a 100644 --- a/plugins/zynaddsubfx/src/Synth/LFO.C +++ b/plugins/zynaddsubfx/src/Synth/LFO.cpp @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + LFO.C - LFO implementation Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -27,37 +27,44 @@ #include "LFO.h" -LFO::LFO(LFOParams *lfopars,REALTYPE basefreq){ +LFO::LFO(LFOParams *lfopars,REALTYPE basefreq) +{ if (lfopars->Pstretch==0) lfopars->Pstretch=1; REALTYPE lfostretch=pow(basefreq/440.0,(lfopars->Pstretch-64.0)/63.0);//max 2x/octave REALTYPE lfofreq=(pow(2,lfopars->Pfreq*10.0)-1.0)/12.0*lfostretch; incx=fabs(lfofreq)*(REALTYPE)SOUND_BUFFER_SIZE/(REALTYPE)SAMPLE_RATE; - if (lfopars->Pcontinous==0){ - if (lfopars->Pstartphase==0) x=RND; - else x=fmod((lfopars->Pstartphase-64.0)/127.0+1.0,1.0); + if (lfopars->Pcontinous==0) { + if (lfopars->Pstartphase==0) x=RND; + else x=fmod((lfopars->Pstartphase-64.0)/127.0+1.0,1.0); } else { - REALTYPE tmp=fmod(lfopars->time*incx,1.0); - x=fmod((lfopars->Pstartphase-64.0)/127.0+1.0+tmp,1.0); + REALTYPE tmp=fmod(lfopars->time*incx,1.0); + x=fmod((lfopars->Pstartphase-64.0)/127.0+1.0+tmp,1.0); }; //Limit the Frequency(or else...) if (incx>0.49999999) incx=0.499999999; - + lfornd=lfopars->Prandomness/127.0; - if (lfornd<0.0) lfornd=0.0; else if (lfornd>1.0) lfornd=1.0; + if (lfornd<0.0) lfornd=0.0; + else if (lfornd>1.0) lfornd=1.0; // lfofreqrnd=pow(lfopars->Pfreqrand/127.0,2.0)*2.0*4.0; lfofreqrnd=pow(lfopars->Pfreqrand/127.0,2.0)*4.0; - switch (lfopars->fel){ - case 1:lfointensity=lfopars->Pintensity/127.0;break; - case 2:lfointensity=lfopars->Pintensity/127.0*4.0;break;//in octave - default:lfointensity=pow(2,lfopars->Pintensity/127.0*11.0)-1.0;//in centi - x-=0.25;//chance the starting phase - break; + switch (lfopars->fel) { + case 1: + lfointensity=lfopars->Pintensity/127.0; + break; + case 2: + lfointensity=lfopars->Pintensity/127.0*4.0; + break;//in octave + default: + lfointensity=pow(2,lfopars->Pintensity/127.0*11.0)-1.0;//in centi + x-=0.25;//chance the starting phase + break; }; amp1=(1-lfornd)+lfornd*RND; @@ -70,57 +77,60 @@ LFO::LFO(LFOParams *lfopars,REALTYPE basefreq){ computenextincrnd();//twice because I want incrnd & nextincrnd to be random }; -LFO::~LFO(){ +LFO::~LFO() +{ }; /* * LFO out */ -REALTYPE LFO::lfoout(){ - REALTYPE out; - switch (lfotype){ - case 1: //LFO_TRIANGLE - if ((x>=0.0)&&(x<0.25)) out=4.0*x; - else if ((x>0.25)&&(x<0.75)) out=2-4*x; - else out=4.0*x-4.0; - break; - case 2: //LFO_SQUARE - if (x<0.5) out=-1; - else out=1; - break; - case 3: //LFO_RAMPUP - out=(x-0.5)*2.0; - break; - case 4: //LFO_RAMPDOWN - out=(0.5-x)*2.0; - break; - case 5: //LFO_EXP_DOWN 1 - out=pow(0.05,x)*2.0-1.0; - break; - case 6: //LFO_EXP_DOWN 2 - out=pow(0.001,x)*2.0-1.0; - break; - default:out=cos(x*2.0*PI);//LFO_SINE +REALTYPE LFO::lfoout() +{ + REALTYPE out; + switch (lfotype) { + case 1: //LFO_TRIANGLE + if ((x>=0.0)&&(x<0.25)) out=4.0*x; + else if ((x>0.25)&&(x<0.75)) out=2-4*x; + else out=4.0*x-4.0; + break; + case 2: //LFO_SQUARE + if (x<0.5) out=-1; + else out=1; + break; + case 3: //LFO_RAMPUP + out=(x-0.5)*2.0; + break; + case 4: //LFO_RAMPDOWN + out=(0.5-x)*2.0; + break; + case 5: //LFO_EXP_DOWN 1 + out=pow(0.05,x)*2.0-1.0; + break; + case 6: //LFO_EXP_DOWN 2 + out=pow(0.001,x)*2.0-1.0; + break; + default: + out=cos(x*2.0*PI);//LFO_SINE }; if ((lfotype==0)||(lfotype==1)) out*=lfointensity*(amp1+x*(amp2-amp1)); - else out*=lfointensity*amp2; + else out*=lfointensity*amp2; if (lfodelay<0.00001) { - if (freqrndenabled==0) x+=incx; - else { - float tmp=(incrnd*(1.0-x)+nextincrnd*x); - if (tmp>1.0) tmp=1.0; - else if (tmp<0.0) tmp=0.0; - x+=incx*tmp; - }; - if (x>=1) { - x=fmod(x,1.0); - amp1=amp2; - amp2=(1-lfornd)+lfornd*RND; + if (freqrndenabled==0) x+=incx; + else { + float tmp=(incrnd*(1.0-x)+nextincrnd*x); + if (tmp>1.0) tmp=1.0; + else if (tmp<0.0) tmp=0.0; + x+=incx*tmp; + }; + if (x>=1) { + x=fmod(x,1.0); + amp1=amp2; + amp2=(1-lfornd)+lfornd*RND; - computenextincrnd(); - }; + computenextincrnd(); + }; } else lfodelay-=(REALTYPE)SOUND_BUFFER_SIZE/(REALTYPE)SAMPLE_RATE; return(out); }; @@ -128,18 +138,20 @@ REALTYPE LFO::lfoout(){ /* * LFO out (for amplitude) */ -REALTYPE LFO::amplfoout(){ +REALTYPE LFO::amplfoout() +{ REALTYPE out; out=1.0-lfointensity+lfoout(); if (out<-1.0) out=-1.0; - else if (out>1.0) out=1.0; + else if (out>1.0) out=1.0; return(out); }; -void LFO::computenextincrnd(){ - if (freqrndenabled==0) return; - incrnd=nextincrnd; - nextincrnd=pow(0.5,lfofreqrnd)+RND*(pow(2.0,lfofreqrnd)-1.0); +void LFO::computenextincrnd() +{ + if (freqrndenabled==0) return; + incrnd=nextincrnd; + nextincrnd=pow(0.5,lfofreqrnd)+RND*(pow(2.0,lfofreqrnd)-1.0); }; diff --git a/plugins/zynaddsubfx/src/Synth/LFO.h b/plugins/zynaddsubfx/src/Synth/LFO.h index ac66e780d..12d01325d 100644 --- a/plugins/zynaddsubfx/src/Synth/LFO.h +++ b/plugins/zynaddsubfx/src/Synth/LFO.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + LFO.h - LFO implementation Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -26,27 +26,35 @@ #include "../globals.h" #include "../Params/LFOParams.h" - -class LFO{ - public: +/**Class for creating Low Frequency Ocillators*/ +class LFO +{ +public: + /**Constructor + * + * @param lfopars pointer to a LFOParams object + * @param basefreq base frequency of LFO + */ LFO(LFOParams *lfopars, REALTYPE basefreq); + /**Deconstructor*/ ~LFO(); REALTYPE lfoout(); REALTYPE amplfoout(); - private: +private: REALTYPE x; REALTYPE incx,incrnd,nextincrnd; REALTYPE amp1,amp2;// used for randomness REALTYPE lfointensity; REALTYPE lfornd,lfofreqrnd; REALTYPE lfodelay; + /**\todo see if an enum would be better here*/ char lfotype; int freqrndenabled; - - + + void computenextincrnd(); - + }; - #endif + diff --git a/plugins/zynaddsubfx/src/Synth/OscilGen.C b/plugins/zynaddsubfx/src/Synth/OscilGen.C deleted file mode 100644 index 8e18ff214..000000000 --- a/plugins/zynaddsubfx/src/Synth/OscilGen.C +++ /dev/null @@ -1,1182 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - OscilGen.C - Waveform generator for ADnote - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include -#include - -#include "OscilGen.h" -#include "../Effects/Distorsion.h" - -OscilGen::OscilGen(FFTwrapper *fft_,Resonance *res_):Presets(){ - setpresettype("Poscilgen"); - fft=fft_; - res=res_; - tmpsmps = new REALTYPE[OSCIL_SIZE]; - newFFTFREQS(&outoscilFFTfreqs, OSCIL_SIZE/2); - newFFTFREQS(&oscilFFTfreqs,OSCIL_SIZE/2); - newFFTFREQS(&basefuncFFTfreqs,OSCIL_SIZE/2); - - randseed=1; - ADvsPAD=false; - - defaults(); -}; - -OscilGen::~OscilGen(){ - delete[] tmpsmps; - deleteFFTFREQS(&outoscilFFTfreqs); - deleteFFTFREQS(&basefuncFFTfreqs); - deleteFFTFREQS(&oscilFFTfreqs); -}; - - -void OscilGen::defaults(){ - - oldbasefunc=0;oldbasepar=64;oldhmagtype=0;oldwaveshapingfunction=0;oldwaveshaping=64; - oldbasefuncmodulation=0;oldharmonicshift=0;oldbasefuncmodulationpar1=0;oldbasefuncmodulationpar2=0;oldbasefuncmodulationpar3=0; - oldmodulation=0;oldmodulationpar1=0;oldmodulationpar2=0;oldmodulationpar3=0; - - for (int i=0;ismps2freqs(oscil,freqs); - delete(fft); - - REALTYPE max=0.0; - - mag[0]=0; - phase[0]=0; - for (int i=0;i127) Phphase[i]=127; - - if (Phmag[i]==64) Phphase[i]=64; - }; - deleteFFTFREQS(&freqs); - prepare(); -}; - -/* - * Base Functions - START - */ -REALTYPE OscilGen::basefunc_pulse(REALTYPE x,REALTYPE a){ - return((fmod(x,1.0)0.99999) a=0.99999; - x=fmod(x,1); - if (x1.0) x=1.0; - return(x); -}; - -REALTYPE OscilGen::basefunc_power(REALTYPE x,REALTYPE a){ - x=fmod(x,1); - if (a<0.00001) a=0.00001; - else if (a>0.99999) a=0.99999; - return(pow(x,exp((a-0.5)*10.0))*2.0-1.0); -}; - -REALTYPE OscilGen::basefunc_gauss(REALTYPE x,REALTYPE a){ - x=fmod(x,1)*2.0-1.0; - if (a<0.00001) a=0.00001; - return(exp(-x*x*(exp(a*8)+5.0))*2.0-1.0); -}; - -REALTYPE OscilGen::basefunc_diode(REALTYPE x,REALTYPE a){ - if (a<0.00001) a=0.00001; - else if (a>0.99999) a=0.99999; - a=a*2.0-1.0; - x=cos((x+0.5)*2.0*PI)-a; - if (x<0.0) x=0.0; - return(x/(1.0-a)*2-1.0); -}; - -REALTYPE OscilGen::basefunc_abssine(REALTYPE x,REALTYPE a){ - x=fmod(x,1); - if (a<0.00001) a=0.00001; - else if (a>0.99999) a=0.99999; - return(sin(pow(x,exp((a-0.5)*5.0))*PI)*2.0-1.0); -}; - -REALTYPE OscilGen::basefunc_pulsesine(REALTYPE x,REALTYPE a){ - if (a<0.00001) a=0.00001; - x=(fmod(x,1)-0.5)*exp((a-0.5)*log(128)); - if (x<-0.5) x=-0.5; - else if (x>0.5) x=0.5; - x=sin(x*PI*2.0); - return(x); -}; - -REALTYPE OscilGen::basefunc_stretchsine(REALTYPE x,REALTYPE a){ - x=fmod(x+0.5,1)*2.0-1.0; - a=(a-0.5)*4;if (a>0.0) a*=2; - a=pow(3.0,a); - REALTYPE b=pow(fabs(x),a); - if (x<0) b=-b; - return(-sin(b*PI)); -}; - -REALTYPE OscilGen::basefunc_chirp(REALTYPE x,REALTYPE a){ - x=fmod(x,1.0)*2.0*PI; - a=(a-0.5)*4;if (a<0.0) a*=2.0; - a=pow(3.0,a); - return(sin(x/2.0)*sin(a*x*x)); -}; - -REALTYPE OscilGen::basefunc_absstretchsine(REALTYPE x,REALTYPE a){ - x=fmod(x+0.5,1)*2.0-1.0; - a=(a-0.5)*9; - a=pow(3.0,a); - REALTYPE b=pow(fabs(x),a); - if (x<0) b=-b; - return(-pow(sin(b*PI),2)); -}; - -REALTYPE OscilGen::basefunc_chebyshev(REALTYPE x,REALTYPE a){ - a=a*a*a*30.0+1.0; - return(cos(acos(x*2.0-1.0)*a)); -}; - -REALTYPE OscilGen::basefunc_sqr(REALTYPE x,REALTYPE a){ - a=a*a*a*a*160.0+0.001; - return(-atan(sin(x*2.0*PI)*a)); -}; -/* - * Base Functions - END - */ - - -/* - * Get the base function - */ -void OscilGen::getbasefunction(REALTYPE *smps){ - int i; - REALTYPE par=(Pbasefuncpar+0.5)/128.0; - if (Pbasefuncpar==64) par=0.5; - - REALTYPE basefuncmodulationpar1=Pbasefuncmodulationpar1/127.0, - basefuncmodulationpar2=Pbasefuncmodulationpar2/127.0, - basefuncmodulationpar3=Pbasefuncmodulationpar3/127.0; - - switch(Pbasefuncmodulation){ - case 1:basefuncmodulationpar1=(pow(2,basefuncmodulationpar1*5.0)-1.0)/10.0; - basefuncmodulationpar3=floor((pow(2,basefuncmodulationpar3*5.0)-1.0)); - if (basefuncmodulationpar3<0.9999) basefuncmodulationpar3=-1.0; - break; - case 2:basefuncmodulationpar1=(pow(2,basefuncmodulationpar1*5.0)-1.0)/10.0; - basefuncmodulationpar3=1.0+floor((pow(2,basefuncmodulationpar3*5.0)-1.0)); - break; - case 3:basefuncmodulationpar1=(pow(2,basefuncmodulationpar1*7.0)-1.0)/10.0; - basefuncmodulationpar3=0.01+(pow(2,basefuncmodulationpar3*16.0)-1.0)/10.0; - break; - }; - -// printf("%.5f %.5f\n",basefuncmodulationpar1,basefuncmodulationpar3); - - for (i=0;ipow(2,(1.0-par)*10)?0.0:1.0)*par2+(1.0-par2);//lp2 - break; - case 7: tmp=pow(par2,0.33); - //tmp=1.0-(1.0-par2)*(1.0-par2); - gain=(i+1>pow(2,(1.0-par)*7)?1.0:0.0)*par2+(1.0-par2);//hp2 - if (Pfilterpar1==0) gain=1.0; - break; - case 8: tmp=pow(par2,0.33); - //tmp=1.0-(1.0-par2)*(1.0-par2); - gain=(fabs(pow(2,(1.0-par)*7)-i)>i/2+1?0.0:1.0)*par2+(1.0-par2);//bp2 - break; - case 9: tmp=pow(par2,0.33); - gain=(fabs(pow(2,(1.0-par)*7)-i)1.0) x=1.0; - tmp=pow(1.0-par2,2.0); - gain=cos(x*PI)*(1.0-tmp)+1.01+tmp;//low shelf - break; - case 13:tmp=(int) (pow(2.0,(1.0-par)*7.2)); - gain=1.0; - if (i==(int) (tmp)) gain=pow(2.0,par2*par2*8.0); - break; - }; - - - oscilFFTfreqs.s[i]*=gain; - oscilFFTfreqs.c[i]*=gain; - REALTYPE tmp=oscilFFTfreqs.s[i]*oscilFFTfreqs.s[i]+ - oscilFFTfreqs.c[i]*oscilFFTfreqs.c[i]; - if (maxsmps2freqs(tmpsmps,basefuncFFTfreqs); - basefuncFFTfreqs.c[0]=0.0; - } else { - for (int i=0;ifreqs2smps(oscilFFTfreqs,tmpsmps); - - //Normalize - REALTYPE max=0.0; - for (i=0;ismps2freqs(tmpsmps,oscilFFTfreqs);//perform FFT -}; - - -/* - * Do the Frequency Modulation of the Oscil - */ -void OscilGen::modulation(){ - int i; - - oldmodulation=Pmodulation; - oldmodulationpar1=Pmodulationpar1; - oldmodulationpar2=Pmodulationpar2; - oldmodulationpar3=Pmodulationpar3; - if (Pmodulation==0) return; - - - REALTYPE modulationpar1=Pmodulationpar1/127.0, - modulationpar2=0.5-Pmodulationpar2/127.0, - modulationpar3=Pmodulationpar3/127.0; - - switch(Pmodulation){ - case 1:modulationpar1=(pow(2,modulationpar1*7.0)-1.0)/100.0; - modulationpar3=floor((pow(2,modulationpar3*5.0)-1.0)); - if (modulationpar3<0.9999) modulationpar3=-1.0; - break; - case 2:modulationpar1=(pow(2,modulationpar1*7.0)-1.0)/100.0; - modulationpar3=1.0+floor((pow(2,modulationpar3*5.0)-1.0)); - break; - case 3:modulationpar1=(pow(2,modulationpar1*9.0)-1.0)/100.0; - modulationpar3=0.01+(pow(2,modulationpar3*16.0)-1.0)/10.0; - break; - }; - - oscilFFTfreqs.c[0]=0.0;//remove the DC - //reduce the amplitude of the freqs near the nyquist - for (i=1;ifreqs2smps(oscilFFTfreqs,tmpsmps); - int extra_points=2; - REALTYPE *in=new REALTYPE[OSCIL_SIZE+extra_points]; - - //Normalize - REALTYPE max=0.0; - for (i=0;ismps2freqs(tmpsmps,oscilFFTfreqs);//perform FFT -}; - - - -/* - * Adjust the spectrum - */ -void OscilGen::spectrumadjust(){ - if (Psatype==0) return; - REALTYPE par=Psapar/127.0; - switch(Psatype){ - case 1: par=1.0-par*2.0; - if (par>=0.0) par=pow(5.0,par); - else par=pow(8.0,par); - break; - case 2: par=pow(10.0,(1.0-par)*3.0)*0.25; - break; - case 3: par=pow(10.0,(1.0-par)*3.0)*0.25; - break; - }; - - - REALTYPE max=0.0; - for (int i=0;i1.0) mag=1.0; - break; - }; - oscilFFTfreqs.c[i]=mag*cos(phase); - oscilFFTfreqs.s[i]=mag*sin(phase); - }; - -}; - -void OscilGen::shiftharmonics(){ - if (Pharmonicshift==0) return; - - REALTYPE hc,hs; - int harmonicshift=-Pharmonicshift; - - if (harmonicshift>0){ - for (int i=OSCIL_SIZE/2-2;i>=0;i--){ - int oldh=i-harmonicshift; - if (oldh<0){ - hc=0.0; - hs=0.0; - } else { - hc=oscilFFTfreqs.c[oldh+1]; - hs=oscilFFTfreqs.s[oldh+1]; - }; - oscilFFTfreqs.c[i+1]=hc; - oscilFFTfreqs.s[i+1]=hs; - }; - } else { - for (int i=0;i=(OSCIL_SIZE/2-1)){ - hc=0.0; - hs=0.0; - } else { - hc=oscilFFTfreqs.c[oldh+1]; - hs=oscilFFTfreqs.s[oldh+1]; - if (fabs(hc)<0.000001) hc=0.0; - if (fabs(hs)<0.000001) hs=0.0; - }; - - oscilFFTfreqs.c[i+1]=hc; - oscilFFTfreqs.s[i+1]=hs; - }; - }; - - oscilFFTfreqs.c[0]=0.0; -}; - -/* - * Prepare the Oscillator - */ -void OscilGen::prepare(){ - int i,j,k; - REALTYPE a,b,c,d,hmagnew; - - if ((oldbasepar!=Pbasefuncpar)||(oldbasefunc!=Pcurrentbasefunc)|| - (oldbasefuncmodulation!=Pbasefuncmodulation)|| - (oldbasefuncmodulationpar1!=Pbasefuncmodulationpar1)|| - (oldbasefuncmodulationpar2!=Pbasefuncmodulationpar2)|| - (oldbasefuncmodulationpar3!=Pbasefuncmodulationpar3)) - changebasefunction(); - - for (i=0;i=OSCIL_SIZE/2) break; - a=basefuncFFTfreqs.c[i]; - b=basefuncFFTfreqs.s[i]; - c=hmag[j]*cos(hphase[j]*k); - d=hmag[j]*sin(hphase[j]*k); - oscilFFTfreqs.c[k]+=a*c-b*d; - oscilFFTfreqs.s[k]+=a*d+b*c; - }; - }; - - }; - - if (Pharmonicshiftfirst!=0) shiftharmonics(); - - - - if (Pfilterbeforews==0){ - waveshape(); - oscilfilter(); - } else { - oscilfilter(); - waveshape(); - }; - - modulation(); - spectrumadjust(); - if (Pharmonicshiftfirst==0) shiftharmonics(); - - oscilFFTfreqs.c[0]=0.0; - - oldhmagtype=Phmagtype; - oldharmonicshift=Pharmonicshift+Pharmonicshiftfirst*256; - - oscilprepared=1; -}; - -void OscilGen::adaptiveharmonic(FFTFREQS f,REALTYPE freq){ - if ((Padaptiveharmonics==0)/*||(freq<1.0)*/) return; - if (freq<1.0) freq=440.0; - - FFTFREQS inf; - newFFTFREQS(&inf,OSCIL_SIZE/2); - for (int i=0;i1.0) { - rap=1.0/rap; - down=true; - }; - - for (int i=0;i=(OSCIL_SIZE/2-2)){ - break; - } else { - if (down){ - f.c[high]+=inf.c[i]*(1.0-low); - f.s[high]+=inf.s[i]*(1.0-low); - f.c[high+1]+=inf.c[i]*low; - f.s[high+1]+=inf.s[i]*low; - } else { - hc=inf.c[high]*(1.0-low)+inf.c[high+1]*low; - hs=inf.s[high]*(1.0-low)+inf.s[high+1]*low; - }; - if (fabs(hc)<0.000001) hc=0.0; - if (fabs(hs)<0.000001) hs=0.0; - }; - - if (!down){ - if (i==0) {//corect the aplitude of the first harmonic - hc*=rap; - hs*=rap; - }; - f.c[i]=hc; - f.s[i]=hs; - }; - }; - - f.c[1]+=f.c[0];f.s[1]+=f.s[0]; - f.c[0]=0.0;f.s[0]=0.0; - deleteFFTFREQS(&inf); -}; - -void OscilGen::adaptiveharmonicpostprocess(REALTYPE *f,int size){ - if (Padaptiveharmonics<=1) return; - REALTYPE *inf=new REALTYPE[size]; - REALTYPE par=Padaptiveharmonicspar*0.01; - par=1.0-pow((1.0-par),1.5); - - for (int i=0;iget(smps,freqHz,0)); -}; - -void OscilGen::newrandseed(unsigned int randseed){ - this->randseed=randseed; -}; - -/* - * Get the oscillator function - */ -short int OscilGen::get(REALTYPE *smps,REALTYPE freqHz,int resonance){ - int i; - int nyquist,outpos; - - if ((oldbasepar!=Pbasefuncpar)||(oldbasefunc!=Pcurrentbasefunc)||(oldhmagtype!=Phmagtype) - ||(oldwaveshaping!=Pwaveshaping)||(oldwaveshapingfunction!=Pwaveshapingfunction)) oscilprepared=0; - if (oldfilterpars!=Pfiltertype*256+Pfilterpar1+Pfilterpar2*65536+Pfilterbeforews*16777216){ - oscilprepared=0; - oldfilterpars=Pfiltertype*256+Pfilterpar1+Pfilterpar2*65536+Pfilterbeforews*16777216; - }; - if (oldsapars!=Psatype*256+Psapar){ - oscilprepared=0; - oldsapars=Psatype*256+Psapar; - }; - - if ((oldbasefuncmodulation!=Pbasefuncmodulation)|| - (oldbasefuncmodulationpar1!=Pbasefuncmodulationpar1)|| - (oldbasefuncmodulationpar2!=Pbasefuncmodulationpar2)|| - (oldbasefuncmodulationpar3!=Pbasefuncmodulationpar3)) - oscilprepared=0; - - if ((oldmodulation!=Pmodulation)|| - (oldmodulationpar1!=Pmodulationpar1)|| - (oldmodulationpar2!=Pmodulationpar2)|| - (oldmodulationpar3!=Pmodulationpar3)) - oscilprepared=0; - - if (oldharmonicshift!=Pharmonicshift+Pharmonicshiftfirst*256) oscilprepared=0; - - if (oscilprepared!=1) prepare(); - - outpos=(int)((RND*2.0-1.0)*(REALTYPE) OSCIL_SIZE*(Prand-64.0)/64.0); - outpos=(outpos+2*OSCIL_SIZE) % OSCIL_SIZE; - - - for (i=0;iOSCIL_SIZE/2) nyquist=OSCIL_SIZE/2; - - - int realnyquist=nyquist; - - if (Padaptiveharmonics!=0) nyquist=OSCIL_SIZE/2; - for (i=1;i64)&&(freqHz>=0.0)&&(!ADvsPAD)){ - REALTYPE rnd,angle,a,b,c,d; - rnd=PI*pow((Prand-64.0)/64.0,2.0); - for (i=1;i0.1)&&(!ADvsPAD)) { - unsigned int realrnd=rand(); - srand(randseed); - REALTYPE power=Pamprandpower/127.0; - REALTYPE normalize=1.0/(1.2-power); - switch (Pamprandtype){ - case 1: power=power*2.0-0.5; - power=pow(15.0,power); - for (i=1;i0.1)&&(resonance!=0)) res->applyres(nyquist-1,outoscilFFTfreqs,freqHz); - - //Full RMS normalize - REALTYPE sum=0; - for (int j=1;j0.1)){//in this case the smps will contain the freqs - for (i=1;ifreqs2smps(outoscilFFTfreqs,smps); - for (i=0;iOSCIL_SIZE/2) n=OSCIL_SIZE/2; - - for (int i=1;ifreqs2smps(basefuncFFTfreqs,smps); - } else getbasefunction(smps);//the sine case -}; - - -void OscilGen::add2XML(XMLwrapper *xml){ - xml->addpar("harmonic_mag_type",Phmagtype); - - xml->addpar("base_function",Pcurrentbasefunc); - xml->addpar("base_function_par",Pbasefuncpar); - xml->addpar("base_function_modulation",Pbasefuncmodulation); - xml->addpar("base_function_modulation_par1",Pbasefuncmodulationpar1); - xml->addpar("base_function_modulation_par2",Pbasefuncmodulationpar2); - xml->addpar("base_function_modulation_par3",Pbasefuncmodulationpar3); - - xml->addpar("modulation",Pmodulation); - xml->addpar("modulation_par1",Pmodulationpar1); - xml->addpar("modulation_par2",Pmodulationpar2); - xml->addpar("modulation_par3",Pmodulationpar3); - - xml->addpar("wave_shaping",Pwaveshaping); - xml->addpar("wave_shaping_function",Pwaveshapingfunction); - - xml->addpar("filter_type",Pfiltertype); - xml->addpar("filter_par1",Pfilterpar1); - xml->addpar("filter_par2",Pfilterpar2); - xml->addpar("filter_before_wave_shaping",Pfilterbeforews); - - xml->addpar("spectrum_adjust_type",Psatype); - xml->addpar("spectrum_adjust_par",Psapar); - - xml->addpar("rand",Prand); - xml->addpar("amp_rand_type",Pamprandtype); - xml->addpar("amp_rand_power",Pamprandpower); - - xml->addpar("harmonic_shift",Pharmonicshift); - xml->addparbool("harmonic_shift_first",Pharmonicshiftfirst); - - xml->addpar("adaptive_harmonics",Padaptiveharmonics); - xml->addpar("adaptive_harmonics_base_frequency",Padaptiveharmonicsbasefreq); - xml->addpar("adaptive_harmonics_power",Padaptiveharmonicspower); - - xml->beginbranch("HARMONICS"); - for (int n=0;nbeginbranch("HARMONIC",n+1); - xml->addpar("mag",Phmag[n]); - xml->addpar("phase",Phphase[n]); - xml->endbranch(); - }; - xml->endbranch(); - - if (Pcurrentbasefunc==127){ - REALTYPE max=0.0; - - for (int i=0;ibeginbranch("BASE_FUNCTION"); - for (int i=1;i0.00001)&&(fabs(xs)>0.00001)){ - xml->beginbranch("BF_HARMONIC",i); - xml->addparreal("cos",xc); - xml->addparreal("sin",xs); - xml->endbranch(); - }; - }; - xml->endbranch(); - }; -}; - - -void OscilGen::getfromXML(XMLwrapper *xml){ - - Phmagtype=xml->getpar127("harmonic_mag_type",Phmagtype); - - Pcurrentbasefunc=xml->getpar127("base_function",Pcurrentbasefunc); - Pbasefuncpar=xml->getpar127("base_function_par",Pbasefuncpar); - - Pbasefuncmodulation=xml->getpar127("base_function_modulation",Pbasefuncmodulation); - Pbasefuncmodulationpar1=xml->getpar127("base_function_modulation_par1",Pbasefuncmodulationpar1); - Pbasefuncmodulationpar2=xml->getpar127("base_function_modulation_par2",Pbasefuncmodulationpar2); - Pbasefuncmodulationpar3=xml->getpar127("base_function_modulation_par3",Pbasefuncmodulationpar3); - - Pmodulation=xml->getpar127("modulation",Pmodulation); - Pmodulationpar1=xml->getpar127("modulation_par1",Pmodulationpar1); - Pmodulationpar2=xml->getpar127("modulation_par2",Pmodulationpar2); - Pmodulationpar3=xml->getpar127("modulation_par3",Pmodulationpar3); - - Pwaveshaping=xml->getpar127("wave_shaping",Pwaveshaping); - Pwaveshapingfunction=xml->getpar127("wave_shaping_function",Pwaveshapingfunction); - - Pfiltertype=xml->getpar127("filter_type",Pfiltertype); - Pfilterpar1=xml->getpar127("filter_par1",Pfilterpar1); - Pfilterpar2=xml->getpar127("filter_par2",Pfilterpar2); - Pfilterbeforews=xml->getpar127("filter_before_wave_shaping",Pfilterbeforews); - - Psatype=xml->getpar127("spectrum_adjust_type",Psatype); - Psapar=xml->getpar127("spectrum_adjust_par",Psapar); - - Prand=xml->getpar127("rand",Prand); - Pamprandtype=xml->getpar127("amp_rand_type",Pamprandtype); - Pamprandpower=xml->getpar127("amp_rand_power",Pamprandpower); - - Pharmonicshift=xml->getpar("harmonic_shift",Pharmonicshift,-64,64); - Pharmonicshiftfirst=xml->getparbool("harmonic_shift_first",Pharmonicshiftfirst); - - Padaptiveharmonics=xml->getpar("adaptive_harmonics",Padaptiveharmonics,0,127); - Padaptiveharmonicsbasefreq=xml->getpar("adaptive_harmonics_base_frequency",Padaptiveharmonicsbasefreq,0,255); - Padaptiveharmonicspower=xml->getpar("adaptive_harmonics_power",Padaptiveharmonicspower,0,200); - - - if (xml->enterbranch("HARMONICS")){ - Phmag[0]=64;Phphase[0]=64; - for (int n=0;nenterbranch("HARMONIC",n+1)==0) continue; - Phmag[n]=xml->getpar127("mag",64); - Phphase[n]=xml->getpar127("phase",64); - xml->exitbranch(); - }; - xml->exitbranch(); - }; - - if (Pcurrentbasefunc!=0) changebasefunction(); - - - if (xml->enterbranch("BASE_FUNCTION")){ - for (int i=1;ienterbranch("BF_HARMONIC",i)){ - basefuncFFTfreqs.c[i]=xml->getparreal("cos",0.0); - basefuncFFTfreqs.s[i]=xml->getparreal("sin",0.0); - xml->exitbranch(); - }; - - - }; - xml->exitbranch(); - - REALTYPE max=0.0; - - basefuncFFTfreqs.c[0]=0.0; - for (int i=0;i +#include +#include + +#include "OscilGen.h" +#include "../Effects/Distorsion.h" + +OscilGen::OscilGen(FFTwrapper *fft_,Resonance *res_):Presets() +{ + setpresettype("Poscilgen"); + fft=fft_; + res=res_; + tmpsmps = new REALTYPE[OSCIL_SIZE]; + newFFTFREQS(&outoscilFFTfreqs, OSCIL_SIZE/2); + newFFTFREQS(&oscilFFTfreqs,OSCIL_SIZE/2); + newFFTFREQS(&basefuncFFTfreqs,OSCIL_SIZE/2); + + randseed=1; + ADvsPAD=false; + + defaults(); +}; + +OscilGen::~OscilGen() +{ + delete[] tmpsmps; + deleteFFTFREQS(&outoscilFFTfreqs); + deleteFFTFREQS(&basefuncFFTfreqs); + deleteFFTFREQS(&oscilFFTfreqs); +}; + + +void OscilGen::defaults() +{ + + oldbasefunc=0; + oldbasepar=64; + oldhmagtype=0; + oldwaveshapingfunction=0; + oldwaveshaping=64; + oldbasefuncmodulation=0; + oldharmonicshift=0; + oldbasefuncmodulationpar1=0; + oldbasefuncmodulationpar2=0; + oldbasefuncmodulationpar3=0; + oldmodulation=0; + oldmodulationpar1=0; + oldmodulationpar2=0; + oldmodulationpar3=0; + + for (int i=0;ismps2freqs(oscil,freqs); + delete(fft); + + REALTYPE max=0.0; + + mag[0]=0; + phase[0]=0; + for (int i=0;i127) Phphase[i]=127; + + if (Phmag[i]==64) Phphase[i]=64; + }; + deleteFFTFREQS(&freqs); + prepare(); +}; + +/* + * Base Functions - START + */ +REALTYPE OscilGen::basefunc_pulse(REALTYPE x,REALTYPE a) +{ + return((fmod(x,1.0)0.99999) a=0.99999; + x=fmod(x,1); + if (x1.0) x=1.0; + return(x); +}; + +REALTYPE OscilGen::basefunc_power(REALTYPE x,REALTYPE a) +{ + x=fmod(x,1); + if (a<0.00001) a=0.00001; + else if (a>0.99999) a=0.99999; + return(pow(x,exp((a-0.5)*10.0))*2.0-1.0); +}; + +REALTYPE OscilGen::basefunc_gauss(REALTYPE x,REALTYPE a) +{ + x=fmod(x,1)*2.0-1.0; + if (a<0.00001) a=0.00001; + return(exp(-x*x*(exp(a*8)+5.0))*2.0-1.0); +}; + +REALTYPE OscilGen::basefunc_diode(REALTYPE x,REALTYPE a) +{ + if (a<0.00001) a=0.00001; + else if (a>0.99999) a=0.99999; + a=a*2.0-1.0; + x=cos((x+0.5)*2.0*PI)-a; + if (x<0.0) x=0.0; + return(x/(1.0-a)*2-1.0); +}; + +REALTYPE OscilGen::basefunc_abssine(REALTYPE x,REALTYPE a) +{ + x=fmod(x,1); + if (a<0.00001) a=0.00001; + else if (a>0.99999) a=0.99999; + return(sin(pow(x,exp((a-0.5)*5.0))*PI)*2.0-1.0); +}; + +REALTYPE OscilGen::basefunc_pulsesine(REALTYPE x,REALTYPE a) +{ + if (a<0.00001) a=0.00001; + x=(fmod(x,1)-0.5)*exp((a-0.5)*log(128)); + if (x<-0.5) x=-0.5; + else if (x>0.5) x=0.5; + x=sin(x*PI*2.0); + return(x); +}; + +REALTYPE OscilGen::basefunc_stretchsine(REALTYPE x,REALTYPE a) +{ + x=fmod(x+0.5,1)*2.0-1.0; + a=(a-0.5)*4; + if (a>0.0) a*=2; + a=pow(3.0,a); + REALTYPE b=pow(fabs(x),a); + if (x<0) b=-b; + return(-sin(b*PI)); +}; + +REALTYPE OscilGen::basefunc_chirp(REALTYPE x,REALTYPE a) +{ + x=fmod(x,1.0)*2.0*PI; + a=(a-0.5)*4; + if (a<0.0) a*=2.0; + a=pow(3.0,a); + return(sin(x/2.0)*sin(a*x*x)); +}; + +REALTYPE OscilGen::basefunc_absstretchsine(REALTYPE x,REALTYPE a) +{ + x=fmod(x+0.5,1)*2.0-1.0; + a=(a-0.5)*9; + a=pow(3.0,a); + REALTYPE b=pow(fabs(x),a); + if (x<0) b=-b; + return(-pow(sin(b*PI),2)); +}; + +REALTYPE OscilGen::basefunc_chebyshev(REALTYPE x,REALTYPE a) +{ + a=a*a*a*30.0+1.0; + return(cos(acos(x*2.0-1.0)*a)); +}; + +REALTYPE OscilGen::basefunc_sqr(REALTYPE x,REALTYPE a) +{ + a=a*a*a*a*160.0+0.001; + return(-atan(sin(x*2.0*PI)*a)); +}; +/* + * Base Functions - END + */ + + +/* + * Get the base function + */ +void OscilGen::getbasefunction(REALTYPE *smps) +{ + int i; + REALTYPE par=(Pbasefuncpar+0.5)/128.0; + if (Pbasefuncpar==64) par=0.5; + + REALTYPE basefuncmodulationpar1=Pbasefuncmodulationpar1/127.0, + basefuncmodulationpar2=Pbasefuncmodulationpar2/127.0, + basefuncmodulationpar3=Pbasefuncmodulationpar3/127.0; + + switch (Pbasefuncmodulation) { + case 1: + basefuncmodulationpar1=(pow(2,basefuncmodulationpar1*5.0)-1.0)/10.0; + basefuncmodulationpar3=floor((pow(2,basefuncmodulationpar3*5.0)-1.0)); + if (basefuncmodulationpar3<0.9999) basefuncmodulationpar3=-1.0; + break; + case 2: + basefuncmodulationpar1=(pow(2,basefuncmodulationpar1*5.0)-1.0)/10.0; + basefuncmodulationpar3=1.0+floor((pow(2,basefuncmodulationpar3*5.0)-1.0)); + break; + case 3: + basefuncmodulationpar1=(pow(2,basefuncmodulationpar1*7.0)-1.0)/10.0; + basefuncmodulationpar3=0.01+(pow(2,basefuncmodulationpar3*16.0)-1.0)/10.0; + break; + }; + +// printf("%.5f %.5f\n",basefuncmodulationpar1,basefuncmodulationpar3); + + for (i=0;ipow(2,(1.0-par)*10)?0.0:1.0)*par2+(1.0-par2);//lp2 + break; + case 7: + tmp=pow(par2,0.33); + //tmp=1.0-(1.0-par2)*(1.0-par2); + gain=(i+1>pow(2,(1.0-par)*7)?1.0:0.0)*par2+(1.0-par2);//hp2 + if (Pfilterpar1==0) gain=1.0; + break; + case 8: + tmp=pow(par2,0.33); + //tmp=1.0-(1.0-par2)*(1.0-par2); + gain=(fabs(pow(2,(1.0-par)*7)-i)>i/2+1?0.0:1.0)*par2+(1.0-par2);//bp2 + break; + case 9: + tmp=pow(par2,0.33); + gain=(fabs(pow(2,(1.0-par)*7)-i)1.0) x=1.0; + tmp=pow(1.0-par2,2.0); + gain=cos(x*PI)*(1.0-tmp)+1.01+tmp;//low shelf + break; + case 13: + tmp=(int) (pow(2.0,(1.0-par)*7.2)); + gain=1.0; + if (i==(int) (tmp)) gain=pow(2.0,par2*par2*8.0); + break; + }; + + + oscilFFTfreqs.s[i]*=gain; + oscilFFTfreqs.c[i]*=gain; + REALTYPE tmp=oscilFFTfreqs.s[i]*oscilFFTfreqs.s[i]+ + oscilFFTfreqs.c[i]*oscilFFTfreqs.c[i]; + if (maxsmps2freqs(tmpsmps,basefuncFFTfreqs); + basefuncFFTfreqs.c[0]=0.0; + } else { + for (int i=0;ifreqs2smps(oscilFFTfreqs,tmpsmps); + + //Normalize + REALTYPE max=0.0; + for (i=0;ismps2freqs(tmpsmps,oscilFFTfreqs);//perform FFT +}; + + +/* + * Do the Frequency Modulation of the Oscil + */ +void OscilGen::modulation() +{ + int i; + + oldmodulation=Pmodulation; + oldmodulationpar1=Pmodulationpar1; + oldmodulationpar2=Pmodulationpar2; + oldmodulationpar3=Pmodulationpar3; + if (Pmodulation==0) return; + + + REALTYPE modulationpar1=Pmodulationpar1/127.0, + modulationpar2=0.5-Pmodulationpar2/127.0, + modulationpar3=Pmodulationpar3/127.0; + + switch (Pmodulation) { + case 1: + modulationpar1=(pow(2,modulationpar1*7.0)-1.0)/100.0; + modulationpar3=floor((pow(2,modulationpar3*5.0)-1.0)); + if (modulationpar3<0.9999) modulationpar3=-1.0; + break; + case 2: + modulationpar1=(pow(2,modulationpar1*7.0)-1.0)/100.0; + modulationpar3=1.0+floor((pow(2,modulationpar3*5.0)-1.0)); + break; + case 3: + modulationpar1=(pow(2,modulationpar1*9.0)-1.0)/100.0; + modulationpar3=0.01+(pow(2,modulationpar3*16.0)-1.0)/10.0; + break; + }; + + oscilFFTfreqs.c[0]=0.0;//remove the DC + //reduce the amplitude of the freqs near the nyquist + for (i=1;ifreqs2smps(oscilFFTfreqs,tmpsmps); + int extra_points=2; + REALTYPE *in=new REALTYPE[OSCIL_SIZE+extra_points]; + + //Normalize + REALTYPE max=0.0; + for (i=0;ismps2freqs(tmpsmps,oscilFFTfreqs);//perform FFT +}; + + + +/* + * Adjust the spectrum + */ +void OscilGen::spectrumadjust() +{ + if (Psatype==0) return; + REALTYPE par=Psapar/127.0; + switch (Psatype) { + case 1: + par=1.0-par*2.0; + if (par>=0.0) par=pow(5.0,par); + else par=pow(8.0,par); + break; + case 2: + par=pow(10.0,(1.0-par)*3.0)*0.25; + break; + case 3: + par=pow(10.0,(1.0-par)*3.0)*0.25; + break; + }; + + + REALTYPE max=0.0; + for (int i=0;i1.0) mag=1.0; + break; + }; + oscilFFTfreqs.c[i]=mag*cos(phase); + oscilFFTfreqs.s[i]=mag*sin(phase); + }; + +}; + +void OscilGen::shiftharmonics() +{ + if (Pharmonicshift==0) return; + + REALTYPE hc,hs; + int harmonicshift=-Pharmonicshift; + + if (harmonicshift>0) { + for (int i=OSCIL_SIZE/2-2;i>=0;i--) { + int oldh=i-harmonicshift; + if (oldh<0) { + hc=0.0; + hs=0.0; + } else { + hc=oscilFFTfreqs.c[oldh+1]; + hs=oscilFFTfreqs.s[oldh+1]; + }; + oscilFFTfreqs.c[i+1]=hc; + oscilFFTfreqs.s[i+1]=hs; + }; + } else { + for (int i=0;i=(OSCIL_SIZE/2-1)) { + hc=0.0; + hs=0.0; + } else { + hc=oscilFFTfreqs.c[oldh+1]; + hs=oscilFFTfreqs.s[oldh+1]; + if (fabs(hc)<0.000001) hc=0.0; + if (fabs(hs)<0.000001) hs=0.0; + }; + + oscilFFTfreqs.c[i+1]=hc; + oscilFFTfreqs.s[i+1]=hs; + }; + }; + + oscilFFTfreqs.c[0]=0.0; +}; + +/* + * Prepare the Oscillator + */ +void OscilGen::prepare() +{ + int i,j,k; + REALTYPE a,b,c,d,hmagnew; + + if ((oldbasepar!=Pbasefuncpar)||(oldbasefunc!=Pcurrentbasefunc)|| + (oldbasefuncmodulation!=Pbasefuncmodulation)|| + (oldbasefuncmodulationpar1!=Pbasefuncmodulationpar1)|| + (oldbasefuncmodulationpar2!=Pbasefuncmodulationpar2)|| + (oldbasefuncmodulationpar3!=Pbasefuncmodulationpar3)) + changebasefunction(); + + for (i=0;i=OSCIL_SIZE/2) break; + a=basefuncFFTfreqs.c[i]; + b=basefuncFFTfreqs.s[i]; + c=hmag[j]*cos(hphase[j]*k); + d=hmag[j]*sin(hphase[j]*k); + oscilFFTfreqs.c[k]+=a*c-b*d; + oscilFFTfreqs.s[k]+=a*d+b*c; + }; + }; + + }; + + if (Pharmonicshiftfirst!=0) shiftharmonics(); + + + + if (Pfilterbeforews==0) { + waveshape(); + oscilfilter(); + } else { + oscilfilter(); + waveshape(); + }; + + modulation(); + spectrumadjust(); + if (Pharmonicshiftfirst==0) shiftharmonics(); + + oscilFFTfreqs.c[0]=0.0; + + oldhmagtype=Phmagtype; + oldharmonicshift=Pharmonicshift+Pharmonicshiftfirst*256; + + oscilprepared=1; +}; + +void OscilGen::adaptiveharmonic(FFTFREQS f,REALTYPE freq) +{ + if ((Padaptiveharmonics==0)/*||(freq<1.0)*/) return; + if (freq<1.0) freq=440.0; + + FFTFREQS inf; + newFFTFREQS(&inf,OSCIL_SIZE/2); + for (int i=0;i1.0) { + rap=1.0/rap; + down=true; + }; + + for (int i=0;i=(OSCIL_SIZE/2-2)) { + break; + } else { + if (down) { + f.c[high]+=inf.c[i]*(1.0-low); + f.s[high]+=inf.s[i]*(1.0-low); + f.c[high+1]+=inf.c[i]*low; + f.s[high+1]+=inf.s[i]*low; + } else { + hc=inf.c[high]*(1.0-low)+inf.c[high+1]*low; + hs=inf.s[high]*(1.0-low)+inf.s[high+1]*low; + }; + if (fabs(hc)<0.000001) hc=0.0; + if (fabs(hs)<0.000001) hs=0.0; + }; + + if (!down) { + if (i==0) {//corect the aplitude of the first harmonic + hc*=rap; + hs*=rap; + }; + f.c[i]=hc; + f.s[i]=hs; + }; + }; + + f.c[1]+=f.c[0]; + f.s[1]+=f.s[0]; + f.c[0]=0.0; + f.s[0]=0.0; + deleteFFTFREQS(&inf); +}; + +void OscilGen::adaptiveharmonicpostprocess(REALTYPE *f,int size) +{ + if (Padaptiveharmonics<=1) return; + REALTYPE *inf=new REALTYPE[size]; + REALTYPE par=Padaptiveharmonicspar*0.01; + par=1.0-pow((1.0-par),1.5); + + for (int i=0;iget(smps,freqHz,0)); +}; + +void OscilGen::newrandseed(unsigned int randseed) +{ + this->randseed=randseed; +}; + +/* + * Get the oscillator function + */ +short int OscilGen::get(REALTYPE *smps,REALTYPE freqHz,int resonance) +{ + int i; + int nyquist,outpos; + + if ((oldbasepar!=Pbasefuncpar)||(oldbasefunc!=Pcurrentbasefunc)||(oldhmagtype!=Phmagtype) + ||(oldwaveshaping!=Pwaveshaping)||(oldwaveshapingfunction!=Pwaveshapingfunction)) oscilprepared=0; + if (oldfilterpars!=Pfiltertype*256+Pfilterpar1+Pfilterpar2*65536+Pfilterbeforews*16777216) { + oscilprepared=0; + oldfilterpars=Pfiltertype*256+Pfilterpar1+Pfilterpar2*65536+Pfilterbeforews*16777216; + }; + if (oldsapars!=Psatype*256+Psapar) { + oscilprepared=0; + oldsapars=Psatype*256+Psapar; + }; + + if ((oldbasefuncmodulation!=Pbasefuncmodulation)|| + (oldbasefuncmodulationpar1!=Pbasefuncmodulationpar1)|| + (oldbasefuncmodulationpar2!=Pbasefuncmodulationpar2)|| + (oldbasefuncmodulationpar3!=Pbasefuncmodulationpar3)) + oscilprepared=0; + + if ((oldmodulation!=Pmodulation)|| + (oldmodulationpar1!=Pmodulationpar1)|| + (oldmodulationpar2!=Pmodulationpar2)|| + (oldmodulationpar3!=Pmodulationpar3)) + oscilprepared=0; + + if (oldharmonicshift!=Pharmonicshift+Pharmonicshiftfirst*256) oscilprepared=0; + + if (oscilprepared!=1) prepare(); + + outpos=(int)((RND*2.0-1.0)*(REALTYPE) OSCIL_SIZE*(Prand-64.0)/64.0); + outpos=(outpos+2*OSCIL_SIZE) % OSCIL_SIZE; + + + for (i=0;iOSCIL_SIZE/2) nyquist=OSCIL_SIZE/2; + + + int realnyquist=nyquist; + + if (Padaptiveharmonics!=0) nyquist=OSCIL_SIZE/2; + for (i=1;i64)&&(freqHz>=0.0)&&(!ADvsPAD)) { + REALTYPE rnd,angle,a,b,c,d; + rnd=PI*pow((Prand-64.0)/64.0,2.0); + for (i=1;i0.1)&&(!ADvsPAD)) { + unsigned int realrnd=rand(); + srand(randseed); + REALTYPE power=Pamprandpower/127.0; + REALTYPE normalize=1.0/(1.2-power); + switch (Pamprandtype) { + case 1: + power=power*2.0-0.5; + power=pow(15.0,power); + for (i=1;i0.1)&&(resonance!=0)) res->applyres(nyquist-1,outoscilFFTfreqs,freqHz); + + //Full RMS normalize + REALTYPE sum=0; + for (int j=1;j0.1)) {//in this case the smps will contain the freqs + for (i=1;ifreqs2smps(outoscilFFTfreqs,smps); + for (i=0;iOSCIL_SIZE/2) n=OSCIL_SIZE/2; + + for (int i=1;ifreqs2smps(basefuncFFTfreqs,smps); + } else getbasefunction(smps);//the sine case +}; + + +void OscilGen::add2XML(XMLwrapper *xml) +{ + xml->addpar("harmonic_mag_type",Phmagtype); + + xml->addpar("base_function",Pcurrentbasefunc); + xml->addpar("base_function_par",Pbasefuncpar); + xml->addpar("base_function_modulation",Pbasefuncmodulation); + xml->addpar("base_function_modulation_par1",Pbasefuncmodulationpar1); + xml->addpar("base_function_modulation_par2",Pbasefuncmodulationpar2); + xml->addpar("base_function_modulation_par3",Pbasefuncmodulationpar3); + + xml->addpar("modulation",Pmodulation); + xml->addpar("modulation_par1",Pmodulationpar1); + xml->addpar("modulation_par2",Pmodulationpar2); + xml->addpar("modulation_par3",Pmodulationpar3); + + xml->addpar("wave_shaping",Pwaveshaping); + xml->addpar("wave_shaping_function",Pwaveshapingfunction); + + xml->addpar("filter_type",Pfiltertype); + xml->addpar("filter_par1",Pfilterpar1); + xml->addpar("filter_par2",Pfilterpar2); + xml->addpar("filter_before_wave_shaping",Pfilterbeforews); + + xml->addpar("spectrum_adjust_type",Psatype); + xml->addpar("spectrum_adjust_par",Psapar); + + xml->addpar("rand",Prand); + xml->addpar("amp_rand_type",Pamprandtype); + xml->addpar("amp_rand_power",Pamprandpower); + + xml->addpar("harmonic_shift",Pharmonicshift); + xml->addparbool("harmonic_shift_first",Pharmonicshiftfirst); + + xml->addpar("adaptive_harmonics",Padaptiveharmonics); + xml->addpar("adaptive_harmonics_base_frequency",Padaptiveharmonicsbasefreq); + xml->addpar("adaptive_harmonics_power",Padaptiveharmonicspower); + + xml->beginbranch("HARMONICS"); + for (int n=0;nbeginbranch("HARMONIC",n+1); + xml->addpar("mag",Phmag[n]); + xml->addpar("phase",Phphase[n]); + xml->endbranch(); + }; + xml->endbranch(); + + if (Pcurrentbasefunc==127) { + REALTYPE max=0.0; + + for (int i=0;ibeginbranch("BASE_FUNCTION"); + for (int i=1;i0.00001)&&(fabs(xs)>0.00001)) { + xml->beginbranch("BF_HARMONIC",i); + xml->addparreal("cos",xc); + xml->addparreal("sin",xs); + xml->endbranch(); + }; + }; + xml->endbranch(); + }; +}; + + +void OscilGen::getfromXML(XMLwrapper *xml) +{ + + Phmagtype=xml->getpar127("harmonic_mag_type",Phmagtype); + + Pcurrentbasefunc=xml->getpar127("base_function",Pcurrentbasefunc); + Pbasefuncpar=xml->getpar127("base_function_par",Pbasefuncpar); + + Pbasefuncmodulation=xml->getpar127("base_function_modulation",Pbasefuncmodulation); + Pbasefuncmodulationpar1=xml->getpar127("base_function_modulation_par1",Pbasefuncmodulationpar1); + Pbasefuncmodulationpar2=xml->getpar127("base_function_modulation_par2",Pbasefuncmodulationpar2); + Pbasefuncmodulationpar3=xml->getpar127("base_function_modulation_par3",Pbasefuncmodulationpar3); + + Pmodulation=xml->getpar127("modulation",Pmodulation); + Pmodulationpar1=xml->getpar127("modulation_par1",Pmodulationpar1); + Pmodulationpar2=xml->getpar127("modulation_par2",Pmodulationpar2); + Pmodulationpar3=xml->getpar127("modulation_par3",Pmodulationpar3); + + Pwaveshaping=xml->getpar127("wave_shaping",Pwaveshaping); + Pwaveshapingfunction=xml->getpar127("wave_shaping_function",Pwaveshapingfunction); + + Pfiltertype=xml->getpar127("filter_type",Pfiltertype); + Pfilterpar1=xml->getpar127("filter_par1",Pfilterpar1); + Pfilterpar2=xml->getpar127("filter_par2",Pfilterpar2); + Pfilterbeforews=xml->getpar127("filter_before_wave_shaping",Pfilterbeforews); + + Psatype=xml->getpar127("spectrum_adjust_type",Psatype); + Psapar=xml->getpar127("spectrum_adjust_par",Psapar); + + Prand=xml->getpar127("rand",Prand); + Pamprandtype=xml->getpar127("amp_rand_type",Pamprandtype); + Pamprandpower=xml->getpar127("amp_rand_power",Pamprandpower); + + Pharmonicshift=xml->getpar("harmonic_shift",Pharmonicshift,-64,64); + Pharmonicshiftfirst=xml->getparbool("harmonic_shift_first",Pharmonicshiftfirst); + + Padaptiveharmonics=xml->getpar("adaptive_harmonics",Padaptiveharmonics,0,127); + Padaptiveharmonicsbasefreq=xml->getpar("adaptive_harmonics_base_frequency",Padaptiveharmonicsbasefreq,0,255); + Padaptiveharmonicspower=xml->getpar("adaptive_harmonics_power",Padaptiveharmonicspower,0,200); + + + if (xml->enterbranch("HARMONICS")) { + Phmag[0]=64; + Phphase[0]=64; + for (int n=0;nenterbranch("HARMONIC",n+1)==0) continue; + Phmag[n]=xml->getpar127("mag",64); + Phphase[n]=xml->getpar127("phase",64); + xml->exitbranch(); + }; + xml->exitbranch(); + }; + + if (Pcurrentbasefunc!=0) changebasefunction(); + + + if (xml->enterbranch("BASE_FUNCTION")) { + for (int i=1;ienterbranch("BF_HARMONIC",i)) { + basefuncFFTfreqs.c[i]=xml->getparreal("cos",0.0); + basefuncFFTfreqs.s[i]=xml->getparreal("sin",0.0); + xml->exitbranch(); + }; + + + }; + xml->exitbranch(); + + REALTYPE max=0.0; + + basefuncFFTfreqs.c[0]=0.0; + for (int i=0;i -#include "PADnote.h" -#include "../Misc/Config.h" - -PADnote::PADnote(PADnoteParameters *parameters, Controller *ctl_,REALTYPE freq, REALTYPE velocity, int portamento_, int midinote, bool besilent){ - ready=0; - - // Initialise some legato-specific vars - Legato.msg=LM_Norm; - Legato.fade.length=(int)(SAMPLE_RATE*0.005);// 0.005 seems ok. - if (Legato.fade.length<1) Legato.fade.length=1;// (if something's fishy) - Legato.fade.step=(1.0/Legato.fade.length); - Legato.decounter=-10; - Legato.param.freq=freq; - Legato.param.vel=velocity; - Legato.param.portamento=portamento_; - Legato.param.midinote=midinote; - Legato.silent=besilent; - - pars=parameters; - portamento=portamento_; - ctl=ctl_; - this->velocity=velocity; - finished_=false; - - - if (pars->Pfixedfreq==0) basefreq=freq; - else { - basefreq=440.0; - int fixedfreqET=pars->PfixedfreqET; - if (fixedfreqET!=0) {//if the frequency varies according the keyboard note - REALTYPE tmp=(midinote-69.0)/12.0*(pow(2.0,(fixedfreqET-1)/63.0)-1.0); - if (fixedfreqET<=64) basefreq*=pow(2.0,tmp); - else basefreq*=pow(3.0,tmp); - }; - - }; - - firsttime=true; - released=false; - realfreq=basefreq; - NoteGlobalPar.Detune=getdetune(pars->PDetuneType - ,pars->PCoarseDetune,pars->PDetune); - - - //find out the closest note - REALTYPE logfreq=log(basefreq*pow(2.0,NoteGlobalPar.Detune/1200.0)); - REALTYPE mindist=fabs(logfreq-log(pars->sample[0].basefreq+0.0001)); - nsample=0; - for (int i=1;isample[i].smp==NULL) break; - REALTYPE dist=fabs(logfreq-log(pars->sample[i].basefreq+0.0001)); -// printf("(mindist=%g) %i %g %g\n",mindist,i,dist,pars->sample[i].basefreq); - - if (distsample[nsample].size; - if (size==0) size=1; - - - poshi_l=(int)(RND*(size-1)); - if (pars->PStereo!=0) poshi_r=(poshi_l+size/2)%size; - else poshi_r=poshi_l; - poslo=0.0; - - tmpwave=new REALTYPE [SOUND_BUFFER_SIZE]; - - - - if (pars->PPanning==0) NoteGlobalPar.Panning=RND; - else NoteGlobalPar.Panning=pars->PPanning/128.0; - - NoteGlobalPar.FilterCenterPitch=pars->GlobalFilter->getfreq()+//center freq - pars->PFilterVelocityScale/127.0*6.0* //velocity sensing - (VelF(velocity,pars->PFilterVelocityScaleFunction)-1); - - if (pars->PPunchStrength!=0) { - NoteGlobalPar.Punch.Enabled=1; - NoteGlobalPar.Punch.t=1.0;//start from 1.0 and to 0.0 - NoteGlobalPar.Punch.initialvalue=( (pow(10,1.5*pars->PPunchStrength/127.0)-1.0) - *VelF(velocity,pars->PPunchVelocitySensing) ); - REALTYPE time=pow(10,3.0*pars->PPunchTime/127.0)/10000.0;//0.1 .. 100 ms - REALTYPE stretch=pow(440.0/freq,pars->PPunchStretch/64.0); - NoteGlobalPar.Punch.dt=1.0/(time*SAMPLE_RATE*stretch); - } else NoteGlobalPar.Punch.Enabled=0; - - - - NoteGlobalPar.FreqEnvelope=new Envelope(pars->FreqEnvelope,basefreq); - NoteGlobalPar.FreqLfo=new LFO(pars->FreqLfo,basefreq); - - NoteGlobalPar.AmpEnvelope=new Envelope(pars->AmpEnvelope,basefreq); - NoteGlobalPar.AmpLfo=new LFO(pars->AmpLfo,basefreq); - - NoteGlobalPar.Volume=4.0*pow(0.1,3.0*(1.0-pars->PVolume/96.0))//-60 dB .. 0 dB - *VelF(velocity,pars->PAmpVelocityScaleFunction);//velocity sensing - - NoteGlobalPar.AmpEnvelope->envout_dB();//discard the first envelope output - globaloldamplitude=globalnewamplitude=NoteGlobalPar.Volume*NoteGlobalPar.AmpEnvelope->envout_dB()*NoteGlobalPar.AmpLfo->amplfoout(); - - NoteGlobalPar.GlobalFilterL=new Filter(pars->GlobalFilter); - NoteGlobalPar.GlobalFilterR=new Filter(pars->GlobalFilter); - - NoteGlobalPar.FilterEnvelope=new Envelope(pars->FilterEnvelope,basefreq); - NoteGlobalPar.FilterLfo=new LFO(pars->FilterLfo,basefreq); - NoteGlobalPar.FilterQ=pars->GlobalFilter->getq(); - NoteGlobalPar.FilterFreqTracking=pars->GlobalFilter->getfreqtracking(basefreq); - - ready=1;///sa il pun pe asta doar cand e chiar gata - - if (parameters->sample[nsample].smp==NULL){ - finished_=true; - return; - }; -}; - - -// PADlegatonote: This function is (mostly) a copy of PADnote(...) -// with some lines removed so that it only alter the already playing -// note (to perform legato). It is possible I left stuff that is not -// required for this. -void PADnote::PADlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int midinote, bool externcall){ - PADnoteParameters *parameters=pars; - //Controller *ctl_=ctl; - - // Manage legato stuff - if (externcall) Legato.msg=LM_Norm; - if (Legato.msg!=LM_CatchUp){ - Legato.lastfreq=Legato.param.freq; - Legato.param.freq=freq; - Legato.param.vel=velocity; - Legato.param.portamento=portamento_; - Legato.param.midinote=midinote; - if (Legato.msg==LM_Norm){ - if (Legato.silent){ - Legato.fade.m=0.0; - Legato.msg=LM_FadeIn; - } else { - Legato.fade.m=1.0; - Legato.msg=LM_FadeOut; - return; - } - } - if (Legato.msg==LM_ToNorm) Legato.msg=LM_Norm; - } - - portamento=portamento_; - this->velocity=velocity; - finished_=false; - - if (pars->Pfixedfreq==0) basefreq=freq; - else { - basefreq=440.0; - int fixedfreqET=pars->PfixedfreqET; - if (fixedfreqET!=0) {//if the frequency varies according the keyboard note - REALTYPE tmp=(midinote-69.0)/12.0*(pow(2.0,(fixedfreqET-1)/63.0)-1.0); - if (fixedfreqET<=64) basefreq*=pow(2.0,tmp); - else basefreq*=pow(3.0,tmp); - }; - }; - - released=false; - realfreq=basefreq; - - getdetune(pars->PDetuneType,pars->PCoarseDetune,pars->PDetune); - - - //find out the closest note - REALTYPE logfreq=log(basefreq*pow(2.0,NoteGlobalPar.Detune/1200.0)); - REALTYPE mindist=fabs(logfreq-log(pars->sample[0].basefreq+0.0001)); - nsample=0; - for (int i=1;isample[i].smp==NULL) break; - REALTYPE dist=fabs(logfreq-log(pars->sample[i].basefreq+0.0001)); - - if (distsample[nsample].size; - if (size==0) size=1; - - if (pars->PPanning==0) NoteGlobalPar.Panning=RND; - else NoteGlobalPar.Panning=pars->PPanning/128.0; - - NoteGlobalPar.FilterCenterPitch=pars->GlobalFilter->getfreq()+//center freq - pars->PFilterVelocityScale/127.0*6.0* //velocity sensing - (VelF(velocity,pars->PFilterVelocityScaleFunction)-1); - - - NoteGlobalPar.Volume=4.0*pow(0.1,3.0*(1.0-pars->PVolume/96.0))//-60 dB .. 0 dB - *VelF(velocity,pars->PAmpVelocityScaleFunction);//velocity sensing - - NoteGlobalPar.AmpEnvelope->envout_dB();//discard the first envelope output - globaloldamplitude=globalnewamplitude=NoteGlobalPar.Volume*NoteGlobalPar.AmpEnvelope->envout_dB()*NoteGlobalPar.AmpLfo->amplfoout(); - - NoteGlobalPar.FilterQ=pars->GlobalFilter->getq(); - NoteGlobalPar.FilterFreqTracking=pars->GlobalFilter->getfreqtracking(basefreq); - - - if (parameters->sample[nsample].smp==NULL){ - finished_=true; - return; - }; - - // End of the PADlegatonote function. -}; - - -PADnote::~PADnote(){ - delete (NoteGlobalPar.FreqEnvelope); - delete (NoteGlobalPar.FreqLfo); - delete (NoteGlobalPar.AmpEnvelope); - delete (NoteGlobalPar.AmpLfo); - delete (NoteGlobalPar.GlobalFilterL); - delete (NoteGlobalPar.GlobalFilterR); - delete (NoteGlobalPar.FilterEnvelope); - delete (NoteGlobalPar.FilterLfo); - delete [] tmpwave; -}; - - -inline void PADnote::fadein(REALTYPE *smps){ - int zerocrossings=0; - for (int i=1;i0.0)) zerocrossings++;//this is only the possitive crossings - - REALTYPE tmp=(SOUND_BUFFER_SIZE-1.0)/(zerocrossings+1)/3.0; - if (tmp<8.0) tmp=8.0; - - int n; - F2I(tmp,n);//how many samples is the fade-in - if (n>SOUND_BUFFER_SIZE) n=SOUND_BUFFER_SIZE; - for (int i=0;ienvout()+ - NoteGlobalPar.FreqLfo->lfoout()*ctl->modwheel.relmod+NoteGlobalPar.Detune); - globaloldamplitude=globalnewamplitude; - globalnewamplitude=NoteGlobalPar.Volume*NoteGlobalPar.AmpEnvelope->envout_dB()*NoteGlobalPar.AmpLfo->amplfoout(); - - globalfilterpitch=NoteGlobalPar.FilterEnvelope->envout()+NoteGlobalPar.FilterLfo->lfoout() - +NoteGlobalPar.FilterCenterPitch; - - REALTYPE tmpfilterfreq=globalfilterpitch+ctl->filtercutoff.relfreq - +NoteGlobalPar.FilterFreqTracking; - - tmpfilterfreq=NoteGlobalPar.GlobalFilterL->getrealfreq(tmpfilterfreq); - - REALTYPE globalfilterq=NoteGlobalPar.FilterQ*ctl->filterq.relq; - NoteGlobalPar.GlobalFilterL->setfreq_and_q(tmpfilterfreq,globalfilterq); - NoteGlobalPar.GlobalFilterR->setfreq_and_q(tmpfilterfreq,globalfilterq); - - //compute the portamento, if it is used by this note - REALTYPE portamentofreqrap=1.0; - if (portamento!=0){//this voice use portamento - portamentofreqrap=ctl->portamento.freqrap; - if (ctl->portamento.used==0){//the portamento has finished - portamento=0;//this note is no longer "portamented" - }; - }; - - realfreq=basefreq*portamentofreqrap*pow(2.0,globalpitch/12.0)*ctl->pitchwheel.relfreq; -}; - - -int PADnote::Compute_Linear(REALTYPE *outl,REALTYPE *outr,int freqhi,REALTYPE freqlo){ - REALTYPE *smps=pars->sample[nsample].smp; - if (smps==NULL){ - finished_=true; - return(1); - }; - int size=pars->sample[nsample].size; - for (int i=0;i=1.0){ - poshi_l+=1; - poshi_r+=1; - poslo-=1.0; - }; - if (poshi_l>=size) poshi_l%=size; - if (poshi_r>=size) poshi_r%=size; - - outl[i]=smps[poshi_l]*(1.0-poslo)+smps[poshi_l+1]*poslo; - outr[i]=smps[poshi_r]*(1.0-poslo)+smps[poshi_r+1]*poslo; - }; - return(1); -}; -int PADnote::Compute_Cubic(REALTYPE *outl,REALTYPE *outr,int freqhi,REALTYPE freqlo){ - REALTYPE *smps=pars->sample[nsample].smp; - if (smps==NULL){ - finished_=true; - return(1); - }; - int size=pars->sample[nsample].size; - REALTYPE xm1,x0,x1,x2,a,b,c; - for (int i=0;i=1.0){ - poshi_l+=1; - poshi_r+=1; - poslo-=1.0; - }; - if (poshi_l>=size) poshi_l%=size; - if (poshi_r>=size) poshi_r%=size; - - - //left - xm1=smps[poshi_l]; - x0=smps[poshi_l + 1]; - x1=smps[poshi_l + 2]; - x2=smps[poshi_l + 3]; - a = (3.0 * (x0-x1) - xm1 + x2)*0.5; - b = 2.0*x1 + xm1 - (5.0*x0 + x2)*0.5; - c = (x1 - xm1)*0.5; - outl[i] = (((a * poslo) + b) * poslo + c) * poslo + x0; - //right - xm1=smps[poshi_r]; - x0=smps[poshi_r + 1]; - x1=smps[poshi_r + 2]; - x2=smps[poshi_r + 3]; - a = (3.0 * (x0-x1) - xm1 + x2)*0.5; - b = 2.0*x1 + xm1 - (5.0*x0 + x2)*0.5; - c = (x1 - xm1)*0.5; - outr[i] = (((a * poslo) + b) * poslo + c) * poslo + x0; - }; - return(1); -}; - - -int PADnote::noteout(REALTYPE *outl,REALTYPE *outr){ - computecurrentparameters(); - REALTYPE *smps=pars->sample[nsample].smp; - if (smps==NULL){ - for (int i=0;isample[nsample].basefreq; - - - REALTYPE freqrap=realfreq/smpfreq; - int freqhi=(int) (floor(freqrap)); - REALTYPE freqlo=freqrap-floor(freqrap); - - - if (config.cfg.Interpolation) Compute_Cubic(outl,outr,freqhi,freqlo); - else Compute_Linear(outl,outr,freqhi,freqlo); - - - if (firsttime){ - fadein(outl); - fadein(outr); - firsttime=false; - }; - - NoteGlobalPar.GlobalFilterL->filterout(outl); - NoteGlobalPar.GlobalFilterR->filterout(outr); - - //Apply the punch - if (NoteGlobalPar.Punch.Enabled!=0){ - for (int i=0;ifinished()!=0) { - for (int i=0;irelasekey(); - NoteGlobalPar.FilterEnvelope->relasekey(); - NoteGlobalPar.AmpEnvelope->relasekey(); -}; - diff --git a/plugins/zynaddsubfx/src/Synth/PADnote.cpp b/plugins/zynaddsubfx/src/Synth/PADnote.cpp new file mode 100644 index 000000000..71b85de4d --- /dev/null +++ b/plugins/zynaddsubfx/src/Synth/PADnote.cpp @@ -0,0 +1,527 @@ +/* + ZynAddSubFX - a software synthesizer + + PADnote.C - The "pad" synthesizer + Copyright (C) 2002-2005 Nasca Octavian Paul + Author: Nasca Octavian Paul + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include +#include "PADnote.h" +#include "../Misc/Config.h" + +PADnote::PADnote(PADnoteParameters *parameters, Controller *ctl_,REALTYPE freq, REALTYPE velocity, int portamento_, int midinote, bool besilent) +{ + ready=0; + + // Initialise some legato-specific vars + Legato.msg=LM_Norm; + Legato.fade.length=(int)(SAMPLE_RATE*0.005);// 0.005 seems ok. + if (Legato.fade.length<1) Legato.fade.length=1;// (if something's fishy) + Legato.fade.step=(1.0/Legato.fade.length); + Legato.decounter=-10; + Legato.param.freq=freq; + Legato.param.vel=velocity; + Legato.param.portamento=portamento_; + Legato.param.midinote=midinote; + Legato.silent=besilent; + + pars=parameters; + portamento=portamento_; + ctl=ctl_; + this->velocity=velocity; + finished_=false; + + + if (pars->Pfixedfreq==0) basefreq=freq; + else { + basefreq=440.0; + int fixedfreqET=pars->PfixedfreqET; + if (fixedfreqET!=0) {//if the frequency varies according the keyboard note + REALTYPE tmp=(midinote-69.0)/12.0*(pow(2.0,(fixedfreqET-1)/63.0)-1.0); + if (fixedfreqET<=64) basefreq*=pow(2.0,tmp); + else basefreq*=pow(3.0,tmp); + }; + + }; + + firsttime=true; + released=false; + realfreq=basefreq; + NoteGlobalPar.Detune=getdetune(pars->PDetuneType + ,pars->PCoarseDetune,pars->PDetune); + + + //find out the closest note + REALTYPE logfreq=log(basefreq*pow(2.0,NoteGlobalPar.Detune/1200.0)); + REALTYPE mindist=fabs(logfreq-log(pars->sample[0].basefreq+0.0001)); + nsample=0; + for (int i=1;isample[i].smp==NULL) break; + REALTYPE dist=fabs(logfreq-log(pars->sample[i].basefreq+0.0001)); +// printf("(mindist=%g) %i %g %g\n",mindist,i,dist,pars->sample[i].basefreq); + + if (distsample[nsample].size; + if (size==0) size=1; + + + poshi_l=(int)(RND*(size-1)); + if (pars->PStereo!=0) poshi_r=(poshi_l+size/2)%size; + else poshi_r=poshi_l; + poslo=0.0; + + tmpwave=new REALTYPE [SOUND_BUFFER_SIZE]; + + + + if (pars->PPanning==0) NoteGlobalPar.Panning=RND; + else NoteGlobalPar.Panning=pars->PPanning/128.0; + + NoteGlobalPar.FilterCenterPitch=pars->GlobalFilter->getfreq()+//center freq + pars->PFilterVelocityScale/127.0*6.0* //velocity sensing + (VelF(velocity,pars->PFilterVelocityScaleFunction)-1); + + if (pars->PPunchStrength!=0) { + NoteGlobalPar.Punch.Enabled=1; + NoteGlobalPar.Punch.t=1.0;//start from 1.0 and to 0.0 + NoteGlobalPar.Punch.initialvalue=( (pow(10,1.5*pars->PPunchStrength/127.0)-1.0) + *VelF(velocity,pars->PPunchVelocitySensing) ); + REALTYPE time=pow(10,3.0*pars->PPunchTime/127.0)/10000.0;//0.1 .. 100 ms + REALTYPE stretch=pow(440.0/freq,pars->PPunchStretch/64.0); + NoteGlobalPar.Punch.dt=1.0/(time*SAMPLE_RATE*stretch); + } else NoteGlobalPar.Punch.Enabled=0; + + + + NoteGlobalPar.FreqEnvelope=new Envelope(pars->FreqEnvelope,basefreq); + NoteGlobalPar.FreqLfo=new LFO(pars->FreqLfo,basefreq); + + NoteGlobalPar.AmpEnvelope=new Envelope(pars->AmpEnvelope,basefreq); + NoteGlobalPar.AmpLfo=new LFO(pars->AmpLfo,basefreq); + + NoteGlobalPar.Volume=4.0*pow(0.1,3.0*(1.0-pars->PVolume/96.0))//-60 dB .. 0 dB + *VelF(velocity,pars->PAmpVelocityScaleFunction);//velocity sensing + + NoteGlobalPar.AmpEnvelope->envout_dB();//discard the first envelope output + globaloldamplitude=globalnewamplitude=NoteGlobalPar.Volume*NoteGlobalPar.AmpEnvelope->envout_dB()*NoteGlobalPar.AmpLfo->amplfoout(); + + NoteGlobalPar.GlobalFilterL=new Filter(pars->GlobalFilter); + NoteGlobalPar.GlobalFilterR=new Filter(pars->GlobalFilter); + + NoteGlobalPar.FilterEnvelope=new Envelope(pars->FilterEnvelope,basefreq); + NoteGlobalPar.FilterLfo=new LFO(pars->FilterLfo,basefreq); + NoteGlobalPar.FilterQ=pars->GlobalFilter->getq(); + NoteGlobalPar.FilterFreqTracking=pars->GlobalFilter->getfreqtracking(basefreq); + + ready=1;///sa il pun pe asta doar cand e chiar gata + + if (parameters->sample[nsample].smp==NULL) { + finished_=true; + return; + }; +}; + + +// PADlegatonote: This function is (mostly) a copy of PADnote(...) +// with some lines removed so that it only alter the already playing +// note (to perform legato). It is possible I left stuff that is not +// required for this. +void PADnote::PADlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int midinote, bool externcall) +{ + PADnoteParameters *parameters=pars; + //Controller *ctl_=ctl; + + // Manage legato stuff + if (externcall) Legato.msg=LM_Norm; + if (Legato.msg!=LM_CatchUp) { + Legato.lastfreq=Legato.param.freq; + Legato.param.freq=freq; + Legato.param.vel=velocity; + Legato.param.portamento=portamento_; + Legato.param.midinote=midinote; + if (Legato.msg==LM_Norm) { + if (Legato.silent) { + Legato.fade.m=0.0; + Legato.msg=LM_FadeIn; + } else { + Legato.fade.m=1.0; + Legato.msg=LM_FadeOut; + return; + } + } + if (Legato.msg==LM_ToNorm) Legato.msg=LM_Norm; + } + + portamento=portamento_; + this->velocity=velocity; + finished_=false; + + if (pars->Pfixedfreq==0) basefreq=freq; + else { + basefreq=440.0; + int fixedfreqET=pars->PfixedfreqET; + if (fixedfreqET!=0) {//if the frequency varies according the keyboard note + REALTYPE tmp=(midinote-69.0)/12.0*(pow(2.0,(fixedfreqET-1)/63.0)-1.0); + if (fixedfreqET<=64) basefreq*=pow(2.0,tmp); + else basefreq*=pow(3.0,tmp); + }; + }; + + released=false; + realfreq=basefreq; + + getdetune(pars->PDetuneType,pars->PCoarseDetune,pars->PDetune); + + + //find out the closest note + REALTYPE logfreq=log(basefreq*pow(2.0,NoteGlobalPar.Detune/1200.0)); + REALTYPE mindist=fabs(logfreq-log(pars->sample[0].basefreq+0.0001)); + nsample=0; + for (int i=1;isample[i].smp==NULL) break; + REALTYPE dist=fabs(logfreq-log(pars->sample[i].basefreq+0.0001)); + + if (distsample[nsample].size; + if (size==0) size=1; + + if (pars->PPanning==0) NoteGlobalPar.Panning=RND; + else NoteGlobalPar.Panning=pars->PPanning/128.0; + + NoteGlobalPar.FilterCenterPitch=pars->GlobalFilter->getfreq()+//center freq + pars->PFilterVelocityScale/127.0*6.0* //velocity sensing + (VelF(velocity,pars->PFilterVelocityScaleFunction)-1); + + + NoteGlobalPar.Volume=4.0*pow(0.1,3.0*(1.0-pars->PVolume/96.0))//-60 dB .. 0 dB + *VelF(velocity,pars->PAmpVelocityScaleFunction);//velocity sensing + + NoteGlobalPar.AmpEnvelope->envout_dB();//discard the first envelope output + globaloldamplitude=globalnewamplitude=NoteGlobalPar.Volume*NoteGlobalPar.AmpEnvelope->envout_dB()*NoteGlobalPar.AmpLfo->amplfoout(); + + NoteGlobalPar.FilterQ=pars->GlobalFilter->getq(); + NoteGlobalPar.FilterFreqTracking=pars->GlobalFilter->getfreqtracking(basefreq); + + + if (parameters->sample[nsample].smp==NULL) { + finished_=true; + return; + }; + + // End of the PADlegatonote function. +}; + + +PADnote::~PADnote() +{ + delete (NoteGlobalPar.FreqEnvelope); + delete (NoteGlobalPar.FreqLfo); + delete (NoteGlobalPar.AmpEnvelope); + delete (NoteGlobalPar.AmpLfo); + delete (NoteGlobalPar.GlobalFilterL); + delete (NoteGlobalPar.GlobalFilterR); + delete (NoteGlobalPar.FilterEnvelope); + delete (NoteGlobalPar.FilterLfo); + delete [] tmpwave; +}; + + +inline void PADnote::fadein(REALTYPE *smps) +{ + int zerocrossings=0; + for (int i=1;i0.0)) zerocrossings++;//this is only the possitive crossings + + REALTYPE tmp=(SOUND_BUFFER_SIZE-1.0)/(zerocrossings+1)/3.0; + if (tmp<8.0) tmp=8.0; + + int n; + F2I(tmp,n);//how many samples is the fade-in + if (n>SOUND_BUFFER_SIZE) n=SOUND_BUFFER_SIZE; + for (int i=0;ienvout()+ + NoteGlobalPar.FreqLfo->lfoout()*ctl->modwheel.relmod+NoteGlobalPar.Detune); + globaloldamplitude=globalnewamplitude; + globalnewamplitude=NoteGlobalPar.Volume*NoteGlobalPar.AmpEnvelope->envout_dB()*NoteGlobalPar.AmpLfo->amplfoout(); + + globalfilterpitch=NoteGlobalPar.FilterEnvelope->envout()+NoteGlobalPar.FilterLfo->lfoout() + +NoteGlobalPar.FilterCenterPitch; + + REALTYPE tmpfilterfreq=globalfilterpitch+ctl->filtercutoff.relfreq + +NoteGlobalPar.FilterFreqTracking; + + tmpfilterfreq=NoteGlobalPar.GlobalFilterL->getrealfreq(tmpfilterfreq); + + REALTYPE globalfilterq=NoteGlobalPar.FilterQ*ctl->filterq.relq; + NoteGlobalPar.GlobalFilterL->setfreq_and_q(tmpfilterfreq,globalfilterq); + NoteGlobalPar.GlobalFilterR->setfreq_and_q(tmpfilterfreq,globalfilterq); + + //compute the portamento, if it is used by this note + REALTYPE portamentofreqrap=1.0; + if (portamento!=0) {//this voice use portamento + portamentofreqrap=ctl->portamento.freqrap; + if (ctl->portamento.used==0) {//the portamento has finished + portamento=0;//this note is no longer "portamented" + }; + }; + + realfreq=basefreq*portamentofreqrap*pow(2.0,globalpitch/12.0)*ctl->pitchwheel.relfreq; +}; + + +int PADnote::Compute_Linear(REALTYPE *outl,REALTYPE *outr,int freqhi,REALTYPE freqlo) +{ + REALTYPE *smps=pars->sample[nsample].smp; + if (smps==NULL) { + finished_=true; + return(1); + }; + int size=pars->sample[nsample].size; + for (int i=0;i=1.0) { + poshi_l+=1; + poshi_r+=1; + poslo-=1.0; + }; + if (poshi_l>=size) poshi_l%=size; + if (poshi_r>=size) poshi_r%=size; + + outl[i]=smps[poshi_l]*(1.0-poslo)+smps[poshi_l+1]*poslo; + outr[i]=smps[poshi_r]*(1.0-poslo)+smps[poshi_r+1]*poslo; + }; + return(1); +}; +int PADnote::Compute_Cubic(REALTYPE *outl,REALTYPE *outr,int freqhi,REALTYPE freqlo) +{ + REALTYPE *smps=pars->sample[nsample].smp; + if (smps==NULL) { + finished_=true; + return(1); + }; + int size=pars->sample[nsample].size; + REALTYPE xm1,x0,x1,x2,a,b,c; + for (int i=0;i=1.0) { + poshi_l+=1; + poshi_r+=1; + poslo-=1.0; + }; + if (poshi_l>=size) poshi_l%=size; + if (poshi_r>=size) poshi_r%=size; + + + //left + xm1=smps[poshi_l]; + x0=smps[poshi_l + 1]; + x1=smps[poshi_l + 2]; + x2=smps[poshi_l + 3]; + a = (3.0 * (x0-x1) - xm1 + x2)*0.5; + b = 2.0*x1 + xm1 - (5.0*x0 + x2)*0.5; + c = (x1 - xm1)*0.5; + outl[i] = (((a * poslo) + b) * poslo + c) * poslo + x0; + //right + xm1=smps[poshi_r]; + x0=smps[poshi_r + 1]; + x1=smps[poshi_r + 2]; + x2=smps[poshi_r + 3]; + a = (3.0 * (x0-x1) - xm1 + x2)*0.5; + b = 2.0*x1 + xm1 - (5.0*x0 + x2)*0.5; + c = (x1 - xm1)*0.5; + outr[i] = (((a * poslo) + b) * poslo + c) * poslo + x0; + }; + return(1); +}; + + +int PADnote::noteout(REALTYPE *outl,REALTYPE *outr) +{ + computecurrentparameters(); + REALTYPE *smps=pars->sample[nsample].smp; + if (smps==NULL) { + for (int i=0;isample[nsample].basefreq; + + + REALTYPE freqrap=realfreq/smpfreq; + int freqhi=(int) (floor(freqrap)); + REALTYPE freqlo=freqrap-floor(freqrap); + + + if (config.cfg.Interpolation) Compute_Cubic(outl,outr,freqhi,freqlo); + else Compute_Linear(outl,outr,freqhi,freqlo); + + + if (firsttime) { + fadein(outl); + fadein(outr); + firsttime=false; + }; + + NoteGlobalPar.GlobalFilterL->filterout(outl); + NoteGlobalPar.GlobalFilterR->filterout(outr); + + //Apply the punch + if (NoteGlobalPar.Punch.Enabled!=0) { + for (int i=0;ifinished()!=0) { + for (int i=0;irelasekey(); + NoteGlobalPar.FilterEnvelope->relasekey(); + NoteGlobalPar.AmpEnvelope->relasekey(); +}; + diff --git a/plugins/zynaddsubfx/src/Synth/PADnote.h b/plugins/zynaddsubfx/src/Synth/PADnote.h index 8d18c75a1..4722857f0 100644 --- a/plugins/zynaddsubfx/src/Synth/PADnote.h +++ b/plugins/zynaddsubfx/src/Synth/PADnote.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + PADnote.h - The "pad" synthesizer Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -29,95 +29,97 @@ #include "../DSP/Filter.h" #include "../Params/Controller.h" -class PADnote{ - public: - PADnote(PADnoteParameters *parameters, Controller *ctl_,REALTYPE freq, REALTYPE velocity, int portamento_, int midinote, bool besilent); - ~PADnote(); +/**The "pad" synthesizer*/ +class PADnote +{ +public: + PADnote(PADnoteParameters *parameters, Controller *ctl_,REALTYPE freq, REALTYPE velocity, int portamento_, int midinote, bool besilent); + ~PADnote(); - void PADlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int midinote, bool externcall); + void PADlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int midinote, bool externcall); - int noteout(REALTYPE *outl,REALTYPE *outr); - int finished(); - void relasekey(); - - int ready; - - private: - void fadein(REALTYPE *smps); - void computecurrentparameters(); - bool finished_; - PADnoteParameters *pars; - - int poshi_l,poshi_r; - REALTYPE poslo; - - REALTYPE basefreq; - bool firsttime,released; - - int nsample,portamento; + int noteout(REALTYPE *outl,REALTYPE *outr); + int finished(); + void relasekey(); - int Compute_Linear(REALTYPE *outl,REALTYPE *outr,int freqhi,REALTYPE freqlo); - int Compute_Cubic(REALTYPE *outl,REALTYPE *outr,int freqhi,REALTYPE freqlo); + int ready; + +private: + void fadein(REALTYPE *smps); + void computecurrentparameters(); + bool finished_; + PADnoteParameters *pars; + + int poshi_l,poshi_r; + REALTYPE poslo; + + REALTYPE basefreq; + bool firsttime,released; + + int nsample,portamento; + + int Compute_Linear(REALTYPE *outl,REALTYPE *outr,int freqhi,REALTYPE freqlo); + int Compute_Cubic(REALTYPE *outl,REALTYPE *outr,int freqhi,REALTYPE freqlo); - struct{ - /****************************************** - * FREQUENCY GLOBAL PARAMETERS * - ******************************************/ - REALTYPE Detune;//cents + struct { + /****************************************** + * FREQUENCY GLOBAL PARAMETERS * + ******************************************/ + REALTYPE Detune;//cents - Envelope *FreqEnvelope; - LFO *FreqLfo; + Envelope *FreqEnvelope; + LFO *FreqLfo; - /******************************************** - * AMPLITUDE GLOBAL PARAMETERS * - ********************************************/ - REALTYPE Volume;// [ 0 .. 1 ] + /******************************************** + * AMPLITUDE GLOBAL PARAMETERS * + ********************************************/ + REALTYPE Volume;// [ 0 .. 1 ] - REALTYPE Panning;// [ 0 .. 1 ] + REALTYPE Panning;// [ 0 .. 1 ] - Envelope *AmpEnvelope; - LFO *AmpLfo; - - struct { - int Enabled; - REALTYPE initialvalue,dt,t; - } Punch; + Envelope *AmpEnvelope; + LFO *AmpLfo; - /****************************************** - * FILTER GLOBAL PARAMETERS * - ******************************************/ - Filter *GlobalFilterL,*GlobalFilterR; + struct { + int Enabled; + REALTYPE initialvalue,dt,t; + } Punch; - REALTYPE FilterCenterPitch;//octaves - REALTYPE FilterQ; - REALTYPE FilterFreqTracking; - - Envelope *FilterEnvelope; - - LFO *FilterLfo; - } NoteGlobalPar; + /****************************************** + * FILTER GLOBAL PARAMETERS * + ******************************************/ + Filter *GlobalFilterL,*GlobalFilterR; - - REALTYPE globaloldamplitude,globalnewamplitude,velocity,realfreq; - REALTYPE *tmpwave; - Controller *ctl; + REALTYPE FilterCenterPitch;//octaves + REALTYPE FilterQ; + REALTYPE FilterFreqTracking; - // Legato vars - struct { - bool silent; - REALTYPE lastfreq; - LegatoMsg msg; - int decounter; - struct { // Fade In/Out vars - int length; - REALTYPE m, step; - } fade; - struct { // Note parameters - REALTYPE freq, vel; - int portamento, midinote; - } param; - } Legato; + Envelope *FilterEnvelope; + + LFO *FilterLfo; + } NoteGlobalPar; + + + REALTYPE globaloldamplitude,globalnewamplitude,velocity,realfreq; + REALTYPE *tmpwave; + Controller *ctl; + + // Legato vars + struct { + bool silent; + REALTYPE lastfreq; + LegatoMsg msg; + int decounter; + struct { // Fade In/Out vars + int length; + REALTYPE m, step; + } fade; + struct { // Note parameters + REALTYPE freq, vel; + int portamento, midinote; + } param; + } Legato; }; diff --git a/plugins/zynaddsubfx/src/Synth/Resonance.C b/plugins/zynaddsubfx/src/Synth/Resonance.cpp similarity index 60% rename from plugins/zynaddsubfx/src/Synth/Resonance.C rename to plugins/zynaddsubfx/src/Synth/Resonance.cpp index ce5d3dd8b..fcf043d3a 100644 --- a/plugins/zynaddsubfx/src/Synth/Resonance.C +++ b/plugins/zynaddsubfx/src/Synth/Resonance.cpp @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + Resonance.C - Resonance Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -26,16 +26,19 @@ #include -Resonance::Resonance():Presets(){ +Resonance::Resonance():Presets() +{ setpresettype("Presonance"); defaults(); }; -Resonance::~Resonance(){ +Resonance::~Resonance() +{ }; -void Resonance::defaults(){ +void Resonance::defaults() +{ Penabled=0; PmaxdB=20; Pcenterfreq=64;//1 kHz @@ -49,7 +52,8 @@ void Resonance::defaults(){ /* * Set a point of resonance function with a value */ -void Resonance::setpoint(int n,unsigned char p){ +void Resonance::setpoint(int n,unsigned char p) +{ if ((n<0)||(n>=N_RES_POINTS)) return; Prespoints[n]=p; }; @@ -57,51 +61,59 @@ void Resonance::setpoint(int n,unsigned char p){ /* * Apply the resonance to FFT data */ -void Resonance::applyres(int n,FFTFREQS fftdata,REALTYPE freq){ +void Resonance::applyres(int n,FFTFREQS fftdata,REALTYPE freq) +{ if (Penabled==0) return;//if the resonance is disabled REALTYPE sum=0.0, - l1=log(getfreqx(0.0)*ctlcenter), - l2=log(2.0)*getoctavesfreq()*ctlbw; + l1=log(getfreqx(0.0)*ctlcenter), + l2=log(2.0)*getoctavesfreq()*ctlbw; for (int i=0;i=N_RES_POINTS) kx1=N_RES_POINTS-1; + int kx2=kx1+1; + if (kx2>=N_RES_POINTS) kx2=N_RES_POINTS-1; + REALTYPE y=(Prespoints[kx1]*(1.0-dx)+Prespoints[kx2]*dx)/127.0-sum/127.0; + + y=pow(10.0,y*PmaxdB/20.0); + + if ((Pprotectthefundamental!=0)&&(i==1)) y=1.0; - x*=N_RES_POINTS; - REALTYPE dx=x-floor(x);x=floor(x); - int kx1=(int)x; if (kx1>=N_RES_POINTS) kx1=N_RES_POINTS-1; - int kx2=kx1+1;if (kx2>=N_RES_POINTS) kx2=N_RES_POINTS-1; - REALTYPE y=(Prespoints[kx1]*(1.0-dx)+Prespoints[kx2]*dx)/127.0-sum/127.0; - - y=pow(10.0,y*PmaxdB/20.0); - - if ((Pprotectthefundamental!=0)&&(i==1)) y=1.0; - fftdata.c[i]*=y; fftdata.s[i]*=y; - }; + }; }; /* * Gets the response at the frequency "freq" */ -REALTYPE Resonance::getfreqresponse(REALTYPE freq){ +REALTYPE Resonance::getfreqresponse(REALTYPE freq) +{ REALTYPE l1=log(getfreqx(0.0)*ctlcenter), - l2=log(2.0)*getoctavesfreq()*ctlbw,sum=0.0; - + l2=log(2.0)*getoctavesfreq()*ctlbw,sum=0.0; + for (int i=0;i=N_RES_POINTS) kx1=N_RES_POINTS-1; - int kx2=kx1+1;if (kx2>=N_RES_POINTS) kx2=N_RES_POINTS-1; + REALTYPE dx=x-floor(x); + x=floor(x); + int kx1=(int)x; + if (kx1>=N_RES_POINTS) kx1=N_RES_POINTS-1; + int kx2=kx1+1; + if (kx2>=N_RES_POINTS) kx2=N_RES_POINTS-1; REALTYPE result=(Prespoints[kx1]*(1.0-dx)+Prespoints[kx2]*dx)/127.0-sum/127.0; result=pow(10.0,result*PmaxdB/20.0); return(result); @@ -111,30 +123,32 @@ REALTYPE Resonance::getfreqresponse(REALTYPE freq){ /* * Smooth the resonance function */ -void Resonance::smooth(){ +void Resonance::smooth() +{ REALTYPE old=Prespoints[0]; - for (int i=0;i0;i--){ + for (int i=N_RES_POINTS-1;i>0;i--) { old=old*0.4+Prespoints[i]*0.6; - Prespoints[i]=(int) old+1; - if (Prespoints[i]>127) Prespoints[i]=127; + Prespoints[i]=(int) old+1; + if (Prespoints[i]>127) Prespoints[i]=127; }; }; /* * Randomize the resonance function */ -void Resonance::randomize(int type){ +void Resonance::randomize(int type) +{ int r=(int)(RND*127.0); - for (int i=0;i1.0) x=1.0; REALTYPE octf=pow(2.0,getoctavesfreq()); return(getcenterfreq()/sqrt(octf)*pow(octf,x)); @@ -170,35 +186,40 @@ REALTYPE Resonance::getfreqx(REALTYPE x){ /* * Get the x coordinate from frequency (used by the UI) */ -REALTYPE Resonance::getfreqpos(REALTYPE freq){ +REALTYPE Resonance::getfreqpos(REALTYPE freq) +{ return((log(freq)-log(getfreqx(0.0)))/log(2.0)/getoctavesfreq()); }; /* * Get the center frequency of the resonance graph */ -REALTYPE Resonance::getcenterfreq(){ +REALTYPE Resonance::getcenterfreq() +{ return(10000.0*pow(10,-(1.0-Pcenterfreq/127.0)*2.0)); }; /* * Get the number of octave that the resonance functions applies to */ -REALTYPE Resonance::getoctavesfreq(){ +REALTYPE Resonance::getoctavesfreq() +{ return(0.25+10.0*Poctavesfreq/127.0); }; -void Resonance::sendcontroller(MidiControllers ctl,REALTYPE par){ +void Resonance::sendcontroller(MidiControllers ctl,REALTYPE par) +{ if (ctl==C_resonance_center) ctlcenter=par; - else ctlbw=par; + else ctlbw=par; }; -void Resonance::add2XML(XMLwrapper *xml){ +void Resonance::add2XML(XMLwrapper *xml) +{ xml->addparbool("enabled",Penabled); - + if ((Penabled==0)&&(xml->minimal)) return; xml->addpar("max_db",PmaxdB); @@ -206,25 +227,26 @@ void Resonance::add2XML(XMLwrapper *xml){ xml->addpar("octaves_freq",Poctavesfreq); xml->addparbool("protect_fundamental_frequency",Pprotectthefundamental); xml->addpar("resonance_points",N_RES_POINTS); - for (int i=0;ibeginbranch("RESPOINT",i); - xml->addpar("val",Prespoints[i]); - xml->endbranch(); + for (int i=0;ibeginbranch("RESPOINT",i); + xml->addpar("val",Prespoints[i]); + xml->endbranch(); }; }; -void Resonance::getfromXML(XMLwrapper *xml){ +void Resonance::getfromXML(XMLwrapper *xml) +{ Penabled=xml->getparbool("enabled",Penabled); PmaxdB=xml->getpar127("max_db",PmaxdB); Pcenterfreq=xml->getpar127("center_freq",Pcenterfreq); Poctavesfreq=xml->getpar127("octaves_freq",Poctavesfreq); Pprotectthefundamental=xml->getparbool("protect_fundamental_frequency",Pprotectthefundamental); - for (int i=0;ienterbranch("RESPOINT",i)==0) continue; - Prespoints[i]=xml->getpar127("val",Prespoints[i]); - xml->exitbranch(); + for (int i=0;ienterbranch("RESPOINT",i)==0) continue; + Prespoints[i]=xml->getpar127("val",Prespoints[i]); + xml->exitbranch(); }; }; diff --git a/plugins/zynaddsubfx/src/Synth/Resonance.h b/plugins/zynaddsubfx/src/Synth/Resonance.h index 31d2fd4e1..458ace0c4 100644 --- a/plugins/zynaddsubfx/src/Synth/Resonance.h +++ b/plugins/zynaddsubfx/src/Synth/Resonance.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - - Resonance.h - Resonance + + Resonance.h - Resonance Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -29,30 +29,31 @@ #define N_RES_POINTS 256 -class Resonance:public Presets{ - public: - Resonance(); - ~Resonance(); - void setpoint(int n,unsigned char p); - void applyres(int n,FFTFREQS fftdata,REALTYPE freq); - void smooth(); - void interpolatepeaks(int type); - void randomize(int type); +class Resonance:public Presets +{ +public: + Resonance(); + ~Resonance(); + void setpoint(int n,unsigned char p); + void applyres(int n,FFTFREQS fftdata,REALTYPE freq); + void smooth(); + void interpolatepeaks(int type); + void randomize(int type); - void add2XML(XMLwrapper *xml); - void defaults(); - void getfromXML(XMLwrapper *xml); + void add2XML(XMLwrapper *xml); + void defaults(); + void getfromXML(XMLwrapper *xml); - REALTYPE getfreqpos(REALTYPE freq); - REALTYPE getfreqx(REALTYPE x); - REALTYPE getfreqresponse(REALTYPE freq); - REALTYPE getcenterfreq(); - REALTYPE getoctavesfreq(); - void sendcontroller(MidiControllers ctl,REALTYPE par); + REALTYPE getfreqpos(REALTYPE freq); + REALTYPE getfreqx(REALTYPE x); + REALTYPE getfreqresponse(REALTYPE freq); + REALTYPE getcenterfreq(); + REALTYPE getoctavesfreq(); + void sendcontroller(MidiControllers ctl,REALTYPE par); //parameters - unsigned char Penabled; //if the ressonance is enabled + unsigned char Penabled; //if the ressonance is enabled unsigned char Prespoints[N_RES_POINTS]; //how many points define the resonance function unsigned char PmaxdB; //how many dB the signal may be amplified unsigned char Pcenterfreq,Poctavesfreq; //the center frequency of the res. func., and the number of octaves @@ -61,8 +62,8 @@ class Resonance:public Presets{ //controllers REALTYPE ctlcenter;//center frequency(relative) REALTYPE ctlbw;//bandwidth(relative) - - private: + +private: }; #endif diff --git a/plugins/zynaddsubfx/src/Synth/SUBnote.C b/plugins/zynaddsubfx/src/Synth/SUBnote.C deleted file mode 100644 index 4b0ca1ecb..000000000 --- a/plugins/zynaddsubfx/src/Synth/SUBnote.C +++ /dev/null @@ -1,641 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - SUBnote.C - The "subtractive" synthesizer - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include -#include -#include "../globals.h" -#include "SUBnote.h" -#include "../Misc/Util.h" - -SUBnote::SUBnote(SUBnoteParameters *parameters,Controller *ctl_,REALTYPE freq,REALTYPE velocity,int portamento_,int midinote,bool besilent){ - ready=0; - - tmpsmp=new REALTYPE[SOUND_BUFFER_SIZE]; - tmprnd=new REALTYPE[SOUND_BUFFER_SIZE]; - - // Initialise some legato-specific vars - Legato.msg=LM_Norm; - Legato.fade.length=(int)(SAMPLE_RATE*0.005);// 0.005 seems ok. - if (Legato.fade.length<1) Legato.fade.length=1;// (if something's fishy) - Legato.fade.step=(1.0/Legato.fade.length); - Legato.decounter=-10; - Legato.param.freq=freq; - Legato.param.vel=velocity; - Legato.param.portamento=portamento_; - Legato.param.midinote=midinote; - Legato.silent=besilent; - - pars=parameters; - ctl=ctl_; - portamento=portamento_; - NoteEnabled=ON; - volume=pow(0.1,3.0*(1.0-pars->PVolume/96.0));//-60 dB .. 0 dB - volume*=VelF(velocity,pars->PAmpVelocityScaleFunction); - if (pars->PPanning!=0) panning=pars->PPanning/127.0; - else panning=RND; - numstages=pars->Pnumstages; - stereo=pars->Pstereo; - start=pars->Pstart; - firsttick=1; - int pos[MAX_SUB_HARMONICS]; - - if (pars->Pfixedfreq==0) basefreq=freq; - else { - basefreq=440.0; - int fixedfreqET=pars->PfixedfreqET; - if (fixedfreqET!=0) {//if the frequency varies according the keyboard note - REALTYPE tmp=(midinote-69.0)/12.0*(pow(2.0,(fixedfreqET-1)/63.0)-1.0); - if (fixedfreqET<=64) basefreq*=pow(2.0,tmp); - else basefreq*=pow(3.0,tmp); - }; - - }; - REALTYPE detune=getdetune(pars->PDetuneType,pars->PCoarseDetune,pars->PDetune); - basefreq*=pow(2.0,detune/1200.0);//detune -// basefreq*=ctl->pitchwheel.relfreq;//pitch wheel - - //global filter - GlobalFilterCenterPitch=pars->GlobalFilter->getfreq()+//center freq - (pars->PGlobalFilterVelocityScale/127.0*6.0)* //velocity sensing - (VelF(velocity,pars->PGlobalFilterVelocityScaleFunction)-1); - - GlobalFilterL=NULL;GlobalFilterR=NULL; - GlobalFilterEnvelope=NULL; - - //select only harmonics that desire to compute - numharmonics=0; - for (int n=0;nPhmag[n]==0)continue; - if (n*basefreq>SAMPLE_RATE/2.0) break;//remove the freqs above the Nyquist freq - pos[numharmonics++]=n; - }; - firstnumharmonics=numharmonics;//(gf)Useful in legato mode. - - if (numharmonics==0) { - NoteEnabled=OFF; - return; - }; - - - lfilter=new bpfilter[numstages*numharmonics]; - if (stereo!=0) rfilter=new bpfilter[numstages*numharmonics]; - - //how much the amplitude is normalised (because the harmonics) - REALTYPE reduceamp=0.0; - - for (int n=0;nPbandwidth-127.0)/127.0*4)*numstages; - - //Bandwidth Scale - bw*=pow(1000/freq,(pars->Pbwscale-64.0)/64.0*3.0); - - //Relative BandWidth - bw*=pow(100,(pars->Phrelbw[pos[n]]-64.0)/64.0); - - if (bw>25.0) bw=25.0; - - //try to keep same amplitude on all freqs and bw. (empirically) - REALTYPE gain=sqrt(1500.0/(bw*freq)); - - REALTYPE hmagnew=1.0-pars->Phmag[pos[n]]/127.0; - REALTYPE hgain; - - switch(pars->Phmagtype){ - case 1:hgain=exp(hmagnew*log(0.01)); break; - case 2:hgain=exp(hmagnew*log(0.001));break; - case 3:hgain=exp(hmagnew*log(0.0001));break; - case 4:hgain=exp(hmagnew*log(0.00001));break; - default:hgain=1.0-hmagnew; - }; - gain*=hgain; - reduceamp+=hgain; - - for (int nph=0;nphPfixedfreq==0) initparameters(basefreq); - else initparameters(basefreq/440.0*freq); - - oldamplitude=newamplitude; - ready=1; -}; - - -// SUBlegatonote: This function is (mostly) a copy of SUBnote(...) and -// initparameters(...) stuck together with some lines removed so that -// it only alter the already playing note (to perform legato). It is -// possible I left stuff that is not required for this. -void SUBnote::SUBlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int midinote, bool externcall){ - //SUBnoteParameters *parameters=pars; - //Controller *ctl_=ctl; - - // Manage legato stuff - if (externcall) Legato.msg=LM_Norm; - if (Legato.msg!=LM_CatchUp){ - Legato.lastfreq=Legato.param.freq; - Legato.param.freq=freq; - Legato.param.vel=velocity; - Legato.param.portamento=portamento_; - Legato.param.midinote=midinote; - if (Legato.msg==LM_Norm){ - if (Legato.silent){ - Legato.fade.m=0.0; - Legato.msg=LM_FadeIn; - } else { - Legato.fade.m=1.0; - Legato.msg=LM_FadeOut; - return; - } - } - if (Legato.msg==LM_ToNorm) Legato.msg=LM_Norm; - } - - portamento=portamento_; - - volume=pow(0.1,3.0*(1.0-pars->PVolume/96.0));//-60 dB .. 0 dB - volume*=VelF(velocity,pars->PAmpVelocityScaleFunction); - if (pars->PPanning!=0) panning=pars->PPanning/127.0; - else panning=RND; - - ///start=pars->Pstart; - - int pos[MAX_SUB_HARMONICS]; - - if (pars->Pfixedfreq==0) basefreq=freq; - else { - basefreq=440.0; - int fixedfreqET=pars->PfixedfreqET; - if (fixedfreqET!=0) {//if the frequency varies according the keyboard note - REALTYPE tmp=(midinote-69.0)/12.0*(pow(2.0,(fixedfreqET-1)/63.0)-1.0); - if (fixedfreqET<=64) basefreq*=pow(2.0,tmp); - else basefreq*=pow(3.0,tmp); - }; - }; - REALTYPE detune=getdetune(pars->PDetuneType,pars->PCoarseDetune,pars->PDetune); - basefreq*=pow(2.0,detune/1200.0);//detune - - //global filter - GlobalFilterCenterPitch=pars->GlobalFilter->getfreq()+//center freq - (pars->PGlobalFilterVelocityScale/127.0*6.0)* //velocity sensing - (VelF(velocity,pars->PGlobalFilterVelocityScaleFunction)-1); - - - int legatonumharmonics=0; - for (int n=0;nPhmag[n]==0)continue; - if (n*basefreq>SAMPLE_RATE/2.0) break;//remove the freqs above the Nyquist freq - pos[legatonumharmonics++]=n; - }; - if (legatonumharmonics>firstnumharmonics) numharmonics=firstnumharmonics; - else numharmonics=legatonumharmonics; - - if (numharmonics==0) { - NoteEnabled=OFF; - return; - }; - - - //how much the amplitude is normalised (because the harmonics) - REALTYPE reduceamp=0.0; - - for (int n=0;nPbandwidth-127.0)/127.0*4)*numstages; - - //Bandwidth Scale - bw*=pow(1000/freq,(pars->Pbwscale-64.0)/64.0*3.0); - - //Relative BandWidth - bw*=pow(100,(pars->Phrelbw[pos[n]]-64.0)/64.0); - - if (bw>25.0) bw=25.0; - - //try to keep same amplitude on all freqs and bw. (empirically) - REALTYPE gain=sqrt(1500.0/(bw*freq)); - - REALTYPE hmagnew=1.0-pars->Phmag[pos[n]]/127.0; - REALTYPE hgain; - - switch(pars->Phmagtype){ - case 1:hgain=exp(hmagnew*log(0.01)); break; - case 2:hgain=exp(hmagnew*log(0.001));break; - case 3:hgain=exp(hmagnew*log(0.0001));break; - case 4:hgain=exp(hmagnew*log(0.00001));break; - default:hgain=1.0-hmagnew; - }; - gain*=hgain; - reduceamp+=hgain; - - for (int nph=0;nphPfixedfreq==0) freq=basefreq; - else freq*=basefreq/440.0; - - - /////////////// - // Altered initparameters(...) content: - - if (pars->PGlobalFilterEnabled!=0){ - globalfiltercenterq=pars->GlobalFilter->getq(); - GlobalFilterFreqTracking=pars->GlobalFilter->getfreqtracking(basefreq); - }; - - // end of the altered initparameters function content. - /////////////// - - oldamplitude=newamplitude; - - // End of the SUBlegatonote function. -}; - - -SUBnote::~SUBnote(){ - if (NoteEnabled!=OFF) KillNote(); - delete [] tmpsmp; - delete [] tmprnd; -}; - -/* - * Kill the note - */ -void SUBnote::KillNote(){ - if (NoteEnabled!=OFF){ - delete [] lfilter; - lfilter=NULL; - if (stereo!=0) delete [] rfilter; - rfilter=NULL; - delete(AmpEnvelope); - if (FreqEnvelope!=NULL) delete(FreqEnvelope); - if (BandWidthEnvelope!=NULL) delete(BandWidthEnvelope); - NoteEnabled=OFF; - }; - -}; - - -/* - * Compute the filters coefficients - */ -void SUBnote::computefiltercoefs(bpfilter &filter,REALTYPE freq,REALTYPE bw,REALTYPE gain){ - if (freq>SAMPLE_RATE/2.0-200.0) { - freq=SAMPLE_RATE/2.0-200.0; - }; - - REALTYPE omega=2.0*PI*freq/SAMPLE_RATE; - REALTYPE sn=sin(omega);REALTYPE cs=cos(omega); - REALTYPE alpha=sn*sinh(LOG_2/2.0*bw*omega/sn); - - if (alpha>1) alpha=1; - if (alpha>bw) alpha=bw; - - filter.b0=alpha/(1.0+alpha)*filter.amp*gain; - filter.b2=-alpha/(1.0+alpha)*filter.amp*gain; - filter.a1=-2.0*cs/(1.0+alpha); - filter.a2=(1.0-alpha)/(1.0+alpha); - -}; - - -/* - * Initialise the filters - */ -void SUBnote::initfilter(bpfilter &filter,REALTYPE freq,REALTYPE bw,REALTYPE amp,REALTYPE mag){ - filter.xn1=0.0;filter.xn2=0.0; - - if (start==0) { - filter.yn1=0.0; - filter.yn2=0.0; - } else { - REALTYPE a=0.1*mag;//empirically - REALTYPE p=RND*2.0*PI; - if (start==1) a*=RND; - filter.yn1=a*cos(p); - filter.yn2=a*cos(p+freq*2.0*PI/SAMPLE_RATE); - - //correct the error of computation the start amplitude - //at very high frequencies - if (freq>SAMPLE_RATE*0.96) { - filter.yn1=0.0; - filter.yn2=0.0; - - }; - }; - - filter.amp=amp; - filter.freq=freq; - filter.bw=bw; - computefiltercoefs(filter,freq,bw,1.0); -}; - -/* - * Do the filtering - */ -void SUBnote::filter(bpfilter &filter,REALTYPE *smps){ - int i; - REALTYPE out; - for (i=0;iAmpEnvelope,freq); - if (pars->PFreqEnvelopeEnabled!=0) FreqEnvelope=new Envelope(pars->FreqEnvelope,freq); - else FreqEnvelope=NULL; - if (pars->PBandWidthEnvelopeEnabled!=0) BandWidthEnvelope=new Envelope(pars->BandWidthEnvelope,freq); - else BandWidthEnvelope=NULL; - if (pars->PGlobalFilterEnabled!=0){ - globalfiltercenterq=pars->GlobalFilter->getq(); - GlobalFilterL=new Filter(pars->GlobalFilter); - if (stereo!=0) GlobalFilterR=new Filter(pars->GlobalFilter); - GlobalFilterEnvelope=new Envelope(pars->GlobalFilterEnvelope,freq); - GlobalFilterFreqTracking=pars->GlobalFilter->getfreqtracking(basefreq); - }; - computecurrentparameters(); -}; - - -/* - * Compute Parameters of SUBnote for each tick - */ -void SUBnote::computecurrentparameters(){ - if ((FreqEnvelope!=NULL)||(BandWidthEnvelope!=NULL)|| - (oldpitchwheel!=ctl->pitchwheel.data)|| - (oldbandwidth!=ctl->bandwidth.data)|| - (portamento!=0)){ - REALTYPE envfreq=1.0; - REALTYPE envbw=1.0; - REALTYPE gain=1.0; - - if (FreqEnvelope!=NULL) { - envfreq=FreqEnvelope->envout()/1200; - envfreq=pow(2.0,envfreq); - }; - envfreq*=ctl->pitchwheel.relfreq;//pitch wheel - if (portamento!=0) {//portamento is used - envfreq*=ctl->portamento.freqrap; - if (ctl->portamento.used==0){//the portamento has finished - portamento=0;//this note is no longer "portamented" - }; - }; - - if (BandWidthEnvelope!=NULL) { - envbw=BandWidthEnvelope->envout(); - envbw=pow(2,envbw); - }; - envbw*=ctl->bandwidth.relbw;//bandwidth controller - - REALTYPE tmpgain=1.0/sqrt(envbw*envfreq); - - for (int n=0;nbandwidth.data; - oldpitchwheel=ctl->pitchwheel.data; - }; - newamplitude=volume*AmpEnvelope->envout_dB()*2.0; - - //Filter - if (GlobalFilterL!=NULL){ - REALTYPE globalfilterpitch=GlobalFilterCenterPitch+GlobalFilterEnvelope->envout(); - REALTYPE filterfreq=globalfilterpitch+ctl->filtercutoff.relfreq+GlobalFilterFreqTracking; - filterfreq=GlobalFilterL->getrealfreq(filterfreq); - - GlobalFilterL->setfreq_and_q(filterfreq,globalfiltercenterq*ctl->filterq.relq); - if (GlobalFilterR!=NULL) GlobalFilterR->setfreq_and_q(filterfreq,globalfiltercenterq*ctl->filterq.relq); - }; - -}; - -/* - * Note Output - */ -int SUBnote::noteout(REALTYPE *outl,REALTYPE *outr){ - int i; - - for (i=0;ifilterout(&outl[0]); - - //right channel - if (stereo!=0){ - for (i=0;ifilterout(&outr[0]); - } else for (i=0;iSOUND_BUFFER_SIZE) n=SOUND_BUFFER_SIZE; - for (i=0;ifinished()!=0){ - for (i=0;irelasekey(); - if (FreqEnvelope!=NULL) FreqEnvelope->relasekey(); - if (BandWidthEnvelope!=NULL) BandWidthEnvelope->relasekey(); - if (GlobalFilterEnvelope!=NULL) GlobalFilterEnvelope->relasekey(); -}; - -/* - * Check if the note is finished - */ -int SUBnote::finished(){ - if (NoteEnabled==OFF) return(1); - else return(0); -}; - diff --git a/plugins/zynaddsubfx/src/Synth/SUBnote.cpp b/plugins/zynaddsubfx/src/Synth/SUBnote.cpp new file mode 100644 index 000000000..b3666229d --- /dev/null +++ b/plugins/zynaddsubfx/src/Synth/SUBnote.cpp @@ -0,0 +1,678 @@ +/* + ZynAddSubFX - a software synthesizer + + SUBnote.C - The "subtractive" synthesizer + Copyright (C) 2002-2005 Nasca Octavian Paul + Author: Nasca Octavian Paul + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2 or later) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include +#include +#include +#include "../globals.h" +#include "SUBnote.h" +#include "../Misc/Util.h" + +SUBnote::SUBnote(SUBnoteParameters *parameters,Controller *ctl_,REALTYPE freq,REALTYPE velocity,int portamento_,int midinote,bool besilent) +{ + ready=0; + + tmpsmp=new REALTYPE[SOUND_BUFFER_SIZE]; + tmprnd=new REALTYPE[SOUND_BUFFER_SIZE]; + + // Initialise some legato-specific vars + Legato.msg=LM_Norm; + Legato.fade.length=(int)(SAMPLE_RATE*0.005);// 0.005 seems ok. + if (Legato.fade.length<1) Legato.fade.length=1;// (if something's fishy) + Legato.fade.step=(1.0/Legato.fade.length); + Legato.decounter=-10; + Legato.param.freq=freq; + Legato.param.vel=velocity; + Legato.param.portamento=portamento_; + Legato.param.midinote=midinote; + Legato.silent=besilent; + + pars=parameters; + ctl=ctl_; + portamento=portamento_; + NoteEnabled=ON; + volume=pow(0.1,3.0*(1.0-pars->PVolume/96.0));//-60 dB .. 0 dB + volume*=VelF(velocity,pars->PAmpVelocityScaleFunction); + if (pars->PPanning!=0) panning=pars->PPanning/127.0; + else panning=RND; + numstages=pars->Pnumstages; + stereo=pars->Pstereo; + start=pars->Pstart; + firsttick=1; + int pos[MAX_SUB_HARMONICS]; + + if (pars->Pfixedfreq==0) basefreq=freq; + else { + basefreq=440.0; + int fixedfreqET=pars->PfixedfreqET; + if (fixedfreqET!=0) {//if the frequency varies according the keyboard note + REALTYPE tmp=(midinote-69.0)/12.0*(pow(2.0,(fixedfreqET-1)/63.0)-1.0); + if (fixedfreqET<=64) basefreq*=pow(2.0,tmp); + else basefreq*=pow(3.0,tmp); + }; + + }; + REALTYPE detune=getdetune(pars->PDetuneType,pars->PCoarseDetune,pars->PDetune); + basefreq*=pow(2.0,detune/1200.0);//detune +// basefreq*=ctl->pitchwheel.relfreq;//pitch wheel + + //global filter + GlobalFilterCenterPitch=pars->GlobalFilter->getfreq()+//center freq + (pars->PGlobalFilterVelocityScale/127.0*6.0)* //velocity sensing + (VelF(velocity,pars->PGlobalFilterVelocityScaleFunction)-1); + + GlobalFilterL=NULL; + GlobalFilterR=NULL; + GlobalFilterEnvelope=NULL; + + //select only harmonics that desire to compute + numharmonics=0; + for (int n=0;nPhmag[n]==0)continue; + if (n*basefreq>SAMPLE_RATE/2.0) break;//remove the freqs above the Nyquist freq + pos[numharmonics++]=n; + }; + firstnumharmonics=numharmonics;//(gf)Useful in legato mode. + + if (numharmonics==0) { + NoteEnabled=OFF; + return; + }; + + + lfilter=new bpfilter[numstages*numharmonics]; + if (stereo!=0) rfilter=new bpfilter[numstages*numharmonics]; + + //how much the amplitude is normalised (because the harmonics) + REALTYPE reduceamp=0.0; + + for (int n=0;nPbandwidth-127.0)/127.0*4)*numstages; + + //Bandwidth Scale + bw*=pow(1000/freq,(pars->Pbwscale-64.0)/64.0*3.0); + + //Relative BandWidth + bw*=pow(100,(pars->Phrelbw[pos[n]]-64.0)/64.0); + + if (bw>25.0) bw=25.0; + + //try to keep same amplitude on all freqs and bw. (empirically) + REALTYPE gain=sqrt(1500.0/(bw*freq)); + + REALTYPE hmagnew=1.0-pars->Phmag[pos[n]]/127.0; + REALTYPE hgain; + + switch (pars->Phmagtype) { + case 1: + hgain=exp(hmagnew*log(0.01)); + break; + case 2: + hgain=exp(hmagnew*log(0.001)); + break; + case 3: + hgain=exp(hmagnew*log(0.0001)); + break; + case 4: + hgain=exp(hmagnew*log(0.00001)); + break; + default: + hgain=1.0-hmagnew; + }; + gain*=hgain; + reduceamp+=hgain; + + for (int nph=0;nphPfixedfreq==0) initparameters(basefreq); + else initparameters(basefreq/440.0*freq); + + oldamplitude=newamplitude; + ready=1; +}; + + +// SUBlegatonote: This function is (mostly) a copy of SUBnote(...) and +// initparameters(...) stuck together with some lines removed so that +// it only alter the already playing note (to perform legato). It is +// possible I left stuff that is not required for this. +void SUBnote::SUBlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int midinote, bool externcall) +{ + //SUBnoteParameters *parameters=pars; + //Controller *ctl_=ctl; + + // Manage legato stuff + if (externcall) Legato.msg=LM_Norm; + if (Legato.msg!=LM_CatchUp) { + Legato.lastfreq=Legato.param.freq; + Legato.param.freq=freq; + Legato.param.vel=velocity; + Legato.param.portamento=portamento_; + Legato.param.midinote=midinote; + if (Legato.msg==LM_Norm) { + if (Legato.silent) { + Legato.fade.m=0.0; + Legato.msg=LM_FadeIn; + } else { + Legato.fade.m=1.0; + Legato.msg=LM_FadeOut; + return; + } + } + if (Legato.msg==LM_ToNorm) Legato.msg=LM_Norm; + } + + portamento=portamento_; + + volume=pow(0.1,3.0*(1.0-pars->PVolume/96.0));//-60 dB .. 0 dB + volume*=VelF(velocity,pars->PAmpVelocityScaleFunction); + if (pars->PPanning!=0) panning=pars->PPanning/127.0; + else panning=RND; + + ///start=pars->Pstart; + + int pos[MAX_SUB_HARMONICS]; + + if (pars->Pfixedfreq==0) basefreq=freq; + else { + basefreq=440.0; + int fixedfreqET=pars->PfixedfreqET; + if (fixedfreqET!=0) {//if the frequency varies according the keyboard note + REALTYPE tmp=(midinote-69.0)/12.0*(pow(2.0,(fixedfreqET-1)/63.0)-1.0); + if (fixedfreqET<=64) basefreq*=pow(2.0,tmp); + else basefreq*=pow(3.0,tmp); + }; + }; + REALTYPE detune=getdetune(pars->PDetuneType,pars->PCoarseDetune,pars->PDetune); + basefreq*=pow(2.0,detune/1200.0);//detune + + //global filter + GlobalFilterCenterPitch=pars->GlobalFilter->getfreq()+//center freq + (pars->PGlobalFilterVelocityScale/127.0*6.0)* //velocity sensing + (VelF(velocity,pars->PGlobalFilterVelocityScaleFunction)-1); + + + int legatonumharmonics=0; + for (int n=0;nPhmag[n]==0)continue; + if (n*basefreq>SAMPLE_RATE/2.0) break;//remove the freqs above the Nyquist freq + pos[legatonumharmonics++]=n; + }; + if (legatonumharmonics>firstnumharmonics) numharmonics=firstnumharmonics; + else numharmonics=legatonumharmonics; + + if (numharmonics==0) { + NoteEnabled=OFF; + return; + }; + + + //how much the amplitude is normalised (because the harmonics) + REALTYPE reduceamp=0.0; + + for (int n=0;nPbandwidth-127.0)/127.0*4)*numstages; + + //Bandwidth Scale + bw*=pow(1000/freq,(pars->Pbwscale-64.0)/64.0*3.0); + + //Relative BandWidth + bw*=pow(100,(pars->Phrelbw[pos[n]]-64.0)/64.0); + + if (bw>25.0) bw=25.0; + + //try to keep same amplitude on all freqs and bw. (empirically) + REALTYPE gain=sqrt(1500.0/(bw*freq)); + + REALTYPE hmagnew=1.0-pars->Phmag[pos[n]]/127.0; + REALTYPE hgain; + + switch (pars->Phmagtype) { + case 1: + hgain=exp(hmagnew*log(0.01)); + break; + case 2: + hgain=exp(hmagnew*log(0.001)); + break; + case 3: + hgain=exp(hmagnew*log(0.0001)); + break; + case 4: + hgain=exp(hmagnew*log(0.00001)); + break; + default: + hgain=1.0-hmagnew; + }; + gain*=hgain; + reduceamp+=hgain; + + for (int nph=0;nphPfixedfreq==0) freq=basefreq; + else freq*=basefreq/440.0; + + + /////////////// + // Altered initparameters(...) content: + + if (pars->PGlobalFilterEnabled!=0) { + globalfiltercenterq=pars->GlobalFilter->getq(); + GlobalFilterFreqTracking=pars->GlobalFilter->getfreqtracking(basefreq); + }; + + // end of the altered initparameters function content. + /////////////// + + oldamplitude=newamplitude; + + // End of the SUBlegatonote function. +}; + + +SUBnote::~SUBnote() +{ + if (NoteEnabled!=OFF) KillNote(); + delete [] tmpsmp; + delete [] tmprnd; +}; + +/* + * Kill the note + */ +void SUBnote::KillNote() +{ + if (NoteEnabled!=OFF) { + delete [] lfilter; + lfilter=NULL; + if (stereo!=0) delete [] rfilter; + rfilter=NULL; + delete(AmpEnvelope); + if (FreqEnvelope!=NULL) delete(FreqEnvelope); + if (BandWidthEnvelope!=NULL) delete(BandWidthEnvelope); + NoteEnabled=OFF; + }; + +}; + + +/* + * Compute the filters coefficients + */ +void SUBnote::computefiltercoefs(bpfilter &filter,REALTYPE freq,REALTYPE bw,REALTYPE gain) +{ + if (freq>SAMPLE_RATE/2.0-200.0) { + freq=SAMPLE_RATE/2.0-200.0; + }; + + REALTYPE omega=2.0*PI*freq/SAMPLE_RATE; + REALTYPE sn=sin(omega); + REALTYPE cs=cos(omega); + REALTYPE alpha=sn*sinh(LOG_2/2.0*bw*omega/sn); + + if (alpha>1) alpha=1; + if (alpha>bw) alpha=bw; + + filter.b0=alpha/(1.0+alpha)*filter.amp*gain; + filter.b2=-alpha/(1.0+alpha)*filter.amp*gain; + filter.a1=-2.0*cs/(1.0+alpha); + filter.a2=(1.0-alpha)/(1.0+alpha); + +}; + + +/* + * Initialise the filters + */ +void SUBnote::initfilter(bpfilter &filter,REALTYPE freq,REALTYPE bw,REALTYPE amp,REALTYPE mag) +{ + filter.xn1=0.0; + filter.xn2=0.0; + + if (start==0) { + filter.yn1=0.0; + filter.yn2=0.0; + } else { + REALTYPE a=0.1*mag;//empirically + REALTYPE p=RND*2.0*PI; + if (start==1) a*=RND; + filter.yn1=a*cos(p); + filter.yn2=a*cos(p+freq*2.0*PI/SAMPLE_RATE); + + //correct the error of computation the start amplitude + //at very high frequencies + if (freq>SAMPLE_RATE*0.96) { + filter.yn1=0.0; + filter.yn2=0.0; + + }; + }; + + filter.amp=amp; + filter.freq=freq; + filter.bw=bw; + computefiltercoefs(filter,freq,bw,1.0); +}; + +/* + * Do the filtering + */ +void SUBnote::filter(bpfilter &filter,REALTYPE *smps) +{ + int i; + REALTYPE out; + for (i=0;iAmpEnvelope,freq); + if (pars->PFreqEnvelopeEnabled!=0) FreqEnvelope=new Envelope(pars->FreqEnvelope,freq); + else FreqEnvelope=NULL; + if (pars->PBandWidthEnvelopeEnabled!=0) BandWidthEnvelope=new Envelope(pars->BandWidthEnvelope,freq); + else BandWidthEnvelope=NULL; + if (pars->PGlobalFilterEnabled!=0) { + globalfiltercenterq=pars->GlobalFilter->getq(); + GlobalFilterL=new Filter(pars->GlobalFilter); + if (stereo!=0) GlobalFilterR=new Filter(pars->GlobalFilter); + GlobalFilterEnvelope=new Envelope(pars->GlobalFilterEnvelope,freq); + GlobalFilterFreqTracking=pars->GlobalFilter->getfreqtracking(basefreq); + }; + computecurrentparameters(); +}; + + +/* + * Compute Parameters of SUBnote for each tick + */ +void SUBnote::computecurrentparameters() +{ + if ((FreqEnvelope!=NULL)||(BandWidthEnvelope!=NULL)|| + (oldpitchwheel!=ctl->pitchwheel.data)|| + (oldbandwidth!=ctl->bandwidth.data)|| + (portamento!=0)) { + REALTYPE envfreq=1.0; + REALTYPE envbw=1.0; + REALTYPE gain=1.0; + + if (FreqEnvelope!=NULL) { + envfreq=FreqEnvelope->envout()/1200; + envfreq=pow(2.0,envfreq); + }; + envfreq*=ctl->pitchwheel.relfreq;//pitch wheel + if (portamento!=0) {//portamento is used + envfreq*=ctl->portamento.freqrap; + if (ctl->portamento.used==0) {//the portamento has finished + portamento=0;//this note is no longer "portamented" + }; + }; + + if (BandWidthEnvelope!=NULL) { + envbw=BandWidthEnvelope->envout(); + envbw=pow(2,envbw); + }; + envbw*=ctl->bandwidth.relbw;//bandwidth controller + + REALTYPE tmpgain=1.0/sqrt(envbw*envfreq); + + for (int n=0;nbandwidth.data; + oldpitchwheel=ctl->pitchwheel.data; + }; + newamplitude=volume*AmpEnvelope->envout_dB()*2.0; + + //Filter + if (GlobalFilterL!=NULL) { + REALTYPE globalfilterpitch=GlobalFilterCenterPitch+GlobalFilterEnvelope->envout(); + REALTYPE filterfreq=globalfilterpitch+ctl->filtercutoff.relfreq+GlobalFilterFreqTracking; + filterfreq=GlobalFilterL->getrealfreq(filterfreq); + + GlobalFilterL->setfreq_and_q(filterfreq,globalfiltercenterq*ctl->filterq.relq); + if (GlobalFilterR!=NULL) GlobalFilterR->setfreq_and_q(filterfreq,globalfiltercenterq*ctl->filterq.relq); + }; + +}; + +/* + * Note Output + */ +int SUBnote::noteout(REALTYPE *outl,REALTYPE *outr) +{ + int i; + + for (i=0;ifilterout(&outl[0]); + + //right channel + if (stereo!=0) { + for (i=0;ifilterout(&outr[0]); + } else for (i=0;iSOUND_BUFFER_SIZE) n=SOUND_BUFFER_SIZE; + for (i=0;ifinished()!=0) { + for (i=0;irelasekey(); + if (FreqEnvelope!=NULL) FreqEnvelope->relasekey(); + if (BandWidthEnvelope!=NULL) BandWidthEnvelope->relasekey(); + if (GlobalFilterEnvelope!=NULL) GlobalFilterEnvelope->relasekey(); +}; + +/* + * Check if the note is finished + */ +int SUBnote::finished() +{ + if (NoteEnabled==OFF) return(1); + else return(0); +}; + diff --git a/plugins/zynaddsubfx/src/Synth/SUBnote.h b/plugins/zynaddsubfx/src/Synth/SUBnote.h index 892e1a476..48b55f1ca 100644 --- a/plugins/zynaddsubfx/src/Synth/SUBnote.h +++ b/plugins/zynaddsubfx/src/Synth/SUBnote.h @@ -1,12 +1,12 @@ /* ZynAddSubFX - a software synthesizer - + SUBnote.h - The subtractive synthesizer Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -29,85 +29,86 @@ #include "Envelope.h" #include "../DSP/Filter.h" -class SUBnote{ - public: - SUBnote(SUBnoteParameters *parameters,Controller *ctl_,REALTYPE freq,REALTYPE velocity,int portamento_,int midinote,bool besilent); - ~SUBnote(); +class SUBnote +{ +public: + SUBnote(SUBnoteParameters *parameters,Controller *ctl_,REALTYPE freq,REALTYPE velocity,int portamento_,int midinote,bool besilent); + ~SUBnote(); - void SUBlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int midinote, bool externcall); + void SUBlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, int midinote, bool externcall); - int noteout(REALTYPE *outl,REALTYPE *outr);//note output,return 0 if the note is finished - void relasekey(); - int finished(); - - int ready; //if I can get the sampledata - - private: - - void computecurrentparameters(); - void initparameters(REALTYPE freq); - void KillNote(); - - SUBnoteParameters *pars; + int noteout(REALTYPE *outl,REALTYPE *outr);//note output,return 0 if the note is finished + void relasekey(); + int finished(); - //parameters - int stereo; - int numstages;//number of stages of filters - int numharmonics;//number of harmonics (after the too higher hamonics are removed) - int firstnumharmonics;//To keep track of the first note's numharmonics value, useful in legato mode. - int start;//how the harmonics start - REALTYPE basefreq; - REALTYPE panning; - Envelope *AmpEnvelope; - Envelope *FreqEnvelope; - Envelope *BandWidthEnvelope; + int ready; //if I can get the sampledata - Filter *GlobalFilterL,*GlobalFilterR; - - Envelope *GlobalFilterEnvelope; - - //internal values - ONOFFTYPE NoteEnabled; - int firsttick,portamento; - REALTYPE volume,oldamplitude,newamplitude; +private: - REALTYPE GlobalFilterCenterPitch;//octaves - REALTYPE GlobalFilterFreqTracking; + void computecurrentparameters(); + void initparameters(REALTYPE freq); + void KillNote(); - struct bpfilter{ - REALTYPE freq,bw,amp; //filter parameters - REALTYPE a1,a2,b0,b2;//filter coefs. b1=0 - REALTYPE xn1,xn2,yn1,yn2; //filter internal values - }; + SUBnoteParameters *pars; - void initfilter(bpfilter &filter,REALTYPE freq,REALTYPE bw,REALTYPE amp,REALTYPE mag); - void computefiltercoefs(bpfilter &filter,REALTYPE freq,REALTYPE bw,REALTYPE gain); - void filter(bpfilter &filter,REALTYPE *smps); + //parameters + int stereo; + int numstages;//number of stages of filters + int numharmonics;//number of harmonics (after the too higher hamonics are removed) + int firstnumharmonics;//To keep track of the first note's numharmonics value, useful in legato mode. + int start;//how the harmonics start + REALTYPE basefreq; + REALTYPE panning; + Envelope *AmpEnvelope; + Envelope *FreqEnvelope; + Envelope *BandWidthEnvelope; - bpfilter *lfilter,*rfilter; - - REALTYPE *tmpsmp; - REALTYPE *tmprnd;//this is filled with random numbers - - Controller *ctl; - int oldpitchwheel,oldbandwidth; - REALTYPE globalfiltercenterq; - - // Legato vars - struct { - bool silent; - REALTYPE lastfreq; - LegatoMsg msg; - int decounter; - struct { // Fade In/Out vars - int length; - REALTYPE m, step; - } fade; - struct { // Note parameters - REALTYPE freq, vel; - int portamento, midinote; - } param; - } Legato; + Filter *GlobalFilterL,*GlobalFilterR; + + Envelope *GlobalFilterEnvelope; + + //internal values + ONOFFTYPE NoteEnabled; + int firsttick,portamento; + REALTYPE volume,oldamplitude,newamplitude; + + REALTYPE GlobalFilterCenterPitch;//octaves + REALTYPE GlobalFilterFreqTracking; + + struct bpfilter { + REALTYPE freq,bw,amp; //filter parameters + REALTYPE a1,a2,b0,b2;//filter coefs. b1=0 + REALTYPE xn1,xn2,yn1,yn2; //filter internal values + }; + + void initfilter(bpfilter &filter,REALTYPE freq,REALTYPE bw,REALTYPE amp,REALTYPE mag); + void computefiltercoefs(bpfilter &filter,REALTYPE freq,REALTYPE bw,REALTYPE gain); + void filter(bpfilter &filter,REALTYPE *smps); + + bpfilter *lfilter,*rfilter; + + REALTYPE *tmpsmp; + REALTYPE *tmprnd;//this is filled with random numbers + + Controller *ctl; + int oldpitchwheel,oldbandwidth; + REALTYPE globalfiltercenterq; + + // Legato vars + struct { + bool silent; + REALTYPE lastfreq; + LegatoMsg msg; + int decounter; + struct { // Fade In/Out vars + int length; + REALTYPE m, step; + } fade; + struct { // Note parameters + REALTYPE freq, vel; + int portamento, midinote; + } param; + } Legato; }; diff --git a/plugins/zynaddsubfx/src/UI/ConfigUI.cc b/plugins/zynaddsubfx/src/UI/ConfigUI.cc index 85ec3b445..0599214ec 100644 --- a/plugins/zynaddsubfx/src/UI/ConfigUI.cc +++ b/plugins/zynaddsubfx/src/UI/ConfigUI.cc @@ -155,6 +155,7 @@ Fl_Menu_Item ConfigUI::menu_Virtual[] = { {"QWERTY", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, {"Dvorak", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, {"QWERTZ", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, + {"AZERTY", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, {0,0,0,0,0,0,0,0,0} }; diff --git a/plugins/zynaddsubfx/src/UI/ConfigUI.fl b/plugins/zynaddsubfx/src/UI/ConfigUI.fl index a17872f40..ddb8e1bd6 100644 --- a/plugins/zynaddsubfx/src/UI/ConfigUI.fl +++ b/plugins/zynaddsubfx/src/UI/ConfigUI.fl @@ -272,6 +272,10 @@ midiinputnamebox->label(config.winmididevices[config.cfg.WindowsMidiInId].name); label QWERTZ xywh {35 35 100 20} labelfont 1 labelsize 11 } + menuitem {} { + label AZERTY + xywh {45 45 100 20} labelfont 1 labelsize 11 + } } } Fl_Group {} { diff --git a/plugins/zynaddsubfx/src/UI/MasterUI.cc b/plugins/zynaddsubfx/src/UI/MasterUI.cc index e37d70b9c..2b91bd54e 100644 --- a/plugins/zynaddsubfx/src/UI/MasterUI.cc +++ b/plugins/zynaddsubfx/src/UI/MasterUI.cc @@ -1,7 +1,7 @@ // generated by Fast Light User Interface Designer (fluid) version 1.0300 #include "MasterUI.h" -//Copyright (c) 2002-2005 Nasca Octavian Paul +//Copyright (c) 2002-2009 Nasca Octavian Paul //License: GNU GPL version 2 or later VUMeter::VUMeter(int x,int y, int w, int h, const char *label):Fl_Box(x,y,w,h,label) { @@ -1766,14 +1766,14 @@ Fl_Double_Window* MasterUI::make_window() { masterwindow->xclass("zynaddsubfx"); masterwindow->end(); } // Fl_Double_Window* masterwindow - { aboutwindow = new Fl_Double_Window(330, 210, "Copyright..."); + { aboutwindow = new Fl_Double_Window(365, 280, "Copyright..."); aboutwindow->user_data((void*)(this)); - { Fl_Box* o = new Fl_Box(0, 35, 330, 25, "Copyright (c) 2002-2005 Nasca O. Paul and others"); + { Fl_Box* o = new Fl_Box(15, 35, 335, 55, "Copyright (c) 2002-2009 Nasca O. PAUL and others. Please read AUTHORS.txt"); o->labeltype(FL_EMBOSSED_LABEL); o->labelsize(15); - o->align(Fl_Align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE)); + o->align(Fl_Align(192|FL_ALIGN_INSIDE)); } // Fl_Box* o - { Fl_Box* o = new Fl_Box(0, 60, 325, 115, "This is free software; you may redistribute it and/or modify it under the ter\ + { Fl_Box* o = new Fl_Box(15, 90, 335, 145, "This is free software; you may redistribute it and/or modify it under the ter\ ms of the \nversion 2 (or any later version) of the GNU General Public License\ as published by the Free Software Fundation.\n This program comes with\n ABS\ OLUTELY NO WARRANTY. \n See the version 2 (or any later version) of the \nGNU \ @@ -1782,12 +1782,12 @@ General Public License for details."); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_WRAP|FL_ALIGN_INSIDE)); } // Fl_Box* o - { Fl_Button* o = new Fl_Button(80, 180, 180, 25, "Close this window"); + { Fl_Button* o = new Fl_Button(80, 245, 190, 25, "Close this window"); o->box(FL_THIN_UP_BOX); o->labelsize(11); o->callback((Fl_Callback*)cb_Close); } // Fl_Button* o - { Fl_Box* o = new Fl_Box(5, 5, 325, 30, "ZynAddSubFX"); + { Fl_Box* o = new Fl_Box(15, 5, 335, 30, "ZynAddSubFX"); o->labeltype(FL_EMBOSSED_LABEL); o->labelfont(1); o->labelsize(20); @@ -2306,7 +2306,7 @@ void MasterUI::updatepanel() { void MasterUI::setfilelabel(const char *filename) { if (filename!=NULL) snprintf(&masterwindowlabel[0],100,"%s - ZynAddSubFX",fl_filename_name(filename)); - else snprintf(&masterwindowlabel[0],100,"%s","ZynAddSubFX (c)2002-2006 Nasca Paul and others"); + else snprintf(&masterwindowlabel[0],100,"%s","ZynAddSubFX"); masterwindowlabel[99]='\0'; masterwindow->label(&masterwindowlabel[0]); simplemasterwindow->label(&masterwindowlabel[0]); @@ -2401,8 +2401,8 @@ void MasterUI::do_new_master() { updatepanel(); } -void MasterUI::do_load_master(char* file ) { - char *filename; +void MasterUI::do_load_master(const char* file ) { + const char *filename; if (file == NULL) { filename=fl_file_chooser("Open:","({*.xmz})",NULL,0); if (filename==NULL) return; @@ -2431,14 +2431,16 @@ if (result==-10) fl_alert("Error: Could not load the file\nbecause it is not a z else if (result<0) fl_alert("Error: Could not load the file."); } -void MasterUI::do_save_master(char* file ) { - char *filename; +void MasterUI::do_save_master(const char* file ) { + const char *filename; +char *tmp; int result=0; if (file == NULL) { - filename=fl_file_chooser("Save:","({*.xmz})",NULL,0); - if (filename==NULL) return; - filename=fl_filename_setext(filename,".xmz"); - result=fileexists(filename); + tmp=fl_file_chooser("Save:","({*.xmz})",NULL,0); + if (tmp==NULL) return; + tmp=fl_filename_setext(tmp,".xmz"); + filename=tmp; + result=fileexists(tmp); if (result) { result=0; if (!fl_choice("The file exists. Overwrite it?","No","Yes",NULL)) return; diff --git a/plugins/zynaddsubfx/src/UI/MasterUI.fl b/plugins/zynaddsubfx/src/UI/MasterUI.fl index dbe81aa03..b0c77d790 100644 --- a/plugins/zynaddsubfx/src/UI/MasterUI.fl +++ b/plugins/zynaddsubfx/src/UI/MasterUI.fl @@ -1,8 +1,9 @@ # data file for the Fltk User Interface Designer (fluid) -version 1.0107 +version 1.0109 header_name {.h} code_name {.cc} -decl {//Copyright (c) 2002-2005 Nasca Octavian Paul} {} +decl {//Copyright (c) 2002-2009 Nasca Octavian Paul} {selected +} decl {//License: GNU GPL version 2 or later} {} @@ -413,12 +414,9 @@ panellistitemgroup->redraw();} {} decl {BankUI *bankui;} {} } -class MasterUI {open -} { - Function {make_window()} {open - } { +class MasterUI {} { + Function {make_window()} {} { Fl_Window masterwindow { - xclass zynaddsubfx label zynaddsubfx callback {\#ifdef VSTAUDIOOUT fl_alert("ZynAddSubFX could not be closed this way, because it's a VST plugin. Please use the host aplication to close it."); @@ -428,7 +426,7 @@ if (fl_choice("Exit and leave the unsaved data?","No","Yes",NULL)) { *exitprogram=1; }; \#endif} - xywh {31 206 390 465} type Double visible + xywh {31 206 390 465} type Double xclass zynaddsubfx visible } { Fl_Menu_Bar mastermenu { xywh {-5 0 690 25} @@ -997,11 +995,11 @@ panelwindow->show();} } Fl_Window aboutwindow { label {Copyright...} - xywh {629 278 330 210} type Double hide + xywh {411 344 365 280} type Double hide } { Fl_Box {} { - label {Copyright (c) 2002-2005 Nasca O. Paul and others} - xywh {0 35 330 25} labeltype EMBOSSED_LABEL labelsize 15 align 16 + label {Copyright (c) 2002-2009 Nasca O. PAUL and others. Please read AUTHORS.txt} + xywh {15 35 335 55} labeltype EMBOSSED_LABEL labelsize 15 align 208 } Fl_Box {} { label {This is free software; you may redistribute it and/or modify it under the terms of the @@ -1010,16 +1008,16 @@ version 2 (or any later version) of the GNU General Public License as published ABSOLUTELY NO WARRANTY. See the version 2 (or any later version) of the GNU General Public License for details.} - xywh {0 60 325 115} labelfont 1 labelsize 11 align 144 + xywh {15 90 335 145} labelfont 1 labelsize 11 align 144 } Fl_Button {} { label {Close this window} callback {aboutwindow->hide();} - xywh {80 180 180 25} box THIN_UP_BOX labelsize 11 + xywh {80 245 190 25} box THIN_UP_BOX labelsize 11 } Fl_Box {} { label ZynAddSubFX - xywh {5 5 325 30} labeltype EMBOSSED_LABEL labelfont 1 labelsize 20 align 16 + xywh {15 5 335 30} labeltype EMBOSSED_LABEL labelfont 1 labelsize 20 align 16 } } Fl_Window syseffsendwindow { @@ -1613,14 +1611,12 @@ config.cfg.UserInterfaceMode=2;} panellistitem[npart]->refresh(); };} {} } - Function {setfilelabel(const char *filename)} {open - } { + Function {setfilelabel(const char *filename)} {} { code {if (filename!=NULL) snprintf(&masterwindowlabel[0],100,"%s - ZynAddSubFX",fl_filename_name(filename)); - else snprintf(&masterwindowlabel[0],100,"%s","ZynAddSubFX (c)2002-2006 Nasca Paul and others"); + else snprintf(&masterwindowlabel[0],100,"%s","ZynAddSubFX"); masterwindowlabel[99]='\\0'; masterwindow->label(&masterwindowlabel[0]); -simplemasterwindow->label(&masterwindowlabel[0]);} {selected - } +simplemasterwindow->label(&masterwindowlabel[0]);} {} } Function {MasterUI(Master *master_,int *exitprogram_)} {} { code {master=master_; @@ -1706,8 +1702,8 @@ simplesyseffsend->value(master->Psysefxvol[nsyseff][npart]);} {} updatepanel();} {} } - Function {do_load_master(char* file = NULL)} {} { - code {char *filename; + Function {do_load_master(const char* file = NULL)} {} { + code {const char *filename; if (file == NULL) { filename=fl_file_chooser("Open:","({*.xmz})",NULL,0); if (filename==NULL) return; @@ -1735,14 +1731,16 @@ if (result>=0) setfilelabel(filename); if (result==-10) fl_alert("Error: Could not load the file\\nbecause it is not a zynaddsubfx parameters file."); else if (result<0) fl_alert("Error: Could not load the file.");} {} } - Function {do_save_master(char* file = NULL)} {} { - code {char *filename; + Function {do_save_master(const char* file = NULL)} {} { + code {const char *filename; +char *tmp; int result=0; if (file == NULL) { - filename=fl_file_chooser("Save:","({*.xmz})",NULL,0); - if (filename==NULL) return; - filename=fl_filename_setext(filename,".xmz"); - result=fileexists(filename); + tmp=fl_file_chooser("Save:","({*.xmz})",NULL,0); + if (tmp==NULL) return; + tmp=fl_filename_setext(tmp,".xmz"); + filename=tmp; + result=fileexists(tmp); if (result) { result=0; if (!fl_choice("The file exists. Overwrite it?","No","Yes",NULL)) return; diff --git a/plugins/zynaddsubfx/src/UI/MasterUI.h b/plugins/zynaddsubfx/src/UI/MasterUI.h index 4eed5af0c..fc1db4b59 100644 --- a/plugins/zynaddsubfx/src/UI/MasterUI.h +++ b/plugins/zynaddsubfx/src/UI/MasterUI.h @@ -427,8 +427,8 @@ public: void showUI(); void simplerefresh(); void do_new_master(); - void do_load_master(char* file = NULL); - void do_save_master(char* file = NULL); + void do_load_master(const char* file = NULL); + void do_save_master(const char* file = NULL); void refresh_master_ui(); private: Master *master; diff --git a/plugins/zynaddsubfx/src/UI/PartUI.cc b/plugins/zynaddsubfx/src/UI/PartUI.cc index 3c1d209ee..986b11995 100644 --- a/plugins/zynaddsubfx/src/UI/PartUI.cc +++ b/plugins/zynaddsubfx/src/UI/PartUI.cc @@ -678,6 +678,29 @@ void PartUI::cb_t(WidgetPDial* o, void* v) { ((PartUI*)(o->parent()->parent()->user_data()))->cb_t_i(o,v); } +void PartUI::cb_propta_i(WidgetPDial* o, void*) { + part->ctl.portamento.propRate=(int) o->value(); +} +void PartUI::cb_propta(WidgetPDial* o, void* v) { + ((PartUI*)(o->parent()->parent()->user_data()))->cb_propta_i(o,v); +} + +void PartUI::cb_proptb_i(WidgetPDial* o, void*) { + part->ctl.portamento.propDepth=(int) o->value(); +} +void PartUI::cb_proptb(WidgetPDial* o, void* v) { + ((PartUI*)(o->parent()->parent()->user_data()))->cb_proptb_i(o,v); +} + +void PartUI::cb_Proprt_i(Fl_Check_Button* o, void*) { + part->ctl.portamento.proportional=(int) o->value(); +if(o->value()){propta->activate();proptb->activate();} +else {propta->deactivate();proptb->deactivate();}; +} +void PartUI::cb_Proprt(Fl_Check_Button* o, void* v) { + ((PartUI*)(o->parent()->parent()->user_data()))->cb_Proprt_i(o,v); +} + void PartUI::cb_BWdpth_i(WidgetPDial* o, void*) { part->ctl.resonancebandwidth.depth=(int) o->value(); } @@ -1168,7 +1191,7 @@ nge the name or middle button to change the instrument information"); } // Fl_Check_Button* o partgroup->end(); } // Fl_Group* partgroup - { ctlwindow = new Fl_Double_Window(460, 130, "Controllers"); + { ctlwindow = new Fl_Double_Window(500, 130, "Controllers"); ctlwindow->user_data((void*)(this)); { Fl_Check_Button* o = new Fl_Check_Button(155, 55, 45, 20, "Expr"); o->tooltip("Expression enable"); @@ -1301,7 +1324,7 @@ nge the name or middle button to change the instrument information"); o->box(FL_THIN_UP_BOX); o->callback((Fl_Callback*)cb_Reset); } // Fl_Button* o - { Fl_Group* o = new Fl_Group(280, 15, 120, 85, "Portamento"); + { Fl_Group* o = new Fl_Group(280, 15, 160, 90, "Portamento"); o->box(FL_ENGRAVED_FRAME); o->labelfont(1); o->labelsize(10); @@ -1340,7 +1363,7 @@ cents)"); o->callback((Fl_Callback*)cb_thresh); o->value(part->ctl.portamento.pitchthresh); } // Fl_Counter* o - { Fl_Check_Button* o = new Fl_Check_Button(370, 70, 15, 15, "th.type"); + { Fl_Check_Button* o = new Fl_Check_Button(365, 70, 15, 15, "th.type"); o->tooltip("Threshold type (min/max)"); o->down_box(FL_DOWN_BOX); o->labelsize(10); @@ -1368,13 +1391,55 @@ cents)"); o->when(FL_WHEN_CHANGED); o->value(part->ctl.portamento.updowntimestretch); } // WidgetPDial* o + { WidgetPDial* o = propta = new WidgetPDial(405, 20, 25, 25, "Prp.Rate"); + propta->tooltip("Distance required to double change from nonpropotinal portamento time"); + propta->box(FL_OVAL_BOX); + propta->color(FL_BACKGROUND_COLOR); + propta->selection_color(FL_INACTIVE_COLOR); + propta->labeltype(FL_NORMAL_LABEL); + propta->labelfont(0); + propta->labelsize(9); + propta->labelcolor(FL_FOREGROUND_COLOR); + propta->maximum(127); + propta->step(1); + propta->callback((Fl_Callback*)cb_propta); + propta->align(Fl_Align(FL_ALIGN_BOTTOM)); + propta->when(FL_WHEN_CHANGED); + o->value(part->ctl.portamento.propRate); + } // WidgetPDial* propta + { WidgetPDial* o = proptb = new WidgetPDial(405, 60, 25, 25, "Prp.Dpth"); + proptb->tooltip("The difference from nonproportinal portamento"); + proptb->box(FL_OVAL_BOX); + proptb->color(FL_BACKGROUND_COLOR); + proptb->selection_color(FL_INACTIVE_COLOR); + proptb->labeltype(FL_NORMAL_LABEL); + proptb->labelfont(0); + proptb->labelsize(9); + proptb->labelcolor(FL_FOREGROUND_COLOR); + proptb->maximum(127); + proptb->step(1); + proptb->callback((Fl_Callback*)cb_proptb); + proptb->align(Fl_Align(FL_ALIGN_BOTTOM)); + proptb->when(FL_WHEN_CHANGED); + o->value(part->ctl.portamento.propDepth); + } // WidgetPDial* proptb + { Fl_Check_Button* o = new Fl_Check_Button(285, 40, 50, 15, "Proprt."); + o->tooltip("Enable Proportinal Portamento (over fixed Portamento)"); + o->box(FL_THIN_UP_BOX); + o->down_box(FL_DOWN_BOX); + o->labelsize(9); + o->callback((Fl_Callback*)cb_Proprt); + o->value(part->ctl.portamento.proportional); + if(o->value()){propta->activate();proptb->activate();} + else {propta->deactivate();proptb->deactivate();} + } // Fl_Check_Button* o o->end(); } // Fl_Group* o - { Fl_Group* o = new Fl_Group(400, 15, 45, 85, "Resonance"); + { Fl_Group* o = new Fl_Group(440, 15, 50, 90, "Resonance"); o->box(FL_ENGRAVED_BOX); o->labelfont(1); o->labelsize(10); - { WidgetPDial* o = new WidgetPDial(410, 60, 25, 25, "BWdpth"); + { WidgetPDial* o = new WidgetPDial(450, 60, 25, 25, "BWdpth"); o->tooltip("BandWidth controller depth"); o->box(FL_OVAL_BOX); o->color(FL_BACKGROUND_COLOR); @@ -1390,7 +1455,7 @@ cents)"); o->when(FL_WHEN_CHANGED); o->value(part->ctl.resonancebandwidth.depth); } // WidgetPDial* o - { WidgetPDial* o = new WidgetPDial(410, 20, 25, 25, "CFdpth"); + { WidgetPDial* o = new WidgetPDial(450, 20, 25, 25, "CFdpth"); o->tooltip("Center Frequency controller Depth"); o->box(FL_OVAL_BOX); o->color(FL_BACKGROUND_COLOR); diff --git a/plugins/zynaddsubfx/src/UI/PartUI.fl b/plugins/zynaddsubfx/src/UI/PartUI.fl index 3a7288514..05fe5151a 100644 --- a/plugins/zynaddsubfx/src/UI/PartUI.fl +++ b/plugins/zynaddsubfx/src/UI/PartUI.fl @@ -42,9 +42,9 @@ decl {\#include "../Misc/Master.h"} {public decl {\#include "../Misc/Part.h"} {public } -class PartSysEffSend {open : {public Fl_Group} +class PartSysEffSend {: {public Fl_Group} } { - Function {make_window()} {open private + Function {make_window()} {private } { Fl_Window syseffsend { private xywh {584 83 90 35} type Double hide @@ -52,7 +52,7 @@ class PartSysEffSend {open : {public Fl_Group} } { Fl_Dial {} { label 01 - callback {master->setPsysefxvol(npart,neff,(int) o->value());} selected + callback {master->setPsysefxvol(npart,neff,(int) o->value());} xywh {0 0 25 25} box ROUND_UP_BOX labelfont 1 labelsize 10 align 130 maximum 127 step 1 code0 {o->size(25,25);} code1 {o->value(master->Psysefxvol[neff][npart]);} @@ -274,9 +274,9 @@ end();} {} decl {PartUI_ *partui;} {} } -class PartUI {open : {public Fl_Group,PartUI_} +class PartUI {: {public Fl_Group,PartUI_} } { - Function {make_window()} {open private + Function {make_window()} {private } { Fl_Window partgroup { private xywh {424 178 385 180} type Double hide @@ -457,7 +457,7 @@ if (part->Penabled==0) partgroupui->deactivate(); } Fl_Window ctlwindow { label Controllers - private xywh {198 472 460 130} type Double hide + private xywh {542 212 500 130} type Double hide } { Fl_Check_Button {} { label Expr @@ -540,8 +540,8 @@ if (part->ctl.sustain.receive==0) { xywh {5 105 210 20} box THIN_UP_BOX } Fl_Group {} { - label Portamento open - xywh {280 15 120 85} box ENGRAVED_FRAME labelfont 1 labelsize 10 + label Portamento + xywh {280 15 160 90} box ENGRAVED_FRAME labelfont 1 labelsize 10 } { Fl_Check_Button {} { label Rcv @@ -565,7 +565,7 @@ if (part->ctl.sustain.receive==0) { Fl_Check_Button {} { label {th.type} callback {part->ctl.portamento.pitchthreshtype=(int) o->value();} - tooltip {Threshold type (min/max)} xywh {370 70 15 15} down_box DOWN_BOX labelsize 10 align 2 + tooltip {Threshold type (min/max)} xywh {365 70 15 15} down_box DOWN_BOX labelsize 10 align 2 code0 {o->value(part->ctl.portamento.pitchthreshtype);} } Fl_Box {} { @@ -581,22 +581,46 @@ part->ctl.portamento.updowntimestretch=x;} code0 {o->value(part->ctl.portamento.updowntimestretch);} class WidgetPDial } + Fl_Dial propta { + label {Prp.Rate} + callback {part->ctl.portamento.propRate=(int) o->value();} + tooltip {Distance required to double change from nonpropotinal portamento time} xywh {405 20 25 25} labelsize 9 maximum 127 step 1 + code0 {o->value(part->ctl.portamento.propRate);} + class WidgetPDial + } + Fl_Dial proptb { + label {Prp.Dpth} + callback {part->ctl.portamento.propDepth=(int) o->value();} selected + tooltip {The difference from nonproportinal portamento} xywh {405 60 25 25} labelsize 9 maximum 127 step 1 + code0 {o->value(part->ctl.portamento.propDepth);} + class WidgetPDial + } + Fl_Check_Button {} { + label {Proprt.} + callback {part->ctl.portamento.proportional=(int) o->value(); +if(o->value()){propta->activate();proptb->activate();} +else {propta->deactivate();proptb->deactivate();}} + tooltip {Enable Proportinal Portamento (over fixed Portamento)} xywh {285 40 50 15} box THIN_UP_BOX down_box DOWN_BOX labelsize 9 + code0 {o->value(part->ctl.portamento.proportional);} + code1 {if(o->value()){propta->activate();proptb->activate();}} + code2 {else {propta->deactivate();proptb->deactivate();}} + } } Fl_Group {} { - label Resonance open - xywh {400 15 45 85} box ENGRAVED_BOX labelfont 1 labelsize 10 + label Resonance + xywh {440 15 50 90} box ENGRAVED_BOX labelfont 1 labelsize 10 } { Fl_Dial {} { label BWdpth callback {part->ctl.resonancebandwidth.depth=(int) o->value();} - tooltip {BandWidth controller depth} xywh {410 60 25 25} labelsize 10 maximum 127 step 1 + tooltip {BandWidth controller depth} xywh {450 60 25 25} labelsize 10 maximum 127 step 1 code0 {o->value(part->ctl.resonancebandwidth.depth);} class WidgetPDial } Fl_Dial {} { label CFdpth callback {part->ctl.resonancecenter.depth=(int) o->value();} - tooltip {Center Frequency controller Depth} xywh {410 20 25 25} labelsize 10 maximum 127 step 1 + tooltip {Center Frequency controller Depth} xywh {450 20 25 25} labelsize 10 maximum 127 step 1 code0 {o->value(part->ctl.resonancecenter.depth);} class WidgetPDial } diff --git a/plugins/zynaddsubfx/src/UI/PartUI.h b/plugins/zynaddsubfx/src/UI/PartUI.h index 5189b790e..6e3f1ada9 100644 --- a/plugins/zynaddsubfx/src/UI/PartUI.h +++ b/plugins/zynaddsubfx/src/UI/PartUI.h @@ -207,6 +207,18 @@ private: static void cb_th(Fl_Check_Button*, void*); void cb_t_i(WidgetPDial*, void*); static void cb_t(WidgetPDial*, void*); +public: + WidgetPDial *propta; +private: + void cb_propta_i(WidgetPDial*, void*); + static void cb_propta(WidgetPDial*, void*); +public: + WidgetPDial *proptb; +private: + void cb_proptb_i(WidgetPDial*, void*); + static void cb_proptb(WidgetPDial*, void*); + void cb_Proprt_i(Fl_Check_Button*, void*); + static void cb_Proprt(Fl_Check_Button*, void*); void cb_BWdpth_i(WidgetPDial*, void*); static void cb_BWdpth(WidgetPDial*, void*); void cb_CFdpth_i(WidgetPDial*, void*); diff --git a/plugins/zynaddsubfx/src/UI/VirKeyboard.cc b/plugins/zynaddsubfx/src/UI/VirKeyboard.cc index 4fc68517d..49491ff62 100644 --- a/plugins/zynaddsubfx/src/UI/VirKeyboard.cc +++ b/plugins/zynaddsubfx/src/UI/VirKeyboard.cc @@ -10,6 +10,8 @@ static const int keysoct1dw[]={'\'','2',',','3','.','p','5','y','6','f','7','g', static const int keysoct2dw[]={';','o','q','e','j','k','i','x','d','b','h','m','w','n','v','s','z',0}; static const int keysoct1qwertz[]={'q','2','w','3','e','r','5','t','6','z','7','u','i','9','o','0','p',252,'\'','+','\\',FL_Enter,0}; static const int keysoct2qwertz[]={'y','s','x','d','c','v','g','b','h','n','j','m',',','l','.',246,'-',0}; +static const int keysoct1az[]={'a',233,'z','\"','e','r','(','t','-','y',232,'u','i',231,'o',224,'p',65106,'=','$',0}; +static const int keysoct2az[]={'w','s','x','d','c','v','g','b','h','n','j',',',';','l',':','m','!',0}; VirKeys::VirKeys(int x,int y, int w, int h, const char *label):Fl_Box(x,y,w,h,label) { master=NULL; @@ -125,6 +127,9 @@ if (config.cfg.VirKeybLayout==2) { }else if (config.cfg.VirKeybLayout==3) { keysoct1=keysoct1qwertz; keysoct2=keysoct2qwertz; +}else if (config.cfg.VirKeybLayout==4) { + keysoct1=keysoct1az; + keysoct2=keysoct2az; }; if ((event==FL_KEYDOWN)||(event==FL_KEYUP)){ @@ -146,11 +151,14 @@ return(1); } void VirKeys::presskey(int nk,int exclusive,int type) { - if (nk>=N_OCT*12) return; + //Exclusive means that multiple keys can be pressed at once +//when the user uses the shift key +if (nk>=N_OCT*12) return; if ((nk<0)&&(exclusive==0)) { relaseallkeys(type); return; }; +if (nk<0) return; if (pressed[nk]!=0) return;//the key is already pressed if (exclusive!=0) relaseallkeys(type); diff --git a/plugins/zynaddsubfx/src/UI/VirKeyboard.fl b/plugins/zynaddsubfx/src/UI/VirKeyboard.fl index 0b1b8c575..0b83b5b56 100644 --- a/plugins/zynaddsubfx/src/UI/VirKeyboard.fl +++ b/plugins/zynaddsubfx/src/UI/VirKeyboard.fl @@ -37,11 +37,15 @@ decl {const int keysoct1dw[]={'\\'','2',',','3','.','p','5','y','6','f','7','g', decl {const int keysoct2dw[]={';','o','q','e','j','k','i','x','d','b','h','m','w','n','v','s','z',0};} {} -decl {const int keysoct1qwertz[]={'q','2','w','3','e','r','5','t','6','z','7','u','i','9','o','0','p',252,'\\\'','+','\\\\',FL_Enter,0};} {} +decl {const int keysoct1qwertz[]={'q','2','w','3','e','r','5','t','6','z','7','u','i','9','o','0','p',252,'\\'','+','\\\\',FL_Enter,0};} {} decl {const int keysoct2qwertz[]={'y','s','x','d','c','v','g','b','h','n','j','m',',','l','.',246,'-',0};} {} -class VirKeys {open : {public Fl_Box} +decl {const int keysoct1az[]={'a',233,'z','\\"','e','r','(','t','-','y',232,'u','i',231,'o',224,'p',65106,'=','$',0};} {} + +decl {const int keysoct2az[]={'w','s','x','d','c','v','g','b','h','n','j',',',';','l',':','m','!',0};} {} + +class VirKeys {: {public Fl_Box} } { decl {static const int N_OCT=6;} {} decl {static const int SIZE_WHITE=14;} {} @@ -158,6 +162,9 @@ if (config.cfg.VirKeybLayout==2) { }else if (config.cfg.VirKeybLayout==3) { keysoct1=keysoct1qwertz; keysoct2=keysoct2qwertz; +}else if (config.cfg.VirKeybLayout==4) { + keysoct1=keysoct1az; + keysoct2=keysoct2az; }; if ((event==FL_KEYDOWN)||(event==FL_KEYUP)){ @@ -179,11 +186,14 @@ return(1);} {} } Function {presskey(int nk,int exclusive,int type)} {selected } { - code {if (nk>=N_OCT*12) return; + code {//Exclusive means that multiple keys can be pressed at once +//when the user uses the shift key +if (nk>=N_OCT*12) return; if ((nk<0)&&(exclusive==0)) { relaseallkeys(type); return; }; +if (nk<0) return; if (pressed[nk]!=0) return;//the key is already pressed if (exclusive!=0) relaseallkeys(type); @@ -228,8 +238,7 @@ pthread_mutex_unlock(&master->mutex);} {} } } -class VirKeyboard {open -} { +class VirKeyboard {} { Function {make_window()} {} { Fl_Window virkeyboardwindow { label {Virtual Keyboard - ZynAddSubFX} diff --git a/plugins/zynaddsubfx/src/bugs.txt b/plugins/zynaddsubfx/src/bugs.txt new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/plugins/zynaddsubfx/src/bugs.txt @@ -0,0 +1 @@ + diff --git a/plugins/zynaddsubfx/src/globals.h b/plugins/zynaddsubfx/src/globals.h index 07ce9a98f..f13da7d95 100644 --- a/plugins/zynaddsubfx/src/globals.h +++ b/plugins/zynaddsubfx/src/globals.h @@ -1,13 +1,13 @@ /* ZynAddSubFX - a software synthesizer - globals.h - it contains program settings and the program capabilities + globals.h - it contains program settings and the program capabilities like number of parts, of effects Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License + it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, @@ -28,42 +28,42 @@ //What float type I use for internal sampledata #define REALTYPE float -struct FFTFREQS{ +struct FFTFREQS { REALTYPE *s,*c;//sine and cosine components }; extern void newFFTFREQS(FFTFREQS *f,int size); extern void deleteFFTFREQS(FFTFREQS *f); -// Sampling rate +/**Sampling rate*/ extern int SAMPLE_RATE; -/* +/** * The size of a sound buffer (or the granularity) * All internal transfer of sound data use buffer of this size * All parameters are constant during this period of time, exception * some parameters(like amplitudes) which are linear interpolated. - * If you increase this you'll ecounter big latencies, but if you + * If you increase this you'll ecounter big latencies, but if you * decrease this the CPU requirements gets high. */ extern int SOUND_BUFFER_SIZE; -/* +/** * The size of ADnote Oscillator * Decrease this => poor quality * Increase this => CPU requirements gets high (only at start of the note) */ extern int OSCIL_SIZE; -/* +/** * The number of harmonics of additive synth * This must be smaller than OSCIL_SIZE/2 */ #define MAX_AD_HARMONICS 128 -/* +/** * The number of harmonics of substractive */ #define MAX_SUB_HARMONICS 64 @@ -107,7 +107,7 @@ extern int OSCIL_SIZE; #define NUM_INS_EFX 8 /* - * Number of part's insertion effects + * Number of part's insertion effects */ #define NUM_PART_EFX 3 @@ -142,7 +142,7 @@ extern int OSCIL_SIZE; #define MAX_FILTER_STAGES 5 /* - * Formant filter (FF) limits + * Formant filter (FF) limits */ #define FF_MAX_VOWELS 6 #define FF_MAX_FORMANTS 12 @@ -173,7 +173,7 @@ extern int OSCIL_SIZE; /* - * dB + * dB */ #define dB2rap(dB) ((exp((dB)*LOG_10/20.0))) #define rap2dB(rap) ((20*log(rap)/LOG_10)) @@ -185,16 +185,17 @@ extern int OSCIL_SIZE; #define ZERO(data,size) {char *data_=(char *) data;for (int i=0;i