diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..79a12e7b1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +tags +*.swp +build/ diff --git a/CMakeLists.txt b/CMakeLists.txt index bd130709b..04ab204c8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -426,7 +426,7 @@ IF(NOT LMMS_HAVE_SAMPLERATE) ${CMAKE_SOURCE_DIR}/src/3rdparty/samplerate/mid_qual_coeffs.h ${CMAKE_SOURCE_DIR}/src/3rdparty/samplerate/fastest_coeffs.h ${CMAKE_SOURCE_DIR}/src/3rdparty/samplerate/common.h - ${CMAKE_SOURCE_DIR}/src/3rdparty/samplerate/config.h + ${CMAKE_SOURCE_DIR}/src/3rdparty/samplerate/src_config.h ${CMAKE_SOURCE_DIR}/src/3rdparty/samplerate/float_cast.h ${CMAKE_SOURCE_DIR}/src/3rdparty/samplerate/src_zoh.c ${CMAKE_SOURCE_DIR}/src/3rdparty/samplerate/src_linear.c) @@ -437,11 +437,12 @@ ENDIF(NOT LMMS_HAVE_SAMPLERATE) CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/lmmsconfig.h.in ${CMAKE_BINARY_DIR}/lmmsconfig.h) CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/lmmsversion.h.in ${CMAKE_BINARY_DIR}/lmmsversion.h) CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/lmms.rc.in ${CMAKE_BINARY_DIR}/lmms.rc) +CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/plugins/zynaddsubfx/zynaddsubfx.rc.in ${CMAKE_BINARY_DIR}/plugins/zynaddsubfx/zynaddsubfx.rc) # set compiler flags #SET(CMAKE_BUILD_TYPE relwithdebug) -SET(CMAKE_C_FLAGS "-O2 -g -Wall -ftree-vectorize ${CMAKE_C_FLAGS}") -SET(CMAKE_CXX_FLAGS "-O2 -g -fno-exceptions -Wall -ftree-vectorize ${CMAKE_CXX_FLAGS}") +SET(CMAKE_C_FLAGS "-O2 -g -Wall ${CMAKE_C_FLAGS}") +SET(CMAKE_CXX_FLAGS "-O2 -g -fno-exceptions -Wall ${CMAKE_CXX_FLAGS}") #SET(CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE} "${CMAKE_C_FLAGS}") #SET(CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE} "${CMAKE_CXX_FLAGS}") @@ -541,9 +542,9 @@ ADD_SUBDIRECTORY(data) # ADD_DEFINITIONS(-D'LIB_DIR="${CMAKE_INSTALL_PREFIX}/${LIB_DIR}/"' -D'PLUGIN_DIR="${CMAKE_INSTALL_PREFIX}/${LIB_DIR}/lmms/"' ${PULSEAUDIO_DEFINITIONS} ${PORTAUDIO_DEFINITIONS}) -INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}/include ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/include ${SDL_INCLUDE_DIR} ${PORTAUDIO_INCLUDE_DIR} ${PULSEAUDIO_INCLUDE_DIR} ${JACK_INCLUDE_DIRS} ${OGGVORBIS_INCLUDE_DIR} ${SAMPLERATE_INCLUDE_DIRS} ${SNDFILE_INCLUDE_DIRS} ${ZIP_INCLUDE_DIR} ${FLAC_INCLUDE_DIR}) +INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}/include ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/include ${SDL_INCLUDE_DIR} ${PORTAUDIO_INCLUDE_DIR} ${PULSEAUDIO_INCLUDE_DIR} ${JACK_INCLUDE_DIRS} ${OGGVORBIS_INCLUDE_DIR} ${SAMPLERATE_INCLUDE_DIRS} ${SNDFILE_INCLUDE_DIRS} ${FLAC_INCLUDE_DIR}) LINK_DIRECTORIES(${CMAKE_INSTALL_PREFIX}/lib ${ASOUND_LIBRARY_DIR} ${JACK_LIBRARY_DIRS} ${SAMPLERATE_LIBRARY_DIRS} ${SNDFILE_LIBRARY_DIRS}) -LINK_LIBRARIES(${QT_LIBRARIES} ${ASOUND_LIBRARY} ${SDL_LIBRARY} ${PORTAUDIO_LIBRARIES} ${PULSEAUDIO_LIBRARIES} ${JACK_LIBRARIES} ${OGGVORBIS_LIBRARIES} ${SAMPLERATE_LIBRARIES} ${SNDFILE_LIBRARIES} ${ZIP_LIBRARIES} ${FLAC_LIBRARIES} ${SLV2_LIBRARY}) +LINK_LIBRARIES(${QT_LIBRARIES} ${ASOUND_LIBRARY} ${SDL_LIBRARY} ${PORTAUDIO_LIBRARIES} ${PULSEAUDIO_LIBRARIES} ${JACK_LIBRARIES} ${OGGVORBIS_LIBRARIES} ${SAMPLERATE_LIBRARIES} ${SNDFILE_LIBRARIES} ${FLAC_LIBRARIES} ${SLV2_LIBRARY}) ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_BINARY_DIR}/lmms.1.gz COMMAND gzip -c ${CMAKE_SOURCE_DIR}/lmms.1 > ${CMAKE_BINARY_DIR}/lmms.1.gz DEPENDS ${CMAKE_SOURCE_DIR}/lmms.1 COMMENT "Generating lmms.1.gz") diff --git a/ChangeLog.old b/ChangeLog.old index a2015cb50..eace201c6 100644 --- a/ChangeLog.old +++ b/ChangeLog.old @@ -1172,7 +1172,7 @@ made 0.4.0 release * CMakeLists.txt: - - include all neccessary DLLs in win64 build + - include all necessary DLLs in win64 build - fix versioning for CPack if no VERSION_SUFFIX is set * plugins/sid/sid_instrument.cpp: @@ -1787,7 +1787,7 @@ * src/core/sample_record_handle.cpp: * src/tracks/instrument_track.cpp: removed obsolete instrument-parallelization support as this is handled - much better by worker threads and adds unneccessary complexity + much better by worker threads and adds unnecessary complexity * cmake/modules/FindPCHSupport.cmake: * INSTALL: @@ -2594,7 +2594,7 @@ * src/gui/track_container_view.cpp: * src/core/track.cpp: disabled undo/redo of track/TCO addition/removal as not mature yet and - causes unneccessary crashes (closes #2014439, #2100407) + causes unnecessary crashes (closes #2014439, #2100407) * data/projects/cool_songs/Skiessi-TurningPoint.mmpz: * data/projects/cool_songs/Skiessi-RandomProjectNumber14253.mmpz: @@ -3360,7 +3360,7 @@ fixed messages * src/core/config_mgr.cpp: - add trailing slashes to paths where neccessary (closes #2056353) + add trailing slashes to paths where necessary (closes #2056353) * data/locale/de.qm: * data/locale/de.ts: @@ -13082,7 +13082,7 @@ double-clicking them * src/tracks/pattern.cpp: - when loading pattern, check type afterwards and correct if neccessary + when loading pattern, check type afterwards and correct if necessary 2006-10-09 Mikael Freeman @@ -13794,7 +13794,7 @@ * Makefile.cvs: small makefile to be run before configure for creating/copying all - neccessary files + necessary files * config.sub: * config.guess: @@ -14955,7 +14955,7 @@ - in vibed::loadSettings(): - simplified loading of wave-shape - delete base64-decoded data at the end - - commented out code in destructor as it is not neccessary - to be + - commented out code in destructor as it is not necessary - to be removed someday * include/base64.h: @@ -15454,7 +15454,7 @@ * src/widgets/automatable_button.cpp: * src/widgets/knob.cpp: added second template-parameter to automatableObject which specifies - the type to be used for internal calculations (neccessary for working + the type to be used for internal calculations (necessary for working undo/redo-implementation for bool-objects like buttons) * include/led_checkbox.h: @@ -15985,7 +15985,7 @@ * include/pattern.h: * src/tracks/pattern.cpp: - only repaint if neccessary, otherwise just paint the pixmap we painted + only repaint if necessary, otherwise just paint the pixmap we painted before * include/bb_editor.h: @@ -16326,7 +16326,7 @@ * include/tool_button.h: * src/widgets/tool_button.cpp: - catch toggle-signals to emit clicked()-signal which is neccessary if a + catch toggle-signals to emit clicked()-signal which is necessary if a button is checked using setChecked()-method and not by the user - fixes some bugs with piano-roll @@ -16513,7 +16513,7 @@ classify files with extension "flac" as samples * src/widgets/tab_widget.cpp: - hide all other tabs when changing active tab - neccessary for working + hide all other tabs when changing active tab - necessary for working with Qt 4.1 2005-12-20 Danny McRae @@ -16721,7 +16721,7 @@ * include/timeline.h: * src/core/timeline.cpp: use timer for periodically screen-updates - locking QApplication-mutex - isn't neccessary anymore which makes LMMS not to hang when creating + isn't necessary anymore which makes LMMS not to hang when creating new song while playing etc. * src/core/piano_roll.cpp: @@ -16930,7 +16930,7 @@ * include/qxembed.h: * src/widgets/qxembed.cpp: - added QXEmbed-widget which is neccessary for embedding VST-plugin + added QXEmbed-widget which is necessary for embedding VST-plugin 2005-11-27 Tobias Doerffel @@ -16998,7 +16998,7 @@ * include/midi_client.h: - added method applyPortMode() for making MIDI-subsystem able to get - known of port-mode changes which is neccessary if they have REAL + known of port-mode changes which is necessary if they have REAL ports like ALSA-seq. has - renamed validatePortName() to applyPortName() and made it non-pure virtual @@ -17518,7 +17518,7 @@ * src/core/track_container.cpp: added parameter _complete_update to trackContainer::realignTracks() - to be able to hide and show all tracks which is neccessary e.g. + to be able to hide and show all tracks which is necessary e.g. after having changed pixels-per-tact-property -> zooming in song-editor works now well @@ -17665,7 +17665,7 @@ * src/lib/mmp.cpp: if saving preset, check whether file-name contains suffix ".cs.xml" - and add it if neccessary + and add it if necessary * include/midi_alsa_raw.h: * src/midi/midi_alsa_raw.cpp: @@ -18325,7 +18325,7 @@ logo originally had been made with Inkscape 0.39) * src/widgets/project_notes.cpp: - removed unneccessary name-strings for QActions + removed unnecessary name-strings for QActions * resources/project_notes.png: replaced 16x16-icon with 22x22-icon to provide big enough icon for @@ -18387,7 +18387,7 @@ performed at the moment and introduced m_action, indicating one of the actions defined in (also new) enum editActions - replaced m_startTone and m_startOctave with one variable m_startKey, - which makes a lot of code unneccessary + which makes a lot of code unnecessary - rewrote loops using note-vectors to use iterators instead of indices and vector::size() - renamed m_evolutionHeight to m_notesEditHeight diff --git a/build_mingw32 b/build_mingw32 index 3dd1f3726..b125afa93 100755 --- a/build_mingw32 +++ b/build_mingw32 @@ -1,4 +1,4 @@ MINGW=/opt/mingw32 export PATH=$PATH:$MINGW/bin -cmake .. -DCMAKE_TOOLCHAIN_FILE=cmake/modules/Win32Toolchain.cmake +cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake/modules/Win32Toolchain.cmake diff --git a/cmake/modules/FindFLAC.cmake b/cmake/modules/FindFLAC.cmake index 850105566..e393b3501 100644 --- a/cmake/modules/FindFLAC.cmake +++ b/cmake/modules/FindFLAC.cmake @@ -11,7 +11,10 @@ FIND_PATH(FLAC_INCLUDE_DIRS encoder.h /usr/include/FLAC++ /usr/local/include/FLA FIND_PATH(FLAC_INCLUDE_DIRS export.h /usr/include/FLAC++ /usr/local/include/FLAC++ ${CMAKE_INSTALL_PREFIX}/include/FLAC++ ${CMAKE_INSTALL_PREFIX}/local/include/FLAC++) FIND_PATH(FLAC_INCLUDE_DIRS metadata.h /usr/include/FLAC++ /usr/local/include/FLAC++ ${CMAKE_INSTALL_PREFIX}/include/FLAC++ ${CMAKE_INSTALL_PREFIX}/local/include/FLAC++) FIND_PATH(FLAC_INCLUDE_DIRS all.h /usr/include/FLAC++ /usr/local/include/FLAC++ ${CMAKE_INSTALL_PREFIX}/include/FLAC++ ${CMAKE_INSTALL_PREFIX}/local/include/FLAC++) -FIND_LIBRARY(FLAC_LIBRARIES NAMES FLAC++ PATH /usr/lib /usr/local/lib ${CMAKE_INSTALL_PREFIX}/lib/FLAC++ ${CMAKE_INSTALL_PREFIX}/local/lib/FLAC++) +FIND_LIBRARY(FLAC_LIBRARIES NAMES FLAC PATH /usr/lib /usr/local/lib ${CMAKE_INSTALL_PREFIX}/lib ${CMAKE_INSTALL_PREFIX}/local/lib) +FIND_LIBRARY(FLACPP_LIBRARIES NAMES FLAC++ PATH /usr/lib /usr/local/lib ${CMAKE_INSTALL_PREFIX}/lib ${CMAKE_INSTALL_PREFIX}/local/lib) + +SET(FLAC_LIBRARIES ${FLAC_LIBRARIES} ${FLACPP_LIBRARIES}) IF(FLAC_INCLUDE_DIRS AND FLAC_LIBRARIES) SET(FLAC_FOUND TRUE) diff --git a/cmake/modules/Win32Toolchain.cmake b/cmake/modules/Win32Toolchain.cmake index 6d5030107..afdd54df5 100644 --- a/cmake/modules/Win32Toolchain.cmake +++ b/cmake/modules/Win32Toolchain.cmake @@ -36,6 +36,9 @@ SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) SET(PKG_CONFIG_EXECUTABLE ${MINGW_PREFIX}/bin/pkg-config) +SET(CMAKE_C_FLAGS "-march=i686 -mtune=generic") +SET(CMAKE_CXX_FLAGS ${CMAKE_C_FLAGS}) + INCLUDE_DIRECTORIES(${MINGW_PREFIX}/include) LINK_DIRECTORIES(${MINGW_PREFIX}/lib ${MINGW_PREFIX}/bin) diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt index 2583c59cf..cdd6d8248 100644 --- a/data/CMakeLists.txt +++ b/data/CMakeLists.txt @@ -6,6 +6,7 @@ ADD_SUBDIRECTORY(samples) ADD_SUBDIRECTORY(themes) IF(LMMS_BUILD_LINUX) +INSTALL(FILES themes/default/icon.png DESTINATION ${DATA_DIR}/pixmaps RENAME lmms.png) INSTALL(FILES lmms DESTINATION ${DATA_DIR}/menu) INSTALL(FILES lmms.desktop DESTINATION ${DATA_DIR}/applications) INSTALL(FILES lmms.xml DESTINATION ${DATA_DIR}/mime/packages) diff --git a/data/lmms b/data/lmms index 1c5266d6b..cd921eaa5 100644 --- a/data/lmms +++ b/data/lmms @@ -1,4 +1,4 @@ ?package(lmms):needs="X11" section="Apps/Sound" \ title="LMMS" hints="Audio" command="/usr/bin/lmms" \ longtitle="Linux MultiMedia Studio" \ - icon="/usr/share/lmms/themes/default/icon.png" + icon="/usr/share/pixmaps/lmms.png" diff --git a/data/lmms.desktop b/data/lmms.desktop index f432fbcf8..c374b7e66 100644 --- a/data/lmms.desktop +++ b/data/lmms.desktop @@ -5,10 +5,9 @@ GenericName[ca]=Programari de producció musical GenericName[de]=Software zur Musik-Produktion Comment=easy music production for everyone! Comment[ca]=Producció fàcil de música per a tothom! -Icon=/usr/share/lmms/themes/default/icon.png -Exec=/usr/bin/lmms +Icon=lmms +Exec=lmms Terminal=false Type=Application -Encoding=UTF-8 -Categories=Application;AudioVideo;Qt -MimeType=application/x-lmms-project +Categories=Qt;AudioVideo;Audio;Midi; +MimeType=application/x-lmms-project; diff --git a/data/locale/ca.ts b/data/locale/ca.ts index 4bceecb00..102f49c0f 100644 --- a/data/locale/ca.ts +++ b/data/locale/ca.ts @@ -1575,7 +1575,7 @@ Per favor, assegura't que tens permís d'escriptura per al fitxer i el OBJECTIU - These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always neccessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! + These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always necessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! @@ -3289,7 +3289,7 @@ p, li { white-space: pre-wrap; } - Click here and select-mode will be activated. In this mode you can select values. This is neccessary if you want to cut, copy, paste, delete, or move values. You can also press 'Shift+S' on your keyboard to activate this mode. + Click here and select-mode will be activated. In this mode you can select values. This is necessary if you want to cut, copy, paste, delete, or move values. You can also press 'Shift+S' on your keyboard to activate this mode. @@ -6361,7 +6361,7 @@ El LED a la cantonada dreta baixa de l'editor de forma d'ona determina Corda - The String selector is used to choose which string the controls are editting. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. + The String selector is used to choose which string the controls are editing. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. El selector String s'usa per a escollir quina corda estan editant els controls. Un instrument Vibed pot tenir fins a nou cordes vibrants independents. El LED a la cantonada dreta baixa de l'editor de forma d'ona indica si la corda seleccionada està activa. diff --git a/data/locale/cs.ts b/data/locale/cs.ts index f900de32d..330350fff 100644 --- a/data/locale/cs.ts +++ b/data/locale/cs.ts @@ -1575,7 +1575,7 @@ Přesvědčte se prosím, že máte právo zápisu do tohoto souboru a příslu CÍL - These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always neccessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! + These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always necessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! @@ -3290,7 +3290,7 @@ p, li { white-space: pre-wrap; } Klikněte zde, pokud chcete aktivovat režim mazání. V tomto režimu lze mazat jednotlivé hodnoty. Pro aktivaci můžete využít též klávesové zkratky Shift+E. - Click here and select-mode will be activated. In this mode you can select values. This is neccessary if you want to cut, copy, paste, delete, or move values. You can also press 'Shift+S' on your keyboard to activate this mode. + Click here and select-mode will be activated. In this mode you can select values. This is necessary if you want to cut, copy, paste, delete, or move values. You can also press 'Shift+S' on your keyboard to activate this mode. Klikněte zde, pokud chcete aktivovat režim výběru. Tento režimu umožňuje hodnoty vybírat a je nezbytný jestliže hodnoty chcete vyjmout, kopírovat, vložit, smazat nebo přesunout. Pro aktivaci můžete využít též klávesové zkratky Shift+S. @@ -6290,7 +6290,7 @@ Jestliže tento plugin funguje v Linuxu v jiném VST softwaru, kontaktujte pros Struna - The String selector is used to choose which string the controls are editting. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. + The String selector is used to choose which string the controls are editing. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. Volič strun se užívá k výběru struny, které bude upravována. Nástroj Vibed může obsahovat maximálně devět nezávisle vibrujících strun. LED v pravém dolním rohu editoru tvaru vlny indikuje zda je vybraná struna aktivní. diff --git a/data/locale/de.ts b/data/locale/de.ts index 78da0edab..eea900852 100644 --- a/data/locale/de.ts +++ b/data/locale/de.ts @@ -1575,7 +1575,7 @@ Bitte stellen Sie sicher, dass Sie Schreibrechte auf diese Datei und das Verzeic ZIEL - These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always neccessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! + These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always necessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! Diese Tabs enthalten Hüllkurven. Diese sind sehr wichtig, um einen Klang zu verändern, insbesondere bei der substraktiven Synthese. Wenn Sie zum Beispiel eine Lautstärke-Hüllkurve haben, können Sie festlegen, wann der Klang welchen Lautstärke-Pegel haben soll. Vielleicht wollen Sie ein weiches Streichinstrument erstellen. Dann muss ihr Sound sehr sanft ein- und ausgeblendet werden. Das kann man ganz einfach erreichen, indem man eine große Anschwell(attack)- und Ausklingzeit (release) einstellt. Mit anderen Hüllkurven, wie Balance, Kennfrequenz des benutzten Filters usw., ist es genau das Gleiche. Probieren Sie einfach ein bisschen herum! Mit ein paar Hüllkurven kann man aus einer Sägezahn-Welle wirklich coole Klänge machen...! @@ -3290,7 +3290,7 @@ p, li { white-space: pre-wrap; } Klicken Sie hier, um den Radier-Modus zu aktivieren. In diesem Modus können Sie einzelne Werte löschen. Sie können auch 'Umschalt+E' auf Ihrer Tastatur drücken, um diesen Modus zu aktivieren. - Click here and select-mode will be activated. In this mode you can select values. This is neccessary if you want to cut, copy, paste, delete, or move values. You can also press 'Shift+S' on your keyboard to activate this mode. + Click here and select-mode will be activated. In this mode you can select values. This is necessary if you want to cut, copy, paste, delete, or move values. You can also press 'Shift+S' on your keyboard to activate this mode. Klicken Sie hier, um den Auswahl-Modus zu aktivieren. In diesem Modus können Sie Werte markieren. Das ist nötig, wenn Sie (mehrere) Werte ausschneiden, kopieren, einfügen, löschen oder verschieben wollen. Sie können auch 'Umschalt+S' auf Ihrer Tastatur drücken, um diesen Modus zu aktivieren. @@ -6351,7 +6351,7 @@ Die LED rechts unterhalb der Wellenform gibt an, ob die Saite aktiviert ist.Saite - The String selector is used to choose which string the controls are editting. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. + The String selector is used to choose which string the controls are editing. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. Der Saiten-Wähler bestimmt die derzeit bearbeitete Saite. Ein Vibed-Instrument kann aus bis zu neun voneinander unabhängig schwingenden Saiten bestehen. Die LED in der Ecke rechts unterhalb der Wellenform gibt an, ob die gewählte Saite aktiv ist. diff --git a/data/locale/en.ts b/data/locale/en.ts index f0a8dc935..c9d6c9d03 100644 --- a/data/locale/en.ts +++ b/data/locale/en.ts @@ -1574,7 +1574,7 @@ Please make sure you have write-permission to the file and the directory contain - These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always neccessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! + These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always necessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! @@ -3285,7 +3285,7 @@ p, li { white-space: pre-wrap; } - Click here and select-mode will be activated. In this mode you can select values. This is neccessary if you want to cut, copy, paste, delete, or move values. You can also press 'Shift+S' on your keyboard to activate this mode. + Click here and select-mode will be activated. In this mode you can select values. This is necessary if you want to cut, copy, paste, delete, or move values. You can also press 'Shift+S' on your keyboard to activate this mode. @@ -6323,7 +6323,7 @@ The LED in the lower right corner of the waveform editor determines whether the - The String selector is used to choose which string the controls are editting. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. + The String selector is used to choose which string the controls are editing. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. diff --git a/data/locale/es.ts b/data/locale/es.ts index d662f99e0..b13026fc0 100644 --- a/data/locale/es.ts +++ b/data/locale/es.ts @@ -1574,7 +1574,7 @@ Please make sure you have write-permission to the file and the directory contain - These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always neccessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! + These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always necessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! @@ -3286,7 +3286,7 @@ p, li { white-space: pre-wrap; } - Click here and select-mode will be activated. In this mode you can select values. This is neccessary if you want to cut, copy, paste, delete, or move values. You can also press 'Shift+S' on your keyboard to activate this mode. + Click here and select-mode will be activated. In this mode you can select values. This is necessary if you want to cut, copy, paste, delete, or move values. You can also press 'Shift+S' on your keyboard to activate this mode. @@ -6324,7 +6324,7 @@ The LED in the lower right corner of the waveform editor determines whether the - The String selector is used to choose which string the controls are editting. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. + The String selector is used to choose which string the controls are editing. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. diff --git a/data/locale/fr.ts b/data/locale/fr.ts index 4b88aeb75..58dc61147 100644 --- a/data/locale/fr.ts +++ b/data/locale/fr.ts @@ -1575,7 +1575,7 @@ Assurez-vous d'avoir les droits d'accès en écriture au fichier et au - These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always neccessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! + These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always necessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! @@ -3286,7 +3286,7 @@ p, li { white-space: pre-wrap; } - Click here and select-mode will be activated. In this mode you can select values. This is neccessary if you want to cut, copy, paste, delete, or move values. You can also press 'Shift+S' on your keyboard to activate this mode. + Click here and select-mode will be activated. In this mode you can select values. This is necessary if you want to cut, copy, paste, delete, or move values. You can also press 'Shift+S' on your keyboard to activate this mode. @@ -6324,7 +6324,7 @@ The LED in the lower right corner of the waveform editor determines whether the - The String selector is used to choose which string the controls are editting. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. + The String selector is used to choose which string the controls are editing. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. diff --git a/data/locale/ir.ts b/data/locale/ir.ts index 1ec177519..90cdc07d4 100644 --- a/data/locale/ir.ts +++ b/data/locale/ir.ts @@ -1574,7 +1574,7 @@ Please make sure you have write-permission to the file and the directory contain - These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always neccessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! + These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always necessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! @@ -3285,7 +3285,7 @@ p, li { white-space: pre-wrap; } - Click here and select-mode will be activated. In this mode you can select values. This is neccessary if you want to cut, copy, paste, delete, or move values. You can also press 'Shift+S' on your keyboard to activate this mode. + Click here and select-mode will be activated. In this mode you can select values. This is necessary if you want to cut, copy, paste, delete, or move values. You can also press 'Shift+S' on your keyboard to activate this mode. @@ -6323,7 +6323,7 @@ The LED in the lower right corner of the waveform editor determines whether the - The String selector is used to choose which string the controls are editting. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. + The String selector is used to choose which string the controls are editing. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. diff --git a/data/locale/it.ts b/data/locale/it.ts index 3205e4674..034434deb 100644 --- a/data/locale/it.ts +++ b/data/locale/it.ts @@ -1587,7 +1587,7 @@ Assicurarsi di avere i permessi in scrittura per il file e la directory contenen SCOPO - These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always neccessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! + These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always necessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! Queste schede contengono envelopes. Sono molto importanti per modificare i suoni, senza contare che sono quasi sempre necessarie per la sintesi sottrattiva. Per esempio se si usa un envelope per il volume, si può impostare quando un suono avrà un certo volume. Si potrebbero voler creare archi dal suono morbido, allora il suono deve iniziare e finire in modo molto morbido; ciò si ottiene impostando tempi di attacco e di rilascio ampi. Lo stesso vale per le altre funzioni degli envelope, come il panning, la frequenza di taglio dei filtri e così via. Bisogna semplicemente giocarci un po'! Si possono ottenere suoni veramente interessanti a partire da un'onda a dente di sega usando soltanto qualche envelope...! @@ -3302,7 +3302,7 @@ p, li { white-space: pre-wrap; } Cliccando qui si attiva la modalità cancellazione. In questa modalità è possibile cancellare singoli valori. Questa modalità si attiva anche premendo la combinazione di tasti 'Shift+E'. - Click here and select-mode will be activated. In this mode you can select values. This is neccessary if you want to cut, copy, paste, delete, or move values. You can also press 'Shift+S' on your keyboard to activate this mode. + Click here and select-mode will be activated. In this mode you can select values. This is necessary if you want to cut, copy, paste, delete, or move values. You can also press 'Shift+S' on your keyboard to activate this mode. Cliccando qui si attiva la modalità selezione. In questa modalità è possibile selezionare i valori. Questo è necessario per tagliare, copiare, incollare o spostare valori. Questa modalità si attiva anche premendo la combinazione di tasti 'Shift+S'. @@ -6375,7 +6375,7 @@ Il LED nell'angolo in basso a destra sull'editor della forma d'on Corda - The String selector is used to choose which string the controls are editting. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. + The String selector is used to choose which string the controls are editing. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. Il selettore della Corda serve per scegliere su quale corda hanno effetto i controlli. Uno strumento Vibed può contenere fino a nove corde che indipendenti. Il LED nell'angolo in basso a destra dell'editor della forma d'onda indica se la corda è attiva. diff --git a/data/locale/ja.ts b/data/locale/ja.ts index c10bb3f4f..772d73b7a 100644 --- a/data/locale/ja.ts +++ b/data/locale/ja.ts @@ -1588,7 +1588,7 @@ Please make sure you have write-permission to the file and the directory contain - These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always neccessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! + These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always necessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! これらのタブにはエンペロープが含まれてます。エンベロープは音を変更するの大変重要です。エンベロープはサブストラクティブな合成をするときはほとんどいつも必要です。たとえばボリウムエンベロープの場合、音が決まった音量になる時間をセットできます。ソフトストリングを作りたいならフェードインフェードアウトを非常にソフトにする必要があります。それはアタックタイムとリリースタイムを長くすることで実現できます。パンニング、フィルターのカットオフ周波数といったほかのエンベロープを制御できるものについても事情はいっしょです。これでちょっと遊んでみてください! のこぎり歯にいくつかのエンベロープを使うだけで実にクールなサウンドを作ることこできます。 @@ -3306,7 +3306,7 @@ p, li { white-space: pre-wrap; } クリックすると消去モードをONにします。消去モードではひとつの値を消去できます。 'Shift+E' をおしても消去モードをONにできます。 - Click here and select-mode will be activated. In this mode you can select values. This is neccessary if you want to cut, copy, paste, delete, or move values. You can also press 'Shift+S' on your keyboard to activate this mode. + Click here and select-mode will be activated. In this mode you can select values. This is necessary if you want to cut, copy, paste, delete, or move values. You can also press 'Shift+S' on your keyboard to activate this mode. クリックすると選択モードをONにします。選択モードではいくつかの値を選択できます。このモードはいくつかの値をカット・コピー・ペースト・消去・移動するときに必要です。 'Shift+S' をおしても選択ーモードをONにできます。 @@ -6377,7 +6377,7 @@ The LED in the lower right corner of the waveform editor determines whether the - The String selector is used to choose which string the controls are editting. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. + The String selector is used to choose which string the controls are editing. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. ストリングセレクタはコントローラーが編集しているストリングを選ぶのにつかいます。Vibed 楽器は 9本までの独立した振動してるストリングを含んでいます。波形エディタの右下すみのLEDはどのストリングがアクティブかを示しています。 diff --git a/data/locale/ko.ts b/data/locale/ko.ts index 0454d1e0c..8c93db2c5 100644 --- a/data/locale/ko.ts +++ b/data/locale/ko.ts @@ -1574,7 +1574,7 @@ Please make sure you have write-permission to the file and the directory contain - These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always neccessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! + These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always necessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! @@ -3287,7 +3287,7 @@ p, li { white-space: pre-wrap; } - Click here and select-mode will be activated. In this mode you can select values. This is neccessary if you want to cut, copy, paste, delete, or move values. You can also press 'Shift+S' on your keyboard to activate this mode. + Click here and select-mode will be activated. In this mode you can select values. This is necessary if you want to cut, copy, paste, delete, or move values. You can also press 'Shift+S' on your keyboard to activate this mode. @@ -6328,7 +6328,7 @@ The LED in the lower right corner of the waveform editor determines whether the - The String selector is used to choose which string the controls are editting. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. + The String selector is used to choose which string the controls are editing. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. diff --git a/data/locale/nl.ts b/data/locale/nl.ts index 39ce871cf..57d6ab6d2 100644 --- a/data/locale/nl.ts +++ b/data/locale/nl.ts @@ -1574,7 +1574,7 @@ Please make sure you have write-permission to the file and the directory contain DOEL - These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always neccessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! + These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always necessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! @@ -3286,7 +3286,7 @@ p, li { white-space: pre-wrap; } - Click here and select-mode will be activated. In this mode you can select values. This is neccessary if you want to cut, copy, paste, delete, or move values. You can also press 'Shift+S' on your keyboard to activate this mode. + Click here and select-mode will be activated. In this mode you can select values. This is necessary if you want to cut, copy, paste, delete, or move values. You can also press 'Shift+S' on your keyboard to activate this mode. @@ -6349,7 +6349,7 @@ De LED in de rechter benedenhoek van de golfvorm bewerker geeft aan of de snaar - The String selector is used to choose which string the controls are editting. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. + The String selector is used to choose which string the controls are editing. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. De snaar-kiezer word gebruikt voor het kiezen van de snar welke bewerkt word. Een Vibed instrument kan tot 9 individueel trillende snaren bevatten. De LED in de rechter benedenhoek van de golfvorm bewerker geeft aan of de geselecteerde snaar actief is. diff --git a/data/locale/pt_br.ts b/data/locale/pt_br.ts index 3517aad21..13cb1ca12 100644 --- a/data/locale/pt_br.ts +++ b/data/locale/pt_br.ts @@ -1575,7 +1575,7 @@ Por favor certifique-se que você tem permissão para gravação no arquivo e se ALVO - These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always neccessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! + These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always necessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! @@ -3287,7 +3287,7 @@ p, li { white-space: pre-wrap; } - Click here and select-mode will be activated. In this mode you can select values. This is neccessary if you want to cut, copy, paste, delete, or move values. You can also press 'Shift+S' on your keyboard to activate this mode. + Click here and select-mode will be activated. In this mode you can select values. This is necessary if you want to cut, copy, paste, delete, or move values. You can also press 'Shift+S' on your keyboard to activate this mode. @@ -6326,7 +6326,7 @@ The LED in the lower right corner of the waveform editor determines whether the - The String selector is used to choose which string the controls are editting. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. + The String selector is used to choose which string the controls are editing. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. diff --git a/data/locale/ru.ts b/data/locale/ru.ts index c2158eb62..83a8ecd95 100644 --- a/data/locale/ru.ts +++ b/data/locale/ru.ts @@ -1588,7 +1588,7 @@ Please make sure you have write-permission to the file and the directory contain ХАРАКТЕРИСТИКА - These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always neccessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! + These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always necessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! Эта вкладка позволяет вам настроить обложки. Они очень важны для настройки звучания. Например, с помощью обложки громкости вы можете задать зависимость громкости звучания от времени. Если вам понадобится эмулировать мягкие струнные, просто задайте большие времена нарастания и исчезновения звука. С помощью обложек и низкочастотного генератора (LFO) вы в несколько щелчков мыши сможете создать просто невероятные звуки! @@ -3307,7 +3307,7 @@ p, li { white-space: pre-wrap; } Для включения этого режима можно использовать комбинацию клавиш Shift+E. - Click here and select-mode will be activated. In this mode you can select values. This is neccessary if you want to cut, copy, paste, delete, or move values. You can also press 'Shift+S' on your keyboard to activate this mode. + Click here and select-mode will be activated. In this mode you can select values. This is necessary if you want to cut, copy, paste, delete, or move values. You can also press 'Shift+S' on your keyboard to activate this mode. При нажатии на эту кнопку активируется режим выбора нот. В этом режиме вы можете выбирать ноты для последующих действий. Это необходимо, если вы хотите вырезать, копировать, вставлять или перемещать сразу несколько нот. Для включения этого режима можно использовать комбинацию клавиш Shift+S. @@ -6387,7 +6387,7 @@ The LED in the lower right corner of the waveform editor determines whether the Струна - The String selector is used to choose which string the controls are editting. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. + The String selector is used to choose which string the controls are editing. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. Переключатель струн позволяет выбрать струну, чьи свойства редактируются. Инструмент Vibed содержит до девяти независимо звучащих струн, индикатор в левом нижнем углу показывает, активна ли текущая струна (т. е. будет ли она слышна). diff --git a/data/locale/sv.ts b/data/locale/sv.ts index fdce93019..8ce2d1656 100644 --- a/data/locale/sv.ts +++ b/data/locale/sv.ts @@ -1574,7 +1574,7 @@ Please make sure you have write-permission to the file and the directory contain MÅL - These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always neccessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! + These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always necessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! @@ -3285,7 +3285,7 @@ p, li { white-space: pre-wrap; } - Click here and select-mode will be activated. In this mode you can select values. This is neccessary if you want to cut, copy, paste, delete, or move values. You can also press 'Shift+S' on your keyboard to activate this mode. + Click here and select-mode will be activated. In this mode you can select values. This is necessary if you want to cut, copy, paste, delete, or move values. You can also press 'Shift+S' on your keyboard to activate this mode. @@ -6326,7 +6326,7 @@ The LED in the lower right corner of the waveform editor determines whether the - The String selector is used to choose which string the controls are editting. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. + The String selector is used to choose which string the controls are editing. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. diff --git a/data/projects/covers/J.S.Bach-Preludium_and_Fugue_A-Minor.mmpz b/data/projects/covers/J.S.Bach-Preludium_and_Fugue_A-Minor.mmpz deleted file mode 100644 index a4833639b..000000000 Binary files a/data/projects/covers/J.S.Bach-Preludium_and_Fugue_A-Minor.mmpz and /dev/null differ diff --git a/data/projects/covers/MonkeyIsland1-Intro.mmpz b/data/projects/covers/MonkeyIsland1-Intro.mmpz deleted file mode 100644 index fbeccb460..000000000 Binary files a/data/projects/covers/MonkeyIsland1-Intro.mmpz and /dev/null differ diff --git a/data/projects/oldstuff/1st.mmpz b/data/projects/oldstuff/1st.mmpz deleted file mode 100644 index 32d95d22b..000000000 Binary files a/data/projects/oldstuff/1st.mmpz and /dev/null differ diff --git a/data/projects/oldstuff/Mart-Dirt_Track.mmpz b/data/projects/oldstuff/Mart-Dirt_Track.mmpz deleted file mode 100644 index c577274e6..000000000 Binary files a/data/projects/oldstuff/Mart-Dirt_Track.mmpz and /dev/null differ diff --git a/data/projects/oldstuff/MaxFellner-Ease.mmpz b/data/projects/oldstuff/MaxFellner-Ease.mmpz deleted file mode 100644 index f61160b69..000000000 Binary files a/data/projects/oldstuff/MaxFellner-Ease.mmpz and /dev/null differ diff --git a/data/projects/oldstuff/SharkyX-DeadManDancing.mmpz b/data/projects/oldstuff/SharkyX-DeadManDancing.mmpz deleted file mode 100644 index 4698e9c81..000000000 Binary files a/data/projects/oldstuff/SharkyX-DeadManDancing.mmpz and /dev/null differ diff --git a/data/projects/oldstuff/time_machine.mmpz b/data/projects/oldstuff/time_machine.mmpz deleted file mode 100644 index 4fe101b2f..000000000 Binary files a/data/projects/oldstuff/time_machine.mmpz and /dev/null differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/BD01.ogg b/data/samples/drums/Korg N1R Stereo Kit/BD01.ogg new file mode 100644 index 000000000..3a76a3607 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/BD01.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/BD02.ogg b/data/samples/drums/Korg N1R Stereo Kit/BD02.ogg new file mode 100644 index 000000000..7effddcdb Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/BD02.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/BD03.ogg b/data/samples/drums/Korg N1R Stereo Kit/BD03.ogg new file mode 100644 index 000000000..1808df3cd Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/BD03.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/BD04.ogg b/data/samples/drums/Korg N1R Stereo Kit/BD04.ogg new file mode 100644 index 000000000..9b50333f2 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/BD04.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/BD05.ogg b/data/samples/drums/Korg N1R Stereo Kit/BD05.ogg new file mode 100644 index 000000000..570d403a7 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/BD05.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/BD06.ogg b/data/samples/drums/Korg N1R Stereo Kit/BD06.ogg new file mode 100644 index 000000000..7d5b0c848 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/BD06.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/BD07.ogg b/data/samples/drums/Korg N1R Stereo Kit/BD07.ogg new file mode 100644 index 000000000..0cf434e89 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/BD07.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/BD08.ogg b/data/samples/drums/Korg N1R Stereo Kit/BD08.ogg new file mode 100644 index 000000000..a85c77f61 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/BD08.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/BD09.ogg b/data/samples/drums/Korg N1R Stereo Kit/BD09.ogg new file mode 100644 index 000000000..6cbf5800c Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/BD09.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/BD10.ogg b/data/samples/drums/Korg N1R Stereo Kit/BD10.ogg new file mode 100644 index 000000000..c3fbf1f3b Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/BD10.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/BD11.ogg b/data/samples/drums/Korg N1R Stereo Kit/BD11.ogg new file mode 100644 index 000000000..e9c4aead1 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/BD11.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/BD12.ogg b/data/samples/drums/Korg N1R Stereo Kit/BD12.ogg new file mode 100644 index 000000000..9cfc00b3a Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/BD12.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/BD13.ogg b/data/samples/drums/Korg N1R Stereo Kit/BD13.ogg new file mode 100644 index 000000000..ebf8a4178 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/BD13.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/CH01.ogg b/data/samples/drums/Korg N1R Stereo Kit/CH01.ogg new file mode 100644 index 000000000..b3303b782 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/CH01.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/CR01.ogg b/data/samples/drums/Korg N1R Stereo Kit/CR01.ogg new file mode 100644 index 000000000..a6f633fa3 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/CR01.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/HC01.ogg b/data/samples/drums/Korg N1R Stereo Kit/HC01.ogg new file mode 100644 index 000000000..a933fd3a7 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/HC01.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/HC02.ogg b/data/samples/drums/Korg N1R Stereo Kit/HC02.ogg new file mode 100644 index 000000000..2f5e39b20 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/HC02.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/HO01.ogg b/data/samples/drums/Korg N1R Stereo Kit/HO01.ogg new file mode 100644 index 000000000..0339256a2 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/HO01.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/HO02.ogg b/data/samples/drums/Korg N1R Stereo Kit/HO02.ogg new file mode 100644 index 000000000..35132f6f4 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/HO02.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/HP01.ogg b/data/samples/drums/Korg N1R Stereo Kit/HP01.ogg new file mode 100644 index 000000000..8ec4c67bf Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/HP01.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/RB01.ogg b/data/samples/drums/Korg N1R Stereo Kit/RB01.ogg new file mode 100644 index 000000000..8cbf87e8b Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/RB01.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/RC01.ogg b/data/samples/drums/Korg N1R Stereo Kit/RC01.ogg new file mode 100644 index 000000000..e6b0950c3 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/RC01.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/RC02.ogg b/data/samples/drums/Korg N1R Stereo Kit/RC02.ogg new file mode 100644 index 000000000..098509c90 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/RC02.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/RC03.ogg b/data/samples/drums/Korg N1R Stereo Kit/RC03.ogg new file mode 100644 index 000000000..b5a9e8756 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/RC03.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/RM01.ogg b/data/samples/drums/Korg N1R Stereo Kit/RM01.ogg new file mode 100644 index 000000000..eeb95202b Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/RM01.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/RVSD.ogg b/data/samples/drums/Korg N1R Stereo Kit/RVSD.ogg new file mode 100644 index 000000000..326614e20 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/RVSD.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/SD01.ogg b/data/samples/drums/Korg N1R Stereo Kit/SD01.ogg new file mode 100644 index 000000000..ec767066a Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/SD01.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/SD02.ogg b/data/samples/drums/Korg N1R Stereo Kit/SD02.ogg new file mode 100644 index 000000000..efa868feb Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/SD02.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/SD03.ogg b/data/samples/drums/Korg N1R Stereo Kit/SD03.ogg new file mode 100644 index 000000000..7fd095f73 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/SD03.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/SD04.ogg b/data/samples/drums/Korg N1R Stereo Kit/SD04.ogg new file mode 100644 index 000000000..a34fe4660 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/SD04.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/SD05.ogg b/data/samples/drums/Korg N1R Stereo Kit/SD05.ogg new file mode 100644 index 000000000..7f8d67c57 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/SD05.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/SD06.ogg b/data/samples/drums/Korg N1R Stereo Kit/SD06.ogg new file mode 100644 index 000000000..3515f4390 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/SD06.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/SD07.ogg b/data/samples/drums/Korg N1R Stereo Kit/SD07.ogg new file mode 100644 index 000000000..3a64b268a Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/SD07.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/SD08.ogg b/data/samples/drums/Korg N1R Stereo Kit/SD08.ogg new file mode 100644 index 000000000..b832eb2fa Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/SD08.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/SD09.ogg b/data/samples/drums/Korg N1R Stereo Kit/SD09.ogg new file mode 100644 index 000000000..d267ecd06 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/SD09.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/SD10.ogg b/data/samples/drums/Korg N1R Stereo Kit/SD10.ogg new file mode 100644 index 000000000..8bb57eeb4 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/SD10.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/SD11.ogg b/data/samples/drums/Korg N1R Stereo Kit/SD11.ogg new file mode 100644 index 000000000..88196b5af Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/SD11.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/SD12.ogg b/data/samples/drums/Korg N1R Stereo Kit/SD12.ogg new file mode 100644 index 000000000..4b0a1055c Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/SD12.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/SD13.ogg b/data/samples/drums/Korg N1R Stereo Kit/SD13.ogg new file mode 100644 index 000000000..e269c514f Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/SD13.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/SD14.ogg b/data/samples/drums/Korg N1R Stereo Kit/SD14.ogg new file mode 100644 index 000000000..62ac401af Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/SD14.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/SD15.ogg b/data/samples/drums/Korg N1R Stereo Kit/SD15.ogg new file mode 100644 index 000000000..25dfcf982 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/SD15.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/SD16.ogg b/data/samples/drums/Korg N1R Stereo Kit/SD16.ogg new file mode 100644 index 000000000..e80312cf6 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/SD16.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/SD17.ogg b/data/samples/drums/Korg N1R Stereo Kit/SD17.ogg new file mode 100644 index 000000000..5060674a3 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/SD17.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/SD18.ogg b/data/samples/drums/Korg N1R Stereo Kit/SD18.ogg new file mode 100644 index 000000000..756c51df2 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/SD18.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/SD19.ogg b/data/samples/drums/Korg N1R Stereo Kit/SD19.ogg new file mode 100644 index 000000000..d926a2532 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/SD19.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/SP01.ogg b/data/samples/drums/Korg N1R Stereo Kit/SP01.ogg new file mode 100644 index 000000000..e7784a7b7 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/SP01.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/TD01.ogg b/data/samples/drums/Korg N1R Stereo Kit/TD01.ogg new file mode 100644 index 000000000..5c58c89f0 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/TD01.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/TD02.ogg b/data/samples/drums/Korg N1R Stereo Kit/TD02.ogg new file mode 100644 index 000000000..cbe244724 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/TD02.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/TD03.ogg b/data/samples/drums/Korg N1R Stereo Kit/TD03.ogg new file mode 100644 index 000000000..34e7ee4e0 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/TD03.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/TD04.ogg b/data/samples/drums/Korg N1R Stereo Kit/TD04.ogg new file mode 100644 index 000000000..bb54af0a9 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/TD04.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/TD05.ogg b/data/samples/drums/Korg N1R Stereo Kit/TD05.ogg new file mode 100644 index 000000000..c6a7bca16 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/TD05.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/TD06.ogg b/data/samples/drums/Korg N1R Stereo Kit/TD06.ogg new file mode 100644 index 000000000..7e3946a7c Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/TD06.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/TD07.ogg b/data/samples/drums/Korg N1R Stereo Kit/TD07.ogg new file mode 100644 index 000000000..19a267ac7 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/TD07.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/TD08.ogg b/data/samples/drums/Korg N1R Stereo Kit/TD08.ogg new file mode 100644 index 000000000..6a86ec87a Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/TD08.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/TD09.ogg b/data/samples/drums/Korg N1R Stereo Kit/TD09.ogg new file mode 100644 index 000000000..65a088a36 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/TD09.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/TD10.ogg b/data/samples/drums/Korg N1R Stereo Kit/TD10.ogg new file mode 100644 index 000000000..df176f32b Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/TD10.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/TD11.ogg b/data/samples/drums/Korg N1R Stereo Kit/TD11.ogg new file mode 100644 index 000000000..73ee386b3 Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/TD11.ogg differ diff --git a/data/samples/drums/Korg N1R Stereo Kit/TD12.ogg b/data/samples/drums/Korg N1R Stereo Kit/TD12.ogg new file mode 100644 index 000000000..dd81a502d Binary files /dev/null and b/data/samples/drums/Korg N1R Stereo Kit/TD12.ogg differ diff --git a/data/themes/cusis/style.css b/data/themes/cusis/style.css index c158e9bad..5cf8095d0 100644 --- a/data/themes/cusis/style.css +++ b/data/themes/cusis/style.css @@ -74,6 +74,11 @@ automationEditor { } +QToolTip { + background: rgb(224,224,224); + color: black; +} + QMenu { border:1px solid black; background-color: rgb( 192, 192, 192 ); diff --git a/data/themes/default/style.css b/data/themes/default/style.css index ec41b9f18..4ac5e1cde 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -45,6 +45,11 @@ automationEditor { } +QToolTip { + background: rgb(224,224,224); + color: black; +} + QMenu { border:1px solid black; background-color: rgb( 192, 192, 192 ); diff --git a/include/AudioOutputContext.h b/include/AudioOutputContext.h index 8bd57ac38..5ed93c176 100644 --- a/include/AudioOutputContext.h +++ b/include/AudioOutputContext.h @@ -193,7 +193,7 @@ public: * * When working with buffer sizes greater than the default buffer size, one * big output buffer is still splitted into smaller chunks. This is - * especially neccessary for automation which takes place once a buffer + * especially necessary for automation which takes place once a buffer * period. Transitions would be anything else but smooth when adjusting a * control just 20 times per second. BufferFifo handles the queueing of * rendered buffers. */ diff --git a/include/AutomatableModel.h b/include/AutomatableModel.h index 0f9308975..e419190d1 100644 --- a/include/AutomatableModel.h +++ b/include/AutomatableModel.h @@ -225,9 +225,6 @@ protected: float fittedValue( float _value ) const; - float m_minValue; - float m_maxValue; - float m_value; private: void linkModel( AutomatableModel * _model ); @@ -235,7 +232,10 @@ private: DataType m_dataType; + float m_value; float m_initValue; + float m_minValue; + float m_maxValue; float m_step; float m_range; diff --git a/include/EffectControls.h b/include/EffectControls.h index 71e58f0a7..a8883b83d 100644 --- a/include/EffectControls.h +++ b/include/EffectControls.h @@ -1,8 +1,8 @@ /* * EffectControls.h - model for effect-controls * - * Copyright (c) 2008 Tobias Doerffel - * + * Copyright (c) 2008-2010 Tobias Doerffel + * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * * This program is free software; you can redistribute it and/or @@ -38,7 +38,8 @@ public: EffectControls( Effect * _eff ) : JournallingObject(), Model( _eff ), - m_effect( _eff ) + m_effect( _eff ), + m_viewVisible( false ) { } @@ -50,6 +51,16 @@ public: virtual EffectControlDialog * createView() = 0; + void setViewVisible( bool _visible ) + { + m_viewVisible = _visible; + } + + bool isViewVisible() const + { + return m_viewVisible; + } + Effect * effect() { return m_effect; @@ -58,6 +69,7 @@ public: private: Effect * m_effect; + bool m_viewVisible; } ; diff --git a/include/EffectView.h b/include/EffectView.h index 172574379..6caa06b1f 100644 --- a/include/EffectView.h +++ b/include/EffectView.h @@ -2,7 +2,7 @@ * EffectView.h - view-component for an effect * * Copyright (c) 2006-2007 Danny McRae - * Copyright (c) 2007-2009 Tobias Doerffel + * Copyright (c) 2007-2010 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -87,7 +87,6 @@ private: knob * m_gate; QMdiSubWindow * m_subWindow; EffectControlDialog * m_controlView; - bool m_show; } ; diff --git a/include/EnvelopeAndLfoParameters.h b/include/EnvelopeAndLfoParameters.h index ca035830f..f7497d860 100644 --- a/include/EnvelopeAndLfoParameters.h +++ b/include/EnvelopeAndLfoParameters.h @@ -1,7 +1,7 @@ /* * EnvelopeAndLfoParameters.h - class EnvelopeAndLfoParameters * - * Copyright (c) 2004-2009 Tobias Doerffel + * Copyright (c) 2004-2010 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -22,7 +22,6 @@ * */ - #ifndef _ENVELOPE_AND_LFO_PARAMETERS_H #define _ENVELOPE_AND_LFO_PARAMETERS_H @@ -35,11 +34,39 @@ #include "lmms_basics.h" - class EXPORT EnvelopeAndLfoParameters : public Model, public JournallingObject { Q_OBJECT public: + class LfoInstances + { + public: + LfoInstances() + { + } + + ~LfoInstances() + { + } + + inline bool isEmpty() const + { + return m_lfos.isEmpty(); + } + + void trigger(); + void reset(); + + void add( EnvelopeAndLfoParameters * lfo ); + void remove( EnvelopeAndLfoParameters * lfo ); + + private: + QMutex m_lfoListMutex; + typedef QList LfoList; + LfoList m_lfos; + + } ; + EnvelopeAndLfoParameters( float _value_for_zero_amount, Model * _parent ); virtual ~EnvelopeAndLfoParameters(); @@ -49,8 +76,10 @@ public: return ( ( _val < 0 ) ? -_val : _val ) * _val; } - static void triggerLfo(); - static void resetLfo(); + static LfoInstances * instances() + { + return s_lfoInstances; + } void fillLevel( float * _buf, f_cnt_t _frame, const f_cnt_t _release_begin, @@ -89,8 +118,7 @@ protected: private: - static QVector s_EaLParametersInstances; - + static LfoInstances * s_lfoInstances; bool m_used; diff --git a/include/FxMixer.h b/include/FxMixer.h index 6e8e29bd5..660d2eace 100644 --- a/include/FxMixer.h +++ b/include/FxMixer.h @@ -69,7 +69,7 @@ class FxChannel : public ThreadableJob -class FxMixer : public JournallingObject, public Model +class EXPORT FxMixer : public JournallingObject, public Model { public: FxMixer(); diff --git a/include/FxMixerView.h b/include/FxMixerView.h index 1dc08a6e5..6449a0306 100644 --- a/include/FxMixerView.h +++ b/include/FxMixerView.h @@ -42,7 +42,7 @@ class QButtonGroup; class FxLine; -class FxMixerView : public QWidget, public ModelView, +class EXPORT FxMixerView : public QWidget, public ModelView, public SerializingObjectHook { Q_OBJECT diff --git a/include/Instrument.h b/include/Instrument.h index 8621dffa5..bfc056272 100644 --- a/include/Instrument.h +++ b/include/Instrument.h @@ -41,64 +41,137 @@ class notePlayHandle; class track; +/*! \brief Provides a standard interface for all instrument plugins. + * + * All instrument plugins have to derive from this class and implement the + * according virtual methods (see below). An instrument is instantiated by an + * InstrumentTrack. + * + * Instrument plugins can operate in two modes: process audio per note or + * process audio per Mixer period (one continuous audio stream). + * For the latter one, the instrument has to create an InstrumentPlayHandle + * for itself and re-implement #play( sampleFrame * ). When processing audio + * per note, overload the #playNote( notePlayHandle *, sampleFrame * ) and + * #deleteNotePluginData( notePlayHandle * ). + */ class EXPORT Instrument : public Plugin { public: - Instrument( InstrumentTrack * _instrument_track, - const Descriptor * _descriptor ); + /*! \brief Constructs an Instrument object. + * + * The constructor for Instrument objects. + * \param instrumentTrack The InstrumentTrack this Instrument belongs to. + * \param descriptor A Plugin::Descriptor holding information about the + * instrument plugin. + */ + Instrument( InstrumentTrack * instrumentTrack, + const Descriptor * descriptor ); virtual ~Instrument(); - // -------------------------------------------------------------------- - // functions that can/should be re-implemented: - // -------------------------------------------------------------------- + /*! \brief Generates audio data for the next mixer period. + * + * If the instrument only generates one continuous audio stream (i.e. is + * not capable of generating individual audio streams for each active + * note), it has to overload this method, generate the audio data (should + * use working buffer to improve cache hit rate and eliminate memory + * de-/allocations) and finally call InstrumentTrack::processAudioBuffer() + * and pass NULL for the last parameter. + * + * \param workingBuf A buffer the instrument should operate on (data in it + * is not used after this function returns). + */ + virtual void play( sampleFrame * workingBuffer ); - // if the plugin doesn't play each note, it can create an instrument- - // play-handle and re-implement this method, so that it mixes its - // output buffer only once per mixer-period - virtual void play( sampleFrame * _working_buffer ); - - // to be implemented by actual plugin - virtual void playNote( notePlayHandle * /* _note_to_play */, - sampleFrame * /* _working_buf */ ) + /*! \brief Generates audio data for the given NotePlayHandle. + * + * When generating audio data per-note (recommended), the instrument has + * to do this in an overloaded version of this method. It can allocate + * note-specific data objects (sound generators, generator settings etc.) + * in the given NotePlayHandle if NotePlayHandle::totalFramesPlayed()==0. + * Store this data in NotePlayHandle::m_pluginData. See the + * deleteNotePluginData() method below for information how to free the + * allocated data. + * Like play(), call Instrument::processAudioBuffer() after sound data + * has been generated and pass the NotePlayHandle as last parameter. + * + * \param noteToPlay A NotePlayHandle handle for the note to play + * \param workingBuf A buffer the instrument should operate on (data in it + * is not used after this function returns). + */ + virtual void playNote( notePlayHandle * noteToPlay, + sampleFrame * workingBuf ) { + Q_UNUSED(noteToPlay) + Q_UNUSED(workingBuf) } - - // needed for deleting plugin-specific-data of a note - plugin has to - // cast void-ptr so that the plugin-data is deleted properly - // (call of dtor if it's a class etc.) - virtual void deleteNotePluginData( notePlayHandle * _note_to_play ); - // Get number of sample-frames that should be used when playing beat - // (note with unspecified length) - // Per default this function returns 0. In this case, channel is using - // the length of the longest envelope (if one active). - virtual f_cnt_t beatLen( notePlayHandle * _n ) const; + /*! \brief Deletes data allocated for playing a certain note. + * + * In Instrument::playNote() an instrument usually allocates data for each + * note to store current state and or generator objects. After a note has + * finished playing, this method is called to free the data that was + * allocated for playing this note. Plugin has to cast + * NotePlayHandle::m_pluginData to according type and delete it. + */ + virtual void deleteNotePluginData( notePlayHandle * noteToPlay ); + + /*! \brief Returns number of frames for notes with unspecified length. + * + * When playing a note with unspecified length (e.g. a step in the + * BB-Editor), the sequencer core somehow has to determine for how long + * to play this note. Plugins can overload this method in order to specify + * the length of such notes (in frames). A sampler for example would return + * the length of the loaded sample at the according pitch. + * Per default this method returns 0 which means the InstrumentTrack will + * look for the longest active envelope and use that value. Otherwise the + * note will not be played. + * + * \param notePlayHandle A NotePlayHandle describing the concerned note. + */ + virtual f_cnt_t beatLen( notePlayHandle * n ) const; - // some instruments need a certain number of release-frames even - // if no envelope is active - such instruments can re-implement this - // method for returning how many frames they at least like to have for - // release + /*! \brief Returns number of desired release frames for this instrument. + * + * Some instruments need a certain number of release frames even + * if no envelope is active - such instruments can re-implement this + * method for returning how many frames they at least like to have for + * release. + */ virtual f_cnt_t desiredReleaseFrames() const { return 0; } - // return false if instrument is not bendable + /*! \brief Returns whether instrument is bendable. + * + * This is particularly important for instruments that do not supporting + * pitch bending. If the overloaded function returns false, the pitch bend + * knob will be hidden in InstrumentTrackWindow. + */ inline virtual bool isBendable() const { return true; } - // return true if instruments reacts to MIDI events passed to - // handleMidiEvent() rather than playNote() & Co + /*! \brief Returns true if instrument if instrument is MIDI based. + * + * Instruments should return true here if they react to MIDI events passed + * to handleMidiEvent() rather than playNote() & Co. + */ inline virtual bool isMidiBased() const { return false; } - // sub-classes can re-implement this for receiving all incoming - // MIDI-events + /*! \brief Allows to handle given MidiEvent. + * + * Subclasses can re-implement this for receiving all incoming MIDI events. + * + * \param midiEvent The MIDI event just received + * \param midiTime An optional offset for the MIDI event within current + * mixer period (e.g. NoteOn at frame X). + */ inline virtual bool handleMidiEvent( const midiEvent &, const midiTime & ) { return false; @@ -106,17 +179,25 @@ public: virtual QString fullDisplayName() const; - // -------------------------------------------------------------------- - // provided functions: - // -------------------------------------------------------------------- - - // instantiate instrument-plugin with given name or return NULL - // on failure - static Instrument * instantiate( const QString & _plugin_name, - InstrumentTrack * _instrument_track ); + /*! \brief Instantiates instrument plugin with given name. + * + * Tries to instantiate instrument plugin with given name from available + * plugin files. + * + * \param pluginName The internal identifier for the plugin + * \param instrumentTrack The InstrumentTrack the new instrument should + * belong to. + * + * \return Pointer to instantiated instrument plugin or NULL on failure. + */ + static Instrument * instantiate( const QString & pluginName, + InstrumentTrack * instrumentTrack ); + /*! \brief Returns whether this instance belongs to given track. */ virtual bool isFromTrack( const track * _track ) const; + /*! \brief Returns whether the InstrumentTrack this instrument is attached + * to is muted. */ bool isMuted() const; @@ -126,10 +207,14 @@ protected: return m_instrumentTrack; } - // instruments may use this to apply a soft fade out at the end of - // notes - method does this only if really less or equal - // desiredReleaseFrames() frames are left - void applyRelease( sampleFrame * buf, const notePlayHandle * _n ); + /*! \brief Internal helper method to apply a release on given buffer. + * + * Instrument plugins may use this to apply a soft fade-out at the end of + * a note. Please note that this is only done if the number of frames + * returned by NotePlayHandle::framesLeft() is equal or below the number + * of frames returned by Instrument::desiredReleaseFrames(). + */ + void applyRelease( sampleFrame * buf, const notePlayHandle * n ); private: diff --git a/include/MidiClient.h b/include/MidiClient.h index 02cca11b6..e92142b97 100644 --- a/include/MidiClient.h +++ b/include/MidiClient.h @@ -172,7 +172,7 @@ private: const MidiPort * _port ); // small helper function returning length of a certain event - this - // is neccessary for parsing raw-MIDI-data + // is necessary for parsing raw-MIDI-data static Uint8 eventLength( const Uint8 _event ); diff --git a/include/automation_editor.h b/include/automation_editor.h index f5f73cb0a..ecce76967 100644 --- a/include/automation_editor.h +++ b/include/automation_editor.h @@ -24,10 +24,10 @@ * */ - #ifndef _AUTOMATION_EDITOR_H #define _AUTOMATION_EDITOR_H +#include #include #include "lmms_basics.h" @@ -76,6 +76,7 @@ public: public slots: void update(); + void updateAfterPatternChange(); protected: @@ -190,6 +191,7 @@ private: ComboBoxModel m_zoomingYModel; ComboBoxModel m_quantizeModel; + QMutex m_patternMutex; automationPattern * m_pattern; float m_minLevel; float m_maxLevel; @@ -242,6 +244,7 @@ private: signals: + void currentPatternChanged(); void positionChanged( const midiTime & ); } ; diff --git a/include/base64.h b/include/base64.h index 74578684f..ebdfe47b3 100644 --- a/include/base64.h +++ b/include/base64.h @@ -2,8 +2,8 @@ * base64.h - namespace base64 with methods for encoding/decoding binary data * to/from base64 * - * Copyright (c) 2006-2008 Tobias Doerffel - * + * Copyright (c) 2006-2009 Tobias Doerffel + * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * * This program is free software; you can redistribute it and/or @@ -23,7 +23,6 @@ * */ - #ifndef _BASE64_H #define _BASE64_H @@ -40,11 +39,12 @@ namespace base64 _dst = QByteArray( _data, _size ).toBase64(); } - inline void decode( const QString & _b64, char * * _data, int * _size ) + template + inline void decode( const QString & _b64, T * * _data, int * _size ) { - QByteArray data = QByteArray::fromBase64( _b64.toAscii() ); + QByteArray data = QByteArray::fromBase64( _b64.toUtf8() ); *_size = data.size(); - *_data = new char[*_size]; + *_data = new T[*_size / sizeof(T)]; memcpy( *_data, data.constData(), *_size ); } // deprecated!! diff --git a/include/engine.h b/include/engine.h index 4a17cee6b..b8bfa704c 100644 --- a/include/engine.h +++ b/include/engine.h @@ -1,7 +1,7 @@ /* * engine.h - engine-system of LMMS * - * Copyright (c) 2006-2009 Tobias Doerffel + * Copyright (c) 2006-2010 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -207,6 +207,16 @@ public: } private: + // small helper function which sets the pointer to NULL before actually deleting + // the object it refers to + template + static inline void deleteHelper( T * * ptr ) + { + T * tmp = *ptr; + *ptr = NULL; + delete tmp; + } + static bool s_hasGUI; static bool s_suppressMessages; static float s_framesPerTick; diff --git a/include/inline_automation.h b/include/inline_automation.h index 4a851b680..6c4d5ea21 100644 --- a/include/inline_automation.h +++ b/include/inline_automation.h @@ -1,8 +1,8 @@ /* * inline_automation.h - class for automating something "inline" * - * Copyright (c) 2008 Tobias Doerffel - * + * Copyright (c) 2008-2010 Tobias Doerffel + * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * * This program is free software; you can redistribute it and/or @@ -22,7 +22,6 @@ * */ - #ifndef _INLINE_AUTOMATION_H #define _INLINE_AUTOMATION_H @@ -44,7 +43,7 @@ public: { if( m_autoPattern ) { - m_autoPattern->deleteLater(); + delete m_autoPattern; } } @@ -65,7 +64,7 @@ public: m_autoPattern = new automationPattern( NULL ); m_autoPattern->addObject( this ); } - return( m_autoPattern ); + return m_autoPattern; } virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent ); diff --git a/include/track.h b/include/track.h index 58d623744..6f5a6fc8e 100644 --- a/include/track.h +++ b/include/track.h @@ -1,5 +1,5 @@ /* - * track.h - declaration of classes concerning tracks -> neccessary for all + * track.h - declaration of classes concerning tracks -> necessary for all * track-like objects (beat/bassline, sample-track...) * * Copyright (c) 2004-2009 Tobias Doerffel diff --git a/include/track_container.h b/include/track_container.h index e81be6b77..7dd93dc1d 100644 --- a/include/track_container.h +++ b/include/track_container.h @@ -2,8 +2,8 @@ * track_container.h - base-class for all track-containers like Song-Editor, * BB-Editor... * - * Copyright (c) 2004-2008 Tobias Doerffel - * + * Copyright (c) 2004-2009 Tobias Doerffel + * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * * This program is free software; you can redistribute it and/or @@ -23,11 +23,10 @@ * */ - #ifndef _TRACK_CONTAINER_H #define _TRACK_CONTAINER_H -#include +#include #include "track.h" #include "JournallingObject.h" diff --git a/lmms.1 b/lmms.1 index b4a5deb3d..3e7955911 100644 --- a/lmms.1 +++ b/lmms.1 @@ -55,7 +55,7 @@ Specify interpolation method - possible values are \fIlinear\fP, \fIsincfastest\ .IP "\fB\-i, --interpolation\fP \fImethod\fP Specify interpolation method - possible values are \fIlinear\fP, \fIsincfastest\fP (default), \fIsincmedium\fP, \fIsincbest\fP .IP "\fB\-x, --oversampling\fP \fIvalue\fP -Specify oversampling, posible values: 1, 2 (default), 4, 8 +Specify oversampling, possible values: 1, 2 (default), 4, 8 .IP "\fB\-u, --upgrade\fP \fIin\fP \fIout\fP Upgrade file \fIin\fP and save as \fIout\fP .IP "\fB\-d, --dump\fP \fIin\fP diff --git a/lmms.rc.in b/lmms.rc.in index c8065017a..822ccaeeb 100644 --- a/lmms.rc.in +++ b/lmms.rc.in @@ -17,7 +17,7 @@ BEGIN VALUE "CompanyName", "LMMS Developers\0" VALUE "FileDescription", "Linux MultiMedia Studio\0" VALUE "FileVersion", "@VERSION@\0" - VALUE "LegalCopyright", "Copyright (c) 2004-2009 LMMS Developers\0" + VALUE "LegalCopyright", "Copyright (c) 2004-2010 LMMS Developers\0" VALUE "OriginalFilename", "lmms.exe\0" VALUE "ProductName", "LMMS\0" VALUE "ProductVersion", "@VERSION@\0" diff --git a/plugins/audio_file_processor/audio_file_processor.cpp b/plugins/audio_file_processor/audio_file_processor.cpp index 4ab69c3f0..45beff8db 100644 --- a/plugins/audio_file_processor/audio_file_processor.cpp +++ b/plugins/audio_file_processor/audio_file_processor.cpp @@ -486,7 +486,7 @@ void AudioFileProcessorView::modelChanged() extern "C" { -// neccessary for getting instance out of shared lib +// necessary for getting instance out of shared lib Plugin * PLUGIN_EXPORT lmms_plugin_main( Model *, void * _data ) { return new audioFileProcessor( diff --git a/plugins/bass_booster/bass_booster.cpp b/plugins/bass_booster/bass_booster.cpp index 1388126d2..b6a765f96 100644 --- a/plugins/bass_booster/bass_booster.cpp +++ b/plugins/bass_booster/bass_booster.cpp @@ -101,7 +101,7 @@ bool bassBoosterEffect::processAudioBuffer( sampleFrame * _buf, extern "C" { -// neccessary for getting instance out of shared lib +// necessary for getting instance out of shared lib Plugin * PLUGIN_EXPORT lmms_plugin_main( Model * _parent, void * _data ) { return( new bassBoosterEffect( _parent, diff --git a/plugins/bit_invader/bit_invader.cpp b/plugins/bit_invader/bit_invader.cpp index c8c8e2f1a..e679c6e73 100644 --- a/plugins/bit_invader/bit_invader.cpp +++ b/plugins/bit_invader/bit_invader.cpp @@ -575,7 +575,7 @@ void bitInvaderView::normalizeToggled( bool value ) extern "C" { -// neccessary for getting instance out of shared lib +// necessary for getting instance out of shared lib Plugin * PLUGIN_EXPORT lmms_plugin_main( Model *, void * _data ) { return( new bitInvader( static_cast( _data ) ) ); diff --git a/plugins/flp_import/CMakeLists.txt b/plugins/flp_import/CMakeLists.txt index 1a2c2c7e4..8f2d05864 100644 --- a/plugins/flp_import/CMakeLists.txt +++ b/plugins/flp_import/CMakeLists.txt @@ -2,4 +2,6 @@ INCLUDE(BuildPlugin) INCLUDE_DIRECTORIES(unrtf) +LINK_LIBRARIES(${ZIP_LIBRARIES}) + BUILD_PLUGIN(flpimport FlpImport.cpp unrtf.cpp FlpImport.h) diff --git a/plugins/flp_import/FlpImport.cpp b/plugins/flp_import/FlpImport.cpp index a4672511f..0ea2b5861 100644 --- a/plugins/flp_import/FlpImport.cpp +++ b/plugins/flp_import/FlpImport.cpp @@ -2031,7 +2031,7 @@ void FlpImport::processPluginParams( FL_Channel * _ch ) extern "C" { -// neccessary for getting instance out of shared lib +// necessary for getting instance out of shared lib Plugin * PLUGIN_EXPORT lmms_plugin_main( Model *, void * _data ) { return new FlpImport( QString::fromUtf8( diff --git a/plugins/kicker/kicker.cpp b/plugins/kicker/kicker.cpp index 1293858fd..c800b24cf 100644 --- a/plugins/kicker/kicker.cpp +++ b/plugins/kicker/kicker.cpp @@ -253,7 +253,7 @@ void kickerInstrumentView::modelChanged() extern "C" { -// neccessary for getting instance out of shared lib +// necessary for getting instance out of shared lib Plugin * PLUGIN_EXPORT lmms_plugin_main( Model *, void * _data ) { return new kickerInstrument( static_cast( _data ) ); diff --git a/plugins/ladspa_browser/ladspa_browser.cpp b/plugins/ladspa_browser/ladspa_browser.cpp index be334b0ad..442edfdf8 100644 --- a/plugins/ladspa_browser/ladspa_browser.cpp +++ b/plugins/ladspa_browser/ladspa_browser.cpp @@ -60,7 +60,7 @@ Plugin::Descriptor PLUGIN_EXPORT ladspabrowser_plugin_descriptor = } ; -// neccessary for getting instance out of shared lib +// necessary for getting instance out of shared lib Plugin * PLUGIN_EXPORT lmms_plugin_main( Model * _parent, void * _data ) { return new ladspaBrowser; diff --git a/plugins/ladspa_effect/LadspaControls.cpp b/plugins/ladspa_effect/LadspaControls.cpp index 86d0807b3..1dd572188 100644 --- a/plugins/ladspa_effect/LadspaControls.cpp +++ b/plugins/ladspa_effect/LadspaControls.cpp @@ -1,8 +1,8 @@ /* - * LadspaControls.cpp - model for LADSPA-plugin controls + * LadspaControls.cpp - model for LADSPA plugin controls + * + * Copyright (c) 2008-2010 Tobias Doerffel * - * Copyright (c) 2008-2009 Tobias Doerffel - * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * * This program is free software; you can redistribute it and/or @@ -22,7 +22,6 @@ * */ - #include #include "LadspaEffect.h" @@ -35,6 +34,10 @@ LadspaControls::LadspaControls( LadspaEffect * _eff ) : m_noLink( false ), m_stereoLinkModel( true, this ) { + + connect( &m_stereoLinkModel, SIGNAL( dataChanged() ), + this, SLOT( updateLinkStatesFromGlobal() ) ); + multi_proc_t controls = m_effect->getPortControls(); m_controlCount = controls.count(); @@ -163,7 +166,7 @@ void LadspaControls::linkPort( Uint16 _port, bool _state ) -void LadspaControls::updateChannelLinkState() +void LadspaControls::updateLinkStatesFromGlobal() { if( m_stereoLinkModel.value() ) { @@ -183,10 +186,10 @@ void LadspaControls::updateChannelLinkState() m_controls[0][port]->setLink( false ); } } - else - { - m_noLink = false; - } + + // if global channel link state has changed, always ignore link + // status of individual ports in the future + m_noLink = false; } diff --git a/plugins/ladspa_effect/LadspaControls.h b/plugins/ladspa_effect/LadspaControls.h index 3e13517a0..1d048aeba 100644 --- a/plugins/ladspa_effect/LadspaControls.h +++ b/plugins/ladspa_effect/LadspaControls.h @@ -1,8 +1,8 @@ /* - * ladspa_controls.h - model for LADSPA-plugin controls + * LadspaControls.h - model for LADSPA plugin controls + * + * Copyright (c) 2008-2010 Tobias Doerffel * - * Copyright (c) 2008 Tobias Doerffel - * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * * This program is free software; you can redistribute it and/or @@ -61,7 +61,7 @@ public: protected slots: - void updateChannelLinkState(); + void updateLinkStatesFromGlobal(); void linkPort( Uint16 _port, bool _state ); diff --git a/plugins/ladspa_effect/LadspaEffect.cpp b/plugins/ladspa_effect/LadspaEffect.cpp index 5dbff0ff6..86e6efafd 100644 --- a/plugins/ladspa_effect/LadspaEffect.cpp +++ b/plugins/ladspa_effect/LadspaEffect.cpp @@ -577,7 +577,7 @@ sample_rate_t LadspaEffect::maxSamplerate( const QString & _name ) extern "C" { -// neccessary for getting instance out of shared lib +// necessary for getting instance out of shared lib Plugin * PLUGIN_EXPORT lmms_plugin_main( Model * _parent, void * _data ) { return new LadspaEffect( _parent, diff --git a/plugins/ladspa_effect/calf/CMakeLists.txt b/plugins/ladspa_effect/calf/CMakeLists.txt index 22a75d7fe..f72f1f2a7 100644 --- a/plugins/ladspa_effect/calf/CMakeLists.txt +++ b/plugins/ladspa_effect/calf/CMakeLists.txt @@ -1,8 +1,7 @@ FILE(GLOB SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp) ADD_LIBRARY(calf MODULE ${SOURCES}) -INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/calf) +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src) INSTALL(TARGETS calf LIBRARY DESTINATION ${PLUGIN_DIR}/ladspa) -ADD_DEFINITIONS(-DUSE_LADSPA=1) SET_TARGET_PROPERTIES(calf PROPERTIES PREFIX "") SET(INLINE_FLAGS "") IF(NOT LMMS_BUILD_APPLE) diff --git a/plugins/ladspa_effect/calf/calf/ladspa_wrap.h b/plugins/ladspa_effect/calf/calf/ladspa_wrap.h deleted file mode 100644 index 73c396914..000000000 --- a/plugins/ladspa_effect/calf/calf/ladspa_wrap.h +++ /dev/null @@ -1,516 +0,0 @@ -/* Calf DSP Library - * API wrappers for LADSPA/DSSI - * - * Copyright (C) 2007-2008 Krzysztof Foltman - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this program; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02111-1307, USA. - */ -#ifndef __CALF_LADSPA_WRAP_H -#define __CALF_LADSPA_WRAP_H - -#if USE_LADSPA - -#include -#if USE_DSSI -#include -#endif -#include "giface.h" - -namespace calf_plugins { - -template -inline int calc_real_param_count() -{ - for (int i=0; i < Module::param_count; i++) - { - if ((Module::param_props[i].flags & PF_TYPEMASK) >= PF_STRING) - return i; - } - return Module::param_count; -} - -/// A template implementing plugin_ctl_iface for a given plugin -template -struct ladspa_instance: public Module, public plugin_ctl_iface -{ - bool activate_flag; -#if USE_DSSI - dssi_feedback_sender *feedback_sender; -#endif - - static int real_param_count() - { - static int _real_param_count = calc_real_param_count(); - return _real_param_count; - } - ladspa_instance() - { - for (int i=0; i < Module::in_count; i++) - Module::ins[i] = NULL; - for (int i=0; i < Module::out_count; i++) - Module::outs[i] = NULL; - int rpc = real_param_count(); - for (int i=0; i < rpc; i++) - Module::params[i] = NULL; - activate_flag = true; -#if USE_DSSI - feedback_sender = NULL; -#endif - } - virtual parameter_properties *get_param_props(int param_no) - { - return &Module::param_props[param_no]; - } - virtual float get_param_value(int param_no) - { - // XXXKF hack - if (param_no >= real_param_count()) - return 0; - return *Module::params[param_no]; - } - virtual void set_param_value(int param_no, float value) - { - // XXXKF hack - if (param_no >= real_param_count()) - return; - *Module::params[param_no] = value; - } - virtual int get_param_count() - { - return real_param_count(); - } - virtual int get_param_port_offset() - { - return Module::in_count + Module::out_count; - } - virtual const char *get_gui_xml() { - return Module::get_gui_xml(); - } - virtual line_graph_iface *get_line_graph_iface() - { - return dynamic_cast(this); - } - virtual bool activate_preset(int bank, int program) { - return false; - } - virtual const char *get_name() - { - return Module::get_name(); - } - virtual const char *get_id() - { - return Module::get_id(); - } - virtual const char *get_label() - { - return Module::get_label(); - } - virtual char *configure(const char *key, const char *value) - { -#if USE_DSSI - if (!strcmp(key, "OSC:FEEDBACK_URI")) - { - line_graph_iface *lgi = dynamic_cast(this); - if (!lgi) - return NULL; - if (*value) - { - if (feedback_sender) { - delete feedback_sender; - feedback_sender = NULL; - } - feedback_sender = new dssi_feedback_sender(value, lgi, get_param_props(0), get_param_count()); - } - else - { - if (feedback_sender) { - delete feedback_sender; - feedback_sender = NULL; - } - } - return NULL; - } - else - if (!strcmp(key, "OSC:UPDATE")) - { - if (feedback_sender) - feedback_sender->update(); - return NULL; - } - else -#endif - if (!strcmp(key, "ExecCommand")) - { - if (*value) - { - execute(atoi(value)); - } - return NULL; - } - return Module::configure(key, value); - } - virtual int get_input_count() { return Module::in_count; } - virtual int get_output_count() { return Module::out_count; } - virtual bool get_midi() { return Module::support_midi; } - virtual float get_level(unsigned int port) { return 0.f; } - virtual void execute(int cmd_no) { - Module::execute(cmd_no); - } - virtual void send_configures(send_configure_iface *sci) { - Module::send_configures(sci); - } -}; - -/// A wrapper class for plugin class object (there is only one ladspa_wrapper for many instances of the same plugin) -template -struct ladspa_wrapper -{ - typedef ladspa_instance instance; - - /// LADSPA descriptor - static LADSPA_Descriptor descriptor; - /// LADSPA descriptor for DSSI (uses a different name for the plugin, otherwise same as descriptor) - static LADSPA_Descriptor descriptor_for_dssi; -#if USE_DSSI - /// Extended DSSI descriptor (points to descriptor_for_dssi for things like name/label/port info etc.) - static DSSI_Descriptor dssi_descriptor; - static DSSI_Program_Descriptor dssi_default_program; - - static std::vector *presets; - static std::vector *preset_descs; -#endif - - ladspa_wrapper() - { - int ins = Module::in_count; - int outs = Module::out_count; - int params = ladspa_instance::real_param_count(); - ladspa_plugin_info &plugin_info = Module::plugin_info; - descriptor.UniqueID = plugin_info.unique_id; - descriptor.Label = plugin_info.label; - descriptor.Name = strdup((std::string(plugin_info.name) + " LADSPA").c_str()); - descriptor.Maker = plugin_info.maker; - descriptor.Copyright = plugin_info.copyright; - descriptor.Properties = Module::rt_capable ? LADSPA_PROPERTY_HARD_RT_CAPABLE : 0; - descriptor.PortCount = ins + outs + params; - descriptor.PortNames = new char *[descriptor.PortCount]; - descriptor.PortDescriptors = new LADSPA_PortDescriptor[descriptor.PortCount]; - descriptor.PortRangeHints = new LADSPA_PortRangeHint[descriptor.PortCount]; - int i; - for (i = 0; i < ins + outs; i++) - { - LADSPA_PortRangeHint &prh = ((LADSPA_PortRangeHint *)descriptor.PortRangeHints)[i]; - ((int *)descriptor.PortDescriptors)[i] = i < ins ? LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO - : i < ins + outs ? LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO - : LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL; - prh.HintDescriptor = 0; - ((const char **)descriptor.PortNames)[i] = Module::port_names[i]; - } - for (; i < ins + outs + params; i++) - { - LADSPA_PortRangeHint &prh = ((LADSPA_PortRangeHint *)descriptor.PortRangeHints)[i]; - parameter_properties &pp = Module::param_props[i - ins - outs]; - ((int *)descriptor.PortDescriptors)[i] = - LADSPA_PORT_CONTROL | (pp.flags & PF_PROP_OUTPUT ? LADSPA_PORT_OUTPUT : LADSPA_PORT_INPUT); - prh.HintDescriptor = LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW; - ((const char **)descriptor.PortNames)[i] = pp.name; - prh.LowerBound = pp.min; - prh.UpperBound = pp.max; - switch(pp.flags & PF_TYPEMASK) { - case PF_BOOL: - prh.HintDescriptor |= LADSPA_HINT_TOGGLED; - prh.HintDescriptor &= ~(LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW); - break; - case PF_INT: - case PF_ENUM: - prh.HintDescriptor |= LADSPA_HINT_INTEGER; - break; - default: { - int defpt = (int)(100 * (pp.def_value - pp.min) / (pp.max - pp.min)); - if ((pp.flags & PF_SCALEMASK) == PF_SCALE_LOG) - defpt = (int)(100 * log(pp.def_value / pp.min) / log(pp.max / pp.min)); - if (defpt < 12) - prh.HintDescriptor |= LADSPA_HINT_DEFAULT_MINIMUM; - else if (defpt < 37) - prh.HintDescriptor |= LADSPA_HINT_DEFAULT_LOW; - else if (defpt < 63) - prh.HintDescriptor |= LADSPA_HINT_DEFAULT_MIDDLE; - else if (defpt < 88) - prh.HintDescriptor |= LADSPA_HINT_DEFAULT_HIGH; - else - prh.HintDescriptor |= LADSPA_HINT_DEFAULT_MAXIMUM; - } - } - if (pp.def_value == 0 || pp.def_value == 1 || pp.def_value == 100 || pp.def_value == 440 ) { - prh.HintDescriptor &= ~LADSPA_HINT_DEFAULT_MASK; - if (pp.def_value == 1) - prh.HintDescriptor |= LADSPA_HINT_DEFAULT_1; - else if (pp.def_value == 100) - prh.HintDescriptor |= LADSPA_HINT_DEFAULT_100; - else if (pp.def_value == 440) - prh.HintDescriptor |= LADSPA_HINT_DEFAULT_440; - else - prh.HintDescriptor |= LADSPA_HINT_DEFAULT_0; - } - switch(pp.flags & PF_SCALEMASK) { - case PF_SCALE_LOG: - prh.HintDescriptor |= LADSPA_HINT_LOGARITHMIC; - break; - } - } - descriptor.ImplementationData = this; - descriptor.instantiate = cb_instantiate; - descriptor.connect_port = cb_connect; - descriptor.activate = cb_activate; - descriptor.run = cb_run; - descriptor.run_adding = NULL; - descriptor.set_run_adding_gain = NULL; - descriptor.deactivate = cb_deactivate; - descriptor.cleanup = cb_cleanup; -#if USE_DSSI - memcpy(&descriptor_for_dssi, &descriptor, sizeof(descriptor)); - descriptor_for_dssi.Name = strdup((std::string(plugin_info.name) + " DSSI").c_str()); - memset(&dssi_descriptor, 0, sizeof(dssi_descriptor)); - dssi_descriptor.DSSI_API_Version = 1; - dssi_descriptor.LADSPA_Plugin = &descriptor_for_dssi; - dssi_descriptor.configure = cb_configure; - dssi_descriptor.get_program = cb_get_program; - dssi_descriptor.select_program = cb_select_program; - if (Module::support_midi) - dssi_descriptor.run_synth = cb_run_synth; - - presets = new std::vector; - preset_descs = new std::vector; - - preset_list plist_tmp, plist; - plist.load_defaults(true); - plist_tmp.load_defaults(false); - plist.presets.insert(plist.presets.end(), plist_tmp.presets.begin(), plist_tmp.presets.end()); - - // XXXKF this assumes that plugin name in preset is case-insensitive equal to plugin label - // if I forget about this, I'll be in a deep trouble - dssi_default_program.Bank = 0; - dssi_default_program.Program = 0; - dssi_default_program.Name = "default"; - - int pos = 1; - for (unsigned int i = 0; i < plist.presets.size(); i++) - { - plugin_preset &pp = plist.presets[i]; - if (strcasecmp(pp.plugin.c_str(), descriptor.Label)) - continue; - DSSI_Program_Descriptor pd; - pd.Bank = pos >> 7; - pd.Program = pos++; - pd.Name = pp.name.c_str(); - preset_descs->push_back(pd); - presets->push_back(pp); - } - // printf("presets = %p:%d name = %s\n", presets, presets->size(), descriptor.Label); - -#endif - } - - ~ladspa_wrapper() - { - delete []descriptor.PortNames; - delete []descriptor.PortDescriptors; - delete []descriptor.PortRangeHints; -#if USE_DSSI - presets->clear(); - preset_descs->clear(); - delete presets; - delete preset_descs; -#endif - } - - /// LADSPA instantiation function (create a plugin instance) - static LADSPA_Handle cb_instantiate(const struct _LADSPA_Descriptor * Descriptor, unsigned long sample_rate) - { - instance *mod = new instance(); - mod->set_sample_rate(sample_rate); - mod->post_instantiate(); - return mod; - } - -#if USE_DSSI - /// DSSI get program descriptor function; for 0, it returns the default program (from parameter properties table), for others, it uses global or user preset - static const DSSI_Program_Descriptor *cb_get_program(LADSPA_Handle Instance, unsigned long index) { - if (index > presets->size()) - return NULL; - if (index) - return &(*preset_descs)[index - 1]; - return &dssi_default_program; - } - - /// DSSI select program function; for 0, it sets the defaults, for others, it sets global or user preset - static void cb_select_program(LADSPA_Handle Instance, unsigned long Bank, unsigned long Program) { - instance *mod = (instance *)Instance; - unsigned int no = (Bank << 7) + Program - 1; - // printf("no = %d presets = %p:%d\n", no, presets, presets->size()); - if (no == -1U) { - int rpc = ladspa_instance::real_param_count(); - for (int i =0 ; i < rpc; i++) - *mod->params[i] = Module::param_props[i].def_value; - return; - } - if (no >= presets->size()) - return; - plugin_preset &p = (*presets)[no]; - // printf("activating preset %s\n", p.name.c_str()); - p.activate(mod); - } - -#endif - - /// LADSPA port connection function - static void cb_connect(LADSPA_Handle Instance, unsigned long port, LADSPA_Data *DataLocation) { - unsigned long ins = Module::in_count; - unsigned long outs = Module::out_count; - unsigned long params = ladspa_instance::real_param_count(); - instance *const mod = (instance *)Instance; - if (port < ins) - mod->ins[port] = DataLocation; - else if (port < ins + outs) - mod->outs[port - ins] = DataLocation; - else if (port < ins + outs + params) { - int i = port - ins - outs; - mod->params[i] = DataLocation; - *mod->params[i] = Module::param_props[i].def_value; - } - } - - /// LADSPA activate function (note that at this moment the ports are not set) - static void cb_activate(LADSPA_Handle Instance) { - instance *const mod = (instance *)Instance; - mod->activate_flag = true; - } - - /// utility function: zero port values if mask is 0 - static inline void zero_by_mask(Module *module, uint32_t mask, uint32_t offset, uint32_t nsamples) - { - for (int i=0; iouts[i] + offset, nsamples); - } - } - } - - /// LADSPA run function - does set sample rate / activate logic when it's run first time after activation - static void cb_run(LADSPA_Handle Instance, unsigned long SampleCount) { - instance *const mod = (instance *)Instance; - if (mod->activate_flag) - { - mod->activate(); - mod->activate_flag = false; - } - mod->params_changed(); - process_slice(mod, 0, SampleCount); - } - - /// utility function: call process, and if it returned zeros in output masks, zero out the relevant output port buffers - static inline void process_slice(Module *mod, uint32_t offset, uint32_t end) - { - while(offset < end) - { - uint32_t newend = std::min(offset + MAX_SAMPLE_RUN, end); - uint32_t out_mask = mod->process(offset, newend - offset, -1, -1); - zero_by_mask(mod, out_mask, offset, newend - offset); - offset = newend; - } - } - -#if USE_DSSI - /// DSSI "run synth" function, same as run() except it allows for event delivery - static void cb_run_synth(LADSPA_Handle Instance, unsigned long SampleCount, - snd_seq_event_t *Events, unsigned long EventCount) { - instance *const mod = (instance *)Instance; - if (mod->activate_flag) - { - mod->activate(); - mod->activate_flag = false; - } - mod->params_changed(); - - uint32_t offset = 0; - for (uint32_t e = 0; e < EventCount; e++) - { - uint32_t timestamp = Events[e].time.tick; - if (timestamp != offset) - process_slice(mod, offset, timestamp); - process_dssi_event(mod, Events[e]); - offset = timestamp; - } - if (offset != SampleCount) - process_slice(mod, offset, SampleCount); - } - - /// DSSI configure function (named properties) - static char *cb_configure(LADSPA_Handle Instance, - const char *Key, - const char *Value) - { - instance *const mod = (instance *)Instance; - return mod->configure(Key, Value); - } - - /// Utility function: handle MIDI event (only handles a subset in this version) - static void process_dssi_event(Module *module, snd_seq_event_t &event) - { - switch(event.type) { - case SND_SEQ_EVENT_NOTEON: - module->note_on(event.data.note.note, event.data.note.velocity); - break; - case SND_SEQ_EVENT_NOTEOFF: - module->note_off(event.data.note.note, event.data.note.velocity); - break; - case SND_SEQ_EVENT_PGMCHANGE: - module->program_change(event.data.control.value); - break; - case SND_SEQ_EVENT_CONTROLLER: - module->control_change(event.data.control.param, event.data.control.value); - break; - case SND_SEQ_EVENT_PITCHBEND: - module->pitch_bend(event.data.control.value); - break; - } - } -#endif - - /// LADSPA deactivate function - static void cb_deactivate(LADSPA_Handle Instance) { - instance *const mod = (instance *)Instance; - mod->deactivate(); - } - - /// LADSPA cleanup (delete instance) function - static void cb_cleanup(LADSPA_Handle Instance) { - instance *const mod = (instance *)Instance; - delete mod; - } - - /// Get a wrapper singleton - used to prevent initialization order problems which were present in older versions - static ladspa_wrapper &get() { - static ladspa_wrapper instance; - return instance; - } -}; - -}; - -#endif - -#endif diff --git a/plugins/ladspa_effect/calf/calf/lv2helpers.h b/plugins/ladspa_effect/calf/calf/lv2helpers.h deleted file mode 100644 index c5a2452c3..000000000 --- a/plugins/ladspa_effect/calf/calf/lv2helpers.h +++ /dev/null @@ -1,281 +0,0 @@ -/* Calf DSP Library - * LV2-related helper classes and functions - * - * Copyright (C) 2001-2008 Krzysztof Foltman - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this program; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02111-1307, USA. - */ -#ifndef CALF_LV2HELPERS_H -#define CALF_LV2HELPERS_H - -#if USE_LV2 - -#include -#include - -class uri_map_access -{ -public: - /// URI map feature pointer (previously in a mixin, but polymorphic ports made it necessary for most plugins) - LV2_URI_Map_Feature *uri_map; - - uri_map_access() - : uri_map(NULL) - {} - - /// Map an URI through an URI map - uint32_t map_uri(const char *ns, const char *URI) - { - if (uri_map) - return uri_map->uri_to_id(uri_map->callback_data, ns, URI); - return 0; - } - /// Called on instantiation for every LV2 feature sent by a host - void use_feature(const char *URI, void *data) { - if (!strcmp(URI, LV2_URI_MAP_URI)) - { - uri_map = (LV2_URI_Map_Feature *)data; - map_uris(); - } - } - virtual void map_uris() - { - } - virtual ~uri_map_access() {} -}; - -/// A mixin for adding the event feature and URI map to the small plugin -template -class event_mixin: public T -{ -public: - /// Event feature pointer - LV2_Event_Feature *event_feature; - virtual void use_feature(const char *URI, void *data) { - if (!strcmp(URI, LV2_EVENT_URI)) - { - event_feature = (LV2_Event_Feature *)data; - } - T::use_feature(URI, data); - } - /// Create a reference - inline void ref_event(LV2_Event *event) { event_feature->lv2_event_ref(event_feature->callback_data, event); } - /// Destroy a reference - inline void unref_event(LV2_Event *event) { event_feature->lv2_event_unref(event_feature->callback_data, event); } -}; - -/// A mixin for adding the URI map and MIDI event type retrieval to small plugins -template -class midi_mixin: public virtual event_mixin -{ -public: - /// MIDI event ID, as resolved using the URI map feature - uint32_t midi_event_type; - virtual void map_uris() { - midi_event_type = this->map_uri("http://lv2plug.in/ns/ext/event", "http://lv2plug.in/ns/ext/midi#MidiEvent"); - printf("MIDI event type = %d\n", midi_event_type); - event_mixin::map_uris(); - } -}; - -/// A mixin for adding the URI map and MIDI event type retrieval to small plugins -template -class message_mixin: public virtual event_mixin -{ -public: - /// MIDI event ID, as resolved using the URI map feature - uint32_t message_event_type; - virtual void map_uris() { - message_event_type = this->map_uri("http://lv2plug.in/ns/ext/event", "http://lv2plug.in/ns/dev/msg#MessageEvent"); - printf("Message event type = %d\n", message_event_type); - event_mixin::map_uris(); - } -}; - -/// LV2 event structure + payload as 0-length array for easy access -struct lv2_event: public LV2_Event -{ - uint8_t data[]; - inline lv2_event &operator=(const lv2_event &src) { - *(LV2_Event *)this = (const LV2_Event &)src; - memcpy(data, src.data, src.size); - return *this; - } - /// Returns a 64-bit timestamp for easy and inefficient comparison - inline uint64_t timestamp() const { - return ((uint64_t)frames << 32) | subframes; - } -private: - /// forbid default constructor - this object cannot be constructed, only obtained via cast from LV2_Event* (or &) to lv2_event* (or &) - lv2_event() {} - /// forbid copy constructor - see default constructor - lv2_event(const lv2_event &) {} -}; - -/// A read-only iterator-like object for reading from event buffers -class event_port_read_iterator -{ -protected: - const LV2_Event_Buffer *buffer; - uint32_t offset; -public: - /// Default constructor creating a useless iterator you can assign to - event_port_read_iterator() - : buffer(NULL) - , offset(0) - { - } - - /// Create an iterator based on specified buffer and index/offset values - event_port_read_iterator(const LV2_Event_Buffer *_buffer, uint32_t _offset = 0) - : buffer(_buffer) - , offset(0) - { - } - - /// Are any data left to be read? - inline operator bool() const { - return offset < buffer->size; - } - - /// Read pointer - inline const lv2_event &operator*() const { - return *(const lv2_event *)(buffer->data + offset); - } - /// Pointer to member - inline const lv2_event *operator->() const { - return &**this; - } - - /// Move to the next element - inline event_port_read_iterator operator++() { - offset += ((**this).size + 19) &~7; - return *this; - } - - /// Move to the next element - inline event_port_read_iterator operator++(int) { - event_port_read_iterator old = *this; - offset += ((**this).size + 19) &~7; - return old; - } -}; - -/// A write-only iterator-like object for writing to event buffers -class event_port_write_iterator -{ -protected: - LV2_Event_Buffer *buffer; -public: - /// Default constructor creating a useless iterator you can assign to - event_port_write_iterator() - : buffer(NULL) - { - } - - /// Create a write iterator based on specified buffer and index/offset values - event_port_write_iterator(LV2_Event_Buffer *_buffer) - : buffer(_buffer) - { - } - - /// @return the remaining buffer space - inline uint32_t space_left() const { - return buffer->capacity - buffer->size; - } - /// @return write pointer - inline lv2_event &operator*() { - return *(lv2_event *)(buffer->data + buffer->size); - } - /// Pointer to member - inline lv2_event *operator->() { - return &**this; - } - /// Move to the next element after the current one has been written (must be called after each write) - inline event_port_write_iterator operator++() { - buffer->size += ((**this).size + 19) &~7; - buffer->event_count ++; - return *this; - } - /// Move to the next element after the current one has been written - inline lv2_event *operator++(int) { - lv2_event *ptr = &**this; - buffer->size += ((**this).size + 19) &~7; - buffer->event_count ++; - return ptr; - } -}; - -template -class event_port_merge_iterator -{ -public: - Iter1 first; - Iter2 second; -public: - event_port_merge_iterator() {} - event_port_merge_iterator(const Iter1 &_first, const Iter2 &_second) - : first(_first) - , second(_second) - { - } - /// @retval true if any of the iterators have any data left - inline operator bool() const { - return ((bool)first) || ((bool)second); - } - inline bool select_first() const - { - if (!(bool)second) - return true; - if (!(bool)first) - return false; - return first->timestamp() < second->timestamp(); - } - /// Returns the earliest of (*first, *second) - inline const lv2_event &operator*() const { - if (select_first()) - { - assert((bool)first); - return *first; - } - assert((bool)second); - return *second; - } - /// Pointer to member - inline const lv2_event *operator->() const { - return &**this; - } - /// Prefix increment - inline event_port_merge_iterator operator++() { - if (select_first()) - first++; - else - second++; - return *this; - } - /// Postfix increment - inline event_port_merge_iterator operator++(int) { - event_port_merge_iterator ptr = *this; - if (select_first()) - first++; - else - second++; - return ptr; - } -}; - -#endif -#endif diff --git a/plugins/ladspa_effect/calf/calf/modulelist.h b/plugins/ladspa_effect/calf/calf/modulelist.h deleted file mode 100644 index 83c123cad..000000000 --- a/plugins/ladspa_effect/calf/calf/modulelist.h +++ /dev/null @@ -1,101 +0,0 @@ -#ifdef PER_MODULE_ITEM - PER_MODULE_ITEM(filter, false, "filter") - PER_MODULE_ITEM(filterclavier, false, "filterclavier") - PER_MODULE_ITEM(flanger, false, "flanger") - PER_MODULE_ITEM(reverb, false, "reverb") - PER_MODULE_ITEM(monosynth, true, "monosynth") - PER_MODULE_ITEM(vintage_delay, false, "vintagedelay") - PER_MODULE_ITEM(organ, true, "organ") - PER_MODULE_ITEM(rotary_speaker, false, "rotaryspeaker") - PER_MODULE_ITEM(phaser, false, "phaser") - PER_MODULE_ITEM(multichorus, false, "multichorus") - PER_MODULE_ITEM(compressor, false, "compressor") - PER_MODULE_ITEM(sidechaincompressor, false, "sidechaincompressor") - PER_MODULE_ITEM(multibandcompressor, false, "multibandcompressor") - PER_MODULE_ITEM(deesser, false, "deesser") - PER_MODULE_ITEM(equalizer5band, false, "equalizer5band") - PER_MODULE_ITEM(equalizer8band, false, "equalizer8band") - PER_MODULE_ITEM(equalizer12band, false, "equalizer12band") -#ifdef ENABLE_EXPERIMENTAL - PER_MODULE_ITEM(fluidsynth, true, "fluidsynth") - PER_MODULE_ITEM(wavetable, true, "wavetable") -#endif -#undef PER_MODULE_ITEM -#endif -#ifdef PER_SMALL_MODULE_ITEM -#ifdef ENABLE_EXPERIMENTAL - PER_SMALL_MODULE_ITEM(lp_filter, "lowpass12") - PER_SMALL_MODULE_ITEM(hp_filter, "highpass12") - PER_SMALL_MODULE_ITEM(bp_filter, "bandpass6") - PER_SMALL_MODULE_ITEM(br_filter, "notch6") - PER_SMALL_MODULE_ITEM(onepole_lp_filter, "lowpass6") - PER_SMALL_MODULE_ITEM(onepole_hp_filter, "highpass6") - PER_SMALL_MODULE_ITEM(onepole_ap_filter, "allpass") - PER_SMALL_MODULE_ITEM(min, "min") - PER_SMALL_MODULE_ITEM(max, "max") - PER_SMALL_MODULE_ITEM(minus, "minus") - PER_SMALL_MODULE_ITEM(mul, "mul") - PER_SMALL_MODULE_ITEM(neg, "neg") - PER_SMALL_MODULE_ITEM(min_c, "min_c") - PER_SMALL_MODULE_ITEM(max_c, "max_c") - PER_SMALL_MODULE_ITEM(minus_c, "minus_c") - PER_SMALL_MODULE_ITEM(mul_c, "mul_c") - PER_SMALL_MODULE_ITEM(neg_c, "neg_c") - PER_SMALL_MODULE_ITEM(level2edge_c, "level2edge_c") - PER_SMALL_MODULE_ITEM(map_lin2exp, "lin2exp") - PER_SMALL_MODULE_ITEM(square_osc, "square_osc") - PER_SMALL_MODULE_ITEM(saw_osc, "saw_osc") - PER_SMALL_MODULE_ITEM(square_lfo, "square_lfo") - PER_SMALL_MODULE_ITEM(saw_lfo, "saw_lfo") - PER_SMALL_MODULE_ITEM(pulse_lfo, "pulse_lfo") - PER_SMALL_MODULE_ITEM(print_a, "print_a") - PER_SMALL_MODULE_ITEM(print_c, "print_c") - PER_SMALL_MODULE_ITEM(print_e, "print_e") - PER_SMALL_MODULE_ITEM(print_em, "print_em") - PER_SMALL_MODULE_ITEM(copy_em, "copy_em") - PER_SMALL_MODULE_ITEM(notefilter_m, "notefilter_m") - PER_SMALL_MODULE_ITEM(ccfilter_m, "ccfilter_m") - PER_SMALL_MODULE_ITEM(pcfilter_m, "pcfilter_m") - PER_SMALL_MODULE_ITEM(pressurefilter_m, "pressurefilter_m") - PER_SMALL_MODULE_ITEM(pitchbendfilter_m, "pitchbendfilter_m") - PER_SMALL_MODULE_ITEM(systemfilter_m, "systemfilter_m") - PER_SMALL_MODULE_ITEM(channelfilter_m, "channelfilter_m") - PER_SMALL_MODULE_ITEM(keyfilter_m, "keyfilter_m") - PER_SMALL_MODULE_ITEM(setchannel_m, "setchannel_m") - PER_SMALL_MODULE_ITEM(key_less_than_m, "key_less_than_m") - PER_SMALL_MODULE_ITEM(channel_less_than_m, "channel_less_than_m") - PER_SMALL_MODULE_ITEM(transpose_m, "transpose_m") - PER_SMALL_MODULE_ITEM(eventmerge_e, "eventmerge_e") - PER_SMALL_MODULE_ITEM(quadpower_a, "quadpower_a") - PER_SMALL_MODULE_ITEM(quadpower_c, "quadpower_c") - PER_SMALL_MODULE_ITEM(crossfader2_a, "crossfader2_a") - PER_SMALL_MODULE_ITEM(crossfader2_c, "crossfader2_c") - PER_SMALL_MODULE_ITEM(linear_inertia_c, "linear_inertia_c") - PER_SMALL_MODULE_ITEM(exp_inertia_c, "exp_inertia_c") - PER_SMALL_MODULE_ITEM(sample_hold_edge_c, "sample_hold_edge_c") - PER_SMALL_MODULE_ITEM(sample_hold_level_c, "sample_hold_level_c") - PER_SMALL_MODULE_ITEM(bit_and_c, "bit_and_c") - PER_SMALL_MODULE_ITEM(bit_or_c, "bit_or_c") - PER_SMALL_MODULE_ITEM(bit_xor_c, "bit_xor_c") - PER_SMALL_MODULE_ITEM(logical_and_c, "logical_and_c") - PER_SMALL_MODULE_ITEM(logical_or_c, "logical_or_c") - PER_SMALL_MODULE_ITEM(logical_xor_c, "logical_xor_c") - PER_SMALL_MODULE_ITEM(logical_not_c, "logical_not_c") - PER_SMALL_MODULE_ITEM(flipflop_c, "flipflop_c") - PER_SMALL_MODULE_ITEM(schmitt_c, "schmitt_c") - PER_SMALL_MODULE_ITEM(between_c, "between_c") - PER_SMALL_MODULE_ITEM(less_c, "less_c") - PER_SMALL_MODULE_ITEM(clip_c, "clip_c") - PER_SMALL_MODULE_ITEM(trigger_a2c, "trigger_a2c") - PER_SMALL_MODULE_ITEM(timer_c, "timer_c") - PER_SMALL_MODULE_ITEM(prio_mux_c, "prio_mux_c") - PER_SMALL_MODULE_ITEM(prio_enc8_c, "prio_enc8_c") - PER_SMALL_MODULE_ITEM(ifthenelse_c, "ifthenelse_c") - PER_SMALL_MODULE_ITEM(counter_c, "counter_c") - PER_SMALL_MODULE_ITEM(mux4_c, "mux4_c") - PER_SMALL_MODULE_ITEM(mux8_c, "mux8_c") - PER_SMALL_MODULE_ITEM(mux16_c, "mux16_c") - PER_SMALL_MODULE_ITEM(msgread_e, "msgread_e") -#endif -#undef PER_SMALL_MODULE_ITEM -#endif diff --git a/plugins/ladspa_effect/calf/calf/modules.h b/plugins/ladspa_effect/calf/calf/modules.h deleted file mode 100644 index e8c4a5e22..000000000 --- a/plugins/ladspa_effect/calf/calf/modules.h +++ /dev/null @@ -1,1425 +0,0 @@ -/* Calf DSP Library - * Example audio modules - * - * Copyright (C) 2001-2007 Krzysztof Foltman - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this program; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02111-1307, USA. - */ -#ifndef __CALF_MODULES_H -#define __CALF_MODULES_H - -#include -#include -#include "biquad.h" -#include "inertia.h" -#include "audio_fx.h" -#include "multichorus.h" -#include "giface.h" -#include "metadata.h" -#include "loudness.h" -#include "primitives.h" - -namespace calf_plugins { - -using namespace dsp; - -struct ladspa_plugin_info; - -#if 0 -class amp_audio_module: public null_audio_module -{ -public: - enum { in_count = 2, out_count = 2, param_count = 1, support_midi = false, require_midi = false, rt_capable = true }; - float *ins[2]; - float *outs[2]; - float *params[1]; - uint32_t srate; - static parameter_properties param_props[]; - uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) { - if (!inputs_mask) - return 0; - float gain = *params[0]; - numsamples += offset; - for (uint32_t i = offset; i < numsamples; i++) { - outs[0][i] = ins[0][i] * gain; - outs[1][i] = ins[1][i] * gain; - } - return inputs_mask; - } -}; -#endif - -class frequency_response_line_graph: public line_graph_iface -{ -public: - bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context); - virtual int get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline); -}; - -class flanger_audio_module: public audio_module, public frequency_response_line_graph -{ -public: - dsp::simple_flanger left, right; - float *ins[in_count]; - float *outs[out_count]; - float *params[param_count]; - uint32_t srate; - bool clear_reset; - float last_r_phase; - bool is_active; -public: - flanger_audio_module() { - is_active = false; - } - void set_sample_rate(uint32_t sr); - void params_changed() { - float dry = *params[par_dryamount]; - float wet = *params[par_amount]; - float rate = *params[par_rate]; // 0.01*pow(1000.0f,*params[par_rate]); - float min_delay = *params[par_delay] / 1000.0; - float mod_depth = *params[par_depth] / 1000.0; - float fb = *params[par_fb]; - left.set_dry(dry); right.set_dry(dry); - left.set_wet(wet); right.set_wet(wet); - left.set_rate(rate); right.set_rate(rate); - left.set_min_delay(min_delay); right.set_min_delay(min_delay); - left.set_mod_depth(mod_depth); right.set_mod_depth(mod_depth); - left.set_fb(fb); right.set_fb(fb); - float r_phase = *params[par_stereo] * (1.f / 360.f); - clear_reset = false; - if (*params[par_reset] >= 0.5) { - clear_reset = true; - left.reset_phase(0.f); - right.reset_phase(r_phase); - } else { - if (fabs(r_phase - last_r_phase) > 0.0001f) { - right.phase = left.phase; - right.inc_phase(r_phase); - last_r_phase = r_phase; - } - } - } - void params_reset() - { - if (clear_reset) { - *params[par_reset] = 0.f; - clear_reset = false; - } - } - void activate(); - void deactivate(); - uint32_t process(uint32_t offset, uint32_t nsamples, uint32_t inputs_mask, uint32_t outputs_mask) { - left.process(outs[0] + offset, ins[0] + offset, nsamples); - right.process(outs[1] + offset, ins[1] + offset, nsamples); - return outputs_mask; // XXXKF allow some delay after input going blank - } - bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context); - float freq_gain(int subindex, float freq, float srate); -}; - -class phaser_audio_module: public audio_module, public frequency_response_line_graph -{ -public: - float *ins[in_count]; - float *outs[out_count]; - float *params[param_count]; - uint32_t srate; - bool clear_reset; - float last_r_phase; - dsp::simple_phaser<12> left, right; - bool is_active; -public: - phaser_audio_module() { - is_active = false; - } - void params_changed() { - float dry = *params[par_dryamount]; - float wet = *params[par_amount]; - float rate = *params[par_rate]; // 0.01*pow(1000.0f,*params[par_rate]); - float base_frq = *params[par_freq]; - float mod_depth = *params[par_depth]; - float fb = *params[par_fb]; - int stages = (int)*params[par_stages]; - left.set_dry(dry); right.set_dry(dry); - left.set_wet(wet); right.set_wet(wet); - left.set_rate(rate); right.set_rate(rate); - left.set_base_frq(base_frq); right.set_base_frq(base_frq); - left.set_mod_depth(mod_depth); right.set_mod_depth(mod_depth); - left.set_fb(fb); right.set_fb(fb); - left.set_stages(stages); right.set_stages(stages); - float r_phase = *params[par_stereo] * (1.f / 360.f); - clear_reset = false; - if (*params[par_reset] >= 0.5) { - clear_reset = true; - left.reset_phase(0.f); - right.reset_phase(r_phase); - } else { - if (fabs(r_phase - last_r_phase) > 0.0001f) { - right.phase = left.phase; - right.inc_phase(r_phase); - last_r_phase = r_phase; - } - } - } - void params_reset() - { - if (clear_reset) { - *params[par_reset] = 0.f; - clear_reset = false; - } - } - void activate(); - void set_sample_rate(uint32_t sr); - void deactivate(); - uint32_t process(uint32_t offset, uint32_t nsamples, uint32_t inputs_mask, uint32_t outputs_mask) { - left.process(outs[0] + offset, ins[0] + offset, nsamples); - right.process(outs[1] + offset, ins[1] + offset, nsamples); - return outputs_mask; // XXXKF allow some delay after input going blank - } - bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context); - bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context); - float freq_gain(int subindex, float freq, float srate); -}; - -class reverb_audio_module: public audio_module -{ -public: - dsp::reverb reverb; - dsp::simple_delay<16384, stereo_sample > pre_delay; - dsp::onepole left_lo, right_lo, left_hi, right_hi; - uint32_t srate; - gain_smoothing amount, dryamount; - int predelay_amt; - float meter_wet, meter_out; - uint32_t clip; - float *ins[in_count]; - float *outs[out_count]; - float *params[param_count]; - - void params_changed() { - //reverb.set_time(0.5*pow(8.0f, *params[par_decay])); - //reverb.set_cutoff(2000*pow(10.0f, *params[par_hfdamp])); - reverb.set_type_and_diffusion(fastf2i_drm(*params[par_roomsize]), *params[par_diffusion]); - reverb.set_time(*params[par_decay]); - reverb.set_cutoff(*params[par_hfdamp]); - amount.set_inertia(*params[par_amount]); - dryamount.set_inertia(*params[par_dry]); - left_lo.set_lp(dsp::clip(*params[par_treblecut], 20.f, (float)(srate * 0.49f)), srate); - left_hi.set_hp(dsp::clip(*params[par_basscut], 20.f, (float)(srate * 0.49f)), srate); - right_lo.copy_coeffs(left_lo); - right_hi.copy_coeffs(left_hi); - predelay_amt = (int) (srate * (*params[par_predelay]) * (1.0f / 1000.0f) + 1); - } - uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) { - numsamples += offset; - clip -= std::min(clip, numsamples); - for (uint32_t i = offset; i < numsamples; i++) { - float dry = dryamount.get(); - float wet = amount.get(); - stereo_sample s(ins[0][i], ins[1][i]); - stereo_sample s2 = pre_delay.process(s, predelay_amt); - - float rl = s2.left, rr = s2.right; - rl = left_lo.process(left_hi.process(rl)); - rr = right_lo.process(right_hi.process(rr)); - reverb.process(rl, rr); - outs[0][i] = dry*s.left + wet*rl; - outs[1][i] = dry*s.right + wet*rr; - meter_wet = std::max(fabs(wet*rl), fabs(wet*rr)); - meter_out = std::max(fabs(outs[0][i]), fabs(outs[1][i])); - if(outs[0][i] > 1.f or outs[1][i] > 1.f) { - clip = srate >> 3; - } - } - reverb.extra_sanitize(); - left_lo.sanitize(); - left_hi.sanitize(); - right_lo.sanitize(); - right_hi.sanitize(); - if(params[par_meter_wet] != NULL) { - *params[par_meter_wet] = meter_wet; - } - if(params[par_meter_out] != NULL) { - *params[par_meter_out] = meter_out; - } - if(params[par_clip] != NULL) { - *params[par_clip] = clip; - } - return outputs_mask; - } - void activate(); - void set_sample_rate(uint32_t sr); - void deactivate(); -}; - -class vintage_delay_audio_module: public audio_module -{ -public: - // 1MB of delay memory per channel... uh, RAM is cheap - enum { MAX_DELAY = 262144, ADDR_MASK = MAX_DELAY - 1 }; - float *ins[in_count]; - float *outs[out_count]; - float *params[param_count]; - float buffers[2][MAX_DELAY]; - int bufptr, deltime_l, deltime_r, mixmode, medium, old_medium; - /// number of table entries written (value is only important when it is less than MAX_DELAY, which means that the buffer hasn't been totally filled yet) - int age; - - gain_smoothing amt_left, amt_right, fb_left, fb_right; - float dry; - - dsp::biquad_d2 biquad_left[2], biquad_right[2]; - - uint32_t srate; - - vintage_delay_audio_module() - { - old_medium = -1; - for (int i = 0; i < MAX_DELAY; i++) { - buffers[0][i] = 0.f; - buffers[1][i] = 0.f; - } - } - - void params_changed() - { - float unit = 60.0 * srate / (*params[par_bpm] * *params[par_divide]); - deltime_l = dsp::fastf2i_drm(unit * *params[par_time_l]); - deltime_r = dsp::fastf2i_drm(unit * *params[par_time_r]); - amt_left.set_inertia(*params[par_amount]); amt_right.set_inertia(*params[par_amount]); - float fb = *params[par_feedback]; - dry = *params[par_dryamount]; - mixmode = dsp::fastf2i_drm(*params[par_mixmode]); - medium = dsp::fastf2i_drm(*params[par_medium]); - if (mixmode == 0) - { - fb_left.set_inertia(fb); - fb_right.set_inertia(pow(fb, *params[par_time_r] / *params[par_time_l])); - } else { - fb_left.set_inertia(fb); - fb_right.set_inertia(fb); - } - if (medium != old_medium) - calc_filters(); - } - void activate() { - bufptr = 0; - age = 0; - } - void deactivate() { - } - void set_sample_rate(uint32_t sr) { - srate = sr; - old_medium = -1; - amt_left.set_sample_rate(sr); amt_right.set_sample_rate(sr); - fb_left.set_sample_rate(sr); fb_right.set_sample_rate(sr); - } - void calc_filters() - { - // parameters are heavily influenced by gordonjcp and his tape delay unit - // although, don't blame him if it sounds bad - I've messed with them too :) - biquad_left[0].set_lp_rbj(6000, 0.707, srate); - biquad_left[1].set_bp_rbj(4500, 0.250, srate); - biquad_right[0].copy_coeffs(biquad_left[0]); - biquad_right[1].copy_coeffs(biquad_left[1]); - } - uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) { - uint32_t ostate = 3; // XXXKF optimize! - uint32_t end = offset + numsamples; - int v = mixmode ? 1 : 0; - int orig_bufptr = bufptr; - for(uint32_t i = offset; i < end; i++) - { - float out_left, out_right, del_left, del_right; - // if the buffer hasn't been cleared yet (after activation), pretend we've read zeros - - if (deltime_l >= age) { - del_left = ins[0][i]; - out_left = dry * del_left; - amt_left.step(); - fb_left.step(); - } - else - { - float in_left = buffers[v][(bufptr - deltime_l) & ADDR_MASK]; - dsp::sanitize(in_left); - out_left = dry * ins[0][i] + in_left * amt_left.get(); - del_left = ins[0][i] + in_left * fb_left.get(); - } - if (deltime_r >= age) { - del_right = ins[1][i]; - out_right = dry * del_right; - amt_right.step(); - fb_right.step(); - } - else - { - float in_right = buffers[1 - v][(bufptr - deltime_r) & ADDR_MASK]; - dsp::sanitize(in_right); - out_right = dry * ins[1][i] + in_right * amt_right.get(); - del_right = ins[1][i] + in_right * fb_right.get(); - } - - age++; - outs[0][i] = out_left; outs[1][i] = out_right; buffers[0][bufptr] = del_left; buffers[1][bufptr] = del_right; - bufptr = (bufptr + 1) & (MAX_DELAY - 1); - } - if (age >= MAX_DELAY) - age = MAX_DELAY; - if (medium > 0) { - bufptr = orig_bufptr; - if (medium == 2) - { - for(uint32_t i = offset; i < end; i++) - { - buffers[0][bufptr] = biquad_left[0].process_lp(biquad_left[1].process(buffers[0][bufptr])); - buffers[1][bufptr] = biquad_right[0].process_lp(biquad_right[1].process(buffers[1][bufptr])); - bufptr = (bufptr + 1) & (MAX_DELAY - 1); - } - biquad_left[0].sanitize();biquad_right[0].sanitize(); - } else { - for(uint32_t i = offset; i < end; i++) - { - buffers[0][bufptr] = biquad_left[1].process(buffers[0][bufptr]); - buffers[1][bufptr] = biquad_right[1].process(buffers[1][bufptr]); - bufptr = (bufptr + 1) & (MAX_DELAY - 1); - } - } - biquad_left[1].sanitize();biquad_right[1].sanitize(); - - } - return ostate; - } -}; - -class rotary_speaker_audio_module: public audio_module -{ -public: - float *ins[in_count]; - float *outs[out_count]; - float *params[param_count]; - /// Current phases and phase deltas for bass and treble rotors - uint32_t phase_l, dphase_l, phase_h, dphase_h; - dsp::simple_delay<1024, float> delay; - dsp::biquad_d2 crossover1l, crossover1r, crossover2l, crossover2r; - dsp::simple_delay<8, float> phaseshift; - uint32_t srate; - int vibrato_mode; - /// Current CC1 (Modulation) value, normalized to [0, 1] - float mwhl_value; - /// Current CC64 (Hold) value, normalized to [0, 1] - float hold_value; - /// Current rotation speed for bass rotor - automatic mode - float aspeed_l; - /// Current rotation speed for treble rotor - automatic mode - float aspeed_h; - /// Desired speed (0=slow, 1=fast) - automatic mode - float dspeed; - /// Current rotation speed for bass rotor - manual mode - float maspeed_l; - /// Current rotation speed for treble rotor - manual mode - float maspeed_h; - - int meter_l, meter_h; - - rotary_speaker_audio_module(); - void set_sample_rate(uint32_t sr); - void setup(); - void activate(); - void deactivate(); - - void params_changed() { - set_vibrato(); - } - void set_vibrato() - { - vibrato_mode = fastf2i_drm(*params[par_speed]); - // manual vibrato - do not recalculate speeds as they're not used anyway - if (vibrato_mode == 5) - return; - if (!vibrato_mode) - dspeed = -1; - else { - float speed = vibrato_mode - 1; - if (vibrato_mode == 3) - speed = hold_value; - if (vibrato_mode == 4) - speed = mwhl_value; - dspeed = (speed < 0.5f) ? 0 : 1; - } - update_speed(); - } - /// Convert RPM speed to delta-phase - inline uint32_t rpm2dphase(float rpm) - { - return (uint32_t)((rpm / (60.0 * srate)) * (1 << 30)) << 2; - } - /// Set delta-phase variables based on current calculated (and interpolated) RPM speed - void update_speed() - { - float speed_h = aspeed_h >= 0 ? (48 + (400-48) * aspeed_h) : (48 * (1 + aspeed_h)); - float speed_l = aspeed_l >= 0 ? 40 + (342-40) * aspeed_l : (40 * (1 + aspeed_l)); - dphase_h = rpm2dphase(speed_h); - dphase_l = rpm2dphase(speed_l); - } - void update_speed_manual(float delta) - { - float ts = *params[par_treblespeed]; - float bs = *params[par_bassspeed]; - incr_towards(maspeed_h, ts, delta * 200, delta * 200); - incr_towards(maspeed_l, bs, delta * 200, delta * 200); - dphase_h = rpm2dphase(maspeed_h); - dphase_l = rpm2dphase(maspeed_l); - } - /// map a ramp [int] to a sinusoid-like function [0, 65536] - static inline int pseudo_sine_scl(int counter) - { - // premature optimization is a root of all evil; it can be done with integers only - but later :) - double v = counter * (1.0 / (65536.0 * 32768.0)); - return (int) (32768 + 32768 * (v - v*v*v) * (1.0 / 0.3849)); - } - /// Increase or decrease aspeed towards raspeed, with required negative and positive rate - inline bool incr_towards(float &aspeed, float raspeed, float delta_decc, float delta_acc) - { - if (aspeed < raspeed) { - aspeed = std::min(raspeed, aspeed + delta_acc); - return true; - } - else if (aspeed > raspeed) - { - aspeed = std::max(raspeed, aspeed - delta_decc); - return true; - } - return false; - } - uint32_t process(uint32_t offset, uint32_t nsamples, uint32_t inputs_mask, uint32_t outputs_mask) - { - int shift = (int)(300000 * (*params[par_shift])), pdelta = (int)(300000 * (*params[par_spacing])); - int md = (int)(100 * (*params[par_moddepth])); - float mix = 0.5 * (1.0 - *params[par_micdistance]); - float mix2 = *params[par_reflection]; - float mix3 = mix2 * mix2; - for (unsigned int i = 0; i < nsamples; i++) { - float in_l = ins[0][i + offset], in_r = ins[1][i + offset]; - float in_mono = 0.5f * (in_l + in_r); - - int xl = pseudo_sine_scl(phase_l), yl = pseudo_sine_scl(phase_l + 0x40000000); - int xh = pseudo_sine_scl(phase_h), yh = pseudo_sine_scl(phase_h + 0x40000000); - // printf("%d %d %d\n", shift, pdelta, shift + pdelta + 20 * xl); - meter_l = xl; - meter_h = xh; - // float out_hi_l = in_mono - delay.get_interp_1616(shift + md * xh) + delay.get_interp_1616(shift + md * 65536 + pdelta - md * yh) - delay.get_interp_1616(shift + md * 65536 + pdelta + pdelta - md * xh); - // float out_hi_r = in_mono + delay.get_interp_1616(shift + md * 65536 - md * yh) - delay.get_interp_1616(shift + pdelta + md * xh) + delay.get_interp_1616(shift + pdelta + pdelta + md * yh); - float out_hi_l = in_mono + delay.get_interp_1616(shift + md * xh) - mix2 * delay.get_interp_1616(shift + md * 65536 + pdelta - md * yh) + mix3 * delay.get_interp_1616(shift + md * 65536 + pdelta + pdelta - md * xh); - float out_hi_r = in_mono + delay.get_interp_1616(shift + md * 65536 - md * yh) - mix2 * delay.get_interp_1616(shift + pdelta + md * xh) + mix3 * delay.get_interp_1616(shift + pdelta + pdelta + md * yh); - - float out_lo_l = in_mono + delay.get_interp_1616(shift + md * xl); // + delay.get_interp_1616(shift + md * 65536 + pdelta - md * yl); - float out_lo_r = in_mono + delay.get_interp_1616(shift + md * yl); // - delay.get_interp_1616(shift + pdelta + md * yl); - - out_hi_l = crossover2l.process(out_hi_l); // sanitize(out_hi_l); - out_hi_r = crossover2r.process(out_hi_r); // sanitize(out_hi_r); - out_lo_l = crossover1l.process(out_lo_l); // sanitize(out_lo_l); - out_lo_r = crossover1r.process(out_lo_r); // sanitize(out_lo_r); - - float out_l = out_hi_l + out_lo_l; - float out_r = out_hi_r + out_lo_r; - - float mic_l = out_l + mix * (out_r - out_l); - float mic_r = out_r + mix * (out_l - out_r); - - outs[0][i + offset] = mic_l * 0.5f; - outs[1][i + offset] = mic_r * 0.5f; - delay.put(in_mono); - phase_l += dphase_l; - phase_h += dphase_h; - } - crossover1l.sanitize(); - crossover1r.sanitize(); - crossover2l.sanitize(); - crossover2r.sanitize(); - float delta = nsamples * 1.0 / srate; - if (vibrato_mode == 5) - update_speed_manual(delta); - else - { - bool u1 = incr_towards(aspeed_l, dspeed, delta * 0.2, delta * 0.14); - bool u2 = incr_towards(aspeed_h, dspeed, delta, delta * 0.5); - if (u1 || u2) - set_vibrato(); - } - if(params[par_meter_l] != NULL) { - *params[par_meter_l] = (float)meter_l / 65536.0; - } - if(params[par_meter_h] != NULL) { - *params[par_meter_h] = (float)meter_h / 65536.0; - } - return outputs_mask; - } - virtual void control_change(int ctl, int val); -}; - -/// Compose two filters in series -template -class filter_compose { -public: - typedef std::complex cfloat; - F1 f1; - F2 f2; -public: - float process(float value) { - return f2.process(f1.process(value)); - } - - cfloat h_z(const cfloat &z) { - return f1.h_z(z) * f2.h_z(z); - } - - /// Return the filter's gain at frequency freq - /// @param freq Frequency to look up - /// @param sr Filter sample rate (used to convert frequency to angular frequency) - float freq_gain(float freq, float sr) - { - typedef std::complex cfloat; - freq *= 2.0 * M_PI / sr; - cfloat z = 1.0 / exp(cfloat(0.0, freq)); - - return std::abs(h_z(z)); - } - - void sanitize() { - f1.sanitize(); - f2.sanitize(); - } -}; - -/// Compose two filters in parallel -template -class filter_sum { -public: - typedef std::complex cfloat; - F1 f1; - F2 f2; -public: - float process(float value) { - return f2.process(value) + f1.process(value); - } - - inline cfloat h_z(const cfloat &z) { - return f1.h_z(z) + f2.h_z(z); - } - - /// Return the filter's gain at frequency freq - /// @param freq Frequency to look up - /// @param sr Filter sample rate (used to convert frequency to angular frequency) - float freq_gain(float freq, float sr) - { - typedef std::complex cfloat; - freq *= 2.0 * M_PI / sr; - cfloat z = 1.0 / exp(cfloat(0.0, freq)); - - return std::abs(h_z(z)); - } - - void sanitize() { - f1.sanitize(); - f2.sanitize(); - } -}; - -template -class filter_module_with_inertia: public FilterClass -{ -public: - typedef filter_module_with_inertia inertia_filter_module; - - float *ins[Metadata::in_count]; - float *outs[Metadata::out_count]; - float *params[Metadata::param_count]; - - inertia inertia_cutoff, inertia_resonance, inertia_gain; - once_per_n timer; - bool is_active; - volatile int last_generation, last_calculated_generation; - - filter_module_with_inertia() - : inertia_cutoff(exponential_ramp(128), 20) - , inertia_resonance(exponential_ramp(128), 20) - , inertia_gain(exponential_ramp(128), 1.0) - , timer(128) - { - is_active = false; - } - - void calculate_filter() - { - float freq = inertia_cutoff.get_last(); - // printf("freq=%g inr.cnt=%d timer.left=%d\n", freq, inertia_cutoff.count, timer.left); - // XXXKF this is resonance of a single stage, obviously for three stages, resonant gain will be different - float q = inertia_resonance.get_last(); - int mode = dsp::fastf2i_drm(*params[Metadata::par_mode]); - // printf("freq = %f q = %f mode = %d\n", freq, q, mode); - - int inertia = dsp::fastf2i_drm(*params[Metadata::par_inertia]); - if (inertia != inertia_cutoff.ramp.length()) { - inertia_cutoff.ramp.set_length(inertia); - inertia_resonance.ramp.set_length(inertia); - inertia_gain.ramp.set_length(inertia); - } - - FilterClass::calculate_filter(freq, q, mode, inertia_gain.get_last()); - } - - virtual void params_changed() - { - calculate_filter(); - } - - void on_timer() - { - int gen = last_generation; - inertia_cutoff.step(); - inertia_resonance.step(); - inertia_gain.step(); - calculate_filter(); - last_calculated_generation = gen; - } - - void activate() - { - params_changed(); - FilterClass::filter_activate(); - timer = once_per_n(FilterClass::srate / 1000); - timer.start(); - is_active = true; - } - - void set_sample_rate(uint32_t sr) - { - FilterClass::srate = sr; - } - - - void deactivate() - { - is_active = false; - } - - uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) { -// printf("sr=%d cutoff=%f res=%f mode=%f\n", FilterClass::srate, *params[Metadata::par_cutoff], *params[Metadata::par_resonance], *params[Metadata::par_mode]); - uint32_t ostate = 0; - numsamples += offset; - while(offset < numsamples) { - uint32_t numnow = numsamples - offset; - // if inertia's inactive, we can calculate the whole buffer at once - if (inertia_cutoff.active() || inertia_resonance.active() || inertia_gain.active()) - numnow = timer.get(numnow); - - if (outputs_mask & 1) { - ostate |= FilterClass::process_channel(0, ins[0] + offset, outs[0] + offset, numnow, inputs_mask & 1); - } - if (outputs_mask & 2) { - ostate |= FilterClass::process_channel(1, ins[1] + offset, outs[1] + offset, numnow, inputs_mask & 2); - } - - if (timer.elapsed()) { - on_timer(); - } - offset += numnow; - } - return ostate; - } -}; - -/// biquad filter module -class filter_audio_module: - public audio_module, - public filter_module_with_inertia, - public frequency_response_line_graph -{ - float old_cutoff, old_resonance, old_mode; -public: - filter_audio_module() - { - last_generation = 0; - } - void params_changed() - { - inertia_cutoff.set_inertia(*params[par_cutoff]); - inertia_resonance.set_inertia(*params[par_resonance]); - inertia_filter_module::params_changed(); - } - - void activate() - { - inertia_filter_module::activate(); - } - - void set_sample_rate(uint32_t sr) - { - inertia_filter_module::set_sample_rate(sr); - } - - - void deactivate() - { - inertia_filter_module::deactivate(); - } - - bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context); - int get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline); -}; - -/// A multitap stereo chorus thing - processing -class multichorus_audio_module: public audio_module, public frequency_response_line_graph -{ -public: - float *ins[in_count]; - float *outs[out_count]; - float *params[param_count]; - uint32_t srate; - dsp::multichorus, filter_sum, dsp::biquad_d2<> >, 4096> left, right; - float last_r_phase; - float cutoff; - bool is_active; - -public: - multichorus_audio_module() - { - is_active = false; - last_r_phase = -1; - } - - void params_changed() - { - // delicious copy-pasta from flanger module - it'd be better to keep it common or something - float dry = *params[par_dryamount]; - float wet = *params[par_amount]; - float rate = *params[par_rate]; - float min_delay = *params[par_delay] / 1000.0; - float mod_depth = *params[par_depth] / 1000.0; - float overlap = *params[par_overlap]; - left.set_dry(dry); right.set_dry(dry); - left.set_wet(wet); right.set_wet(wet); - left.set_rate(rate); right.set_rate(rate); - left.set_min_delay(min_delay); right.set_min_delay(min_delay); - left.set_mod_depth(mod_depth); right.set_mod_depth(mod_depth); - int voices = (int)*params[par_voices]; - left.lfo.set_voices(voices); right.lfo.set_voices(voices); - left.lfo.set_overlap(overlap);right.lfo.set_overlap(overlap); - float vphase = *params[par_vphase] * (1.f / 360.f); - left.lfo.vphase = right.lfo.vphase = vphase * (4096 / std::max(voices - 1, 1)); - float r_phase = *params[par_stereo] * (1.f / 360.f); - if (fabs(r_phase - last_r_phase) > 0.0001f) { - right.lfo.phase = left.lfo.phase; - right.lfo.phase += chorus_phase(r_phase * 4096); - last_r_phase = r_phase; - } - left.post.f1.set_bp_rbj(*params[par_freq], *params[par_q], srate); - left.post.f2.set_bp_rbj(*params[par_freq2], *params[par_q], srate); - right.post.f1.copy_coeffs(left.post.f1); - right.post.f2.copy_coeffs(left.post.f2); - } - uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) { - left.process(outs[0] + offset, ins[0] + offset, numsamples); - right.process(outs[1] + offset, ins[1] + offset, numsamples); - return outputs_mask; // XXXKF allow some delay after input going blank - } - void activate(); - void deactivate(); - void set_sample_rate(uint32_t sr); - bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context); - float freq_gain(int subindex, float freq, float srate); - bool get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context); - bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context); -}; - -class compressor_audio_module: public audio_module, public line_graph_iface { -private: - float linSlope, peak, detected, kneeSqrt, kneeStart, linKneeStart, kneeStop, threshold, ratio, knee, makeup, compressedKneeStop, adjKneeStart; - float old_threshold, old_ratio, old_knee, old_makeup, old_bypass; - int last_generation; - uint32_t clip; - aweighter awL, awR; - biquad_d2 bpL, bpR; -public: - float *ins[in_count]; - float *outs[out_count]; - float *params[param_count]; - uint32_t srate; - bool is_active; - compressor_audio_module(); - void activate(); - void deactivate(); - uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask); - - inline float output_level(float slope) { - return slope * output_gain(slope, false) * makeup; - } - - inline float output_gain(float linSlope, bool rms) { - if(linSlope > (rms ? adjKneeStart : linKneeStart)) { - float slope = log(linSlope); - if(rms) slope *= 0.5f; - - float gain = 0.f; - float delta = 0.f; - if(IS_FAKE_INFINITY(ratio)) { - gain = threshold; - delta = 0.f; - } else { - gain = (slope - threshold) / ratio + threshold; - delta = 1.f / ratio; - } - - if(knee > 1.f && slope < kneeStop) { - gain = hermite_interpolation(slope, kneeStart, kneeStop, kneeStart, compressedKneeStop, 1.f, delta); - } - - return exp(gain - slope); - } - - return 1.f; - } - - void set_sample_rate(uint32_t sr); - - virtual bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context); - virtual bool get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context); - virtual bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context); - - virtual int get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) - { - subindex_graph = 0; - subindex_dot = 0; - subindex_gridline = generation ? INT_MAX : 0; - - if (fabs(threshold-old_threshold) + fabs(ratio - old_ratio) + fabs(knee - old_knee) + fabs( makeup - old_makeup) + fabs( *params[param_bypass] - old_bypass) > 0.01f) - { - old_threshold = threshold; - old_ratio = ratio; - old_knee = knee; - old_makeup = makeup; - old_bypass = *params[param_bypass]; - last_generation++; - } - - if (generation == last_generation) - subindex_graph = 2; - return last_generation; - } -}; - -class gain_reduction_audio_module { -private: - float linSlope, detected, kneeSqrt, kneeStart, linKneeStart, kneeStop; - float compressedKneeStop, adjKneeStart, thres; - float attack, release, threshold, ratio, knee, makeup, detection, stereo_link, bypass, mute, meter_out, meter_comp; - float old_threshold, old_ratio, old_knee, old_makeup, old_bypass, old_mute, old_detection, old_stereo_link; - int last_generation; - uint32_t srate; - bool is_active; - inline float output_level(float slope); - inline float output_gain(float linSlope, bool rms); -public: - gain_reduction_audio_module(); - void set_params(float att, float rel, float thr, float rat, float kn, float mak, float det, float stl, float byp, float mu); - void process(float &left, float &right, float det_left = NULL, float det_right = NULL); - void activate(); - void deactivate(); - int id; - void set_sample_rate(uint32_t sr); - float get_output_level(); - float get_comp_level(); - virtual bool get_graph(int subindex, float *data, int points, cairo_iface *context); - virtual bool get_dot(int subindex, float &x, float &y, int &size, cairo_iface *context); - virtual bool get_gridline(int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context); - virtual int get_changed_offsets(int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline); -}; - -/// Sidecain Compressor by Markus Schmidt (based on Thor's compressor and Krzysztof's filters) -class sidechaincompressor_audio_module: public audio_module, public frequency_response_line_graph { -private: - enum CalfScModes { - WIDEBAND, - DEESSER_WIDE, - DEESSER_SPLIT, - DERUMBLER_WIDE, - DERUMBLER_SPLIT, - WEIGHTED_1, - WEIGHTED_2, - WEIGHTED_3, - BANDPASS_1, - BANDPASS_2 - }; - float f1_freq_old, f2_freq_old, f1_level_old, f2_level_old; - float f1_freq_old1, f2_freq_old1, f1_level_old1, f2_level_old1; - CalfScModes sc_mode, sc_mode_old, sc_mode_old1; - float f1_active, f2_active; - uint32_t clip_in, clip_out; - float meter_in, meter_out; - gain_reduction_audio_module compressor; - biquad_d2 f1L, f1R, f2L, f2R; -public: - typedef std::complex cfloat; - float *ins[in_count]; - float *outs[out_count]; - float *params[param_count]; - uint32_t srate; - bool is_active; - volatile int last_generation, last_calculated_generation; - sidechaincompressor_audio_module(); - void activate(); - void deactivate(); - void params_changed(); - inline cfloat h_z(const cfloat &z) { - switch (sc_mode) { - default: - case WIDEBAND: - return false; - break; - case DEESSER_WIDE: - case DERUMBLER_WIDE: - case WEIGHTED_1: - case WEIGHTED_2: - case WEIGHTED_3: - case BANDPASS_2: - return f1L.h_z(z) * f2L.h_z(z); - break; - case DEESSER_SPLIT: - return f2L.h_z(z); - break; - case DERUMBLER_SPLIT: - case BANDPASS_1: - return f1L.h_z(z); - break; - } - - } - float freq_gain(int index, double freq, uint32_t sr) - { - typedef std::complex cfloat; - freq *= 2.0 * M_PI / sr; - cfloat z = 1.0 / exp(cfloat(0.0, freq)); - - return std::abs(h_z(z)); - } - void set_sample_rate(uint32_t sr); - uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask); - bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context); - bool get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context); - bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context); - int get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline); -}; - -/// Multibandcompressor by Markus Schmidt -class multibandcompressor_audio_module: public audio_module, public line_graph_iface { -private: - static const int strips = 4; - bool mute[strips]; - uint32_t clip_inL, clip_inR, clip_outL, clip_outR; - float meter_inL, meter_inR, meter_outL, meter_outR; - gain_reduction_audio_module strip[strips]; - dsp::biquad_d2 lpL0, lpR0, lpL1, lpR1, lpL2, lpR2, hpL0, hpR0, hpL1, hpR1, hpL2, hpR2; - float freq_old[strips - 1], sep_old[strips - 1], q_old[strips - 1]; -public: - float *ins[in_count]; - float *outs[out_count]; - float *params[param_count]; - uint32_t srate; - bool is_active; - multibandcompressor_audio_module(); - void activate(); - void deactivate(); - void params_changed(); - uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask); - void set_sample_rate(uint32_t sr); - virtual bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context); - virtual bool get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context); - virtual bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context); - virtual int get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline); -}; - -/// Deesser by Markus Schmidt (based on Thor's compressor and Krzysztof's filters) -class deesser_audio_module: public audio_module, public frequency_response_line_graph { -private: - enum CalfDeessModes { - WIDE, - SPLIT - }; - float f1_freq_old, f2_freq_old, f1_level_old, f2_level_old, f2_q_old; - float f1_freq_old1, f2_freq_old1, f1_level_old1, f2_level_old1, f2_q_old1; - uint32_t detected_led; - float detected, clip_out; - uint32_t clip_led; - gain_reduction_audio_module compressor; - biquad_d2 hpL, hpR, lpL, lpR, pL, pR; -public: - float *ins[in_count]; - float *outs[out_count]; - float *params[param_count]; - uint32_t srate; - bool is_active; - volatile int last_generation, last_calculated_generation; - deesser_audio_module(); - void activate(); - void deactivate(); - void params_changed(); - float freq_gain(int index, double freq, uint32_t sr) - { - return hpL.freq_gain(freq, sr) * pL.freq_gain(freq, sr); - } - void set_sample_rate(uint32_t sr); - uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask); - bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context); - bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context); - int get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline); -}; - -/// Equalizer 12 Band by Markus Schmidt (based on Krzysztof's filters) -class equalizer12band_audio_module: public audio_module, public frequency_response_line_graph { -private: - float hp_mode_old, hp_freq_old; - float lp_mode_old, lp_freq_old; - float ls_level_old, ls_freq_old; - float hs_level_old, hs_freq_old; - float p_level_old[8], p_freq_old[8], p_q_old[8]; - float hp_mode_old1, hp_freq_old1, hp_active_old1; - float lp_mode_old1, lp_freq_old1, lp_active_old1; - float ls_level_old1, ls_freq_old1, ls_active_old1; - float hs_level_old1, hs_freq_old1, hs_active_old1; - float p_level_old1[8], p_freq_old1[8], p_q_old1[8], p_active_old1[8]; - enum CalfEqModes { - MODE12DB, - MODE24DB, - MODE36DB - }; - CalfEqModes eq_mode, eq_mode_old1[2]; - uint32_t clip_inL, clip_outL, clip_inR, clip_outR; - float meter_inL, meter_outL, meter_inR, meter_outR; - biquad_d2 hpL[3], hpR[3], lpL[3], lpR[3]; - biquad_d2 lsL, lsR, hsL, hsR; - biquad_d2 pL[8], pR[8]; -public: - typedef std::complex cfloat; - float *ins[in_count]; - float *outs[out_count]; - float *params[param_count]; - uint32_t srate; - bool is_active; - volatile int last_generation, last_calculated_generation; - equalizer12band_audio_module(); - void activate(); - void deactivate(); - void params_changed(); - float freq_gain(int index, double freq, uint32_t sr) - { - float ret = 1.f; - if(*params[param_hp_active] > 0.f) { - switch((int)*params[param_hp_mode]) { - case MODE12DB: - ret *= hpL[0].freq_gain(freq, sr); - ret *= hpR[0].freq_gain(freq, sr); - break; - case MODE24DB: - ret *= hpL[0].freq_gain(freq, sr) * hpL[0].freq_gain(freq, sr); - ret *= hpR[0].freq_gain(freq, sr) * hpR[0].freq_gain(freq, sr); - break; - case MODE36DB: - ret *= hpL[0].freq_gain(freq, sr) * hpL[0].freq_gain(freq, sr) * hpL[0].freq_gain(freq, sr); - ret *= hpR[0].freq_gain(freq, sr) * hpR[0].freq_gain(freq, sr) * hpR[0].freq_gain(freq, sr); - break; - } - } - if(*params[param_lp_active] > 0.f) { - switch((int)*params[param_lp_mode]) { - case MODE12DB: - ret *= lpL[0].freq_gain(freq, sr); - ret *= lpR[0].freq_gain(freq, sr); - break; - case MODE24DB: - ret *= lpL[0].freq_gain(freq, sr) * lpL[0].freq_gain(freq, sr); - ret *= lpR[0].freq_gain(freq, sr) * lpR[0].freq_gain(freq, sr); - break; - case MODE36DB: - ret *= lpL[0].freq_gain(freq, sr) * lpL[0].freq_gain(freq, sr) * lpL[0].freq_gain(freq, sr); - ret *= lpR[0].freq_gain(freq, sr) * lpR[0].freq_gain(freq, sr) * lpR[0].freq_gain(freq, sr); - break; - } - } - ret *= (*params[param_ls_active] > 0.f) ? lsL.freq_gain(freq, sr) : 1; - ret *= (*params[param_hs_active] > 0.f) ? hsL.freq_gain(freq, sr) : 1; - ret *= (*params[param_p1_active] > 0.f) ? pL[0].freq_gain(freq, sr) : 1; - ret *= (*params[param_p2_active] > 0.f) ? pL[1].freq_gain(freq, sr) : 1; - ret *= (*params[param_p3_active] > 0.f) ? pL[2].freq_gain(freq, sr) : 1; - ret *= (*params[param_p4_active] > 0.f) ? pL[3].freq_gain(freq, sr) : 1; - ret *= (*params[param_p5_active] > 0.f) ? pL[4].freq_gain(freq, sr) : 1; - ret *= (*params[param_p6_active] > 0.f) ? pL[5].freq_gain(freq, sr) : 1; - ret *= (*params[param_p7_active] > 0.f) ? pL[6].freq_gain(freq, sr) : 1; - ret *= (*params[param_p8_active] > 0.f) ? pL[7].freq_gain(freq, sr) : 1; - return ret; - } - void set_sample_rate(uint32_t sr); - uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask); - bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context); - bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context); - int get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline); -}; - -/// Equalizer 8 Band by Markus Schmidt (based on Krzysztof's filters) -class equalizer8band_audio_module: public audio_module, public frequency_response_line_graph { -private: - float hp_mode_old, hp_freq_old; - float lp_mode_old, lp_freq_old; - float ls_level_old, ls_freq_old; - float hs_level_old, hs_freq_old; - float p_level_old[4], p_freq_old[4], p_q_old[4]; - float hp_mode_old1, hp_freq_old1, hp_active_old1; - float lp_mode_old1, lp_freq_old1, lp_active_old1; - float ls_level_old1, ls_freq_old1, ls_active_old1; - float hs_level_old1, hs_freq_old1, hs_active_old1; - float p_level_old1[4], p_freq_old1[4], p_q_old1[4], p_active_old1[4]; - enum CalfEqModes { - MODE12DB, - MODE24DB, - MODE36DB - }; - CalfEqModes eq_mode, eq_mode_old1[2]; - uint32_t clip_inL, clip_outL, clip_inR, clip_outR; - float meter_inL, meter_outL, meter_inR, meter_outR; - biquad_d2 hpL[3], hpR[3], lpL[3], lpR[3]; - biquad_d2 lsL, lsR, hsL, hsR; - biquad_d2 pL[4], pR[4]; -public: - typedef std::complex cfloat; - float *ins[in_count]; - float *outs[out_count]; - float *params[param_count]; - uint32_t srate; - bool is_active; - volatile int last_generation, last_calculated_generation; - equalizer8band_audio_module(); - void activate(); - void deactivate(); - void params_changed(); - float freq_gain(int index, double freq, uint32_t sr) - { - float ret = 1.f; - if(*params[param_hp_active] > 0.f) { - switch((int)*params[param_hp_mode]) { - case MODE12DB: - ret *= hpL[0].freq_gain(freq, sr); - ret *= hpR[0].freq_gain(freq, sr); - break; - case MODE24DB: - ret *= hpL[0].freq_gain(freq, sr) * hpL[0].freq_gain(freq, sr); - ret *= hpR[0].freq_gain(freq, sr) * hpR[0].freq_gain(freq, sr); - break; - case MODE36DB: - ret *= hpL[0].freq_gain(freq, sr) * hpL[0].freq_gain(freq, sr) * hpL[0].freq_gain(freq, sr); - ret *= hpR[0].freq_gain(freq, sr) * hpR[0].freq_gain(freq, sr) * hpR[0].freq_gain(freq, sr); - break; - } - } - if(*params[param_lp_active] > 0.f) { - switch((int)*params[param_lp_mode]) { - case MODE12DB: - ret *= lpL[0].freq_gain(freq, sr); - ret *= lpR[0].freq_gain(freq, sr); - break; - case MODE24DB: - ret *= lpL[0].freq_gain(freq, sr) * lpL[0].freq_gain(freq, sr); - ret *= lpR[0].freq_gain(freq, sr) * lpR[0].freq_gain(freq, sr); - break; - case MODE36DB: - ret *= lpL[0].freq_gain(freq, sr) * lpL[0].freq_gain(freq, sr) * lpL[0].freq_gain(freq, sr); - ret *= lpR[0].freq_gain(freq, sr) * lpR[0].freq_gain(freq, sr) * lpR[0].freq_gain(freq, sr); - break; - } - } - ret *= (*params[param_ls_active] > 0.f) ? lsL.freq_gain(freq, sr) : 1; - ret *= (*params[param_hs_active] > 0.f) ? hsL.freq_gain(freq, sr) : 1; - ret *= (*params[param_p1_active] > 0.f) ? pL[0].freq_gain(freq, sr) : 1; - ret *= (*params[param_p2_active] > 0.f) ? pL[1].freq_gain(freq, sr) : 1; - ret *= (*params[param_p3_active] > 0.f) ? pL[2].freq_gain(freq, sr) : 1; - ret *= (*params[param_p4_active] > 0.f) ? pL[3].freq_gain(freq, sr) : 1; - return ret; - } - void set_sample_rate(uint32_t sr); - uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask); - bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context); - bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context); - int get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline); -}; - -/// Equalizer 5 Band by Markus Schmidt (based on Krzysztof's filters) -class equalizer5band_audio_module: public audio_module, public frequency_response_line_graph { -private: - float ls_level_old, ls_freq_old; - float hs_level_old, hs_freq_old; - float p_level_old[3], p_freq_old[3], p_q_old[3]; - float ls_level_old1, ls_freq_old1, ls_active_old1; - float hs_level_old1, hs_freq_old1, hs_active_old1; - float p_level_old1[3], p_freq_old1[3], p_q_old1[3], p_active_old1[3]; - uint32_t clip_in, clip_out; - float meter_in, meter_out; - biquad_d2 lsL, lsR, hsL, hsR; - biquad_d2 pL[3], pR[3]; -public: - typedef std::complex cfloat; - float *ins[in_count]; - float *outs[out_count]; - float *params[param_count]; - uint32_t srate; - bool is_active; - volatile int last_generation, last_calculated_generation; - equalizer5band_audio_module(); - void activate(); - void deactivate(); - void params_changed(); - float freq_gain(int index, double freq, uint32_t sr) - { - float ret = 1.f; - ret *= (*params[param_ls_active] > 0.f) ? lsL.freq_gain(freq, sr) : 1; - ret *= (*params[param_hs_active] > 0.f) ? hsL.freq_gain(freq, sr) : 1; - ret *= (*params[param_p1_active] > 0.f) ? pL[0].freq_gain(freq, sr) : 1; - ret *= (*params[param_p2_active] > 0.f) ? pL[1].freq_gain(freq, sr) : 1; - ret *= (*params[param_p3_active] > 0.f) ? pL[2].freq_gain(freq, sr) : 1; - return ret; - } - void set_sample_rate(uint32_t sr); - uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask); - bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context); - bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context); - int get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline); -}; - -/// Filterclavier --- MIDI controlled filter by Hans Baier -class filterclavier_audio_module: - public audio_module, - public filter_module_with_inertia, - public frequency_response_line_graph -{ - const float min_gain; - const float max_gain; - - int last_note; - int last_velocity; - -public: - filterclavier_audio_module() - : - min_gain(1.0), - max_gain(32.0), - last_note(-1), - last_velocity(-1) {} - - void params_changed() - { - inertia_filter_module::inertia_cutoff.set_inertia( - note_to_hz(last_note + *params[par_transpose], *params[par_detune])); - - float min_resonance = param_props[par_max_resonance].min; - inertia_filter_module::inertia_resonance.set_inertia( - (float(last_velocity) / 127.0) - // 0.001: see below - * (*params[par_max_resonance] - min_resonance + 0.001) - + min_resonance); - - adjust_gain_according_to_filter_mode(last_velocity); - - inertia_filter_module::calculate_filter(); - } - - void activate() - { - inertia_filter_module::activate(); - } - - void set_sample_rate(uint32_t sr) - { - inertia_filter_module::set_sample_rate(sr); - } - - - void deactivate() - { - inertia_filter_module::deactivate(); - } - - /// MIDI control - virtual void note_on(int note, int vel) - { - last_note = note; - last_velocity = vel; - inertia_filter_module::inertia_cutoff.set_inertia( - note_to_hz(note + *params[par_transpose], *params[par_detune])); - - float min_resonance = param_props[par_max_resonance].min; - inertia_filter_module::inertia_resonance.set_inertia( - (float(vel) / 127.0) - // 0.001: if the difference is equal to zero (which happens - // when the max_resonance knom is at minimum position - // then the filter gain doesnt seem to snap to zero on most note offs - * (*params[par_max_resonance] - min_resonance + 0.001) - + min_resonance); - - adjust_gain_according_to_filter_mode(vel); - - inertia_filter_module::calculate_filter(); - } - - virtual void note_off(int note, int vel) - { - if (note == last_note) { - inertia_filter_module::inertia_resonance.set_inertia(param_props[par_max_resonance].min); - inertia_filter_module::inertia_gain.set_inertia(min_gain); - inertia_filter_module::calculate_filter(); - last_velocity = 0; - } - } - - bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context); - -private: - void adjust_gain_according_to_filter_mode(int velocity) { - int mode = dsp::fastf2i_drm(*params[par_mode]); - - // for bandpasses: boost gain for velocities > 0 - if ( (mode_6db_bp <= mode) && (mode <= mode_18db_bp) ) { - // gain for velocity 0: 1.0 - // gain for velocity 127: 32.0 - float mode_max_gain = max_gain; - // max_gain is right for mode_6db_bp - if (mode == mode_12db_bp) - mode_max_gain /= 6.0; - if (mode == mode_18db_bp) - mode_max_gain /= 10.5; - - inertia_filter_module::inertia_gain.set_now( - (float(velocity) / 127.0) * (mode_max_gain - min_gain) + min_gain); - } else { - inertia_filter_module::inertia_gain.set_now(min_gain); - } - } -}; - -extern std::string get_builtin_modules_rdf(); - -}; - -#include "modules_synths.h" - -#endif diff --git a/plugins/ladspa_effect/calf/calf/modules_small.h b/plugins/ladspa_effect/calf/calf/modules_small.h deleted file mode 100644 index c186e9972..000000000 --- a/plugins/ladspa_effect/calf/calf/modules_small.h +++ /dev/null @@ -1,202 +0,0 @@ -/* Calf DSP Library - * "Small" audio modules for modular synthesis - * - * Copyright (C) 2001-2007 Krzysztof Foltman - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this program; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02111-1307, USA. - */ -#ifndef __CALF_MODULES_SMALL_H -#define __CALF_MODULES_SMALL_H - -#if USE_LV2 - -#include -#include "plugininfo.h" -#include "lv2_polymorphic_port.h" -#include "lv2helpers.h" - -namespace calf_plugins { - -/// Empty implementations for plugin functions. Note, that some functions aren't virtual, because they're called via the particular -/// subclass via template wrappers (ladspa_small_wrapper<> etc), not via base class pointer/reference. On the other hand, -/// other functions are virtual when overhead is acceptable (instantiation time functions etc.) -class null_small_audio_module: public uri_map_access -{ -public: - uint32_t srate; - double odsr; - uint32_t poly_type_control, poly_type_audio; - /// for polymorphic ports: "is audio" flags for first 32 ports (should be sufficient for most plugins) - uint32_t poly_port_types; - - null_small_audio_module() - : srate((uint32_t)-1) - , odsr(0.) - , poly_type_control(0) - , poly_type_audio(0) - , poly_port_types(0) - { - } - - /// Called when host changes type of the polymorphic port - inline void set_port_type(uint32_t port, uint32_t type, void *type_data) { - if (port >= 32) - return; - uint32_t port_mask = 1 << port; - if (type == poly_type_control) - poly_port_types &= ~port_mask; - else if (type == poly_type_audio) - poly_port_types |= port_mask; - on_port_types_changed(); - } - - /// Returns 1 for audio ports and 0 for control ports - inline unsigned int port_is_audio(unsigned int port) { - return (poly_port_types >> port) & 1; - } - - /// Returns (unsigned)-1 for audio ports and 0 for control ports - inline unsigned int port_audio_mask(unsigned int port) { - return 0 - ((poly_port_types >> port) & 1); - } - - /// Returns (unsigned)-1 for audio ports and 0 for control ports - static inline unsigned int port_audio_mask(unsigned int port, uint32_t poly_port_types) { - return 0 - ((poly_port_types >> port) & 1); - } - - virtual void on_port_types_changed() {} - inline void set_bundle_path(const char *path) {} - /// Called to map all the necessary URIs - virtual void map_uris() - { - poly_type_control = map_uri(LV2_POLYMORPHIC_PORT_URI, "http://lv2plug.in/ns/lv2core#ControlPort"); - poly_type_audio = map_uri(LV2_POLYMORPHIC_PORT_URI, "http://lv2plug.in/ns/lv2core#AudioPort"); - } - /// Called on instantiation with the list of LV2 features called - virtual void use_features(const LV2_Feature *const *features) { - while(*features) - { - use_feature((*features)->URI, (*features)->data); - features++; - } - } - /// LADSPA-esque activate function, except it is called after ports are connected, not before - inline void activate() {} - /// LADSPA-esque deactivate function - inline void deactivate() {} - /// Set sample rate for the plugin - inline void set_sample_rate(uint32_t sr) { srate = sr; odsr = 1.0 / sr; } - static inline const void *ext_data(const char *URI) { return NULL; } -}; - -/// Templatized version useful when the number of inputs and outputs is small -template -class small_audio_module_base: public null_small_audio_module -{ -public: - enum { in_count = Inputs, out_count = Outputs }; - /// Input pointers - float *ins[in_count]; - /// Output pointers - float *outs[out_count]; -}; - -template -struct lv2_small_wrapper -{ - typedef Module instance; - static LV2_Descriptor descriptor; - std::string uri; - static uint32_t poly_port_types; - - lv2_small_wrapper(const char *id) - { - uri = "http://calf.sourceforge.net/small_plugins/" + std::string(id); - descriptor.URI = uri.c_str(); - descriptor.instantiate = cb_instantiate; - descriptor.connect_port = cb_connect; - descriptor.activate = cb_activate; - descriptor.run = cb_run; - descriptor.deactivate = cb_deactivate; - descriptor.cleanup = cb_cleanup; - descriptor.extension_data = cb_ext_data; - - plugin_port_type_grabber ptg(poly_port_types); - Module::plugin_info(&ptg); - } - - static void cb_connect(LV2_Handle Instance, uint32_t port, void *DataLocation) { - unsigned long ins = Module::in_count; - unsigned long outs = Module::out_count; - instance *const mod = (instance *)Instance; - if (port < ins) - mod->ins[port] = (float *)DataLocation; - else if (port < ins + outs) - mod->outs[port - ins] = (float *)DataLocation; - } - - static void cb_activate(LV2_Handle Instance) { - // Note the changed semantics (now more LV2-like) - instance *const mod = (instance *)Instance; - mod->activate(); - } - - static void cb_deactivate(LV2_Handle Instance) { - instance *const mod = (instance *)Instance; - mod->deactivate(); - } - - static uint32_t cb_set_type(LV2_Handle Instance, uint32_t port, uint32_t type, void *type_data) - { - instance *const mod = (instance *)Instance; - mod->set_port_type(port, type, type_data); - return 0; - } - - static LV2_Handle cb_instantiate(const LV2_Descriptor * Descriptor, double sample_rate, const char *bundle_path, const LV2_Feature *const *features) - { - instance *mod = new instance(); - mod->poly_port_types = poly_port_types; - // XXXKF some people use fractional sample rates; we respect them ;-) - mod->set_bundle_path(bundle_path); - mod->use_features(features); - mod->set_sample_rate((uint32_t)sample_rate); - return mod; - } - - static void cb_run(LV2_Handle Instance, uint32_t SampleCount) { - instance *const mod = (instance *)Instance; - mod->process(SampleCount); - } - - static void cb_cleanup(LV2_Handle Instance) { - instance *const mod = (instance *)Instance; - delete mod; - } - - static const void *cb_ext_data(const char *URI) { - return Module::ext_data(URI); - } -}; - -extern const LV2_Descriptor *lv2_small_descriptor(uint32_t index); - -}; - -#endif - -#endif diff --git a/plugins/ladspa_effect/calf/calf/plugininfo.h b/plugins/ladspa_effect/calf/calf/plugininfo.h deleted file mode 100644 index 46181998d..000000000 --- a/plugins/ladspa_effect/calf/calf/plugininfo.h +++ /dev/null @@ -1,105 +0,0 @@ -/* Calf DSP Library - * Plugin introspection interface - * - * Copyright (C) 2008 Krzysztof Foltman - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this program; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __CALF_PLUGININFO_H -#define __CALF_PLUGININFO_H - -#include - -namespace calf_plugins { - -/// A sink to send information about an audio port -struct plain_port_info_iface -{ - /// Called if it's an input port - virtual plain_port_info_iface& input() { return *this; } - /// Called if it's an output port - virtual plain_port_info_iface& output() { return *this; } - virtual plain_port_info_iface& lv2_ttl(const std::string &text) { return *this; } - virtual ~plain_port_info_iface() {} -}; - -/// A sink to send information about a control port (very incomplete, missing stuff: units, integer, boolean, toggled, notAutomatic, notGUI...) -struct control_port_info_iface -{ - /// Called if it's an input port - virtual control_port_info_iface& input() { return *this; } - /// Called if it's an output port - virtual control_port_info_iface& output() { return *this; } - /// Called to mark the port as using linear range [from, to] - virtual control_port_info_iface& lin_range(double from, double to) { return *this; } - /// Called to mark the port as using log range [from, to] - virtual control_port_info_iface& log_range(double from, double to) { return *this; } - virtual control_port_info_iface& toggle() { return *this; } - virtual control_port_info_iface& trigger() { return *this; } - virtual control_port_info_iface& integer() { return *this; } - virtual control_port_info_iface& lv2_ttl(const std::string &text) { return *this; } - virtual control_port_info_iface& polymorphic() { return lv2_ttl("a poly:PolymorphicPort ;"); } - virtual control_port_info_iface& poly_audio() { return lv2_ttl("poly:supportsType lv2:AudioPort ;"); } - virtual ~control_port_info_iface() {} -}; - -/// A sink to send information about a plugin -struct plugin_info_iface -{ - /// Set plugin names (ID, name and label) - virtual void names(const std::string &name, const std::string &label, const std::string &category, const std::string µname = std::string()) {} - /// Add an audio port (returns a sink which accepts further description) - virtual plain_port_info_iface &audio_port(const std::string &id, const std::string &name, const std::string µname = std::string("N/A"))=0; - /// Add an event port (returns a sink which accepts further description) - virtual plain_port_info_iface &event_port(const std::string &id, const std::string &name, const std::string µname = std::string("N/A"))=0; - /// Add a control port (returns a sink which accepts further description) - virtual control_port_info_iface &control_port(const std::string &id, const std::string &name, double def_value, const std::string µname = "N/A")=0; - /// Add arbitrary TTL clauses - virtual void lv2_ttl(const std::string &text) {} - /// Add small plugin GUI - virtual void has_gui() { lv2_ttl("uiext:ui ;"); } - /// Called after plugin has reported all the information - virtual void finalize() {} - virtual ~plugin_info_iface() {} -}; - -struct plugin_port_type_grabber: public plugin_info_iface, public control_port_info_iface -{ - uint32_t ⌖ - uint32_t index; - - plain_port_info_iface pp; - control_port_info_iface cp; - - plugin_port_type_grabber(uint32_t &_target) : target(_target), index(0) { target = 0; } - - virtual plain_port_info_iface &audio_port(const std::string &id, const std::string &name, const std::string µname = std::string("N/A")) { target |= (1 << index); index++; return pp; } - virtual plain_port_info_iface &event_port(const std::string &id, const std::string &name, const std::string µname = std::string("N/A")) { index++; return pp; } - virtual control_port_info_iface &control_port(const std::string &id, const std::string &name, double def_value, const std::string µname = "N/A") { index++; return cp; } -}; - -/// A sink to send information about plugins -struct plugin_list_info_iface -{ - /// Add an empty plugin object and return the sink to be filled with information - virtual plugin_info_iface &plugin(const std::string &id) = 0; - virtual ~plugin_list_info_iface() {} -}; - -}; - -#endif diff --git a/plugins/ladspa_effect/calf/src/audio_fx.cpp b/plugins/ladspa_effect/calf/src/audio_fx.cpp new file mode 100644 index 000000000..54d6b77df --- /dev/null +++ b/plugins/ladspa_effect/calf/src/audio_fx.cpp @@ -0,0 +1,532 @@ +/* Calf DSP Library + * Reusable audio effect classes - implementation. + * + * Copyright (C) 2001-2010 Krzysztof Foltman, Markus Schmidt, Thor Harald Johansen and others + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include +#include + +using namespace calf_plugins; +using namespace dsp; + +simple_phaser::simple_phaser(int _max_stages, float *x1vals, float *y1vals) +{ + max_stages = _max_stages; + x1 = x1vals; + y1 = y1vals; + + set_base_frq(1000); + set_mod_depth(1000); + set_fb(0); + state = 0; + cnt = 0; + stages = 0; + set_stages(_max_stages); +} + +void simple_phaser::set_stages(int _stages) +{ + if (_stages > stages) + { + assert(_stages <= max_stages); + if (_stages > max_stages) + _stages = max_stages; + for (int i = stages; i < _stages; i++) + { + x1[i] = x1[stages-1]; + y1[i] = y1[stages-1]; + } + } + stages = _stages; +} + +void simple_phaser::reset() +{ + cnt = 0; + state = 0; + phase.set(0); + for (int i = 0; i < max_stages; i++) + x1[i] = y1[i] = 0; + control_step(); +} + +void simple_phaser::control_step() +{ + cnt = 0; + int v = phase.get() + 0x40000000; + int sign = v >> 31; + v ^= sign; + // triangle wave, range from 0 to INT_MAX + double vf = (double)((v >> 16) * (1.0 / 16384.0) - 1); + + float freq = base_frq * pow(2.0, vf * mod_depth / 1200.0); + freq = dsp::clip(freq, 10.0, 0.49 * sample_rate); + stage1.set_ap_w(freq * (M_PI / 2.0) * odsr); + phase += dphase * 32; + for (int i = 0; i < stages; i++) + { + dsp::sanitize(x1[i]); + dsp::sanitize(y1[i]); + } + dsp::sanitize(state); +} + +void simple_phaser::process(float *buf_out, float *buf_in, int nsamples) +{ + for (int i=0; i cfloat; + freq *= 2.0 * M_PI / sr; + cfloat z = 1.0 / exp(cfloat(0.0, freq)); // z^-1 + + cfloat p = cfloat(1.0); + cfloat stg = stage1.h_z(z); + + for (int i = 0; i < stages; i++) + p = p * stg; + + p = p / (cfloat(1.0) - cfloat(fb) * p); + return std::abs(cfloat(gs_dry.get_last()) + cfloat(gs_wet.get_last()) * p); +} + +/////////////////////////////////////////////////////////////////////////////////// + +void biquad_filter_module::calculate_filter(float freq, float q, int mode, float gain) +{ + if (mode <= mode_36db_lp) { + order = mode + 1; + left[0].set_lp_rbj(freq, pow(q, 1.0 / order), srate, gain); + } else if ( mode_12db_hp <= mode && mode <= mode_36db_hp ) { + order = mode - mode_12db_hp + 1; + left[0].set_hp_rbj(freq, pow(q, 1.0 / order), srate, gain); + } else if ( mode_6db_bp <= mode && mode <= mode_18db_bp ) { + order = mode - mode_6db_bp + 1; + left[0].set_bp_rbj(freq, pow(q, 1.0 / order), srate, gain); + } else { // mode_6db_br <= mode <= mode_18db_br + order = mode - mode_6db_br + 1; + left[0].set_br_rbj(freq, order * 0.1 * q, srate, gain); + } + + right[0].copy_coeffs(left[0]); + for (int i = 1; i < order; i++) { + left[i].copy_coeffs(left[0]); + right[i].copy_coeffs(left[0]); + } +} + +void biquad_filter_module::filter_activate() +{ + for (int i=0; i < order; i++) { + left[i].reset(); + right[i].reset(); + } +} + +void biquad_filter_module::sanitize() +{ + for (int i=0; i < order; i++) { + left[i].sanitize(); + right[i].sanitize(); + } +} + +int biquad_filter_module::process_channel(uint16_t channel_no, const float *in, float *out, uint32_t numsamples, int inmask) { + dsp::biquad_d1 *filter; + switch (channel_no) { + case 0: + filter = left; + break; + + case 1: + filter = right; + break; + + default: + assert(false); + return 0; + } + + if (inmask) { + switch(order) { + case 1: + for (uint32_t i = 0; i < numsamples; i++) + out[i] = filter[0].process(in[i]); + break; + case 2: + for (uint32_t i = 0; i < numsamples; i++) + out[i] = filter[1].process(filter[0].process(in[i])); + break; + case 3: + for (uint32_t i = 0; i < numsamples; i++) + out[i] = filter[2].process(filter[1].process(filter[0].process(in[i]))); + break; + } + } else { + if (filter[order - 1].empty()) + return 0; + switch(order) { + case 1: + for (uint32_t i = 0; i < numsamples; i++) + out[i] = filter[0].process_zeroin(); + break; + case 2: + if (filter[0].empty()) + for (uint32_t i = 0; i < numsamples; i++) + out[i] = filter[1].process_zeroin(); + else + for (uint32_t i = 0; i < numsamples; i++) + out[i] = filter[1].process(filter[0].process_zeroin()); + break; + case 3: + if (filter[1].empty()) + for (uint32_t i = 0; i < numsamples; i++) + out[i] = filter[2].process_zeroin(); + else + for (uint32_t i = 0; i < numsamples; i++) + out[i] = filter[2].process(filter[1].process(filter[0].process_zeroin())); + break; + } + } + for (int i = 0; i < order; i++) + filter[i].sanitize(); + return filter[order - 1].empty() ? 0 : inmask; +} + +float biquad_filter_module::freq_gain(int subindex, float freq, float srate) const +{ + float level = 1.0; + for (int j = 0; j < order; j++) + level *= left[j].freq_gain(freq, srate); + return level; +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +void reverb::update_times() +{ + switch(type) + { + case 0: + tl[0] = 397 << 16, tr[0] = 383 << 16; + tl[1] = 457 << 16, tr[1] = 429 << 16; + tl[2] = 549 << 16, tr[2] = 631 << 16; + tl[3] = 649 << 16, tr[3] = 756 << 16; + tl[4] = 773 << 16, tr[4] = 803 << 16; + tl[5] = 877 << 16, tr[5] = 901 << 16; + break; + case 1: + tl[0] = 697 << 16, tr[0] = 783 << 16; + tl[1] = 957 << 16, tr[1] = 929 << 16; + tl[2] = 649 << 16, tr[2] = 531 << 16; + tl[3] = 1049 << 16, tr[3] = 1177 << 16; + tl[4] = 473 << 16, tr[4] = 501 << 16; + tl[5] = 587 << 16, tr[5] = 681 << 16; + break; + case 2: + default: + tl[0] = 697 << 16, tr[0] = 783 << 16; + tl[1] = 957 << 16, tr[1] = 929 << 16; + tl[2] = 649 << 16, tr[2] = 531 << 16; + tl[3] = 1249 << 16, tr[3] = 1377 << 16; + tl[4] = 1573 << 16, tr[4] = 1671 << 16; + tl[5] = 1877 << 16, tr[5] = 1781 << 16; + break; + case 3: + tl[0] = 1097 << 16, tr[0] = 1087 << 16; + tl[1] = 1057 << 16, tr[1] = 1031 << 16; + tl[2] = 1049 << 16, tr[2] = 1039 << 16; + tl[3] = 1083 << 16, tr[3] = 1055 << 16; + tl[4] = 1075 << 16, tr[4] = 1099 << 16; + tl[5] = 1003 << 16, tr[5] = 1073 << 16; + break; + case 4: + tl[0] = 197 << 16, tr[0] = 133 << 16; + tl[1] = 357 << 16, tr[1] = 229 << 16; + tl[2] = 549 << 16, tr[2] = 431 << 16; + tl[3] = 949 << 16, tr[3] = 1277 << 16; + tl[4] = 1173 << 16, tr[4] = 1671 << 16; + tl[5] = 1477 << 16, tr[5] = 1881 << 16; + break; + case 5: + tl[0] = 197 << 16, tr[0] = 133 << 16; + tl[1] = 257 << 16, tr[1] = 179 << 16; + tl[2] = 549 << 16, tr[2] = 431 << 16; + tl[3] = 619 << 16, tr[3] = 497 << 16; + tl[4] = 1173 << 16, tr[4] = 1371 << 16; + tl[5] = 1577 << 16, tr[5] = 1881 << 16; + break; + } + + float fDec=1000 + 2400.f * diffusion; + for (int i = 0 ; i < 6; i++) { + ldec[i]=exp(-float(tl[i] >> 16) / fDec), + rdec[i]=exp(-float(tr[i] >> 16) / fDec); + } +} + +void reverb::reset() +{ + apL1.reset();apR1.reset(); + apL2.reset();apR2.reset(); + apL3.reset();apR3.reset(); + apL4.reset();apR4.reset(); + apL5.reset();apR5.reset(); + apL6.reset();apR6.reset(); + lp_left.reset();lp_right.reset(); + old_left = 0; old_right = 0; +} + +void reverb::process(float &left, float &right) +{ + unsigned int ipart = phase.ipart(); + + // the interpolated LFO might be an overkill here + int lfo = phase.lerp_by_fract_int(sine.data[ipart], sine.data[ipart+1]) >> 2; + phase += dphase; + + left += old_right; + left = apL1.process_allpass_comb_lerp16(left, tl[0] - 45*lfo, ldec[0]); + left = apL2.process_allpass_comb_lerp16(left, tl[1] + 47*lfo, ldec[1]); + float out_left = left; + left = apL3.process_allpass_comb_lerp16(left, tl[2] + 54*lfo, ldec[2]); + left = apL4.process_allpass_comb_lerp16(left, tl[3] - 69*lfo, ldec[3]); + left = apL5.process_allpass_comb_lerp16(left, tl[4] + 69*lfo, ldec[4]); + left = apL6.process_allpass_comb_lerp16(left, tl[5] - 46*lfo, ldec[5]); + old_left = lp_left.process(left * fb); + sanitize(old_left); + + right += old_left; + right = apR1.process_allpass_comb_lerp16(right, tr[0] - 45*lfo, rdec[0]); + right = apR2.process_allpass_comb_lerp16(right, tr[1] + 47*lfo, rdec[1]); + float out_right = right; + right = apR3.process_allpass_comb_lerp16(right, tr[2] + 54*lfo, rdec[2]); + right = apR4.process_allpass_comb_lerp16(right, tr[3] - 69*lfo, rdec[3]); + right = apR5.process_allpass_comb_lerp16(right, tr[4] + 69*lfo, rdec[4]); + right = apR6.process_allpass_comb_lerp16(right, tr[5] - 46*lfo, rdec[5]); + old_right = lp_right.process(right * fb); + sanitize(old_right); + + left = out_left, right = out_right; +} + +/// Distortion Module by Tom Szilagyi +/// +/// This module provides a blendable saturation stage +/////////////////////////////////////////////////////////////////////////////////////////////// + +tap_distortion::tap_distortion() +{ + is_active = false; + srate = 0; + meter = 0.f; +} + +void tap_distortion::activate() +{ + is_active = true; + set_params(0.f, 0.f); +} +void tap_distortion::deactivate() +{ + is_active = false; +} + +void tap_distortion::set_params(float blend, float drive) +{ + // set distortion coeffs + if ((drive_old != drive) || (blend_old != blend)) { + rdrive = 12.0f / drive; + rbdr = rdrive / (10.5f - blend) * 780.0f / 33.0f; + kpa = D(2.0f * (rdrive*rdrive) - 1.0f) + 1.0f; + kpb = (2.0f - kpa) / 2.0f; + ap = ((rdrive*rdrive) - kpa + 1.0f) / 2.0f; + kc = kpa / D(2.0f * D(2.0f * (rdrive*rdrive) - 1.0f) - 2.0f * rdrive*rdrive); + + srct = (0.1f * srate) / (0.1f * srate + 1.0f); + sq = kc*kc + 1.0f; + knb = -1.0f * rbdr / D(sq); + kna = 2.0f * kc * rbdr / D(sq); + an = rbdr*rbdr / sq; + imr = 2.0f * knb + D(2.0f * kna + 4.0f * an - 1.0f); + pwrq = 2.0f / (imr + 1.0f); + + drive_old = drive; + blend_old = blend; + } +} + +void tap_distortion::set_sample_rate(uint32_t sr) +{ + srate = sr; +} + +float tap_distortion::process(float in) +{ + meter = 0.f; + float out = 0.f; + float proc = in; + float med; + if (proc >= 0.0f) { + med = (D(ap + proc * (kpa - proc)) + kpb) * pwrq; + } else { + med = (D(an - proc * (kna + proc)) + knb) * pwrq * -1.0f; + } + proc = srct * (med - prev_med + prev_out); + prev_med = M(med); + prev_out = M(proc); + out = proc; + meter = proc; + return out; +} + +float tap_distortion::get_distortion_level() +{ + return meter; +} + +//////////////////////////////////////////////////////////////////////////////// + +simple_lfo::simple_lfo() +{ + is_active = false; + phase = 0.f; +} + +void simple_lfo::activate() +{ + is_active = true; + phase = 0.f; +} + +void simple_lfo::deactivate() +{ + is_active = false; +} + +float simple_lfo::get_value() +{ + return get_value_from_phase(phase, offset) * amount; +} + +float simple_lfo::get_value_from_phase(float ph, float off) const +{ + float val = 0.f; + float phs = ph + off; + if (phs >= 1.0) + phs = fmod(phs, 1.f); + switch (mode) { + default: + case 0: + // sine + val = sin((phs * 360.f) * M_PI / 180); + break; + case 1: + // triangle + if(phs > 0.75) + val = (phs - 0.75) * 4 - 1; + else if(phs > 0.5) + val = (phs - 0.5) * 4 * -1; + else if(phs > 0.25) + val = 1 - (phs - 0.25) * 4; + else + val = phs * 4; + break; + case 2: + // square + val = (phs < 0.5) ? -1 : +1; + break; + case 3: + // saw up + val = phs * 2.f - 1; + break; + case 4: + // saw down + val = 1 - phs * 2.f; + break; + } + return val; +} + +void simple_lfo::advance(uint32_t count) +{ + //this function walks from 0.f to 1.f and starts all over again + phase += count * freq * (1.0 / srate); + if (phase >= 1.0) + phase = fmod(phase, 1.f); +} + +void simple_lfo::set_phase(float ph) +{ + //set the phase from outsinde + phase = fabs(ph); + if (phase >= 1.0) + phase = fmod(phase, 1.f); +} + +void simple_lfo::set_params(float f, int m, float o, uint32_t sr, float a) +{ + // freq: a value in Hz + // mode: sine=0, triangle=1, square=2, saw_up=3, saw_down=4 + // offset: value between 0.f and 1.f to offset the lfo in time + freq = f; + mode = m; + offset = o; + srate = sr; + amount = a; +} + +bool simple_lfo::get_graph(float *data, int points, cairo_iface *context) const +{ + if (!is_active) + return false; + for (int i = 0; i < points; i++) { + float ph = (float)i / (float)points; + data[i] = get_value_from_phase(ph, offset) * amount; + } + return true; +} + +bool simple_lfo::get_dot(float &x, float &y, int &size, cairo_iface *context) const +{ + if (!is_active) + return false; + float phs = phase + offset; + if (phs >= 1.0) + phs = fmod(phs, 1.f); + x = phase; + y = get_value_from_phase(phase, offset) * amount; + return true; +} + diff --git a/plugins/ladspa_effect/calf/calf/audio_fx.h b/plugins/ladspa_effect/calf/src/calf/audio_fx.h similarity index 53% rename from plugins/ladspa_effect/calf/calf/audio_fx.h rename to plugins/ladspa_effect/calf/src/calf/audio_fx.h index 56d08f6d6..b9e5012fe 100644 --- a/plugins/ladspa_effect/calf/calf/audio_fx.h +++ b/plugins/ladspa_effect/calf/src/calf/audio_fx.h @@ -1,7 +1,7 @@ /* Calf DSP Library * Reusable audio effect classes. * - * Copyright (C) 2001-2007 Krzysztof Foltman + * Copyright (C) 2001-2010 Krzysztof Foltman, Markus Schmidt, Thor Harald Johansen and others * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -18,17 +18,19 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA */ -#ifndef __CALF_AUDIOFX_H -#define __CALF_AUDIOFX_H +#ifndef CALF_AUDIOFX_H +#define CALF_AUDIOFX_H -#include -#include -#include -#include -#include "primitives.h" +#include "biquad.h" #include "delay.h" #include "fixed_point.h" #include "inertia.h" +#include "onepole.h" +#include + +namespace calf_plugins { + struct cairo_iface; +}; namespace dsp { #if 0 @@ -53,21 +55,21 @@ protected: gain_smoothing gs_wet, gs_dry; public: fixed_point phase, dphase; - float get_rate() { + float get_rate() const { return rate; } void set_rate(float rate) { this->rate = rate; dphase = rate/sample_rate*4096; } - float get_wet() { + float get_wet() const { return wet; } void set_wet(float wet) { this->wet = wet; gs_wet.set_inertia(wet); } - float get_dry() { + float get_dry() const { return dry; } void set_dry(float dry) { @@ -95,122 +97,50 @@ public: * A monophonic phaser. If you want stereo, combine two :) * Also, gave up on using template args for signal type. */ -template class simple_phaser: public modulation_effect { protected: float base_frq, mod_depth, fb; float state; - int cnt, stages; + int cnt, stages, max_stages; dsp::onepole stage1; - float x1[MaxStages], y1[MaxStages]; + float *x1, *y1; public: - simple_phaser() - { - set_base_frq(1000); - set_mod_depth(1000); - set_fb(0); - state = 0; - cnt = 0; - stages = 0; - set_stages(6); - } - float get_base_frq() { + simple_phaser(int _max_stages, float *x1vals, float *y1vals); + + float get_base_frq() const { return base_frq; } void set_base_frq(float _base_frq) { base_frq = _base_frq; } - int get_stages() { + int get_stages() const { return stages; } - void set_stages(int _stages) { - if (_stages > stages) - { - for (int i = stages; i < _stages; i++) - { - x1[i] = x1[stages-1]; - y1[i] = y1[stages-1]; - } - } - stages = _stages; - } - float get_mod_depth() { + void set_stages(int _stages); + + float get_mod_depth() const { return mod_depth; } void set_mod_depth(float _mod_depth) { mod_depth = _mod_depth; } - float get_fb() { + + float get_fb() const { return fb; } void set_fb(float fb) { this->fb = fb; } + virtual void setup(int sample_rate) { modulation_effect::setup(sample_rate); reset(); } - void reset() - { - cnt = 0; - state = 0; - phase.set(0); - for (int i = 0; i < MaxStages; i++) - x1[i] = y1[i] = 0; - control_step(); - } - inline void control_step() - { - cnt = 0; - int v = phase.get() + 0x40000000; - int sign = v >> 31; - v ^= sign; - // triangle wave, range from 0 to INT_MAX - double vf = (double)((v >> 16) * (1.0 / 16384.0) - 1); - - float freq = base_frq * pow(2.0, vf * mod_depth / 1200.0); - freq = dsp::clip(freq, 10.0, 0.49 * sample_rate); - stage1.set_ap_w(freq * (M_PI / 2.0) * odsr); - phase += dphase * 32; - for (int i = 0; i < stages; i++) - { - dsp::sanitize(x1[i]); - dsp::sanitize(y1[i]); - } - dsp::sanitize(state); - } - void process(float *buf_out, float *buf_in, int nsamples) { - for (int i=0; i cfloat; - freq *= 2.0 * M_PI / sr; - cfloat z = 1.0 / exp(cfloat(0.0, freq)); // z^-1 - - cfloat p = cfloat(1.0); - cfloat stg = stage1.h_z(z); - - for (int i = 0; i < stages; i++) - p = p * stg; - - p = p / (cfloat(1.0) - cfloat(fb) * p); - return std::abs(cfloat(gs_dry.get_last()) + cfloat(gs_wet.get_last()) * p); - } + void reset(); + void control_step(); + void process(float *buf_out, float *buf_in, int nsamples); + float freq_gain(float freq, float sr) const; }; /** @@ -225,14 +155,14 @@ protected: float min_delay, mod_depth; sine_table sine; public: - float get_min_delay() { + float get_min_delay() const { return min_delay; } void set_min_delay(float min_delay) { this->min_delay = min_delay; this->min_delay_samples = (int)(min_delay * 65536.0 * sample_rate); } - float get_mod_depth() { + float get_mod_depth() const { return mod_depth; } void set_mod_depth(float mod_depth) { @@ -319,7 +249,7 @@ public: set_rate(get_rate()); set_min_delay(get_min_delay()); } - float get_fb() { + float get_fb() const { return fb; } void set_fb(float fb) { @@ -386,7 +316,7 @@ public: } last_delay_pos = delay_pos; } - float freq_gain(float freq, float sr) + float freq_gain(float freq, float sr) const { typedef std::complex cfloat; freq *= 2.0 * M_PI / sr; @@ -410,15 +340,14 @@ public: * Just started implementing it, so there is no control over many * parameters. */ -template class reverb: public audio_effect { - simple_delay<2048, T> apL1, apL2, apL3, apL4, apL5, apL6; - simple_delay<2048, T> apR1, apR2, apR3, apR4, apR5, apR6; + simple_delay<2048, float> apL1, apL2, apL3, apL4, apL5, apL6; + simple_delay<2048, float> apR1, apR2, apR3, apR4, apR5, apR6; fixed_point phase, dphase; sine_table sine; - onepole lp_left, lp_right; - T old_left, old_right; + onepole lp_left, lp_right; + float old_left, old_right; int type; float time, fb, cutoff, diffusion; int tl[6], tr[6]; @@ -443,68 +372,8 @@ public: dphase = 0.5*128/sr; update_times(); } - void update_times() - { - switch(type) - { - case 0: - tl[0] = 397 << 16, tr[0] = 383 << 16; - tl[1] = 457 << 16, tr[1] = 429 << 16; - tl[2] = 549 << 16, tr[2] = 631 << 16; - tl[3] = 649 << 16, tr[3] = 756 << 16; - tl[4] = 773 << 16, tr[4] = 803 << 16; - tl[5] = 877 << 16, tr[5] = 901 << 16; - break; - case 1: - tl[0] = 697 << 16, tr[0] = 783 << 16; - tl[1] = 957 << 16, tr[1] = 929 << 16; - tl[2] = 649 << 16, tr[2] = 531 << 16; - tl[3] = 1049 << 16, tr[3] = 1177 << 16; - tl[4] = 473 << 16, tr[4] = 501 << 16; - tl[5] = 587 << 16, tr[5] = 681 << 16; - break; - case 2: - default: - tl[0] = 697 << 16, tr[0] = 783 << 16; - tl[1] = 957 << 16, tr[1] = 929 << 16; - tl[2] = 649 << 16, tr[2] = 531 << 16; - tl[3] = 1249 << 16, tr[3] = 1377 << 16; - tl[4] = 1573 << 16, tr[4] = 1671 << 16; - tl[5] = 1877 << 16, tr[5] = 1781 << 16; - break; - case 3: - tl[0] = 1097 << 16, tr[0] = 1087 << 16; - tl[1] = 1057 << 16, tr[1] = 1031 << 16; - tl[2] = 1049 << 16, tr[2] = 1039 << 16; - tl[3] = 1083 << 16, tr[3] = 1055 << 16; - tl[4] = 1075 << 16, tr[4] = 1099 << 16; - tl[5] = 1003 << 16, tr[5] = 1073 << 16; - break; - case 4: - tl[0] = 197 << 16, tr[0] = 133 << 16; - tl[1] = 357 << 16, tr[1] = 229 << 16; - tl[2] = 549 << 16, tr[2] = 431 << 16; - tl[3] = 949 << 16, tr[3] = 1277 << 16; - tl[4] = 1173 << 16, tr[4] = 1671 << 16; - tl[5] = 1477 << 16, tr[5] = 1881 << 16; - break; - case 5: - tl[0] = 197 << 16, tr[0] = 133 << 16; - tl[1] = 257 << 16, tr[1] = 179 << 16; - tl[2] = 549 << 16, tr[2] = 431 << 16; - tl[3] = 619 << 16, tr[3] = 497 << 16; - tl[4] = 1173 << 16, tr[4] = 1371 << 16; - tl[5] = 1577 << 16, tr[5] = 1881 << 16; - break; - } - - float fDec=1000 + 2400.f * diffusion; - for (int i = 0 ; i < 6; i++) { - ldec[i]=exp(-float(tl[i] >> 16) / fDec), - rdec[i]=exp(-float(tr[i] >> 16) / fDec); - } - } - float get_time() { + void update_times(); + float get_time() const { return time; } void set_time(float time) { @@ -512,14 +381,14 @@ public: // fb = pow(1.0f/4096.0f, (float)(1700/(time*sr))); fb = 1.0 - 0.3 / (time * sr / 44100.0); } - float get_type() { + float get_type() const { return type; } void set_type(int type) { this->type = type; update_times(); } - float get_diffusion() { + float get_diffusion() const { return diffusion; } void set_diffusion(float diffusion) { @@ -531,7 +400,7 @@ public: this->diffusion = diffusion; update_times(); } - float get_fb() + float get_fb() const { return this->fb; } @@ -539,7 +408,7 @@ public: { this->fb = fb; } - float get_cutoff() { + float get_cutoff() const { return cutoff; } void set_cutoff(float cutoff) { @@ -547,49 +416,8 @@ public: lp_left.set_lp(cutoff,sr); lp_right.set_lp(cutoff,sr); } - void reset() - { - apL1.reset();apR1.reset(); - apL2.reset();apR2.reset(); - apL3.reset();apR3.reset(); - apL4.reset();apR4.reset(); - apL5.reset();apR5.reset(); - apL6.reset();apR6.reset(); - lp_left.reset();lp_right.reset(); - old_left = 0; old_right = 0; - } - void process(T &left, T &right) - { - unsigned int ipart = phase.ipart(); - - // the interpolated LFO might be an overkill here - int lfo = phase.lerp_by_fract_int(sine.data[ipart], sine.data[ipart+1]) >> 2; - phase += dphase; - - left += old_right; - left = apL1.process_allpass_comb_lerp16(left, tl[0] - 45*lfo, ldec[0]); - left = apL2.process_allpass_comb_lerp16(left, tl[1] + 47*lfo, ldec[1]); - float out_left = left; - left = apL3.process_allpass_comb_lerp16(left, tl[2] + 54*lfo, ldec[2]); - left = apL4.process_allpass_comb_lerp16(left, tl[3] - 69*lfo, ldec[3]); - left = apL5.process_allpass_comb_lerp16(left, tl[4] + 69*lfo, ldec[4]); - left = apL6.process_allpass_comb_lerp16(left, tl[5] - 46*lfo, ldec[5]); - old_left = lp_left.process(left * fb); - sanitize(old_left); - - right += old_left; - right = apR1.process_allpass_comb_lerp16(right, tr[0] - 45*lfo, rdec[0]); - right = apR2.process_allpass_comb_lerp16(right, tr[1] + 47*lfo, rdec[1]); - float out_right = right; - right = apR3.process_allpass_comb_lerp16(right, tr[2] + 54*lfo, rdec[2]); - right = apR4.process_allpass_comb_lerp16(right, tr[3] - 69*lfo, rdec[3]); - right = apR5.process_allpass_comb_lerp16(right, tr[4] + 69*lfo, rdec[4]); - right = apR6.process_allpass_comb_lerp16(right, tr[5] - 46*lfo, rdec[5]); - old_right = lp_right.process(right * fb); - sanitize(old_right); - - left = out_left, right = out_right; - } + void reset(); + void process(float &left, float &right); void extra_sanitize() { lp_left.sanitize(); @@ -603,8 +431,8 @@ public: virtual void calculate_filter(float freq, float q, int mode, float gain = 1.0) = 0; virtual void filter_activate() = 0; virtual void sanitize() = 0; - virtual int process_channel(uint16_t channel_no, float *in, float *out, uint32_t numsamples, int inmask) = 0; - virtual float freq_gain(int subindex, float freq, float srate) = 0; + virtual int process_channel(uint16_t channel_no, const float *in, float *out, uint32_t numsamples, int inmask) = 0; + virtual float freq_gain(int subindex, float freq, float srate) const = 0; virtual ~filter_module_iface() {} }; @@ -627,116 +455,18 @@ public: }; public: - biquad_filter_module() : order(0) {} - - void calculate_filter(float freq, float q, int mode, float gain = 1.0) - { - if (mode <= mode_36db_lp) { - order = mode + 1; - left[0].set_lp_rbj(freq, pow(q, 1.0 / order), srate, gain); - } else if ( mode_12db_hp <= mode && mode <= mode_36db_hp ) { - order = mode - mode_12db_hp + 1; - left[0].set_hp_rbj(freq, pow(q, 1.0 / order), srate, gain); - } else if ( mode_6db_bp <= mode && mode <= mode_18db_bp ) { - order = mode - mode_6db_bp + 1; - left[0].set_bp_rbj(freq, pow(q, 1.0 / order), srate, gain); - } else { // mode_6db_br <= mode <= mode_18db_br - order = mode - mode_6db_br + 1; - left[0].set_br_rbj(freq, order * 0.1 * q, srate, gain); - } - - right[0].copy_coeffs(left[0]); - for (int i = 1; i < order; i++) { - left[i].copy_coeffs(left[0]); - right[i].copy_coeffs(left[0]); - } - } - - void filter_activate() - { - for (int i=0; i < order; i++) { - left[i].reset(); - right[i].reset(); - } - } - - void sanitize() - { - for (int i=0; i < order; i++) { - left[i].sanitize(); - right[i].sanitize(); - } - } - - inline int process_channel(uint16_t channel_no, float *in, float *out, uint32_t numsamples, int inmask) { - dsp::biquad_d1 *filter; - switch (channel_no) { - case 0: - filter = left; - break; - - case 1: - filter = right; - break; - - default: - assert(false); - return 0; - } - - if (inmask) { - switch(order) { - case 1: - for (uint32_t i = 0; i < numsamples; i++) - out[i] = filter[0].process(in[i]); - break; - case 2: - for (uint32_t i = 0; i < numsamples; i++) - out[i] = filter[1].process(filter[0].process(in[i])); - break; - case 3: - for (uint32_t i = 0; i < numsamples; i++) - out[i] = filter[2].process(filter[1].process(filter[0].process(in[i]))); - break; - } - } else { - if (filter[order - 1].empty()) - return 0; - switch(order) { - case 1: - for (uint32_t i = 0; i < numsamples; i++) - out[i] = filter[0].process_zeroin(); - break; - case 2: - if (filter[0].empty()) - for (uint32_t i = 0; i < numsamples; i++) - out[i] = filter[1].process_zeroin(); - else - for (uint32_t i = 0; i < numsamples; i++) - out[i] = filter[1].process(filter[0].process_zeroin()); - break; - case 3: - if (filter[1].empty()) - for (uint32_t i = 0; i < numsamples; i++) - out[i] = filter[2].process_zeroin(); - else - for (uint32_t i = 0; i < numsamples; i++) - out[i] = filter[2].process(filter[1].process(filter[0].process_zeroin())); - break; - } - } - for (int i = 0; i < order; i++) - filter[i].sanitize(); - return filter[order - 1].empty() ? 0 : inmask; - } - - float freq_gain(int subindex, float freq, float srate) - { - float level = 1.0; - for (int j = 0; j < order; j++) - level *= left[j].freq_gain(freq, srate); - return level; - } + biquad_filter_module() + : order(0) {} + /// Calculate filter coefficients based on parameters - cutoff/center frequency, q, filter type, output gain + void calculate_filter(float freq, float q, int mode, float gain = 1.0); + /// Reset filter state + void filter_activate(); + /// Remove denormals + void sanitize(); + /// Process a single channel (float buffer) of data + int process_channel(uint16_t channel_no, const float *in, float *out, uint32_t numsamples, int inmask); + /// Determine gain (|H(z)|) for a given frequency + float freq_gain(int subindex, float freq, float srate) const; }; class two_band_eq @@ -782,6 +512,59 @@ public: } }; +/// Tom Szilagyi's distortion code, used with permission +/// KF: I'm not 100% sure how this is supposed to work, but it does. +/// I'm planning to rewrite it using more modular approach when I have more time. +class tap_distortion { +private: + float blend_old, drive_old; + float meter; + float rdrive, rbdr, kpa, kpb, kna, knb, ap, an, imr, kc, srct, sq, pwrq; + float prev_med, prev_out; +public: + uint32_t srate; + bool is_active; + tap_distortion(); + void activate(); + void deactivate(); + void set_params(float blend, float drive); + void set_sample_rate(uint32_t sr); + float process(float in); + float get_distortion_level(); + static inline float M(float x) + { + return (fabs(x) > 0.000000001f) ? x : 0.0f; + } + + static inline float D(float x) + { + x = fabs(x); + return (x > 0.000000001f) ? sqrtf(x) : 0.0f; + } +}; + +/// LFO module by Markus +/// This module provides simple LFO's (sine=0, triangle=1, square=2, saw_up=3, saw_down=4) +/// get_value() returns a value between -1 and 1 +class simple_lfo { +private: + float phase, freq, offset, amount; + int mode; + uint32_t srate; + bool is_active; +public: + simple_lfo(); + void set_params(float f, int m, float o, uint32_t sr, float amount = 1.f); + float get_value(); + void advance(uint32_t count); + void set_phase(float ph); + void activate(); + void deactivate(); + float get_value_from_phase(float ph, float off) const; + bool get_graph(float *data, int points, calf_plugins::cairo_iface *context) const; + bool get_dot(float &x, float &y, int &size, calf_plugins::cairo_iface *context) const; +}; + #if 0 { to keep editor happy #endif diff --git a/plugins/ladspa_effect/calf/calf/biquad.h b/plugins/ladspa_effect/calf/src/calf/biquad.h similarity index 90% rename from plugins/ladspa_effect/calf/calf/biquad.h rename to plugins/ladspa_effect/calf/src/calf/biquad.h index e1f419508..99cf2a40a 100644 --- a/plugins/ladspa_effect/calf/calf/biquad.h +++ b/plugins/ladspa_effect/calf/src/calf/biquad.h @@ -305,7 +305,7 @@ public: /// Return the filter's gain at frequency freq /// @param freq Frequency to look up /// @param sr Filter sample rate (used to convert frequency to angular frequency) - float freq_gain(float freq, float sr) + float freq_gain(float freq, float sr) const { typedef std::complex cfloat; freq *= 2.0 * M_PI / sr; @@ -316,7 +316,7 @@ public: /// Return H(z) the filter's gain at frequency freq /// @param z Z variable (e^jw) - cfloat h_z(const cfloat &z) + cfloat h_z(const cfloat &z) const { return (cfloat(a0) + double(a1) * z + double(a2) * z*z) / (cfloat(1.0) + double(b1) * z + double(b2) * z*z); @@ -396,7 +396,7 @@ struct biquad_d1: public biquad_coeffs dsp::zero(x2); dsp::zero(y2); } - inline bool empty() { + inline bool empty() const { return (y1 == 0.f && y2 == 0.f); } @@ -448,7 +448,7 @@ struct biquad_d2: public biquad_coeffs } /// Is the filter state completely silent? (i.e. set to 0 by sanitize function) - inline bool empty() { + inline bool empty() const { return (w1 == 0.f && w2 == 0.f); } @@ -575,6 +575,74 @@ struct biquad_d1_lerp: public biquad_coeffs }; +/// Compose two filters in series +template +class filter_compose { +public: + typedef std::complex cfloat; + F1 f1; + F2 f2; +public: + float process(float value) { + return f2.process(f1.process(value)); + } + + inline cfloat h_z(const cfloat &z) const { + return f1.h_z(z) * f2.h_z(z); + } + + /// Return the filter's gain at frequency freq + /// @param freq Frequency to look up + /// @param sr Filter sample rate (used to convert frequency to angular frequency) + float freq_gain(float freq, float sr) const + { + typedef std::complex cfloat; + freq *= 2.0 * M_PI / sr; + cfloat z = 1.0 / exp(cfloat(0.0, freq)); + + return std::abs(h_z(z)); + } + + void sanitize() { + f1.sanitize(); + f2.sanitize(); + } +}; + +/// Compose two filters in parallel +template +class filter_sum { +public: + typedef std::complex cfloat; + F1 f1; + F2 f2; +public: + float process(float value) { + return f2.process(value) + f1.process(value); + } + + inline cfloat h_z(const cfloat &z) const { + return f1.h_z(z) + f2.h_z(z); + } + + /// Return the filter's gain at frequency freq + /// @param freq Frequency to look up + /// @param sr Filter sample rate (used to convert frequency to angular frequency) + float freq_gain(float freq, float sr) const + { + typedef std::complex cfloat; + freq *= 2.0 * M_PI / sr; + cfloat z = 1.0 / exp(cfloat(0.0, freq)); + + return std::abs(h_z(z)); + } + + void sanitize() { + f1.sanitize(); + f2.sanitize(); + } +}; + }; #endif diff --git a/plugins/ladspa_effect/calf/calf/buffer.h b/plugins/ladspa_effect/calf/src/calf/buffer.h similarity index 100% rename from plugins/ladspa_effect/calf/calf/buffer.h rename to plugins/ladspa_effect/calf/src/calf/buffer.h diff --git a/plugins/ladspa_effect/calf/calf/delay.h b/plugins/ladspa_effect/calf/src/calf/delay.h similarity index 100% rename from plugins/ladspa_effect/calf/calf/delay.h rename to plugins/ladspa_effect/calf/src/calf/delay.h diff --git a/plugins/ladspa_effect/calf/calf/envelope.h b/plugins/ladspa_effect/calf/src/calf/envelope.h similarity index 80% rename from plugins/ladspa_effect/calf/calf/envelope.h rename to plugins/ladspa_effect/calf/src/calf/envelope.h index 8a8fce13e..302e4c06c 100644 --- a/plugins/ladspa_effect/calf/calf/envelope.h +++ b/plugins/ladspa_effect/calf/src/calf/envelope.h @@ -197,6 +197,82 @@ public: { return old_value + (value - old_value) * pos; } + inline float get_amp_value() + { + if (state == RELEASE && sustain > 0 && value < sustain) + { + return value * value * value / (sustain * sustain); + } + return value; + } +}; + +/// Simple linear fade out for note tails +struct fadeout +{ + float value; + float step, step_orig; + bool done, undoing; + + fadeout(int steps = 256) + { + step_orig = (float)(1.f / steps); + value = 1.f; + reset(); + } + + /// Prepare fade out + void reset() + { + value = 1.f; + step = -step_orig; + done = false; + undoing = false; + } + + /// Fade back in with double speed (to prevent click on note restart) + void undo() + { + step = step_orig; + done = false; + undoing = true; + } + + /// Reset if fully faded out; fade back in if in the middle of fading out + void reset_soft() + { + if (value <= 0.f || value >= 1.f) + reset(); + else + undo(); + } + + void process(float *buffer, int len) + { + int i = 0; + if (!done) + { + for (; value > 0 && value <= 1.0 && i < len; i++) + { + buffer[i] *= value; + value += step; + } + if (value <= 0 || value > 1) + done = true; + } + if (done && value <= 0) + { + while (i < len) + buffer[i++] = 0.f; + } + if (done && undoing && value >= 1) + { + undoing = false; + done = false; + // prepare for the next fade-out + value = 1.f; + } + } }; }; diff --git a/plugins/ladspa_effect/calf/calf/fft.h b/plugins/ladspa_effect/calf/src/calf/fft.h similarity index 100% rename from plugins/ladspa_effect/calf/calf/fft.h rename to plugins/ladspa_effect/calf/src/calf/fft.h diff --git a/plugins/ladspa_effect/calf/calf/fixed_point.h b/plugins/ladspa_effect/calf/src/calf/fixed_point.h similarity index 100% rename from plugins/ladspa_effect/calf/calf/fixed_point.h rename to plugins/ladspa_effect/calf/src/calf/fixed_point.h diff --git a/plugins/ladspa_effect/calf/calf/giface.h b/plugins/ladspa_effect/calf/src/calf/giface.h similarity index 60% rename from plugins/ladspa_effect/calf/calf/giface.h rename to plugins/ladspa_effect/calf/src/calf/giface.h index 56305bcb9..08954c695 100644 --- a/plugins/ladspa_effect/calf/calf/giface.h +++ b/plugins/ladspa_effect/calf/src/calf/giface.h @@ -1,7 +1,7 @@ /* Calf DSP Library * Common plugin interface definitions (shared between LADSPA/LV2/DSSI/standalone). * - * Copyright (C) 2007 Krzysztof Foltman + * Copyright (C) 2007-2010 Krzysztof Foltman * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -18,16 +18,15 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02111-1307, USA. */ -#ifndef __CALF_GIFACE_H -#define __CALF_GIFACE_H +#ifndef CALF_GIFACE_H +#define CALF_GIFACE_H -#include -#include -#include +#include +#include "primitives.h" +#include #include #include -#include "primitives.h" -#include "preset.h" +#include namespace osctl { struct osc_client; @@ -167,17 +166,17 @@ struct line_graph_iface /// @param context cairo context to adjust (for multicolour graphs etc.) /// @retval true graph data was returned; subindex+1 graph may or may not be available /// @retval false graph data was not returned; subindex+1 graph does not exist either - virtual bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context) { return false; } + virtual bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const { return false; } /// Obtain subindex'th dot of parameter 'index' /// @param index parameter/dot number (usually tied to particular plugin control port) /// @param subindex dot number (there may be multiple dots graphs for one parameter) - virtual bool get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context) { return false; } + virtual bool get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context) const { return false; } /// Obtain subindex'th dot of parameter 'index' /// @param index parameter/dot number (usually tied to particular plugin control port) /// @param subindex dot number (there may be multiple dots graphs for one parameter) - virtual bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) { return false; } + virtual bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const { return false; } /// Obtain subindex'th static graph of parameter index (static graphs are only dependent on parameter value, not plugin state) /// @param index parameter/graph number (usually tied to particular plugin control port) @@ -188,7 +187,7 @@ struct line_graph_iface /// @param context cairo context to adjust (for multicolour graphs etc.) /// @retval true graph data was returned; subindex+1 graph may or may not be available /// @retval false graph data was not returned; subindex+1 graph does not exist either - virtual bool get_static_graph(int index, int subindex, float value, float *data, int points, cairo_iface *context) { return false; } + virtual bool get_static_graph(int index, int subindex, float value, float *data, int points, cairo_iface *context) const { return false; } /// Return which graphs need to be redrawn and which can be cached for later reuse /// @param index Parameter/graph number (usually tied to particular plugin control port) @@ -197,7 +196,7 @@ struct line_graph_iface /// @param subindex_dot First dot that has to be redrawn /// @param subindex_gridline First gridline/legend that has to be redrawn /// @retval Current generation (to pass when calling the function next time); if different than passed generation value, call the function again to retrieve which graph offsets should be put into cache - virtual int get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) { subindex_graph = subindex_dot = subindex_gridline = 0; return 0; } + virtual int get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) const { subindex_graph = subindex_dot = subindex_gridline = 0; return 0; } /// Standard destructor to make compiler happy virtual ~line_graph_iface() {} @@ -228,22 +227,22 @@ struct table_column_info struct table_edit_iface { /// retrieve the table layout for specific parameter - virtual const table_column_info *get_table_columns(int param) = 0; + virtual const table_column_info *get_table_columns(int param) const = 0; /// return the current number of rows - virtual uint32_t get_table_rows(int param) = 0; + virtual uint32_t get_table_rows(int param) const = 0; /// retrieve data item from the plugin - virtual std::string get_cell(int param, int row, int column) { return calf_utils::i2s(row)+":"+calf_utils::i2s(column); } + virtual std::string get_cell(int param, int row, int column) const; /// set data item to the plugin - virtual void set_cell(int param, int row, int column, const std::string &src, std::string &error) { error.clear(); } + virtual void set_cell(int param, int row, int column, const std::string &src, std::string &error) const { error.clear(); } /// return a line graph interface for a specific parameter/column (unused for now) - virtual line_graph_iface *get_graph_iface(int param, int column) { return NULL; } + virtual const line_graph_iface *get_graph_iface(int param, int column) const { return NULL; } /// return an editor name for a specific grid cell (unused for now - I don't even know how editors be implemented) - virtual const char *get_cell_editor(int param, int column) { return NULL; } + virtual const char *get_cell_editor(int param, int column) const { return NULL; } virtual ~table_edit_iface() {} }; @@ -293,56 +292,58 @@ struct ladspa_plugin_info struct plugin_metadata_iface { /// @return plugin long name - virtual const char *get_name() = 0; + virtual const char *get_name() const = 0; /// @return plugin LV2 label - virtual const char *get_id() = 0; + virtual const char *get_id() const = 0; /// @return plugin human-readable label - virtual const char *get_label() = 0; + virtual const char *get_label() const = 0; /// @return total number of parameters - virtual int get_param_count() = 0; + virtual int get_param_count() const = 0; /// Return custom XML - virtual const char *get_gui_xml() = 0; + virtual const char *get_gui_xml() const = 0; /// @return number of audio inputs - virtual int get_input_count()=0; + virtual int get_input_count() const =0; /// @return number of audio outputs - virtual int get_output_count()=0; + virtual int get_output_count() const =0; + /// @return number of optional inputs + virtual int get_inputs_optional() const =0; + /// @return number of optional outputs + virtual int get_outputs_optional() const =0; /// @return true if plugin can work in hard-realtime conditions - virtual bool is_rt_capable()=0; + virtual bool is_rt_capable() const =0; /// @return true if plugin has MIDI input - virtual bool get_midi()=0; + virtual bool get_midi() const =0; /// @return true if plugin has MIDI input - virtual bool requires_midi()=0; + virtual bool requires_midi() const =0; /// @return port offset of first control (parameter) port (= number of audio inputs + number of audio outputs in all existing plugins as for 1 Aug 2008) - virtual int get_param_port_offset() = 0; - /// @return line_graph_iface if any - virtual line_graph_iface *get_line_graph_iface() = 0; + virtual int get_param_port_offset() const = 0; /// @return table_edit_iface if any - virtual table_edit_iface *get_table_edit_iface() = 0; + virtual const table_edit_iface *get_table_edit_iface() const = 0; /// @return NULL-terminated list of menu commands - virtual plugin_command_info *get_commands() { return NULL; } + virtual plugin_command_info *get_commands() const { return NULL; } /// @return description structure for given parameter - virtual parameter_properties *get_param_props(int param_no) = 0; + virtual const parameter_properties *get_param_props(int param_no) const = 0; /// @return retrieve names of audio ports (@note control ports are named in parameter_properties, not here) - virtual const char **get_port_names() = 0; + virtual const char **get_port_names() const = 0; /// @return description structure for the plugin - virtual const ladspa_plugin_info &get_plugin_info() = 0; + virtual const ladspa_plugin_info &get_plugin_info() const = 0; /// is a given parameter a control voltage? - virtual bool is_cv(int param_no) = 0; + virtual bool is_cv(int param_no) const = 0; /// is the given parameter non-interpolated? - virtual bool is_noisy(int param_no) = 0; + virtual bool is_noisy(int param_no) const = 0; /// does the plugin require message context? (or DSSI configure) may be slow - virtual bool requires_message_context() = 0; + virtual bool requires_message_context() const = 0; /// does the plugin require string port extension? (or DSSI configure) may be slow - virtual bool requires_string_ports() = 0; + virtual bool requires_string_ports() const = 0; /// add all message context parameter numbers to the ports vector - virtual void get_message_context_parameters(std::vector &ports) = 0; + virtual void get_message_context_parameters(std::vector &ports) const = 0; /// Do-nothing destructor to silence compiler warning virtual ~plugin_metadata_iface() {} }; /// Interface for host-GUI-plugin interaction (should be really split in two, but ... meh) -struct plugin_ctl_iface: public virtual plugin_metadata_iface +struct plugin_ctl_iface { /// @return value of given parameter virtual float get_param_value(int param_no) = 0; @@ -355,7 +356,7 @@ struct plugin_ctl_iface: public virtual plugin_metadata_iface /// Execute menu command with given number virtual void execute(int cmd_no)=0; /// Set a configure variable on a plugin - virtual char *configure(const char *key, const char *value) { return NULL; } + virtual char *configure(const char *key, const char *value) = 0; /// Send all configure variables set within a plugin to given destination (which may be limited to only those that plugin understands) virtual void send_configures(send_configure_iface *)=0; /// Restore all state (parameters and configure vars) to default values - implemented in giface.cpp @@ -365,80 +366,196 @@ struct plugin_ctl_iface: public virtual plugin_metadata_iface virtual bool blobcall(const char *command, const std::string &request, std::string &result) { result = "Call not supported"; return false; } /// Update status variables changed since last_serial /// @return new last_serial - virtual int send_status_updates(send_updates_iface *sui, int last_serial) { return last_serial; } + virtual int send_status_updates(send_updates_iface *sui, int last_serial) = 0; + /// Return metadata object + virtual const plugin_metadata_iface *get_metadata_iface() const = 0; + /// @return line_graph_iface if any + virtual const line_graph_iface *get_line_graph_iface() const = 0; /// Do-nothing destructor to silence compiler warning virtual ~plugin_ctl_iface() {} }; struct plugin_list_info_iface; -/// Get a list of all "large" (effect/synthesizer) plugins -extern void get_all_plugins(std::vector &plugins); -/// Get a list of all "small" (module) plugins -extern void get_all_small_plugins(plugin_list_info_iface *plii); +/// A class to retrieve and query the list of Calf plugins +class plugin_registry +{ +public: + typedef std::vector plugin_vector; +private: + plugin_vector plugins; + plugin_registry(); +public: + /// Get the singleton object. + static plugin_registry &instance(); + + /// Get all plugin metadata objects + const plugin_vector &get_all() { return plugins; } + /// Get single plugin metadata object by URI + const plugin_metadata_iface *get_by_uri(const char *URI); + /// Get single plugin metadata object by URI + const plugin_metadata_iface *get_by_id(const char *id, bool case_sensitive = false); +}; + /// Load and strdup a text file with GUI definition extern const char *load_gui_xml(const std::string &plugin_id); -/// Empty implementations for plugin functions. Note, that functions aren't virtual, because they're called via the particular -/// subclass (flanger_audio_module etc) via template wrappers (ladspa_wrapper<> etc), not via base class pointer/reference +/// Interface to audio processing plugins (the real things, not only metadata) +struct audio_module_iface +{ + /// Handle MIDI Note On + virtual void note_on(int note, int velocity) = 0; + /// Handle MIDI Note Off + virtual void note_off(int note, int velocity) = 0; + /// Handle MIDI Program Change + virtual void program_change(int program) = 0; + /// Handle MIDI Control Change + virtual void control_change(int controller, int value) = 0; + /// Handle MIDI Pitch Bend + /// @param value pitch bend value (-8192 to 8191, defined as in MIDI ie. 8191 = 200 ct by default) + virtual void pitch_bend(int value) = 0; + /// Handle MIDI Channel Pressure + /// @param value channel pressure (0 to 127) + virtual void channel_pressure(int value) = 0; + /// Called when params are changed (before processing) + virtual void params_changed() = 0; + /// LADSPA-esque activate function, except it is called after ports are connected, not before + virtual void activate() = 0; + /// LADSPA-esque deactivate function + virtual void deactivate() = 0; + /// Set sample rate for the plugin + virtual void set_sample_rate(uint32_t sr) = 0; + /// Execute menu command with given number + virtual void execute(int cmd_no) = 0; + /// DSSI configure call + virtual char *configure(const char *key, const char *value) = 0; + /// Send all understood configure vars (none by default) + virtual void send_configures(send_configure_iface *sci) = 0; + /// Send all supported status vars (none by default) + virtual int send_status_updates(send_updates_iface *sui, int last_serial) = 0; + /// Reset parameter values for epp:trigger type parameters (ones activated by oneshot push button instead of check box) + virtual void params_reset() = 0; + /// Called after instantiating (after all the feature pointers are set - including interfaces like progress_report_iface) + virtual void post_instantiate() = 0; + /// Return the arrays of port buffer pointers + virtual void get_port_arrays(float **&ins_ptrs, float **&outs_ptrs, float **¶ms_ptrs) = 0; + /// Return metadata object + virtual const plugin_metadata_iface *get_metadata_iface() const = 0; + /// Set the progress report interface to communicate progress to + virtual void set_progress_report_iface(progress_report_iface *iface) = 0; + /// Clear a part of output buffers that have 0s at mask + virtual void process_slice(uint32_t offset, uint32_t end) = 0; + /// The audio processing loop + virtual uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) = 0; + /// Message port processing function + virtual uint32_t message_run(const void *valid_ports, void *output_ports) = 0; + /// @return line_graph_iface if any + virtual const line_graph_iface *get_line_graph_iface() const = 0; + virtual ~audio_module_iface() {} +}; + +/// Empty implementations for plugin functions. template -class audio_module: public Metadata +class audio_module: public Metadata, public audio_module_iface { public: typedef Metadata metadata_type; + using Metadata::in_count; + using Metadata::out_count; + using Metadata::param_count; + float *ins[Metadata::in_count]; + float *outs[Metadata::out_count]; + float *params[Metadata::param_count]; progress_report_iface *progress_report; audio_module() { progress_report = NULL; + memset(ins, 0, sizeof(ins)); + memset(outs, 0, sizeof(outs)); + memset(params, 0, sizeof(params)); } /// Handle MIDI Note On - inline void note_on(int note, int velocity) {} + void note_on(int note, int velocity) {} /// Handle MIDI Note Off - inline void note_off(int note, int velocity) {} + void note_off(int note, int velocity) {} /// Handle MIDI Program Change - inline void program_change(int program) {} + void program_change(int program) {} /// Handle MIDI Control Change - inline void control_change(int controller, int value) {} + void control_change(int controller, int value) {} /// Handle MIDI Pitch Bend /// @param value pitch bend value (-8192 to 8191, defined as in MIDI ie. 8191 = 200 ct by default) - inline void pitch_bend(int value) {} + void pitch_bend(int value) {} /// Handle MIDI Channel Pressure /// @param value channel pressure (0 to 127) - inline void channel_pressure(int value) {} + void channel_pressure(int value) {} /// Called when params are changed (before processing) - inline void params_changed() {} + void params_changed() {} /// LADSPA-esque activate function, except it is called after ports are connected, not before - inline void activate() {} + void activate() {} /// LADSPA-esque deactivate function - inline void deactivate() {} + void deactivate() {} /// Set sample rate for the plugin - inline void set_sample_rate(uint32_t sr) { } + void set_sample_rate(uint32_t sr) { } /// Execute menu command with given number - inline void execute(int cmd_no) {} + void execute(int cmd_no) {} /// DSSI configure call virtual char *configure(const char *key, const char *value) { return NULL; } /// Send all understood configure vars (none by default) - inline void send_configures(send_configure_iface *sci) {} + void send_configures(send_configure_iface *sci) {} /// Send all supported status vars (none by default) - inline int send_status_updates(send_updates_iface *sui, int last_serial) { return last_serial; } + int send_status_updates(send_updates_iface *sui, int last_serial) { return last_serial; } /// Reset parameter values for epp:trigger type parameters (ones activated by oneshot push button instead of check box) - inline void params_reset() {} + void params_reset() {} /// Called after instantiating (after all the feature pointers are set - including interfaces like progress_report_iface) - inline void post_instantiate() {} + void post_instantiate() {} /// Handle 'message context' port message /// @arg output_ports pointer to bit array of output port "changed" flags, note that 0 = first audio input, not first parameter (use input_count + output_count) - inline uint32_t message_run(const void *valid_ports, void *output_ports) { + uint32_t message_run(const void *valid_ports, void *output_ports) { fprintf(stderr, "ERROR: message run not implemented\n"); return 0; } + /// Return the array of input port pointers + virtual void get_port_arrays(float **&ins_ptrs, float **&outs_ptrs, float **¶ms_ptrs) + { + ins_ptrs = ins; + outs_ptrs = outs; + params_ptrs = params; + } + /// Return metadata object + virtual const plugin_metadata_iface *get_metadata_iface() const { return this; } + /// Set the progress report interface to communicate progress to + virtual void set_progress_report_iface(progress_report_iface *iface) { progress_report = iface; } + + /// utility function: zero port values if mask is 0 + inline void zero_by_mask(uint32_t mask, uint32_t offset, uint32_t nsamples) + { + for (int i=0; i(this); } }; -extern bool check_for_message_context_ports(parameter_properties *parameters, int count); -extern bool check_for_string_ports(parameter_properties *parameters, int count); +extern bool check_for_message_context_ports(const parameter_properties *parameters, int count); +extern bool check_for_string_ports(const parameter_properties *parameters, int count); -#if USE_DSSI +#if USE_EXEC_GUI || USE_DSSI enum line_graph_item { @@ -457,16 +574,19 @@ struct dssi_feedback_sender { /// OSC client object used to send updates osctl::osc_client *client; - /// Background thread handle - pthread_t bg_thread; + /// Is client shared with something else? + bool is_client_shared; /// Quit flag (used to terminate the thread) bool quit; /// Indices of graphs to send std::vector indices; /// Source for the graph data (interface to marshal) - calf_plugins::line_graph_iface *graph; + const calf_plugins::line_graph_iface *graph; - dssi_feedback_sender(const char *URI, line_graph_iface *_graph, calf_plugins::parameter_properties *props, int num_params); + /// Create using a new client + dssi_feedback_sender(const char *URI, const line_graph_iface *_graph); + dssi_feedback_sender(osctl::osc_client *_client, const line_graph_iface *_graph); + void add_graphs(const calf_plugins::parameter_properties *props, int num_params); void update(); ~dssi_feedback_sender(); }; @@ -474,38 +594,40 @@ struct dssi_feedback_sender /// Metadata base class template, to provide default versions of interface functions template -class plugin_metadata: public virtual plugin_metadata_iface +class plugin_metadata: public plugin_metadata_iface { public: static const char *port_names[]; static parameter_properties param_props[]; static ladspa_plugin_info plugin_info; + typedef plugin_metadata metadata_class; // These below are stock implementations based on enums and static members in Metadata classes // they may be overridden to provide more interesting functionality - const char *get_name() { return Metadata::impl_get_name(); } - const char *get_id() { return Metadata::impl_get_id(); } - const char *get_label() { return Metadata::impl_get_label(); } - int get_input_count() { return Metadata::in_count; } - int get_output_count() { return Metadata::out_count; } - int get_param_count() { return Metadata::param_count; } - bool get_midi() { return Metadata::support_midi; } - bool requires_midi() { return Metadata::require_midi; } - bool is_rt_capable() { return Metadata::rt_capable; } - line_graph_iface *get_line_graph_iface() { return dynamic_cast(this); } - table_edit_iface *get_table_edit_iface() { return dynamic_cast(this); } - int get_param_port_offset() { return Metadata::in_count + Metadata::out_count; } - const char *get_gui_xml() { static const char *data_ptr = calf_plugins::load_gui_xml(get_id()); return data_ptr; } - plugin_command_info *get_commands() { return NULL; } - parameter_properties *get_param_props(int param_no) { return ¶m_props[param_no]; } - const char **get_port_names() { return port_names; } - bool is_cv(int param_no) { return true; } - bool is_noisy(int param_no) { return false; } - const ladspa_plugin_info &get_plugin_info() { return plugin_info; } - bool requires_message_context() { return check_for_message_context_ports(param_props, Metadata::param_count); } - bool requires_string_ports() { return check_for_string_ports(param_props, Metadata::param_count); } - void get_message_context_parameters(std::vector &ports) { + const char *get_name() const { return Metadata::impl_get_name(); } + const char *get_id() const { return Metadata::impl_get_id(); } + const char *get_label() const { return Metadata::impl_get_label(); } + int get_input_count() const { return Metadata::in_count; } + int get_output_count() const { return Metadata::out_count; } + int get_inputs_optional() const { return Metadata::ins_optional; } + int get_outputs_optional() const { return Metadata::outs_optional; } + int get_param_count() const { return Metadata::param_count; } + bool get_midi() const { return Metadata::support_midi; } + bool requires_midi() const { return Metadata::require_midi; } + bool is_rt_capable() const { return Metadata::rt_capable; } + const table_edit_iface *get_table_edit_iface() const { return dynamic_cast(this); } + int get_param_port_offset() const { return Metadata::in_count + Metadata::out_count; } + const char *get_gui_xml() const { static const char *data_ptr = calf_plugins::load_gui_xml(get_id()); return data_ptr; } + plugin_command_info *get_commands() const { return NULL; } + const parameter_properties *get_param_props(int param_no) const { return ¶m_props[param_no]; } + const char **get_port_names() const { return port_names; } + bool is_cv(int param_no) const { return true; } + bool is_noisy(int param_no) const { return false; } + const ladspa_plugin_info &get_plugin_info() const { return plugin_info; } + bool requires_message_context() const { return check_for_message_context_ports(param_props, Metadata::param_count); } + bool requires_string_ports() const { return check_for_string_ports(param_props, Metadata::param_count); } + void get_message_context_parameters(std::vector &ports) const { for (int i = 0; i < get_param_count(); ++i) { if (get_param_props(i)->flags & PF_PROP_MSGCONTEXT) ports.push_back(i); @@ -513,40 +635,6 @@ public: } }; -/// A class for delegating metadata implementation to a "remote" metadata class. -/// Used for GUI wrappers that cannot have a dependency on actual classes, -/// and which instead take an "external" metadata object pointer, obtained -/// through get_all_plugins. -class plugin_metadata_proxy: public virtual plugin_metadata_iface -{ -public: - plugin_metadata_iface *impl; -public: - plugin_metadata_proxy(plugin_metadata_iface *_impl) { impl = _impl; } - const char *get_name() { return impl->get_name(); } - const char *get_id() { return impl->get_id(); } - const char *get_label() { return impl->get_label(); } - int get_input_count() { return impl->get_input_count(); } - int get_output_count() { return impl->get_output_count(); } - int get_param_count() { return impl->get_param_count(); } - bool get_midi() { return impl->get_midi(); } - bool requires_midi() { return impl->requires_midi(); } - bool is_rt_capable() { return impl->is_rt_capable(); } - line_graph_iface *get_line_graph_iface() { return impl->get_line_graph_iface(); } - table_edit_iface *get_table_edit_iface() { return impl->get_table_edit_iface(); } - int get_param_port_offset() { return impl->get_param_port_offset(); } - const char *get_gui_xml() { return impl->get_gui_xml(); } - plugin_command_info *get_commands() { return impl->get_commands(); } - parameter_properties *get_param_props(int param_no) { return impl->get_param_props(param_no); } - const char **get_port_names() { return impl->get_port_names(); } - bool is_cv(int param_no) { return impl->is_cv(param_no); } - bool is_noisy(int param_no) { return impl->is_noisy(param_no); } - const ladspa_plugin_info &get_plugin_info() { return impl->get_plugin_info(); } - bool requires_message_context() { return impl->requires_message_context(); } - bool requires_string_ports() { return impl->requires_string_ports(); } - void get_message_context_parameters(std::vector &ports) { impl->get_message_context_parameters(ports); } -}; - #define CALF_PORT_NAMES(name) template<> const char *::plugin_metadata::port_names[] #define CALF_PORT_PROPS(name) template<> parameter_properties plugin_metadata::param_props[] #define CALF_PLUGIN_INFO(name) template<> calf_plugins::ladspa_plugin_info plugin_metadata::plugin_info @@ -555,9 +643,52 @@ public: static const char *impl_get_id() { return id; } \ static const char *impl_get_label() { return label; } \ - extern const char *calf_copyright_info; +bool get_freq_gridline(int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context, bool use_frequencies = true); + +/// convert amplitude value to normalized grid-ish value (0dB = 0.5, 30dB = 1.0, -30 dB = 0.0, -60dB = -0.5, -90dB = -1.0) +static inline float dB_grid(float amp) +{ + return log(amp) * (1.0 / log(256.0)) + 0.4; +} + +template +static bool get_graph(Fx &fx, int subindex, float *data, int points) +{ + for (int i = 0; i < points; i++) + { + typedef std::complex cfloat; + double freq = 20.0 * pow (20000.0 / 20.0, i * 1.0 / points); + data[i] = dB_grid(fx.freq_gain(subindex, freq, fx.srate)); + } + return true; +} + +/// convert normalized grid-ish value back to amplitude value +static inline float dB_grid_inv(float pos) +{ + return pow(256.0, pos - 0.4); +} + +/// Line graph interface implementation for frequency response graphs +class frequency_response_line_graph: public line_graph_iface +{ +public: + bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const; + virtual int get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) const; +}; + +/// set drawing color based on channel index (0 or 1) +void set_channel_color(cairo_iface *context, int channel); + +struct preset_access_iface +{ + virtual void store_preset() = 0; + virtual void activate_preset(int preset, bool builtin) = 0; + virtual ~preset_access_iface() {} +}; + }; #endif diff --git a/plugins/ladspa_effect/calf/calf/inertia.h b/plugins/ladspa_effect/calf/src/calf/inertia.h similarity index 99% rename from plugins/ladspa_effect/calf/calf/inertia.h rename to plugins/ladspa_effect/calf/src/calf/inertia.h index aca1fbfec..d6bbd297a 100644 --- a/plugins/ladspa_effect/calf/calf/inertia.h +++ b/plugins/ladspa_effect/calf/src/calf/inertia.h @@ -245,7 +245,7 @@ public: } void set_sample_rate(int sr) { - ramp = linear_ramp(sr / 441); + ramp = linear_ramp(sr / 100); } // to change param, use set_inertia(value) // to read param, use get() diff --git a/plugins/ladspa_effect/calf/src/calf/ladspa_wrap.h b/plugins/ladspa_effect/calf/src/calf/ladspa_wrap.h new file mode 100644 index 000000000..68009b8cb --- /dev/null +++ b/plugins/ladspa_effect/calf/src/calf/ladspa_wrap.h @@ -0,0 +1,130 @@ +/* Calf DSP Library + * API wrappers for LADSPA/DSSI + * + * Copyright (C) 2007-2008 Krzysztof Foltman + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02111-1307, USA. + */ +#ifndef __CALF_LADSPA_WRAP_H +#define __CALF_LADSPA_WRAP_H + +#if USE_LADSPA + +#include +#include +#if USE_DSSI +#include +#endif +#include "giface.h" +#include "preset.h" + +namespace calf_plugins { + +struct ladspa_plugin_metadata_set; +/// A template implementing plugin_ctl_iface for a given plugin +struct ladspa_instance: public plugin_ctl_iface +{ + audio_module_iface *module; + const plugin_metadata_iface *metadata; + ladspa_plugin_metadata_set *ladspa; + bool activate_flag; + float **ins, **outs, **params; +#if USE_DSSI + dssi_feedback_sender *feedback_sender; +#endif + + ladspa_instance(audio_module_iface *_module, ladspa_plugin_metadata_set *_ladspa, int sample_rate); + virtual const line_graph_iface *get_line_graph_iface() const { return module->get_line_graph_iface(); } + virtual float get_param_value(int param_no); + virtual void set_param_value(int param_no, float value); + virtual bool activate_preset(int bank, int program); + virtual char *configure(const char *key, const char *value); + virtual float get_level(unsigned int port) { return 0.f; } + virtual void execute(int cmd_no) { + module->execute(cmd_no); + } + virtual void send_configures(send_configure_iface *sci) { + module->send_configures(sci); + } + virtual int send_status_updates(send_updates_iface *sui, int last_serial) { return module->send_status_updates(sui, last_serial); } + void run(unsigned long SampleCount); +#if USE_DSSI + /// Utility function: handle MIDI event (only handles a subset in this version) + void process_dssi_event(snd_seq_event_t &event); + void run_synth(unsigned long SampleCount, snd_seq_event_t *Events, unsigned long EventCount); +#endif + virtual const plugin_metadata_iface *get_metadata_iface() const + { + return metadata; + } +}; + +/// Set of metadata produced by LADSPA wrapper for LADSPA-related purposes +struct ladspa_plugin_metadata_set +{ + /// LADSPA descriptor + LADSPA_Descriptor descriptor; + /// LADSPA descriptor for DSSI (uses a different name for the plugin, otherwise same as descriptor) + LADSPA_Descriptor descriptor_for_dssi; +#if USE_DSSI + /// Extended DSSI descriptor (points to descriptor_for_dssi for things like name/label/port info etc.) + DSSI_Descriptor dssi_descriptor; + DSSI_Program_Descriptor dssi_default_program; + + std::vector *presets; + std::vector *preset_descs; +#endif + + int input_count, output_count, param_count, real_param_count; + const plugin_metadata_iface *metadata; + + ladspa_plugin_metadata_set(); + void prepare(const plugin_metadata_iface *md, LADSPA_Handle (*cb_instantiate)(const struct _LADSPA_Descriptor * Descriptor, unsigned long sample_rate)); + void prepare_dssi(); + ~ladspa_plugin_metadata_set(); +}; + +/// A wrapper class for plugin class object (there is only one ladspa_wrapper singleton for many instances of the same plugin) +template +struct ladspa_wrapper +{ + static ladspa_plugin_metadata_set output; + +private: + ladspa_wrapper(const plugin_metadata_iface *md) + { + output.prepare(md, cb_instantiate); + } + +public: + /// LADSPA instantiation function (create a plugin instance) + static LADSPA_Handle cb_instantiate(const struct _LADSPA_Descriptor * Descriptor, unsigned long sample_rate) + { + return new ladspa_instance(new Module, &output, sample_rate); + } + + /// Get a wrapper singleton - used to prevent initialization order problems which were present in older versions + static ladspa_plugin_metadata_set &get() { + static ladspa_wrapper instance(new typename Module::metadata_class); + return instance.output; + } +}; + +}; + +#endif + +#endif diff --git a/plugins/ladspa_effect/calf/calf/loudness.h b/plugins/ladspa_effect/calf/src/calf/loudness.h similarity index 100% rename from plugins/ladspa_effect/calf/calf/loudness.h rename to plugins/ladspa_effect/calf/src/calf/loudness.h diff --git a/plugins/ladspa_effect/calf/src/calf/lv2_external_ui.h b/plugins/ladspa_effect/calf/src/calf/lv2_external_ui.h new file mode 100644 index 000000000..242271ecc --- /dev/null +++ b/plugins/ladspa_effect/calf/src/calf/lv2_external_ui.h @@ -0,0 +1,101 @@ +/* -*- Mode: C ; c-basic-offset: 2 -*- */ +/***************************************************************************** + * + * This work is in public domain. + * + * This file 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. + * + * If you have questions, contact Nedko Arnaudov or + * ask in #lad channel, FreeNode IRC network. + * + *****************************************************************************/ + +#ifndef LV2_EXTERNAL_UI_H__5AFE09A5_0FB7_47AF_924E_2AF0F8DE8873__INCLUDED +#define LV2_EXTERNAL_UI_H__5AFE09A5_0FB7_47AF_924E_2AF0F8DE8873__INCLUDED + +/** UI extension suitable for out-of-process UIs */ +#define LV2_EXTERNAL_UI_URI "http://lv2plug.in/ns/extensions/ui#external" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} /* Adjust editor indent */ +#endif + +/** + * When LV2_EXTERNAL_UI_URI UI is instantiated, the returned + * LV2UI_Widget handle must be cast to pointer to struct lv2_external_ui. + * UI is created in invisible state. + */ +struct lv2_external_ui +{ + /** + * Host calls this function regulary. UI library implementing the + * callback may do IPC or redraw the UI. + * + * @param _this_ the UI context + */ + void (* run)(struct lv2_external_ui * _this_); + + /** + * Host calls this function to make the plugin UI visible. + * + * @param _this_ the UI context + */ + void (* show)(struct lv2_external_ui * _this_); + + /** + * Host calls this function to make the plugin UI invisible again. + * + * @param _this_ the UI context + */ + void (* hide)(struct lv2_external_ui * _this_); +}; + +#define LV2_EXTERNAL_UI_RUN(ptr) (ptr)->run(ptr) +#define LV2_EXTERNAL_UI_SHOW(ptr) (ptr)->show(ptr) +#define LV2_EXTERNAL_UI_HIDE(ptr) (ptr)->hide(ptr) + +/** + * On UI instantiation, host must supply LV2_EXTERNAL_UI_URI + * feature. LV2_Feature::data must be pointer to struct lv2_external_ui_host. */ +struct lv2_external_ui_host +{ + /** + * Callback that plugin UI will call + * when UI (GUI window) is closed by user. + * This callback wil; be called during execution of lv2_external_ui::run() + * (i.e. not from background thread). + * + * After this callback is called, UI is defunct. Host must call + * LV2UI_Descriptor::cleanup(). If host wants to make the UI visible + * again UI must be reinstantiated. + * + * @param controller Host context associated with plugin UI, as + * supplied to LV2UI_Descriptor::instantiate() + */ + void (* ui_closed)(LV2UI_Controller controller); + + /** + * Optional (may be NULL) "user friendly" identifier which the UI + * may display to allow a user to easily associate this particular + * UI instance with the correct plugin instance as it is represented + * by the host (e.g. "track 1" or "channel 4"). + * + * If supplied by host, the string will be referenced only during + * LV2UI_Descriptor::instantiate() + */ + const char * plugin_human_id; +}; + +#if 0 +{ /* Adjust editor indent */ +#endif +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* #ifndef LV2_EXTERNAL_UI_H__5AFE09A5_0FB7_47AF_924E_2AF0F8DE8873__INCLUDED */ diff --git a/plugins/ladspa_effect/calf/src/calf/lv2helpers.h b/plugins/ladspa_effect/calf/src/calf/lv2helpers.h new file mode 100644 index 000000000..21e6cfc00 --- /dev/null +++ b/plugins/ladspa_effect/calf/src/calf/lv2helpers.h @@ -0,0 +1,30 @@ +/* Calf DSP Library + * LV2-related helper classes and functions + * + * Copyright (C) 2001-2008 Krzysztof Foltman + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02111-1307, USA. + */ +#ifndef CALF_LV2HELPERS_H +#define CALF_LV2HELPERS_H + +#if USE_LV2 + +#include +#include + +#endif +#endif diff --git a/plugins/ladspa_effect/calf/calf/lv2wrap.h b/plugins/ladspa_effect/calf/src/calf/lv2wrap.h similarity index 56% rename from plugins/ladspa_effect/calf/calf/lv2wrap.h rename to plugins/ladspa_effect/calf/src/calf/lv2wrap.h index 8d2f172c8..6a9bc40d0 100644 --- a/plugins/ladspa_effect/calf/calf/lv2wrap.h +++ b/plugins/ladspa_effect/calf/src/calf/lv2wrap.h @@ -33,12 +33,14 @@ #include #include #include +#include namespace calf_plugins { -template -struct lv2_instance: public plugin_ctl_iface, public progress_report_iface, public Module +struct lv2_instance: public plugin_ctl_iface, public progress_report_iface { + const plugin_metadata_iface *metadata; + audio_module_iface *module; bool set_srate; int srate_to_set; LV2_MIDI *midi_data; @@ -48,121 +50,120 @@ struct lv2_instance: public plugin_ctl_iface, public progress_report_iface, publ uint32_t midi_event_type; std::vector message_params; LV2_Progress *progress_report_feature; - lv2_instance() + float **ins, **outs, **params; + int out_count; + lv2_instance(audio_module_iface *_module) { - for (int i=0; i < Module::in_count; i++) - Module::ins[i] = NULL; - for (int i=0; i < Module::out_count; i++) - Module::outs[i] = NULL; - for (int i=0; i < Module::param_count; i++) - Module::params[i] = NULL; + module = _module; + module->get_port_arrays(ins, outs, params); + metadata = module->get_metadata_iface(); + metadata->get_message_context_parameters(message_params); + out_count = metadata->get_output_count(); + uri_map = NULL; midi_data = NULL; event_data = NULL; - midi_event_type = 0xFFFFFFFF; - set_srate = true; - srate_to_set = 44100; - get_message_context_parameters(message_params); progress_report_feature = NULL; + midi_event_type = 0xFFFFFFFF; + + srate_to_set = 44100; + set_srate = true; // printf("message params %d\n", (int)message_params.size()); } /// This, and not Module::post_instantiate, is actually called by lv2_wrapper class void post_instantiate() { if (progress_report_feature) - Module::progress_report = this; - Module::post_instantiate(); - } - virtual parameter_properties *get_param_props(int param_no) - { - return &Module::param_props[param_no]; - } - virtual float get_param_value(int param_no) - { - return *Module::params[param_no]; - } - virtual void set_param_value(int param_no, float value) - { - *Module::params[param_no] = value; - } - virtual int get_param_count() - { - return Module::param_count; - } - virtual int get_param_port_offset() - { - return Module::in_count + Module::out_count; - } - virtual const char *get_gui_xml() { - return Module::get_gui_xml(); - } - virtual line_graph_iface *get_line_graph_iface() - { - return dynamic_cast(this); + module->set_progress_report_iface(this); + module->post_instantiate(); } virtual bool activate_preset(int bank, int program) { return false; } - virtual const char *get_name() - { - return Module::get_name(); - } - virtual const char *get_id() - { - return Module::get_id(); - } - virtual const char *get_label() - { - return Module::get_label(); - } - virtual int get_input_count() { return Module::in_count; } - virtual int get_output_count() { return Module::out_count; } - virtual bool get_midi() { return Module::support_midi; } virtual float get_level(unsigned int port) { return 0.f; } virtual void execute(int cmd_no) { - Module::execute(cmd_no); + module->execute(cmd_no); } virtual void report_progress(float percentage, const std::string &message) { if (progress_report_feature) (*progress_report_feature->progress)(progress_report_feature->context, percentage, !message.empty() ? message.c_str() : NULL); } void send_configures(send_configure_iface *sci) { - Module::send_configures(sci); + module->send_configures(sci); } uint32_t impl_message_run(const void *valid_inputs, void *output_ports) { + uint8_t *vi = (uint8_t *)valid_inputs; + int ofs = metadata->get_param_port_offset(); for (unsigned int i = 0; i < message_params.size(); i++) { int pn = message_params[i]; - parameter_properties &pp = *get_param_props(pn); - if ((pp.flags & PF_TYPEMASK) == PF_STRING - && (((LV2_String_Data *)Module::params[pn])->flags & LV2_STRING_DATA_CHANGED_FLAG)) { + const parameter_properties &pp = *metadata->get_param_props(pn); + int ppn = pn + ofs; + if ((pp.flags & PF_TYPEMASK) == PF_STRING && (vi[ppn >> 3] & (1 << (ppn & 7))) + && (((LV2_String_Data *)params[pn])->flags & LV2_STRING_DATA_CHANGED_FLAG)) { printf("Calling configure on %s\n", pp.short_name); - configure(pp.short_name, ((LV2_String_Data *)Module::params[pn])->data); + configure(pp.short_name, ((LV2_String_Data *)params[pn])->data); } } - return Module::message_run(valid_inputs, output_ports); + return module->message_run(valid_inputs, output_ports); } char *configure(const char *key, const char *value) { // disambiguation - the plugin_ctl_iface version is just a stub, so don't use it - return Module::configure(key, value); + return module->configure(key, value); } -#if 0 - // the default implementation should be fine - virtual void clear_preset() { - // This is never called in practice, at least for now - // However, it will change when presets are implemented - for (int i=0; i < Module::param_count; i++) - *Module::params[i] = Module::param_props[i].def_value; - /* - const char **p = Module::get_default_configure_vars(); - if (p) - { - for(; p[0]; p += 2) - configure(p[0], p[1]); + + void process_events(uint32_t &offset) { + struct LV2_Midi_Event: public LV2_Event { + unsigned char data[1]; + }; + unsigned char *data = (unsigned char *)(event_data->data); + for (uint32_t i = 0; i < event_data->event_count; i++) { + LV2_Midi_Event *item = (LV2_Midi_Event *)data; + uint32_t ts = item->frames; + // printf("Event: timestamp %d subframes %d type %d vs %d\n", item->frames, item->subframes, item->type, mod->midi_event_type); + if (ts > offset) + { + module->process_slice(offset, ts); + offset = ts; + } + if (item->type == midi_event_type) + { + // printf("Midi message %x %x %x %x %d\n", item->data[0], item->data[1], item->data[2], item->data[3], item->size); + switch(item->data[0] >> 4) + { + case 8: module->note_off(item->data[1], item->data[2]); break; + case 9: module->note_on(item->data[1], item->data[2]); break; + case 11: module->control_change(item->data[1], item->data[2]); break; + case 12: module->program_change(item->data[1]); break; + case 13: module->channel_pressure(item->data[1]); break; + case 14: module->pitch_bend(item->data[1] + 128 * item->data[2] - 8192); break; + } + } + else + if (item->type == 0 && event_feature) + event_feature->lv2_event_unref(event_feature->callback_data, item); + // printf("timestamp %f item size %d first byte %x\n", item->timestamp, item->size, item->data[0]); + data += ((sizeof(LV2_Event) + item->size + 7))&~7; } - */ } -#endif + + virtual float get_param_value(int param_no) + { + // XXXKF hack + if (param_no >= metadata->get_param_count()) + return 0; + return (*params)[param_no]; + } + virtual void set_param_value(int param_no, float value) + { + // XXXKF hack + if (param_no >= metadata->get_param_count()) + return; + *params[param_no] = value; + } + virtual const plugin_metadata_iface *get_metadata_iface() const { return metadata; } + virtual const line_graph_iface *get_line_graph_iface() const { return module->get_line_graph_iface(); } + virtual int send_status_updates(send_updates_iface *sui, int last_serial) { return module->send_status_updates(sui, last_serial); } }; struct LV2_Calf_Descriptor { @@ -172,7 +173,7 @@ struct LV2_Calf_Descriptor { template struct lv2_wrapper { - typedef lv2_instance instance; + typedef lv2_instance instance; static LV2_Descriptor descriptor; static LV2_Calf_Descriptor calf_descriptor; static LV2MessageContext message_context; @@ -196,10 +197,11 @@ struct lv2_wrapper } static void cb_connect(LV2_Handle Instance, uint32_t port, void *DataLocation) { - unsigned long ins = Module::in_count; - unsigned long outs = Module::out_count; - unsigned long params = Module::param_count; instance *const mod = (instance *)Instance; + const plugin_metadata_iface *md = mod->metadata; + unsigned long ins = md->get_input_count(); + unsigned long outs = md->get_output_count(); + unsigned long params = md->get_param_count(); if (port < ins) mod->ins[port] = (float *)DataLocation; else if (port < ins + outs) @@ -208,7 +210,7 @@ struct lv2_wrapper int i = port - ins - outs; mod->params[i] = (float *)DataLocation; } - else if (Module::support_midi && port == ins + outs + params) { + else if (md->get_midi() && port == ins + outs + params) { mod->event_data = (LV2_Event_Buffer *)DataLocation; } } @@ -220,12 +222,12 @@ struct lv2_wrapper static void cb_deactivate(LV2_Handle Instance) { instance *const mod = (instance *)Instance; - mod->deactivate(); + mod->module->deactivate(); } static LV2_Handle cb_instantiate(const LV2_Descriptor * Descriptor, double sample_rate, const char *bundle_path, const LV2_Feature *const *features) { - instance *mod = new instance(); + instance *mod = new instance(new Module); // XXXKF some people use fractional sample rates; we respect them ;-) mod->srate_to_set = (uint32_t)sample_rate; mod->set_srate = true; @@ -252,79 +254,30 @@ struct lv2_wrapper mod->post_instantiate(); return mod; } - static inline void zero_by_mask(Module *module, uint32_t mask, uint32_t offset, uint32_t nsamples) - { - for (int i=0; iouts[i] + offset, nsamples); - } - } - } static plugin_ctl_iface *cb_get_pci(LV2_Handle Instance) { return static_cast(Instance); } - static inline void process_slice(Module *mod, uint32_t offset, uint32_t end) - { - while(offset < end) - { - uint32_t newend = std::min(offset + MAX_SAMPLE_RUN, end); - uint32_t out_mask = mod->process(offset, newend - offset, -1, -1); - zero_by_mask(mod, out_mask, offset, newend - offset); - offset = newend; - } - } - static uint32_t cb_message_run(LV2_Handle Instance, const void *valid_inputs, void *outputs_written) { instance *mod = (instance *)Instance; return mod->impl_message_run(valid_inputs, outputs_written); } static void cb_run(LV2_Handle Instance, uint32_t SampleCount) { - instance *const mod = (instance *)Instance; - if (mod->set_srate) { - mod->set_sample_rate(mod->srate_to_set); + instance *const inst = (instance *)Instance; + audio_module_iface *mod = inst->module; + if (inst->set_srate) { + mod->set_sample_rate(inst->srate_to_set); mod->activate(); - mod->set_srate = false; + inst->set_srate = false; } mod->params_changed(); uint32_t offset = 0; - if (mod->event_data) + if (inst->event_data) { - // printf("Event data: count %d\n", mod->event_data->event_count); - struct LV2_Midi_Event: public LV2_Event { - unsigned char data[1]; - }; - unsigned char *data = (unsigned char *)(mod->event_data->data); - for (uint32_t i = 0; i < mod->event_data->event_count; i++) { - LV2_Midi_Event *item = (LV2_Midi_Event *)data; - uint32_t ts = item->frames; - // printf("Event: timestamp %d subframes %d type %d vs %d\n", item->frames, item->subframes, item->type, mod->midi_event_type); - if (ts > offset) - { - process_slice(mod, offset, ts); - offset = ts; - } - if (item->type == mod->midi_event_type) - { - // printf("Midi message %x %x %x %x %d\n", item->data[0], item->data[1], item->data[2], item->data[3], item->size); - switch(item->data[0] >> 4) - { - case 8: mod->note_off(item->data[1], item->data[2]); break; - case 9: mod->note_on(item->data[1], item->data[2]); break; - case 11: mod->control_change(item->data[1], item->data[2]); break; - case 12: mod->program_change(item->data[1]); break; - case 14: mod->pitch_bend(item->data[1] + 128 * item->data[2] - 8192); break; - } - } - else - if (item->type == 0 && mod->event_feature) - mod->event_feature->lv2_event_unref(mod->event_feature->callback_data, item); - // printf("timestamp %f item size %d first byte %x\n", item->timestamp, item->size, item->data[0]); - data += ((sizeof(LV2_Event) + item->size + 7))&~7; - } + inst->process_events(offset); } - process_slice(mod, offset, SampleCount); + inst->module->process_slice(offset, SampleCount); } static void cb_cleanup(LV2_Handle Instance) { instance *const mod = (instance *)Instance; diff --git a/plugins/ladspa_effect/calf/calf/metadata.h b/plugins/ladspa_effect/calf/src/calf/metadata.h similarity index 67% rename from plugins/ladspa_effect/calf/calf/metadata.h rename to plugins/ladspa_effect/calf/src/calf/metadata.h index c959e1940..de17490c3 100644 --- a/plugins/ladspa_effect/calf/calf/metadata.h +++ b/plugins/ladspa_effect/calf/src/calf/metadata.h @@ -31,21 +31,21 @@ struct flanger_metadata: public plugin_metadata { public: enum { par_delay, par_depth, par_rate, par_fb, par_stereo, par_reset, par_amount, par_dryamount, param_count }; - enum { in_count = 2, out_count = 2, support_midi = false, require_midi = false, rt_capable = true }; + enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = false, require_midi = false, rt_capable = true }; PLUGIN_NAME_ID_LABEL("flanger", "flanger", "Flanger") }; struct phaser_metadata: public plugin_metadata { enum { par_freq, par_depth, par_rate, par_fb, par_stages, par_stereo, par_reset, par_amount, par_dryamount, param_count }; - enum { in_count = 2, out_count = 2, support_midi = false, require_midi = false, rt_capable = true }; + enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = false, require_midi = false, rt_capable = true }; PLUGIN_NAME_ID_LABEL("phaser", "phaser", "Phaser") }; struct filter_metadata: public plugin_metadata { enum { par_cutoff, par_resonance, par_mode, par_inertia, param_count }; - enum { in_count = 2, out_count = 2, rt_capable = true, require_midi = false, support_midi = false }; + enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, rt_capable = true, require_midi = false, support_midi = false }; PLUGIN_NAME_ID_LABEL("filter", "filter", "Filter") /// do not export mode and inertia as CVs, as those are settings and not parameters bool is_cv(int param_no) { return param_no != par_mode && param_no != par_inertia; } @@ -55,7 +55,7 @@ struct filter_metadata: public plugin_metadata struct filterclavier_metadata: public plugin_metadata { enum { par_transpose, par_detune, par_max_resonance, par_mode, par_inertia, param_count }; - enum { in_count = 2, out_count = 2, rt_capable = true, require_midi = true, support_midi = true }; + enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, rt_capable = true, require_midi = true, support_midi = true }; PLUGIN_NAME_ID_LABEL("filterclavier", "filterclavier", "Filterclavier") /// do not export mode and inertia as CVs, as those are settings and not parameters bool is_cv(int param_no) { return param_no != par_mode && param_no != par_inertia; } @@ -64,14 +64,14 @@ struct filterclavier_metadata: public plugin_metadata struct reverb_metadata: public plugin_metadata { enum { par_clip, par_meter_wet, par_meter_out, par_decay, par_hfdamp, par_roomsize, par_diffusion, par_amount, par_dry, par_predelay, par_basscut, par_treblecut, param_count }; - enum { in_count = 2, out_count = 2, support_midi = false, require_midi = false, rt_capable = true }; + enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = false, require_midi = false, rt_capable = true }; PLUGIN_NAME_ID_LABEL("reverb", "reverb", "Reverb") }; struct vintage_delay_metadata: public plugin_metadata { - enum { par_bpm, par_divide, par_time_l, par_time_r, par_feedback, par_amount, par_mixmode, par_medium, par_dryamount, param_count }; - enum { in_count = 2, out_count = 2, rt_capable = true, support_midi = false, require_midi = false }; + enum { par_bpm, par_divide, par_time_l, par_time_r, par_feedback, par_amount, par_mixmode, par_medium, par_dryamount, par_width, param_count }; + enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, rt_capable = true, support_midi = false, require_midi = false }; PLUGIN_NAME_ID_LABEL("vintage_delay", "vintagedelay", "Vintage Delay") }; @@ -79,7 +79,7 @@ struct rotary_speaker_metadata: public plugin_metadata { public: enum { par_speed, par_spacing, par_shift, par_moddepth, par_treblespeed, par_bassspeed, par_micdistance, par_reflection, par_meter_l, par_meter_h, param_count }; - enum { in_count = 2, out_count = 2, support_midi = true, require_midi = false, rt_capable = true }; + enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = true, require_midi = false, rt_capable = true }; PLUGIN_NAME_ID_LABEL("rotary_speaker", "rotaryspeaker", "Rotary Speaker") }; @@ -88,20 +88,32 @@ struct multichorus_metadata: public plugin_metadata { public: enum { par_delay, par_depth, par_rate, par_stereo, par_voices, par_vphase, par_amount, par_dryamount, par_freq, par_freq2, par_q, par_overlap, param_count }; - enum { in_count = 2, out_count = 2, rt_capable = true, support_midi = false, require_midi = false }; + enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, rt_capable = true, support_midi = false, require_midi = false }; PLUGIN_NAME_ID_LABEL("multichorus", "multichorus", "Multi Chorus") }; +enum CalfEqMode { + MODE12DB, + MODE24DB, + MODE36DB +}; + /// Monosynth - metadata struct monosynth_metadata: public plugin_metadata { enum { wave_saw, wave_sqr, wave_pulse, wave_sine, wave_triangle, wave_varistep, wave_skewsaw, wave_skewsqr, wave_test1, wave_test2, wave_test3, wave_test4, wave_test5, wave_test6, wave_test7, wave_test8, wave_count }; enum { flt_lp12, flt_lp24, flt_2lp12, flt_hp12, flt_lpbr, flt_hpbr, flt_bp6, flt_2bp6 }; - enum { par_wave1, par_wave2, par_pw1, par_pw2, par_detune, par_osc2xpose, par_oscmode, par_oscmix, par_filtertype, par_cutoff, par_resonance, par_cutoffsep, par_envmod, par_envtores, par_envtoamp, par_attack, par_decay, par_sustain, par_fade, par_release, + enum { par_wave1, par_wave2, par_pw1, par_pw2, par_detune, par_osc2xpose, par_oscmode, par_oscmix, par_filtertype, par_cutoff, par_resonance, par_cutoffsep, par_env1tocutoff, par_env1tores, par_env1toamp, + par_env1attack, par_env1decay, par_env1sustain, par_env1fade, par_env1release, par_keyfollow, par_legato, par_portamento, par_vel2filter, par_vel2amp, par_master, par_pwhlrange, par_lforate, par_lfodelay, par_lfofilter, par_lfopitch, par_lfopw, par_mwhl_lfo, par_scaledetune, + par_env2tocutoff, par_env2tores, par_env2toamp, + par_env2attack, par_env2decay, par_env2sustain, par_env2fade, par_env2release, + par_stretch1, par_window1, + par_lfo1trig, par_lfo2trig, + par_lfo2rate, par_lfo2delay, param_count }; - enum { in_count = 0, out_count = 2, support_midi = true, require_midi = true, rt_capable = true }; + enum { in_count = 0, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = true, require_midi = true, rt_capable = true }; enum { step_size = 64, step_shift = 6 }; enum { modsrc_none, @@ -109,7 +121,9 @@ struct monosynth_metadata: public plugin_metadata modsrc_pressure, modsrc_modwheel, modsrc_env1, + modsrc_env2, modsrc_lfo1, + modsrc_lfo2, modsrc_count, }; enum { @@ -122,24 +136,27 @@ struct monosynth_metadata: public plugin_metadata moddest_o2detune, moddest_o1pw, moddest_o2pw, + moddest_o1stretch, moddest_count, }; PLUGIN_NAME_ID_LABEL("monosynth", "monosynth", "Monosynth") }; /// Thor's compressor - metadata +/// Added some meters and stripped the weighting part struct compressor_metadata: public plugin_metadata { - enum { in_count = 2, out_count = 2, support_midi = false, require_midi = false, rt_capable = true }; - enum { param_threshold, param_ratio, param_attack, param_release, param_makeup, param_knee, param_detection, param_stereo_link, param_aweighting, param_compression, param_peak, param_clip, param_bypass, param_input,// param_freq, param_bw, - param_count }; + enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = false, require_midi = false, rt_capable = true }; + enum { param_bypass, param_level_in, param_meter_in, param_meter_out, param_clip_in, param_clip_out, + param_threshold, param_ratio, param_attack, param_release, param_makeup, param_knee, param_detection, param_stereo_link, param_compression, + param_count }; PLUGIN_NAME_ID_LABEL("compressor", "compressor", "Compressor") }; /// Markus's sidechain compressor - metadata struct sidechaincompressor_metadata: public plugin_metadata { - enum { in_count = 2, out_count = 2, support_midi = false, require_midi = false, rt_capable = true }; + enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = false, require_midi = false, rt_capable = true }; enum { param_bypass, param_level_in, param_meter_in, param_meter_out, param_clip_in, param_clip_out, param_threshold, param_ratio, param_attack, param_release, param_makeup, param_knee, param_detection, param_stereo_link, param_compression, param_sc_mode, param_f1_freq, param_f2_freq, param_f1_level, param_f2_level, @@ -150,7 +167,7 @@ struct sidechaincompressor_metadata: public plugin_metadata { - enum { in_count = 2, out_count = 2, support_midi = false, require_midi = false, rt_capable = true }; + enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = false, require_midi = false, rt_capable = true }; enum { param_bypass, param_level_in, param_level_out, param_meter_inL, param_meter_inR, param_meter_outL, param_meter_outR, param_clip_inL, param_clip_inR, param_clip_outL, param_clip_outR, param_freq0, param_freq1, param_freq2, @@ -171,7 +188,7 @@ struct multibandcompressor_metadata: public plugin_metadata { - enum { in_count = 2, out_count = 2, support_midi = false, require_midi = false, rt_capable = true }; + enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = false, require_midi = false, rt_capable = true }; enum { param_bypass, param_detected, param_compression, param_detected_led, param_clip_out, param_detection, param_mode, param_threshold, param_ratio, param_laxity, param_makeup, @@ -183,21 +200,25 @@ struct deesser_metadata: public plugin_metadata /// Markus's 5-band EQ - metadata struct equalizer5band_metadata: public plugin_metadata { - enum { in_count = 2, out_count = 2, support_midi = false, require_midi = false, rt_capable = true }; - enum { param_bypass, param_level_in, param_level_out, param_meter_in, - param_meter_out, param_clip_in, param_clip_out, + enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = false, require_midi = false, rt_capable = true }; + enum { param_bypass, param_level_in, param_level_out, param_meter_inL, param_meter_inR, + param_meter_outL, param_meter_outR, param_clip_inL, param_clip_outL, param_clip_inR, param_clip_outR, param_ls_active, param_ls_level, param_ls_freq, param_hs_active, param_hs_level, param_hs_freq, param_p1_active, param_p1_level, param_p1_freq, param_p1_q, param_p2_active, param_p2_level, param_p2_freq, param_p2_q, param_p3_active, param_p3_level, param_p3_freq, param_p3_q, param_count }; - PLUGIN_NAME_ID_LABEL("equalizer5band", "equalizer5band", "Equalizer 5 Band") + // dummy parameter numbers, shouldn't be used EVER, they're only there to avoid pushing LP/HP filters to a separate class + // and potentially making inlining and optimization harder for the compiler + enum { param_lp_active = 0xDEADBEEF, param_hp_active, param_hp_mode, param_lp_mode, param_hp_freq, param_lp_freq }; + enum { PeakBands = 3, first_graph_param = param_ls_active, last_graph_param = param_p3_q }; + PLUGIN_NAME_ID_LABEL("equalizer5band", "eq5", "Equalizer 5 Band") }; /// Markus's 8-band EQ - metadata struct equalizer8band_metadata: public plugin_metadata { - enum { in_count = 2, out_count = 2, support_midi = false, require_midi = false, rt_capable = true }; + enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = false, require_midi = false, rt_capable = true }; enum { param_bypass, param_level_in, param_level_out, param_meter_inL, param_meter_inR, param_meter_outL, param_meter_outR, param_clip_inL, param_clip_inR, param_clip_outL, param_clip_outR, param_hp_active, param_hp_freq, param_hp_mode, @@ -209,12 +230,13 @@ struct equalizer8band_metadata: public plugin_metadata param_p3_active, param_p3_level, param_p3_freq, param_p3_q, param_p4_active, param_p4_level, param_p4_freq, param_p4_q, param_count }; - PLUGIN_NAME_ID_LABEL("equalizer8band", "equalizer8band", "Equalizer 8 Band") + enum { PeakBands = 4, first_graph_param = param_hp_active, last_graph_param = param_p4_q }; + PLUGIN_NAME_ID_LABEL("equalizer8band", "eq8", "Equalizer 8 Band") }; /// Markus's 12-band EQ - metadata struct equalizer12band_metadata: public plugin_metadata { - enum { in_count = 2, out_count = 2, support_midi = false, require_midi = false, rt_capable = true }; + enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = false, require_midi = false, rt_capable = true }; enum { param_bypass, param_level_in, param_level_out, param_meter_inL, param_meter_inR, param_meter_outL, param_meter_outR, param_clip_inL, param_clip_inR, param_clip_outL, param_clip_outR, param_hp_active, param_hp_freq, param_hp_mode, @@ -230,7 +252,56 @@ struct equalizer12band_metadata: public plugin_metadata +{ + enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = false, require_midi = false, rt_capable = true }; + enum { param_bypass, param_level_in, param_level_out, param_meter_inL, param_meter_inR, + param_meter_outL, param_meter_outR, param_clip_inL, param_clip_inR, param_clip_outL, param_clip_outR, + param_mode, param_freq, param_amount, param_offset, param_mono, param_reset, param_count }; + PLUGIN_NAME_ID_LABEL("pulsator", "pulsator", "Pulsator") +}; + +/// Markus's Saturator - metadata +struct saturator_metadata: public plugin_metadata +{ + enum { in_count = 2, out_count = 2, ins_optional = 1, outs_optional = 1, support_midi = false, require_midi = false, rt_capable = true }; + enum { param_bypass, param_level_in, param_level_out, param_mix, param_meter_in, + param_meter_out, param_clip_in, param_clip_out, param_drive, param_blend, param_meter_drive, + param_lp_pre_freq, param_hp_pre_freq, param_lp_post_freq, param_hp_post_freq, + param_p_freq, param_p_level, param_p_q, param_count }; + PLUGIN_NAME_ID_LABEL("saturator", "saturator", "Saturator") +}; +/// Markus's Exciter - metadata +struct exciter_metadata: public plugin_metadata +{ + enum { in_count = 2, out_count = 2, ins_optional = 1, outs_optional = 1, support_midi = false, require_midi = false, rt_capable = true }; + enum { param_bypass, param_level_in, param_level_out, param_amount, param_meter_in, + param_meter_out, param_clip_in, param_clip_out, param_drive, param_blend, param_meter_drive, + param_freq, param_listen, param_count }; + PLUGIN_NAME_ID_LABEL("exciter", "exciter", "Exciter") +}; +/// Markus's Bass Enhancer - metadata +struct bassenhancer_metadata: public plugin_metadata +{ + enum { in_count = 2, out_count = 2, ins_optional = 1, outs_optional = 1, support_midi = false, require_midi = false, rt_capable = true }; + enum { param_bypass, param_level_in, param_level_out, param_amount, param_meter_in, + param_meter_out, param_clip_in, param_clip_out, param_drive, param_blend, param_meter_drive, + param_freq, param_listen, param_count }; + PLUGIN_NAME_ID_LABEL("bassenhancer", "bassenhancer", "Bass Enhancer") +}; + +/// Damien's gate - metadata +struct gate_metadata: public plugin_metadata +{ + enum { in_count = 3, out_count = 2, ins_optional = 1, outs_optional = 0, support_midi = false, require_midi = false, rt_capable = true }; + enum { param_threshold, param_ratio, param_attack, param_release, param_makeup, param_knee, param_detection, param_stereo_link, param_aweighting, param_gating, param_peak, param_clip, param_bypass, param_range, param_mono, param_trigger, // param_freq, param_bw, + param_count }; + PLUGIN_NAME_ID_LABEL("gate", "gate", "Gate") }; /// Organ - enums for parameter IDs etc. (this mess is caused by organ split between plugin and generic class - which was @@ -319,19 +390,17 @@ struct organ_enums /// Organ - metadata struct organ_metadata: public organ_enums, public plugin_metadata { - enum { in_count = 0, out_count = 2, support_midi = true, require_midi = true, rt_capable = true }; + enum { in_count = 0, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = true, require_midi = true, rt_capable = true }; PLUGIN_NAME_ID_LABEL("organ", "organ", "Organ") plugin_command_info *get_commands(); - const char **get_default_configure_vars(); }; /// FluidSynth - metadata struct fluidsynth_metadata: public plugin_metadata { - enum { par_master, par_soundfont, par_interpolation, par_reverb, par_chorus, param_count }; - enum { in_count = 0, out_count = 2, support_midi = true, require_midi = true, rt_capable = false }; + enum { par_master, par_interpolation, par_reverb, par_chorus, par_soundfont, par_preset_key_set, param_count }; + enum { in_count = 0, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = true, require_midi = true, rt_capable = false }; PLUGIN_NAME_ID_LABEL("fluidsynth", "fluidsynth", "Fluidsynth") - const char **get_default_configure_vars(); }; /// Wavetable - metadata @@ -399,7 +468,7 @@ struct wavetable_metadata: public plugin_metadata par_eg3attack, par_eg3decay, par_eg3sustain, par_eg3fade, par_eg3release, par_eg3velscl, par_pwhlrange, param_count }; - enum { in_count = 0, out_count = 2, support_midi = true, require_midi = true, rt_capable = true }; + enum { in_count = 0, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = true, require_midi = true, rt_capable = true }; enum { step_size = 64 }; PLUGIN_NAME_ID_LABEL("wavetable", "wavetable", "Wavetable") }; diff --git a/plugins/ladspa_effect/calf/calf/modmatrix.h b/plugins/ladspa_effect/calf/src/calf/modmatrix.h similarity index 96% rename from plugins/ladspa_effect/calf/calf/modmatrix.h rename to plugins/ladspa_effect/calf/src/calf/modmatrix.h index e43e09f7a..5db95fc92 100644 --- a/plugins/ladspa_effect/calf/calf/modmatrix.h +++ b/plugins/ladspa_effect/calf/src/calf/modmatrix.h @@ -84,10 +84,10 @@ protected: mod_matrix(dsp::modulation_entry *_matrix, unsigned int _rows, const char **_src_names, const char **_dest_names); public: - virtual const table_column_info *get_table_columns(int param); - virtual uint32_t get_table_rows(int param); - virtual std::string get_cell(int param, int row, int column); - virtual void set_cell(int param, int row, int column, const std::string &src, std::string &error); + virtual const table_column_info *get_table_columns(int param) const; + virtual uint32_t get_table_rows(int param) const; + virtual std::string get_cell(int param, int row, int column) const; + virtual void set_cell(int param, int row, int column, const std::string &src, std::string &error) const; /// Process modulation matrix, calculate outputs from inputs inline void calculate_modmatrix(float *moddest, int moddest_count, float *modsrc) diff --git a/plugins/ladspa_effect/calf/src/calf/modulelist.h b/plugins/ladspa_effect/calf/src/calf/modulelist.h new file mode 100644 index 000000000..baaa5d90f --- /dev/null +++ b/plugins/ladspa_effect/calf/src/calf/modulelist.h @@ -0,0 +1,29 @@ +#ifdef PER_MODULE_ITEM + PER_MODULE_ITEM(filter, false, "filter") + PER_MODULE_ITEM(filterclavier, false, "filterclavier") + PER_MODULE_ITEM(flanger, false, "flanger") + PER_MODULE_ITEM(reverb, false, "reverb") + PER_MODULE_ITEM(monosynth, true, "monosynth") + PER_MODULE_ITEM(vintage_delay, false, "vintagedelay") + PER_MODULE_ITEM(organ, true, "organ") + PER_MODULE_ITEM(rotary_speaker, false, "rotaryspeaker") + PER_MODULE_ITEM(phaser, false, "phaser") + PER_MODULE_ITEM(multichorus, false, "multichorus") + PER_MODULE_ITEM(compressor, false, "compressor") + PER_MODULE_ITEM(sidechaincompressor, false, "sidechaincompressor") + PER_MODULE_ITEM(multibandcompressor, false, "multibandcompressor") + PER_MODULE_ITEM(deesser, false, "deesser") + PER_MODULE_ITEM(pulsator, false, "pulsator") + PER_MODULE_ITEM(equalizer5band, false, "eq5") + PER_MODULE_ITEM(equalizer8band, false, "eq8") + PER_MODULE_ITEM(equalizer12band, false, "eq12") + PER_MODULE_ITEM(saturator, false, "saturator") + PER_MODULE_ITEM(exciter, false, "exciter") + PER_MODULE_ITEM(bassenhancer, false, "bassenhancer") + PER_MODULE_ITEM(gate, false, "gate") +#ifdef ENABLE_EXPERIMENTAL + PER_MODULE_ITEM(fluidsynth, true, "fluidsynth") + PER_MODULE_ITEM(wavetable, true, "wavetable") +#endif +#undef PER_MODULE_ITEM +#endif diff --git a/plugins/ladspa_effect/calf/src/calf/modules.h b/plugins/ladspa_effect/calf/src/calf/modules.h new file mode 100644 index 000000000..d20421879 --- /dev/null +++ b/plugins/ladspa_effect/calf/src/calf/modules.h @@ -0,0 +1,245 @@ +/* Calf DSP plugin pack + * Assorted plugins + * + * Copyright (C) 2001-2010 Krzysztof Foltman, Markus Schmidt, Thor Harald Johansen and others + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02111-1307, USA. + */ +#ifndef CALF_MODULES_H +#define CALF_MODULES_H + +#include +#include +#include "biquad.h" +#include "inertia.h" +#include "audio_fx.h" +#include "giface.h" +#include "metadata.h" +#include "loudness.h" +#include "primitives.h" + +namespace calf_plugins { + +struct ladspa_plugin_info; + +class reverb_audio_module: public audio_module +{ +public: + dsp::reverb reverb; + dsp::simple_delay<16384, dsp::stereo_sample > pre_delay; + dsp::onepole left_lo, right_lo, left_hi, right_hi; + uint32_t srate; + dsp::gain_smoothing amount, dryamount; + int predelay_amt; + float meter_wet, meter_out; + uint32_t clip; + + void params_changed(); + uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask); + void activate(); + void set_sample_rate(uint32_t sr); + void deactivate(); +}; + +class vintage_delay_audio_module: public audio_module +{ +public: + // 1MB of delay memory per channel... uh, RAM is cheap + enum { MAX_DELAY = 262144, ADDR_MASK = MAX_DELAY - 1 }; + enum { MIXMODE_STEREO, MIXMODE_PINGPONG, MIXMODE_LR, MIXMODE_RL }; + float buffers[2][MAX_DELAY]; + int bufptr, deltime_l, deltime_r, mixmode, medium, old_medium; + /// number of table entries written (value is only important when it is less than MAX_DELAY, which means that the buffer hasn't been totally filled yet) + int age; + + dsp::gain_smoothing amt_left, amt_right, fb_left, fb_right, dry, chmix; + + dsp::biquad_d2 biquad_left[2], biquad_right[2]; + + uint32_t srate; + + vintage_delay_audio_module(); + + void params_changed(); + void activate(); + void deactivate(); + void set_sample_rate(uint32_t sr); + void calc_filters(); + uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask); +}; + +template +class filter_module_with_inertia: public audio_module, public FilterClass +{ +public: + /// These are pointers to the ins, outs, params arrays in the main class + typedef filter_module_with_inertia inertia_filter_module; + using audio_module::ins; + using audio_module::outs; + using audio_module::params; + + dsp::inertia inertia_cutoff, inertia_resonance, inertia_gain; + dsp::once_per_n timer; + bool is_active; + mutable volatile int last_generation, last_calculated_generation; + + filter_module_with_inertia(float **ins, float **outs, float **params) + : inertia_cutoff(dsp::exponential_ramp(128), 20) + , inertia_resonance(dsp::exponential_ramp(128), 20) + , inertia_gain(dsp::exponential_ramp(128), 1.0) + , timer(128) + { + is_active = false; + } + + void calculate_filter() + { + float freq = inertia_cutoff.get_last(); + // printf("freq=%g inr.cnt=%d timer.left=%d\n", freq, inertia_cutoff.count, timer.left); + // XXXKF this is resonance of a single stage, obviously for three stages, resonant gain will be different + float q = inertia_resonance.get_last(); + int mode = dsp::fastf2i_drm(*params[Metadata::par_mode]); + // printf("freq = %f q = %f mode = %d\n", freq, q, mode); + + int inertia = dsp::fastf2i_drm(*params[Metadata::par_inertia]); + if (inertia != inertia_cutoff.ramp.length()) { + inertia_cutoff.ramp.set_length(inertia); + inertia_resonance.ramp.set_length(inertia); + inertia_gain.ramp.set_length(inertia); + } + + FilterClass::calculate_filter(freq, q, mode, inertia_gain.get_last()); + } + + virtual void params_changed() + { + calculate_filter(); + } + + void on_timer() + { + int gen = last_generation; + inertia_cutoff.step(); + inertia_resonance.step(); + inertia_gain.step(); + calculate_filter(); + last_calculated_generation = gen; + } + + void activate() + { + params_changed(); + FilterClass::filter_activate(); + timer = dsp::once_per_n(FilterClass::srate / 1000); + timer.start(); + is_active = true; + } + + void set_sample_rate(uint32_t sr) + { + FilterClass::srate = sr; + } + + + void deactivate() + { + is_active = false; + } + + uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) { +// printf("sr=%d cutoff=%f res=%f mode=%f\n", FilterClass::srate, *params[Metadata::par_cutoff], *params[Metadata::par_resonance], *params[Metadata::par_mode]); + uint32_t ostate = 0; + numsamples += offset; + while(offset < numsamples) { + uint32_t numnow = numsamples - offset; + // if inertia's inactive, we can calculate the whole buffer at once + if (inertia_cutoff.active() || inertia_resonance.active() || inertia_gain.active()) + numnow = timer.get(numnow); + + if (outputs_mask & 1) { + ostate |= FilterClass::process_channel(0, ins[0] + offset, outs[0] + offset, numnow, inputs_mask & 1); + } + if (outputs_mask & 2) { + ostate |= FilterClass::process_channel(1, ins[1] + offset, outs[1] + offset, numnow, inputs_mask & 2); + } + + if (timer.elapsed()) { + on_timer(); + } + offset += numnow; + } + return ostate; + } +}; + +/// biquad filter module +class filter_audio_module: + public filter_module_with_inertia, + public frequency_response_line_graph +{ + mutable float old_cutoff, old_resonance, old_mode; +public: + filter_audio_module() + : filter_module_with_inertia(ins, outs, params) + { + last_generation = 0; + } + void params_changed() + { + inertia_cutoff.set_inertia(*params[par_cutoff]); + inertia_resonance.set_inertia(*params[par_resonance]); + inertia_filter_module::params_changed(); + } + + bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const; + int get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) const; +}; + +/// Filterclavier --- MIDI controlled filter by Hans Baier +class filterclavier_audio_module: + public filter_module_with_inertia, + public frequency_response_line_graph +{ + using audio_module::ins; + using audio_module::outs; + using audio_module::params; + + const float min_gain; + const float max_gain; + + int last_note; + int last_velocity; + +public: + filterclavier_audio_module(); + void params_changed(); + void activate(); + void set_sample_rate(uint32_t sr); + void deactivate(); + + /// MIDI control + virtual void note_on(int note, int vel); + virtual void note_off(int note, int vel); + + bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const; + +private: + void adjust_gain_according_to_filter_mode(int velocity); +}; + +}; + +#endif diff --git a/plugins/ladspa_effect/calf/src/calf/modules_comp.h b/plugins/ladspa_effect/calf/src/calf/modules_comp.h new file mode 100644 index 000000000..1c85820ec --- /dev/null +++ b/plugins/ladspa_effect/calf/src/calf/modules_comp.h @@ -0,0 +1,249 @@ +/* Calf DSP plugin pack + * Compression related plugins + * + * Copyright (C) 2001-2010 Krzysztof Foltman, Markus Schmidt, Thor Harald Johansen and others + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02111-1307, USA. + */ +#ifndef CALF_MODULES_COMP_H +#define CALF_MODULES_COMP_H + +#include +#include +#include "biquad.h" +#include "inertia.h" +#include "audio_fx.h" +#include "giface.h" +#include "loudness.h" +#include "metadata.h" + +namespace calf_plugins { + +/// Not a true _audio_module style class, just pretends to be one! +class gain_reduction_audio_module +{ +private: + float linSlope, detected, kneeSqrt, kneeStart, linKneeStart, kneeStop; + float compressedKneeStop, adjKneeStart, thres; + float attack, release, threshold, ratio, knee, makeup, detection, stereo_link, bypass, mute, meter_out, meter_comp; + mutable float old_threshold, old_ratio, old_knee, old_makeup, old_bypass, old_mute, old_detection, old_stereo_link; + mutable volatile int last_generation; + uint32_t srate; + bool is_active; + inline float output_level(float slope) const; + inline float output_gain(float linSlope, bool rms) const; +public: + gain_reduction_audio_module(); + void set_params(float att, float rel, float thr, float rat, float kn, float mak, float det, float stl, float byp, float mu); + void update_curve(); + void process(float &left, float &right, const float *det_left = NULL, const float *det_right = NULL); + void activate(); + void deactivate(); + int id; + void set_sample_rate(uint32_t sr); + float get_output_level(); + float get_comp_level(); + bool get_graph(int subindex, float *data, int points, cairo_iface *context) const; + bool get_dot(int subindex, float &x, float &y, int &size, cairo_iface *context) const; + bool get_gridline(int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const; + int get_changed_offsets(int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) const; +}; + +/// Compressor by Thor +class compressor_audio_module: public audio_module, public line_graph_iface { +private: + typedef compressor_audio_module AM; + uint32_t clip_in, clip_out; + float meter_in, meter_out; + gain_reduction_audio_module compressor; +public: + typedef std::complex cfloat; + uint32_t srate; + bool is_active; + mutable volatile int last_generation, last_calculated_generation; + compressor_audio_module(); + void activate(); + void deactivate(); + void params_changed(); + void set_sample_rate(uint32_t sr); + uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask); + bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const; + bool get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context) const; + bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const; + int get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) const; +}; + +/// Sidecain Compressor by Markus Schmidt (based on Thor's compressor and Krzysztof's filters) +class sidechaincompressor_audio_module: public audio_module, public frequency_response_line_graph { +private: + typedef sidechaincompressor_audio_module AM; + enum CalfScModes { + WIDEBAND, + DEESSER_WIDE, + DEESSER_SPLIT, + DERUMBLER_WIDE, + DERUMBLER_SPLIT, + WEIGHTED_1, + WEIGHTED_2, + WEIGHTED_3, + BANDPASS_1, + BANDPASS_2 + }; + mutable float f1_freq_old, f2_freq_old, f1_level_old, f2_level_old; + mutable float f1_freq_old1, f2_freq_old1, f1_level_old1, f2_level_old1; + CalfScModes sc_mode; + mutable CalfScModes sc_mode_old, sc_mode_old1; + float f1_active, f2_active; + uint32_t clip_in, clip_out; + float meter_in, meter_out; + gain_reduction_audio_module compressor; + dsp::biquad_d2 f1L, f1R, f2L, f2R; +public: + typedef std::complex cfloat; + uint32_t srate; + bool is_active; + mutable volatile int last_generation, last_calculated_generation; + sidechaincompressor_audio_module(); + void activate(); + void deactivate(); + void params_changed(); + cfloat h_z(const cfloat &z) const; + float freq_gain(int index, double freq, uint32_t sr) const; + void set_sample_rate(uint32_t sr); + uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask); + bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const; + bool get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context) const; + bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const; + int get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) const; +}; + +/// Multibandcompressor by Markus Schmidt +class multibandcompressor_audio_module: public audio_module, public line_graph_iface { +private: + typedef multibandcompressor_audio_module AM; + static const int strips = 4; + bool mute[strips]; + uint32_t clip_inL, clip_inR, clip_outL, clip_outR; + float meter_inL, meter_inR, meter_outL, meter_outR; + gain_reduction_audio_module strip[strips]; + dsp::biquad_d2 lpL0, lpR0, lpL1, lpR1, lpL2, lpR2, hpL0, hpR0, hpL1, hpR1, hpL2, hpR2; + float freq_old[strips - 1], sep_old[strips - 1], q_old[strips - 1]; +public: + uint32_t srate; + bool is_active; + multibandcompressor_audio_module(); + void activate(); + void deactivate(); + void params_changed(); + uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask); + void set_sample_rate(uint32_t sr); + const gain_reduction_audio_module *get_strip_by_param_index(int index) const; + virtual bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const; + virtual bool get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context) const; + virtual bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const; + virtual int get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) const; +}; + +/// Deesser by Markus Schmidt (based on Thor's compressor and Krzysztof's filters) +class deesser_audio_module: public audio_module, public frequency_response_line_graph { +private: + enum CalfDeessModes { + WIDE, + SPLIT + }; + mutable float f1_freq_old, f2_freq_old, f1_level_old, f2_level_old, f2_q_old; + mutable float f1_freq_old1, f2_freq_old1, f1_level_old1, f2_level_old1, f2_q_old1; + uint32_t detected_led; + float detected, clip_out; + uint32_t clip_led; + gain_reduction_audio_module compressor; + dsp::biquad_d2 hpL, hpR, lpL, lpR, pL, pR; +public: + uint32_t srate; + bool is_active; + mutable volatile int last_generation, last_calculated_generation; + deesser_audio_module(); + void activate(); + void deactivate(); + void params_changed(); + float freq_gain(int index, double freq, uint32_t sr) const + { + return hpL.freq_gain(freq, sr) * pL.freq_gain(freq, sr); + } + void set_sample_rate(uint32_t sr); + uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask); + bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const; + bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const; + int get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) const; +}; + + +class gate_audio_module: public audio_module, public line_graph_iface { +private: + float linSlope, peak, detected, kneeSqrt, kneeStart, linKneeStart, kneeStop, linKneeStop, threshold, ratio, knee, makeup, compressedKneeStop, adjKneeStart, range; + mutable float old_threshold, old_ratio, old_knee, old_makeup, old_bypass, old_range, old_trigger, old_mono; + mutable volatile int last_generation; + uint32_t clip; + dsp::aweighter awL, awR; + dsp::biquad_d2 bpL, bpR; +public: + uint32_t srate; + bool is_active; + gate_audio_module(); + void activate(); + void deactivate(); + uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask); + + inline float output_level(float slope) const { + bool rms = *params[param_detection] == 0; + return slope * output_gain(rms ? slope*slope : slope, rms) * makeup; + } + + inline float output_gain(float linSlope, bool rms) const { + if(linSlope < linKneeStop) { + float slope = log(linSlope); + + //float tratio = rms ? sqrt(ratio) : ratio; + float tratio = ratio; + float gain = 0.f; + float delta = 0.f; + if(IS_FAKE_INFINITY(ratio)) + tratio = 1000.f; + gain = (slope-threshold) * tratio + threshold; + delta = tratio; + + if(knee > 1.f && slope > kneeStart ) { + gain = dsp::hermite_interpolation(slope, kneeStart, kneeStop, ((kneeStart - threshold) * tratio + threshold), kneeStop, delta,1.f); + } + return std::max(range, expf(gain-slope)); + } + + + return 1.f; + } + + void set_sample_rate(uint32_t sr); + + virtual bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const; + virtual bool get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context) const; + virtual bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const; + virtual int get_changed_offsets(int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) const; +}; + + +}; + +#endif diff --git a/plugins/ladspa_effect/calf/calf/modules_dev.h b/plugins/ladspa_effect/calf/src/calf/modules_dev.h similarity index 96% rename from plugins/ladspa_effect/calf/calf/modules_dev.h rename to plugins/ladspa_effect/calf/src/calf/modules_dev.h index 9861d1495..727e5ec73 100644 --- a/plugins/ladspa_effect/calf/calf/modules_dev.h +++ b/plugins/ladspa_effect/calf/src/calf/modules_dev.h @@ -22,7 +22,6 @@ #define __CALF_MODULES_DEV_H #include -#include #if ENABLE_EXPERIMENTAL #include @@ -35,11 +34,6 @@ namespace calf_plugins { /// Tiny wrapper for fluidsynth class fluidsynth_audio_module: public audio_module { -public: - float *ins[in_count]; - float *outs[out_count]; - float *params[param_count]; - protected: /// Current sample rate uint32_t srate; diff --git a/plugins/ladspa_effect/calf/src/calf/modules_dist.h b/plugins/ladspa_effect/calf/src/calf/modules_dist.h new file mode 100644 index 000000000..6c49c372d --- /dev/null +++ b/plugins/ladspa_effect/calf/src/calf/modules_dist.h @@ -0,0 +1,96 @@ +/* Calf DSP plugin pack + * Distortion related plugins + * + * Copyright (C) 2001-2010 Krzysztof Foltman, Markus Schmidt, Thor Harald Johansen and others + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02111-1307, USA. + */ +#ifndef CALF_MODULES_DIST_H +#define CALF_MODULES_DIST_H + +#include +#include +#include "biquad.h" +#include "inertia.h" +#include "audio_fx.h" +#include "giface.h" +#include "metadata.h" + +namespace calf_plugins { + +/// Saturator by Markus Schmidt (based on Krzysztof's filters and Tom's distortion algorythm) +class saturator_audio_module: public audio_module { +private: + float hp_pre_freq_old, lp_pre_freq_old; + float hp_post_freq_old, lp_post_freq_old; + float p_level_old, p_freq_old, p_q_old; + uint32_t clip_in, clip_out; + float meter_in, meter_out, meter_drive; + dsp::biquad_d2 lp[2][4], hp[2][4]; + dsp::biquad_d2 p[2]; + dsp::tap_distortion dist[2]; +public: + uint32_t srate; + bool is_active; + saturator_audio_module(); + void activate(); + void deactivate(); + void params_changed(); + void set_sample_rate(uint32_t sr); + uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask); +}; + +/// Exciter by Markus Schmidt (based on Krzysztof's filters and Tom's distortion algorythm) +class exciter_audio_module: public audio_module { +private: + float freq_old; + uint32_t clip_in, clip_out; + float meter_in, meter_out, meter_drive; + dsp::biquad_d2 hp[2][4]; + dsp::tap_distortion dist[2]; +public: + uint32_t srate; + bool is_active; + exciter_audio_module(); + void activate(); + void deactivate(); + void params_changed(); + void set_sample_rate(uint32_t sr); + uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask); +}; + +/// Bass Enhancer by Markus Schmidt (based on Krzysztof's filters and Tom's distortion algorythm) +class bassenhancer_audio_module: public audio_module { +private: + float freq_old; + uint32_t clip_in, clip_out; + float meter_in, meter_out, meter_drive; + dsp::biquad_d2 lp[2][4]; + dsp::tap_distortion dist[2]; +public: + uint32_t srate; + bool is_active; + bassenhancer_audio_module(); + void activate(); + void deactivate(); + void params_changed(); + void set_sample_rate(uint32_t sr); + uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask); +}; + +}; + +#endif diff --git a/plugins/ladspa_effect/calf/src/calf/modules_eq.h b/plugins/ladspa_effect/calf/src/calf/modules_eq.h new file mode 100644 index 000000000..14cad3ce8 --- /dev/null +++ b/plugins/ladspa_effect/calf/src/calf/modules_eq.h @@ -0,0 +1,89 @@ +/* Calf DSP plugin pack + * Equalization related plugins + * + * Copyright (C) 2001-2010 Krzysztof Foltman, Markus Schmidt, Thor Harald Johansen and others + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02111-1307, USA. + */ +#ifndef CALF_MODULES_EQ_H +#define CALF_MODULES_EQ_H + +#include +#include +#include "biquad.h" +#include "inertia.h" +#include "audio_fx.h" +#include "giface.h" +#include "metadata.h" + +namespace calf_plugins { + +/// Equalizer N Band by Markus Schmidt (based on Krzysztof's filters) +template +class equalizerNband_audio_module: public audio_module, public frequency_response_line_graph { +public: + typedef audio_module AM; + using AM::ins; + using AM::outs; + using AM::params; + using AM::in_count; + using AM::out_count; + using AM::param_count; + using AM::PeakBands; +private: + enum { graph_param_count = BaseClass::last_graph_param - BaseClass::first_graph_param + 1, params_per_band = AM::param_p2_active - AM::param_p1_active }; + float hp_mode_old, hp_freq_old; + float lp_mode_old, lp_freq_old; + float ls_level_old, ls_freq_old; + float hs_level_old, hs_freq_old; + float p_level_old[PeakBands], p_freq_old[PeakBands], p_q_old[PeakBands]; + mutable float old_params_for_graph[graph_param_count]; + uint32_t clip_inL, clip_outL, clip_inR, clip_outR; + float meter_inL, meter_outL, meter_inR, meter_outR; + CalfEqMode hp_mode, lp_mode; + dsp::biquad_d2 hp[3][2], lp[3][2]; + dsp::biquad_d2 lsL, lsR, hsL, hsR; + dsp::biquad_d2 pL[PeakBands], pR[PeakBands]; + + inline void process_hplp(float &left, float &right); +public: + typedef std::complex cfloat; + uint32_t srate; + bool is_active; + mutable volatile int last_generation, last_calculated_generation; + equalizerNband_audio_module(); + void activate(); + void deactivate(); + + void params_changed(); + float freq_gain(int index, double freq, uint32_t sr) const; + void set_sample_rate(uint32_t sr) + { + srate = sr; + } + uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask); + bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const; + bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const; + int get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) const; +}; + +typedef equalizerNband_audio_module equalizer5band_audio_module; +typedef equalizerNband_audio_module equalizer8band_audio_module; +typedef equalizerNband_audio_module equalizer12band_audio_module; + +}; + +#endif diff --git a/plugins/ladspa_effect/calf/src/calf/modules_mod.h b/plugins/ladspa_effect/calf/src/calf/modules_mod.h new file mode 100644 index 000000000..78244913b --- /dev/null +++ b/plugins/ladspa_effect/calf/src/calf/modules_mod.h @@ -0,0 +1,190 @@ +/* Calf DSP plugin pack + * Modulation effect plugins + * + * Copyright (C) 2001-2010 Krzysztof Foltman, Markus Schmidt, Thor Harald Johansen and others + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02111-1307, USA. + */ +#ifndef CALF_MODULES_MOD_H +#define CALF_MODULES_MOD_H + +#include +#include +#include "biquad.h" +#include "inertia.h" +#include "audio_fx.h" +#include "giface.h" +#include "metadata.h" +#include "multichorus.h" + +namespace calf_plugins { + +class flanger_audio_module: public audio_module, public frequency_response_line_graph +{ +public: + dsp::simple_flanger left, right; + uint32_t srate; + bool clear_reset; + float last_r_phase; + bool is_active; +public: + flanger_audio_module() { + is_active = false; + } + void set_sample_rate(uint32_t sr); + void params_changed(); + void params_reset(); + void activate(); + void deactivate(); + uint32_t process(uint32_t offset, uint32_t nsamples, uint32_t inputs_mask, uint32_t outputs_mask) { + left.process(outs[0] + offset, ins[0] + offset, nsamples); + right.process(outs[1] + offset, ins[1] + offset, nsamples); + return outputs_mask; // XXXKF allow some delay after input going blank + } + bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const; + float freq_gain(int subindex, float freq, float srate) const; +}; + +class phaser_audio_module: public audio_module, public frequency_response_line_graph +{ +public: + enum { MaxStages = 12 }; + uint32_t srate; + bool clear_reset; + float last_r_phase; + dsp::simple_phaser left, right; + float x1vals[2][MaxStages], y1vals[2][MaxStages]; + bool is_active; +public: + phaser_audio_module(); + void params_changed(); + void params_reset(); + void activate(); + void set_sample_rate(uint32_t sr); + void deactivate(); + uint32_t process(uint32_t offset, uint32_t nsamples, uint32_t inputs_mask, uint32_t outputs_mask) { + left.process(outs[0] + offset, ins[0] + offset, nsamples); + right.process(outs[1] + offset, ins[1] + offset, nsamples); + return outputs_mask; // XXXKF allow some delay after input going blank + } + bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const; + bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const; + float freq_gain(int subindex, float freq, float srate) const; +}; + +class rotary_speaker_audio_module: public audio_module +{ +public: + /// Current phases and phase deltas for bass and treble rotors + uint32_t phase_l, dphase_l, phase_h, dphase_h; + dsp::simple_delay<1024, float> delay; + dsp::biquad_d2 crossover1l, crossover1r, crossover2l, crossover2r; + dsp::simple_delay<8, float> phaseshift; + uint32_t srate; + int vibrato_mode; + /// Current CC1 (Modulation) value, normalized to [0, 1] + float mwhl_value; + /// Current CC64 (Hold) value, normalized to [0, 1] + float hold_value; + /// Current rotation speed for bass rotor - automatic mode + float aspeed_l; + /// Current rotation speed for treble rotor - automatic mode + float aspeed_h; + /// Desired speed (0=slow, 1=fast) - automatic mode + float dspeed; + /// Current rotation speed for bass rotor - manual mode + float maspeed_l; + /// Current rotation speed for treble rotor - manual mode + float maspeed_h; + + int meter_l, meter_h; + + rotary_speaker_audio_module(); + void set_sample_rate(uint32_t sr); + void setup(); + void activate(); + void deactivate(); + + void params_changed(); + void set_vibrato(); + /// Convert RPM speed to delta-phase + uint32_t rpm2dphase(float rpm); + /// Set delta-phase variables based on current calculated (and interpolated) RPM speed + void update_speed(); + void update_speed_manual(float delta); + /// Increase or decrease aspeed towards raspeed, with required negative and positive rate + bool incr_towards(float &aspeed, float raspeed, float delta_decc, float delta_acc); + uint32_t process(uint32_t offset, uint32_t nsamples, uint32_t inputs_mask, uint32_t outputs_mask); + virtual void control_change(int ctl, int val); +}; + +/// A multitap stereo chorus thing +class multichorus_audio_module: public audio_module, public frequency_response_line_graph +{ +public: + uint32_t srate; + dsp::multichorus, dsp::filter_sum, dsp::biquad_d2<> >, 4096> left, right; + float last_r_phase; + float cutoff; + bool is_active; + +public: + multichorus_audio_module(); + void params_changed(); + uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask); + void activate(); + void deactivate(); + void set_sample_rate(uint32_t sr); + bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const; + float freq_gain(int subindex, float freq, float srate) const; + bool get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context) const; + bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const; +}; + +/// Pulsator by Markus Schmidt +class pulsator_audio_module: public audio_module, public frequency_response_line_graph { +private: + typedef pulsator_audio_module AM; + uint32_t clip_inL, clip_inR, clip_outL, clip_outR; + float meter_inL, meter_inR, meter_outL, meter_outR; + float offset_old; + int mode_old; + bool clear_reset; + dsp::simple_lfo lfoL, lfoR; +public: + uint32_t srate; + bool is_active; + pulsator_audio_module(); + void activate(); + void deactivate(); + void params_changed(); + void set_sample_rate(uint32_t sr); + void params_reset() + { + if (clear_reset) { + *params[param_reset] = 0.f; + clear_reset = false; + } + } + uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask); + bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const; + bool get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context) const; + bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const; +}; + +}; + +#endif diff --git a/plugins/ladspa_effect/calf/calf/modules_synths.h b/plugins/ladspa_effect/calf/src/calf/modules_synths.h similarity index 61% rename from plugins/ladspa_effect/calf/calf/modules_synths.h rename to plugins/ladspa_effect/calf/src/calf/modules_synths.h index 090acbdca..8cd1c0ba4 100644 --- a/plugins/ladspa_effect/calf/calf/modules_synths.h +++ b/plugins/ladspa_effect/calf/src/calf/modules_synths.h @@ -21,7 +21,6 @@ #ifndef __CALF_MODULES_SYNTHS_H #define __CALF_MODULES_SYNTHS_H -#include #include "biquad.h" #include "onepole.h" #include "audio_fx.h" @@ -29,8 +28,8 @@ #include "osc.h" #include "synth.h" #include "envelope.h" -#include "organ.h" #include "modmatrix.h" +#include "metadata.h" namespace calf_plugins { @@ -42,21 +41,26 @@ class monosynth_audio_module: public audio_module, public li { public: enum { mod_matrix_slots = 10 }; - float *ins[in_count]; - float *outs[out_count]; - float *params[param_count]; uint32_t srate, crate; static dsp::waveform_family *waves; dsp::waveform_oscillator osc1, osc2; - dsp::triangle_lfo lfo; - bool running, stopping, gate, force_fadeout; + dsp::triangle_lfo lfo1, lfo2; + dsp::biquad_d1_lerp filter, filter2; + /// The step code is producing non-zero values + bool running; + /// This is the last non-zero buffer (set on calculate_step after fadeout is complete, the next calculate_step will zero running) + bool stopping; + /// A key is kept pressed + bool gate; + /// All notes off fadeout + bool force_fadeout; + /// Last triggered note int last_key; + /// Output buffers, used to ensure updates are done every step_size regardless of process buffer size float buffer[step_size], buffer2[step_size]; + /// Read position within the buffers, on each '0' the buffers are being filled with new data by calculate_step uint32_t output_pos; - dsp::onepole phaseshifter; - dsp::biquad_d1_lerp filter; - dsp::biquad_d1_lerp filter2; /// Waveform number - OSC1 int wave1; /// Waveform number - OSC2 @@ -65,19 +69,40 @@ public: int prev_wave1; /// Last used waveform number - OSC2 int prev_wave2; - int filter_type, last_filter_type; - float freq, start_freq, target_freq, cutoff, decay_factor, fgain, fgain_delta, separation; - float detune, xpose, xfade, ampctl, fltctl, queue_vel; - float odcr, porta_time, lfo_bend, lfo_clock, last_lfov, modwheel_value; + /// Filter type + int filter_type; + /// Filter type on the last calculate_step + int last_filter_type; + float freq, start_freq, target_freq, cutoff, fgain, fgain_delta, separation; + float detune, xpose, xfade, ampctl, fltctl; + float odcr, porta_time, lfo_bend; + /// Modulation wheel position (0.f-1.f) + float modwheel_value; + /// Delay counter for LFOs + float lfo_clock; /// Last value of phase shift for pulse width emulation for OSC1 int32_t last_pwshift1; /// Last value of phase shift for pulse width emulation for OSC2 int32_t last_pwshift2; - int queue_note_on, stop_count, modwheel_value_int; + /// Last value of stretch for osc sync emulation for OSC1 + int32_t last_stretch1; + /// Next note to play on the next calculate_step + int queue_note_on; + /// Velocity of the next note to play + float queue_vel; + /// Integer value for modwheel (0-16383, read from CC1 - MSBs and CC33 - LSBs) + int modwheel_value_int; + /// Legato mode (bitmask) int legato; - dsp::adsr envelope; + /// Envelope Generators + dsp::adsr envelope1, envelope2; dsp::keystack stack; + /// Smoothing for master volume dsp::gain_smoothing master; + /// Fadeout for buffer 1 + dsp::fadeout fadeout; + /// Fadeout for buffer 2 + dsp::fadeout fadeout2; /// Smoothed cutoff value dsp::inertia inertia_cutoff; /// Smoothed pitch bend value @@ -132,7 +157,7 @@ public: /// Run two filters (one per channel) to produce stereo output samples. void calculate_buffer_stereo(); /// Retrieve filter graph (which is 'live' so it cannot be generated by get_static_graph), or fall back to get_static_graph. - bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context); + bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const; /// @retval true if the filter 1 is to be used for the left channel and filter 2 for the right channel /// @retval false if filters are to be connected in series and sent (mono) to both channels inline bool is_stereo_filter() const @@ -140,91 +165,17 @@ public: return filter_type == flt_2lp12 || filter_type == flt_2bp6; } /// No CV inputs for now - bool is_cv(int param_no) { return false; } + bool is_cv(int param_no) const { return false; } /// Practically all the stuff here is noisy - bool is_noisy(int param_no) { return param_no != par_cutoff; } + bool is_noisy(int param_no) const { return param_no != par_cutoff; } /// Calculate control signals and produce step_size samples of output. void calculate_step(); + /// Apply anti-click'n'pop fadeout (used at the end of the sound) + void apply_fadeout(); /// Main processing function uint32_t process(uint32_t offset, uint32_t nsamples, uint32_t inputs_mask, uint32_t outputs_mask); }; -struct organ_audio_module: public audio_module, public dsp::drawbar_organ, public line_graph_iface -{ -public: - using drawbar_organ::note_on; - using drawbar_organ::note_off; - using drawbar_organ::control_change; - enum { param_count = drawbar_organ::param_count}; - float *ins[in_count]; - float *outs[out_count]; - float *params[param_count]; - dsp::organ_parameters par_values; - uint32_t srate; - bool panic_flag; - /// Value for configure variable map_curve - std::string var_map_curve; - - organ_audio_module() - : drawbar_organ(&par_values) - { - var_map_curve = "2\n0 1\n1 1\n"; // XXXKF hacky bugfix - } - - void post_instantiate() - { - dsp::organ_voice_base::precalculate_waves(progress_report); - } - - void set_sample_rate(uint32_t sr) { - srate = sr; - } - void params_changed() { - for (int i = 0; i < param_count - var_count; i++) - ((float *)&par_values)[i] = *params[i]; - - unsigned int old_poly = polyphony_limit; - polyphony_limit = dsp::clip(dsp::fastf2i_drm(*params[par_polyphony]), 1, 32); - if (polyphony_limit < old_poly) - trim_voices(); - - update_params(); - } - inline void pitch_bend(int amt) - { - drawbar_organ::pitch_bend(amt); - } - void activate() { - setup(srate); - panic_flag = false; - } - void deactivate(); - uint32_t process(uint32_t offset, uint32_t nsamples, uint32_t inputs_mask, uint32_t outputs_mask) { - float *o[2] = { outs[0] + offset, outs[1] + offset }; - if (panic_flag) - { - control_change(120, 0); // stop all sounds - control_change(121, 0); // reset all controllers - panic_flag = false; - } - render_separate(o, nsamples); - return 3; - } - /// No CV inputs for now - bool is_cv(int param_no) { return false; } - /// Practically all the stuff here is noisy - bool is_noisy(int param_no) { return true; } - void execute(int cmd_no); - bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context); - - char *configure(const char *key, const char *value); - void send_configures(send_configure_iface *); - uint32_t message_run(const void *valid_inputs, void *output_ports) { - // silence a default printf (which is kind of a warning about unhandled message_run) - return 0; - } -}; - }; #if ENABLE_EXPERIMENTAL diff --git a/plugins/ladspa_effect/calf/calf/multichorus.h b/plugins/ladspa_effect/calf/src/calf/multichorus.h similarity index 98% rename from plugins/ladspa_effect/calf/calf/multichorus.h rename to plugins/ladspa_effect/calf/src/calf/multichorus.h index 23a1f4fde..b954603ab 100644 --- a/plugins/ladspa_effect/calf/calf/multichorus.h +++ b/plugins/ladspa_effect/calf/src/calf/multichorus.h @@ -80,7 +80,7 @@ public: voice_depth = (unsigned int)((1U << 30) * 1.0 * scaling); } /// Get LFO value for given voice, returns a values in range of [-65536, 65535] (or close) - inline int get_value(uint32_t voice) { + inline int get_value(uint32_t voice) const { // find this voice's phase (= phase + voice * 360 degrees / number of voices) chorus_phase voice_phase = phase + vphase * (int)voice; // find table offset @@ -178,7 +178,7 @@ public: } post.sanitize(); } - float freq_gain(float freq, float sr) + float freq_gain(float freq, float sr) const { typedef std::complex cfloat; freq *= 2.0 * M_PI / sr; diff --git a/plugins/ladspa_effect/calf/calf/onepole.h b/plugins/ladspa_effect/calf/src/calf/onepole.h similarity index 97% rename from plugins/ladspa_effect/calf/calf/onepole.h rename to plugins/ladspa_effect/calf/src/calf/onepole.h index 2bc23257b..5fdc66942 100644 --- a/plugins/ladspa_effect/calf/calf/onepole.h +++ b/plugins/ladspa_effect/calf/src/calf/onepole.h @@ -144,7 +144,7 @@ public: return out; } - inline bool empty() { + inline bool empty() const { return y1 == 0; } @@ -171,7 +171,7 @@ public: /// Return the filter's gain at frequency freq /// @param freq Frequency to look up /// @param sr Filter sample rate (used to convert frequency to angular frequency) - float freq_gain(float freq, float sr) + float freq_gain(float freq, float sr) const { freq *= 2.0 * M_PI / sr; cfloat z = 1.0 / exp(cfloat(0.0, freq)); @@ -181,7 +181,7 @@ public: /// Return H(z) the filter's gain at frequency freq /// @param z Z variable (e^jw) - cfloat h_z(const cfloat &z) + cfloat h_z(const cfloat &z) const { return (cfloat(a0) + double(a1) * z) / (cfloat(1.0) + double(b1) * z); } diff --git a/plugins/ladspa_effect/calf/calf/organ.h b/plugins/ladspa_effect/calf/src/calf/organ.h similarity index 72% rename from plugins/ladspa_effect/calf/calf/organ.h rename to plugins/ladspa_effect/calf/src/calf/organ.h index 8a9b31666..efb39137b 100644 --- a/plugins/ladspa_effect/calf/calf/organ.h +++ b/plugins/ladspa_effect/calf/src/calf/organ.h @@ -22,9 +22,11 @@ #ifndef __CALF_ORGAN_H #define __CALF_ORGAN_H -#include "synth.h" +#include "audio_fx.h" #include "envelope.h" #include "metadata.h" +#include "osc.h" +#include "synth.h" #define ORGAN_KEYTRACK_POINTS 4 @@ -133,7 +135,6 @@ protected: static small_wave_family (*waves)[wave_count_small]; static big_wave_family (*big_waves)[wave_count_big]; - // dsp::sine_table sine_wave; int note; dsp::decay amp; /// percussion FM carrier amplitude envelope @@ -165,24 +166,12 @@ public: return (*big_waves)[wave]; } static void precalculate_waves(calf_plugins::progress_report_iface *reporter); - void update_pitch() - { - float phase = dsp::midi_note_to_phase(note, 100 * parameters->global_transpose + parameters->global_detune, sample_rate_ref); - dpphase.set((long int) (phase * parameters->percussion_harmonic * parameters->pitch_bend)); - moddphase.set((long int) (phase * parameters->percussion_fm_harmonic * parameters->pitch_bend)); - } + void update_pitch(); // this doesn't really have a voice interface void render_percussion_to(float (*buf)[2], int nsamples); void perc_note_on(int note, int vel); void perc_note_off(int note, int vel); - void perc_reset() - { - pphase = 0; - modphase = 0; - dpphase = 0; - moddphase = 0; - note = -1; - } + void perc_reset(); }; class organ_vibrato @@ -224,57 +213,11 @@ public: inertia_pitchbend.set_now(1); } - void reset() { - inertia_pitchbend.ramp.set_length(sample_rate / (BlockSize * 30)); // 1/30s - vibrato.reset(); - phase = 0; - for (int i = 0; i < FilterCount; i++) - { - filterL[i].reset(); - filterR[i].reset(); - } - } - - void note_on(int note, int vel) { - stolen = false; - finishing = false; - perc_released = false; - released = false; - reset(); - this->note = note; - const float sf = 0.001f; - for (int i = 0; i < EnvCount; i++) - { - organ_parameters::organ_env_parameters &p = parameters->envs[i]; - envs[i].set(sf * p.attack, sf * p.decay, p.sustain, sf * p.release, sample_rate / BlockSize); - envs[i].note_on(); - } - update_pitch(); - velocity = vel * 1.0 / 127.0; - amp.set(1.0f); - perc_note_on(note, vel); - } - - void note_off(int /* vel */) { - // reset age to 0 (because decay will turn from exponential to linear, necessary because of error cumulation prevention) - perc_released = true; - if (pamp.get_active()) - { - pamp.reinit(); - } - rel_age_const = pamp.get() * ((1.0/44100.0)/0.03); - for (int i = 0; i < EnvCount; i++) - envs[i].note_off(); - } - + void reset(); + void note_on(int note, int vel); + void note_off(int /* vel */); virtual float get_priority() { return stolen ? 20000 : (perc_released ? 1 : (sostenuto ? 200 : 100)); } - - virtual void steal() { - perc_released = true; - finishing = true; - stolen = true; - } - + virtual void steal(); void render_block(); virtual int get_current_note() { @@ -325,48 +268,63 @@ struct drawbar_organ: public dsp::basic_synth, public calf_plugins::organ_enums , percussion(_parameters) { } void render_separate(float *output[], int nsamples); - dsp::voice *alloc_voice() { - block_voice *v = new block_voice(); - v->parameters = parameters; - return v; - } - virtual void percussion_note_on(int note, int vel) { - percussion.perc_note_on(note, vel); - } + dsp::voice *alloc_voice(); + virtual void percussion_note_on(int note, int vel); virtual void params_changed() = 0; - virtual void setup(int sr) { - basic_synth::setup(sr); - percussion.setup(sr); - parameters->cutoff = 0; - params_changed(); - global_vibrato.reset(); - } + virtual void setup(int sr); void update_params(); void control_change(int controller, int value) { -#if 0 - if (controller == 11) - { - parameters->cutoff = value / 64.0 - 1; - } -#endif dsp::basic_synth::control_change(controller, value); } void pitch_bend(int amt); - virtual bool check_percussion() { - switch(dsp::fastf2i_drm(parameters->percussion_trigger)) - { - case organ_voice_base::perctrig_first: - return active_voices.empty(); - case organ_voice_base::perctrig_each: - default: - return true; - case organ_voice_base::perctrig_eachplus: - return !percussion.get_noticable(); - case organ_voice_base::perctrig_polyphonic: - return false; - } + virtual bool check_percussion(); +}; + +}; + +namespace calf_plugins { + +struct organ_audio_module: public audio_module, public dsp::drawbar_organ, public line_graph_iface +{ +public: + using drawbar_organ::note_on; + using drawbar_organ::note_off; + using drawbar_organ::control_change; + enum { param_count = drawbar_organ::param_count}; + dsp::organ_parameters par_values; + uint32_t srate; + bool panic_flag; + /// Value for configure variable map_curve + std::string var_map_curve; + + organ_audio_module(); + + void post_instantiate(); + + void set_sample_rate(uint32_t sr) { + srate = sr; } + void params_changed(); + + void activate(); + void deactivate(); + uint32_t process(uint32_t offset, uint32_t nsamples, uint32_t inputs_mask, uint32_t outputs_mask); + /// No CV inputs for now + bool is_cv(int param_no) { return false; } + /// Practically all the stuff here is noisy + bool is_noisy(int param_no) { return true; } + void execute(int cmd_no); + bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const; + char *configure(const char *key, const char *value); + void send_configures(send_configure_iface *); + uint32_t message_run(const void *valid_inputs, void *output_ports); +public: + // overrides + virtual void note_on(int note, int velocity) { dsp::drawbar_organ::note_on(note, velocity); } + virtual void note_off(int note, int velocity) { dsp::drawbar_organ::note_off(note, velocity); } + virtual void control_change(int controller, int value) { dsp::drawbar_organ::control_change(controller, value); } + virtual void pitch_bend(int value) { dsp::drawbar_organ::pitch_bend(value); } }; }; diff --git a/plugins/ladspa_effect/calf/calf/osc.h b/plugins/ladspa_effect/calf/src/calf/osc.h similarity index 90% rename from plugins/ladspa_effect/calf/calf/osc.h rename to plugins/ladspa_effect/calf/src/calf/osc.h index ba01a2f38..779f1c009 100644 --- a/plugins/ladspa_effect/calf/calf/osc.h +++ b/plugins/ladspa_effect/calf/src/calf/osc.h @@ -19,8 +19,8 @@ * Boston, MA 02111-1307, USA. */ -#ifndef __CALF_OSC_H -#define __CALF_OSC_H +#ifndef CALF_OSC_H +#define CALF_OSC_H #include "fft.h" #include @@ -245,12 +245,12 @@ struct waveform_oscillator: public simple_oscillator { waveform = NULL; } + + /// Get the value from single oscillator at current position inline float get() { uint32_t wpos = phase >> (32 - SIZE_BITS); - float value = dsp::lerp(waveform[wpos], waveform[(wpos + 1) & MASK], (phase & (SCALE - 1)) * (1.0f / SCALE)); - phase += phasedelta; - return value; + return dsp::lerp(waveform[wpos], waveform[(wpos + 1) & MASK], (phase & (SCALE - 1)) * (1.0f / SCALE)); } /// Add/substract two phase-shifted values inline float get_phaseshifted(uint32_t shift, float mix) @@ -259,9 +259,23 @@ struct waveform_oscillator: public simple_oscillator float value1 = dsp::lerp(waveform[wpos], waveform[(wpos + 1) & MASK], (phase & (SCALE - 1)) * (1.0f / SCALE)); wpos = (phase + shift) >> (32 - SIZE_BITS); float value2 = dsp::lerp(waveform[wpos], waveform[(wpos + 1) & MASK], ((phase + shift) & (SCALE - 1)) * (1.0f / SCALE)); - float value = value1 + mix * value2; + return value1 + mix * value2; + } + /// Get the value of a hard synced osc (65536 = 1:1 ratio) + inline float get_phasedist(uint32_t sync, uint32_t shift, float mix) + { + uint32_t phase_mod = (uint64_t(phase) * sync >> 16); + + uint32_t wpos = phase_mod >> (32 - SIZE_BITS); + float value1 = dsp::lerp(waveform[wpos], waveform[(wpos + 1) & MASK], (phase & (SCALE - 1)) * (1.0f / SCALE)); + wpos = (phase_mod + shift) >> (32 - SIZE_BITS); + float value2 = dsp::lerp(waveform[wpos], waveform[(wpos + 1) & MASK], ((phase + shift) & (SCALE - 1)) * (1.0f / SCALE)); + return value1 + mix * value2; + } + /// One step + inline void advance() + { phase += phasedelta; - return value; } }; @@ -270,6 +284,18 @@ struct waveform_oscillator: public simple_oscillator */ struct triangle_lfo: public simple_oscillator { + /// Previous value (not stored here, but may be used by calling code) + float last; + + triangle_lfo() + { + reset(); + } + void reset() + { + simple_oscillator::reset(); + last = 0; + } inline float get() { uint32_t phase2 = phase; diff --git a/plugins/ladspa_effect/calf/calf/osctl.h b/plugins/ladspa_effect/calf/src/calf/osctl.h similarity index 89% rename from plugins/ladspa_effect/calf/calf/osctl.h rename to plugins/ladspa_effect/calf/src/calf/osctl.h index ff7a2fff2..2b500174f 100644 --- a/plugins/ladspa_effect/calf/calf/osctl.h +++ b/plugins/ladspa_effect/calf/src/calf/osctl.h @@ -293,6 +293,11 @@ template inline osc_stream & operator <<(osc_stream &s, uint32_t val) { +#if 0 + val = htonl(val); + s.write(&val, 4); + s.write_type(osc_i32); +#endif return s; } @@ -300,6 +305,10 @@ template inline osc_stream & operator >>(osc_stream &s, uint32_t &val) { +#if 0 + s.read(&val, 4); + val = htonl(val); +#endif return s; } @@ -307,6 +316,10 @@ template inline osc_stream & operator >>(osc_stream &s, int32_t &val) { +#if 0 + s.read(&val, 4); + val = htonl(val); +#endif return s; } @@ -314,6 +327,11 @@ template inline osc_stream & operator <<(osc_stream &s, float val) { + union { float v; uint32_t i; } val2; + val2.v = val; + val2.i = htonl(val2.i); + s.write(&val2.i, 4); + s.write_type(osc_f32); return s; } @@ -321,6 +339,10 @@ template inline osc_stream & operator >>(osc_stream &s, float &val) { + union { float v; uint32_t i; } val2; + s.read(&val2.i, 4); + val2.i = htonl(val2.i); + val = val2.v; return s; } @@ -358,6 +380,21 @@ template inline osc_stream & read_buffer_from_osc_stream(osc_stream &s, DestBuffer &buf) { +#if 0 + uint32_t nlen = 0; + s.read(&nlen, 4); + uint32_t len = htonl(nlen); + // write length in network order + for (uint32_t i = 0; i < len; i += 1024) + { + uint8_t tmp[1024]; + uint32_t part = std::min((uint32_t)1024, len - i); + s.read(tmp, part); + buf.write(tmp, part); + } + // pad + s.read(&nlen, 4 - (len & 3)); +#endif return s; } @@ -365,6 +402,21 @@ template inline osc_stream & write_buffer_to_osc_stream(osc_stream &s, SrcBuffer &buf) { +#if 0 + uint32_t len = buf.read_left(); + uint32_t nlen = ntohl(len); + s.write(&nlen, 4); + // write length in network order + for (uint32_t i = 0; i < len; i += 1024) + { + uint8_t tmp[1024]; + uint32_t part = std::min((uint32_t)1024, len - i); + buf.read(tmp, part); + s.write(tmp, part); + } + s.pad(); + s.write_type(osc_blob); +#endif return s; } @@ -397,7 +449,7 @@ operator <<(osc_stream &s, string_buffer &str) } // XXXKF: I don't support reading binary blobs yet -#if 0 + struct osc_net_bad_address: public std::exception { std::string addr, error_msg; @@ -426,12 +478,19 @@ struct osc_net_exception: public std::exception struct osc_net_dns_exception: public std::exception { +#if 0 int net_errno; std::string command, error_msg; + osc_net_dns_exception(const char *cmd, int _errno = h_errno) + { + command = cmd; + net_errno = _errno; + error_msg = "OSC error in "+command+": "+hstrerror(_errno); + } virtual const char *what() const throw() { return error_msg.c_str(); } virtual ~osc_net_dns_exception() throw () {} -}; #endif +}; template struct osc_message_sink diff --git a/plugins/ladspa_effect/calf/src/calf/osctlnet.h b/plugins/ladspa_effect/calf/src/calf/osctlnet.h new file mode 100644 index 000000000..df4c9c7ab --- /dev/null +++ b/plugins/ladspa_effect/calf/src/calf/osctlnet.h @@ -0,0 +1,2 @@ +#include + diff --git a/plugins/ladspa_effect/calf/calf/preset.h b/plugins/ladspa_effect/calf/src/calf/preset.h similarity index 81% rename from plugins/ladspa_effect/calf/calf/preset.h rename to plugins/ladspa_effect/calf/src/calf/preset.h index c6a6ec4f8..c6b93a722 100644 --- a/plugins/ladspa_effect/calf/calf/preset.h +++ b/plugins/ladspa_effect/calf/src/calf/preset.h @@ -22,10 +22,6 @@ #define __CALF_PRESET_H #include -#include -#include -#include -#include #include #include "utils.h" @@ -89,6 +85,26 @@ typedef std::vector preset_vector; /// A single list of presets (usually there are two - @see get_builtin_presets(), get_user_presets() ) struct preset_list { + /// Plugin list item + struct plugin_snapshot + { + /// Preset offset + int preset_offset; + /// Plugin type + std::string type; + /// Instance name + std::string instance_name; + /// Index of the first input port + int input_index; + /// Index of the first output port + int output_index; + /// Index of the first MIDI port + int midi_index; + + /// Reset to initial values + void reset(); + }; + /// Parser states enum parser_state { @@ -97,24 +113,33 @@ struct preset_list PRESET, ///< Inside preset definition VALUE, ///< Inside (empty) param tag VAR, ///< Inside (non-empty) var tag + PLUGIN, ///< Inside plugin element (calfjackhost snapshots only) + RACK, ///< Inside rack element (calfjackhost snapshots only) } state; /// Contained presets (usually for all plugins) preset_vector presets; /// Temporary preset used during parsing process plugin_preset parser_preset; + /// Temporary plugin desc used during parsing process + plugin_snapshot parser_plugin; /// Preset number counters for DSSI (currently broken) std::map last_preset_ids; /// The key used in current tag (for state == VAR) std::string current_key; + /// The file is loaded in rack mode (and rack/plugin elements are expected) + bool rack_mode; + /// List of plugin states for rack mode + std::vector plugins; /// Return the name of the built-in or user-defined preset file static std::string get_preset_filename(bool builtin); /// Load default preset list (built-in or user-defined) bool load_defaults(bool builtin); - void parse(const std::string &data); + /// Load preset list from an in-memory XML string + void parse(const std::string &data, bool in_rack_mode); /// Load preset list from XML file - void load(const char *filename); + void load(const char *filename, bool in_rack_mode); /// Save preset list as XML file void save(const char *filename); /// Append or replace a preset (replaces a preset with the same plugin and preset name) diff --git a/plugins/ladspa_effect/calf/calf/primitives.h b/plugins/ladspa_effect/calf/src/calf/primitives.h similarity index 99% rename from plugins/ladspa_effect/calf/calf/primitives.h rename to plugins/ladspa_effect/calf/src/calf/primitives.h index 79cbe3f96..efc820feb 100644 --- a/plugins/ladspa_effect/calf/calf/primitives.h +++ b/plugins/ladspa_effect/calf/src/calf/primitives.h @@ -21,12 +21,13 @@ #ifndef __CALF_PRIMITIVES_H #define __CALF_PRIMITIVES_H -#include -#include -#include -#include +#include #include #include +#include +#include +#include +#include namespace dsp { diff --git a/plugins/ladspa_effect/calf/calf/synth.h b/plugins/ladspa_effect/calf/src/calf/synth.h similarity index 98% rename from plugins/ladspa_effect/calf/calf/synth.h rename to plugins/ladspa_effect/calf/src/calf/synth.h index dc5c8ebae..85fb35404 100644 --- a/plugins/ladspa_effect/calf/calf/synth.h +++ b/plugins/ladspa_effect/calf/src/calf/synth.h @@ -19,14 +19,16 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02111-1307, USA. */ -#ifndef __CALF_SYNTH_H -#define __CALF_SYNTH_H +#ifndef CALF_SYNTH_H +#define CALF_SYNTH_H +#include +#include +#include +#include +#include #include #include -#include -#include "primitives.h" -#include "audio_fx.h" namespace dsp { diff --git a/plugins/ladspa_effect/calf/calf/utils.h b/plugins/ladspa_effect/calf/src/calf/utils.h similarity index 90% rename from plugins/ladspa_effect/calf/calf/utils.h rename to plugins/ladspa_effect/calf/src/calf/utils.h index 406c71ee7..3dd83de60 100644 --- a/plugins/ladspa_effect/calf/calf/utils.h +++ b/plugins/ladspa_effect/calf/src/calf/utils.h @@ -93,12 +93,13 @@ public: }; /// Exception-safe temporary assignment -template +template class scope_assign { - T &data, old_value; + Tref data; + T old_value; public: - scope_assign(T &_data, T new_value) + scope_assign(Tref _data, T new_value) : data(_data), old_value(_data) { data = new_value; @@ -124,8 +125,8 @@ struct file_exception: public std::exception const char *text; std::string message, filename, container; public: - file_exception(const std::string &f) : message(strerror(errno)), filename(f), container(filename + ":" + message) { text = container.c_str(); } - file_exception(const std::string &f, const std::string &t) : message(t), filename(f), container(filename + ":" + message) { text = container.c_str(); } + file_exception(const std::string &f); + file_exception(const std::string &f, const std::string &t); virtual const char *what() const throw () { return text; } virtual ~file_exception() throw () {} }; @@ -147,6 +148,9 @@ extern std::string f2s(double value); /// float-to-string-that-doesn't-resemble-an-int extern std::string ff2s(double value); +/// Encode a key-value pair as XML attribute +std::string to_xml_attr(const std::string &key, const std::string &value); + /// Escape a string to be used in XML file std::string xml_escape(const std::string &src); diff --git a/plugins/ladspa_effect/calf/calf/waveshaping.h b/plugins/ladspa_effect/calf/src/calf/waveshaping.h similarity index 100% rename from plugins/ladspa_effect/calf/calf/waveshaping.h rename to plugins/ladspa_effect/calf/src/calf/waveshaping.h diff --git a/plugins/ladspa_effect/calf/src/config.h b/plugins/ladspa_effect/calf/src/config.h new file mode 100644 index 000000000..0ddd570c8 --- /dev/null +++ b/plugins/ladspa_effect/calf/src/config.h @@ -0,0 +1 @@ +#define USE_LADSPA 1 diff --git a/plugins/ladspa_effect/calf/src/giface.cpp b/plugins/ladspa_effect/calf/src/giface.cpp index 62d5157ed..f94fa207e 100644 --- a/plugins/ladspa_effect/calf/src/giface.cpp +++ b/plugins/ladspa_effect/calf/src/giface.cpp @@ -1,7 +1,7 @@ /* Calf DSP Library - * Module wrapper methods. + * Implementation of various helpers for the plugin interface. * - * Copyright (C) 2001-2007 Krzysztof Foltman + * Copyright (C) 2001-2010 Krzysztof Foltman * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -18,10 +18,12 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA */ -#include -#include +#include +#include #include -#include +#include +#include + using namespace std; using namespace calf_utils; using namespace calf_plugins; @@ -187,10 +189,10 @@ std::string parameter_properties::to_string(float value) const } void calf_plugins::plugin_ctl_iface::clear_preset() { - int param_count = get_param_count(); + int param_count = get_metadata_iface()->get_param_count(); for (int i=0; i < param_count; i++) { - parameter_properties &pp = *get_param_props(i); + const parameter_properties &pp = *get_metadata_iface()->get_param_props(i); if ((pp.flags & PF_TYPEMASK) == PF_STRING) { configure(pp.short_name, pp.choices ? pp.choices[0] : ""); @@ -213,7 +215,7 @@ const char *calf_plugins::load_gui_xml(const std::string &plugin_id) } } -bool calf_plugins::check_for_message_context_ports(parameter_properties *parameters, int count) +bool calf_plugins::check_for_message_context_ports(const parameter_properties *parameters, int count) { for (int i = count - 1; i >= 0; i--) { @@ -223,7 +225,7 @@ bool calf_plugins::check_for_message_context_ports(parameter_properties *paramet return false; } -bool calf_plugins::check_for_string_ports(parameter_properties *parameters, int count) +bool calf_plugins::check_for_string_ports(const parameter_properties *parameters, int count) { for (int i = count - 1; i >= 0; i--) { @@ -235,7 +237,121 @@ bool calf_plugins::check_for_string_ports(parameter_properties *parameters, int return false; } -#if USE_DSSI +bool calf_plugins::get_freq_gridline(int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context, bool use_frequencies) +{ + if (subindex < 0 ) + return false; + if (use_frequencies) + { + if (subindex < 28) + { + vertical = true; + if (subindex == 9) legend = "100 Hz"; + if (subindex == 18) legend = "1 kHz"; + if (subindex == 27) legend = "10 kHz"; + float freq = 100; + if (subindex < 9) + freq = 10 * (subindex + 1); + else if (subindex < 18) + freq = 100 * (subindex - 9 + 1); + else if (subindex < 27) + freq = 1000 * (subindex - 18 + 1); + else + freq = 10000 * (subindex - 27 + 1); + pos = log(freq / 20.0) / log(1000); + if (!legend.empty()) + context->set_source_rgba(0, 0, 0, 0.2); + else + context->set_source_rgba(0, 0, 0, 0.1); + return true; + } + subindex -= 28; + } + if (subindex >= 32) + return false; + float gain = 16.0 / (1 << subindex); + pos = dB_grid(gain); + if (pos < -1) + return false; + if (subindex != 4) + context->set_source_rgba(0, 0, 0, subindex & 1 ? 0.1 : 0.2); + if (!(subindex & 1)) + { + std::stringstream ss; + ss << (24 - 6 * subindex) << " dB"; + legend = ss.str(); + } + vertical = false; + return true; +} + +void calf_plugins::set_channel_color(cairo_iface *context, int channel) +{ + if (channel & 1) + context->set_source_rgba(0.35, 0.4, 0.2, 1); + else + context->set_source_rgba(0.35, 0.4, 0.2, 0.5); + context->set_line_width(1.5); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +bool frequency_response_line_graph::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const +{ + return get_freq_gridline(subindex, pos, vertical, legend, context); +} + +int frequency_response_line_graph::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) const +{ + subindex_graph = 0; + subindex_dot = 0; + subindex_gridline = generation ? INT_MAX : 0; + return 1; +} + +/////////////////////////////////////////////////////////////////////////////////////// + +calf_plugins::plugin_registry &calf_plugins::plugin_registry::instance() +{ + static calf_plugins::plugin_registry registry; + return registry; +} + +const plugin_metadata_iface *calf_plugins::plugin_registry::get_by_uri(const char *plugin_uri) +{ + static const char prefix[] = "http://calf.sourceforge.net/plugins/"; + if (strncmp(plugin_uri, prefix, sizeof(prefix) - 1)) + return NULL; + const char *label = plugin_uri + sizeof(prefix) - 1; + for (unsigned int i = 0; i < plugins.size(); i++) + { + if (!strcmp(plugins[i]->get_plugin_info().label, label)) + return plugins[i]; + } + return NULL; +} + +const plugin_metadata_iface *calf_plugins::plugin_registry::get_by_id(const char *id, bool case_sensitive) +{ + typedef int (*comparator)(const char *, const char *); + comparator comp = case_sensitive ? strcmp : strcasecmp; + for (unsigned int i = 0; i < plugins.size(); i++) + { + if (!comp(plugins[i]->get_id(), id)) + return plugins[i]; + } + return NULL; +} +/////////////////////////////////////////////////////////////////////////////////////// + +std::string table_edit_iface::get_cell(int param, int row, int column) const +{ + return calf_utils::i2s(row)+":"+calf_utils::i2s(column); +} + +/////////////////////////////////////////////////////////////////////////////////////// + +#if USE_EXEC_GUI struct osc_cairo_control: public cairo_iface { osctl::osc_inline_typed_strstream &os; @@ -251,9 +367,8 @@ struct osc_cairo_control: public cairo_iface } }; -static void send_graph_via_osc(osctl::osc_client &client, const std::string &address, line_graph_iface *graph, std::vector ¶ms) +static void serialize_graphs(osctl::osc_inline_typed_strstream &os, const line_graph_iface *graph, std::vector ¶ms) { - osctl::osc_inline_typed_strstream os; osc_cairo_control cairoctl(os); for (size_t i = 0; i < params.size(); i++) { @@ -295,15 +410,26 @@ static void send_graph_via_osc(osctl::osc_client &client, const std::string &add os << (uint32_t)LGI_END_ITEM; } os << (uint32_t)LGI_END; - client.send(address, os); } -calf_plugins::dssi_feedback_sender::dssi_feedback_sender(const char *URI, line_graph_iface *_graph, calf_plugins::parameter_properties *props, int num_params) +calf_plugins::dssi_feedback_sender::dssi_feedback_sender(const char *URI, const line_graph_iface *_graph) { graph = _graph; + is_client_shared = false; client = new osctl::osc_client; client->bind("0.0.0.0", 0); client->set_url(URI); +} + +calf_plugins::dssi_feedback_sender::dssi_feedback_sender(osctl::osc_client *_client, const line_graph_iface *_graph) +{ + graph = _graph; + client = _client; + is_client_shared = true; +} + +void calf_plugins::dssi_feedback_sender::add_graphs(const calf_plugins::parameter_properties *props, int num_params) +{ for (int i = 0; i < num_params; i++) { if (props[i].flags & PF_PROP_GRAPH) @@ -313,13 +439,18 @@ calf_plugins::dssi_feedback_sender::dssi_feedback_sender(const char *URI, line_g void calf_plugins::dssi_feedback_sender::update() { - send_graph_via_osc(*client, "/lineGraph", graph, indices); + if (graph) + { + osctl::osc_inline_typed_strstream os; + serialize_graphs(os, graph, indices); + client->send("/lineGraph", os); + } } calf_plugins::dssi_feedback_sender::~dssi_feedback_sender() { - // this would not be received by GUI's main loop because it's already been terminated - // client->send("/iQuit"); - delete client; + if (!is_client_shared) + delete client; } + #endif diff --git a/plugins/ladspa_effect/calf/src/metadata.cpp b/plugins/ladspa_effect/calf/src/metadata.cpp new file mode 100644 index 000000000..4bfc37793 --- /dev/null +++ b/plugins/ladspa_effect/calf/src/metadata.cpp @@ -0,0 +1,1019 @@ +/* Calf DSP Library + * Example audio modules - parameters and LADSPA wrapper instantiation + * + * Copyright (C) 2001-2008 Krzysztof Foltman + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include + +using namespace dsp; +using namespace calf_plugins; + +const char *calf_plugins::calf_copyright_info = "(C) 2001-2009 Krzysztof Foltman, Thor Harald Johanssen, Markus Schmidt and others; license: LGPL"; + +//////////////////////////////////////////////////////////////////////////// + +CALF_PORT_NAMES(flanger) = {"In L", "In R", "Out L", "Out R"}; + +CALF_PORT_PROPS(flanger) = { + { 0.1, 0.1, 10, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC | PF_PROP_GRAPH, NULL, "min_delay", "Min delay" }, + { 0.5, 0.1, 10, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "mod_depth", "Mod depth" }, + { 0.25, 0.01, 20, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "mod_rate", "Mod rate" }, + { 0.90, -0.99, 0.99, 0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "feedback", "Feedback" }, + { 0, 0, 360, 9, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_DEG, NULL, "stereo", "Stereo phase" }, + { 0, 0, 1, 2, PF_BOOL | PF_CTL_BUTTON , NULL, "reset", "Reset" }, + { 1, 0, 4, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "amount", "Amount" }, + { 1.0, 0, 4, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "dry", "Dry Amount" }, +}; + +CALF_PLUGIN_INFO(flanger) = { 0x847d, "Flanger", "Calf Flanger", "Krzysztof Foltman", calf_plugins::calf_copyright_info, "FlangerPlugin" }; + +//////////////////////////////////////////////////////////////////////////// + +CALF_PORT_NAMES(phaser) = {"In L", "In R", "Out L", "Out R"}; + +CALF_PORT_PROPS(phaser) = { + { 1000, 20, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "base_freq", "Center Freq" }, + { 4000, 0, 10800, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "mod_depth", "Mod depth" }, + { 0.25, 0.01, 20, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "mod_rate", "Mod rate" }, + { 0.25, -0.99, 0.99, 0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "feedback", "Feedback" }, + { 6, 1, 12, 12, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "stages", "# Stages" }, + { 180, 0, 360, 9, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_DEG, NULL, "stereo", "Stereo phase" }, + { 0, 0, 1, 2, PF_BOOL | PF_CTL_BUTTON , NULL, "reset", "Reset" }, + { 1, 0, 4, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "amount", "Amount" }, + { 1.0, 0, 4, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "dry", "Dry Amount" }, +}; + +CALF_PLUGIN_INFO(phaser) = { 0x8484, "Phaser", "Calf Phaser", "Krzysztof Foltman", calf_plugins::calf_copyright_info, "PhaserPlugin" }; + +//////////////////////////////////////////////////////////////////////////// + +CALF_PORT_NAMES(reverb) = {"In L", "In R", "Out L", "Out R"}; + +const char *reverb_room_sizes[] = { "Small", "Medium", "Large", "Tunnel-like", "Large/smooth", "Experimental" }; + +CALF_PORT_PROPS(reverb) = { + { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip", "0dB" }, + { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_wet", "Wet amount" }, + { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_out", "Output" }, + { 1.5, 0.4, 15.0, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_SEC, NULL, "decay_time", "Decay time" }, + { 5000, 2000,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "hf_damp", "High Frq Damp" }, + { 2, 0, 5, 0, PF_ENUM | PF_CTL_COMBO , reverb_room_sizes, "room_size", "Room size", }, + { 0.5, 0, 1, 0, PF_FLOAT | PF_CTL_KNOB | PF_SCALE_PERC, NULL, "diffusion", "Diffusion" }, + { 0.25, 0, 2, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "amount", "Wet Amount" }, + { 1.0, 0, 2, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "dry", "Dry Amount" }, + { 0, 0, 50, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "predelay", "Pre Delay" }, + { 300, 20, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "bass_cut", "Bass Cut" }, + { 5000, 20, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "treble_cut", "Treble Cut" }, +}; + +CALF_PLUGIN_INFO(reverb) = { 0x847e, "Reverb", "Calf Reverb", "Krzysztof Foltman", calf_plugins::calf_copyright_info, "ReverbPlugin" }; + +//////////////////////////////////////////////////////////////////////////// + +CALF_PORT_NAMES(filter) = {"In L", "In R", "Out L", "Out R"}; + +const char *filter_choices[] = { + "12dB/oct Lowpass", + "24dB/oct Lowpass", + "36dB/oct Lowpass", + "12dB/oct Highpass", + "24dB/oct Highpass", + "36dB/oct Highpass", + "6dB/oct Bandpass", + "12dB/oct Bandpass", + "18dB/oct Bandpass", + "6dB/oct Bandreject", + "12dB/oct Bandreject", + "18dB/oct Bandreject", +}; + +CALF_PORT_PROPS(filter) = { + { 2000, 10,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "freq", "Frequency" }, + { 0.707, 0.707, 32, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "res", "Resonance" }, + { biquad_filter_module::mode_12db_lp, + biquad_filter_module::mode_12db_lp, + biquad_filter_module::mode_count - 1, + 1, PF_ENUM | PF_CTL_COMBO, filter_choices, "mode", "Mode" }, + { 20, 5, 100, 20, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "inertia", "Inertia"}, +}; + +CALF_PLUGIN_INFO(filter) = { 0x847f, "Filter", "Calf Filter", "Krzysztof Foltman", calf_plugins::calf_copyright_info, "FilterPlugin" }; + +//////////////////////////////////////////////////////////////////////////// + +CALF_PORT_NAMES(filterclavier) = {"In L", "In R", "Out L", "Out R"}; + +CALF_PORT_PROPS(filterclavier) = { + { 0, -48, 48, 48*2+1, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_SEMITONES, NULL, "transpose", "Transpose" }, + { 0, -100, 100, 0, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "detune", "Detune" }, + { 32, 0.707, 32, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "maxres", "Max. Resonance" }, + { biquad_filter_module::mode_6db_bp, + biquad_filter_module::mode_12db_lp, + biquad_filter_module::mode_count - 1, + 1, PF_ENUM | PF_CTL_COMBO | PF_PROP_GRAPH, filter_choices, "mode", "Mode" }, + { 20, 1, 2000, 20, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "inertia", "Portamento time"} +}; + +CALF_PLUGIN_INFO(filterclavier) = { 0x849f, "Filterclavier", "Calf Filterclavier", "Krzysztof Foltman / Hans Baier", calf_plugins::calf_copyright_info, "FilterclavierPlugin" }; + +//////////////////////////////////////////////////////////////////////////// + +CALF_PORT_NAMES(vintage_delay) = {"In L", "In R", "Out L", "Out R"}; + +const char *vintage_delay_mixmodes[] = { + "Stereo", + "Ping-Pong", + "L then R", + "R then L", +}; + +const char *vintage_delay_fbmodes[] = { + "Plain", + "Tape", + "Old Tape", +}; + +CALF_PORT_PROPS(vintage_delay) = { + { 120, 30, 300, 1, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_BPM, NULL, "bpm", "Tempo" }, + { 4, 1, 16, 1, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "subdiv", "Subdivide"}, + { 3, 1, 16, 1, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "time_l", "Time L"}, + { 5, 1, 16, 1, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "time_r", "Time R"}, + { 0.5, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "feedback", "Feedback" }, + { 0.25, 0, 4, 100, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "amount", "Amount" }, + { 1, 0, 3, 0, PF_ENUM | PF_CTL_COMBO, vintage_delay_mixmodes, "mix_mode", "Mix mode" }, + { 1, 0, 2, 0, PF_ENUM | PF_CTL_COMBO, vintage_delay_fbmodes, "medium", "Medium" }, + { 1.0, 0, 4, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "dry", "Dry Amount" }, + { 1.0, -1, 1, 0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB , NULL, "width", "Stereo Width" }, +}; + +CALF_PLUGIN_INFO(vintage_delay) = { 0x8482, "VintageDelay", "Calf Vintage Delay", "Krzysztof Foltman", calf_plugins::calf_copyright_info, "DelayPlugin" }; + +//////////////////////////////////////////////////////////////////////////// + +CALF_PORT_NAMES(rotary_speaker) = {"In L", "In R", "Out L", "Out R"}; + +const char *rotary_speaker_speed_names[] = { "Off", "Chorale", "Tremolo", "HoldPedal", "ModWheel", "Manual" }; + +CALF_PORT_PROPS(rotary_speaker) = { + { 5, 0, 5, 1.01, PF_ENUM | PF_CTL_COMBO, rotary_speaker_speed_names, "vib_speed", "Speed Mode" }, + { 0.5, 0, 1, 0, PF_FLOAT | PF_CTL_KNOB | PF_SCALE_PERC, NULL, "spacing", "Tap Spacing" }, + { 0.5, 0, 1, 0, PF_FLOAT | PF_CTL_KNOB | PF_SCALE_PERC, NULL, "shift", "Tap Offset" }, + { 0.10, 0, 1, 0, PF_FLOAT | PF_CTL_KNOB | PF_SCALE_PERC, NULL, "mod_depth", "Mod Depth" }, + { 36, 10, 600, 0, PF_FLOAT | PF_CTL_KNOB | PF_SCALE_LOG | PF_UNIT_RPM, NULL, "treble_speed", "Treble Motor" }, + { 30, 10, 600, 0, PF_FLOAT | PF_CTL_KNOB | PF_SCALE_LOG | PF_UNIT_RPM, NULL, "bass_speed", "Bass Motor" }, + { 0.7, 0, 1, 101, PF_FLOAT | PF_CTL_KNOB | PF_SCALE_PERC, NULL, "mic_distance", "Mic Distance" }, + { 0.3, 0, 1, 101, PF_FLOAT | PF_CTL_KNOB | PF_SCALE_PERC, NULL, "reflection", "Reflection" }, + { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_l", "Low rotor" }, + { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_h", "High rotor" }, +}; + +CALF_PLUGIN_INFO(rotary_speaker) = { 0x8483, "RotarySpeaker", "Calf Rotary Speaker", "Krzysztof Foltman", calf_plugins::calf_copyright_info, "SimulatorPlugin" }; + +//////////////////////////////////////////////////////////////////////////// + +CALF_PORT_NAMES(multichorus) = {"In L", "In R", "Out L", "Out R"}; + +CALF_PORT_PROPS(multichorus) = { + { 5, 0.1, 10, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC | PF_PROP_GRAPH, NULL, "min_delay", "Min delay" }, + { 6, 0.1, 10, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC| PF_PROP_GRAPH, NULL, "mod_depth", "Mod depth" }, + { 0.5, 0.01, 20, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ| PF_PROP_GRAPH, NULL, "mod_rate", "Modulation rate" }, + { 180, 0, 360, 91, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_DEG, NULL, "stereo", "Stereo phase" }, + { 4, 1, 8, 8, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "voices", "Voices"}, + { 64, 0, 360, 91, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_DEG, NULL, "vphase", "Inter-voice phase" }, + { 2, 0, 4, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "amount", "Amount" }, + { 1.0, 0, 4, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "dry", "Dry Amount" }, + { 100, 10,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "freq", "Center Frq 1" }, + { 5000, 10,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "freq2", "Center Frq 2" }, + { 0.125, 0.125, 8, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "q", "Q" }, + { 1, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "overlap", "Overlap" }, +}; + +CALF_PLUGIN_INFO(multichorus) = { 0x8501, "MultiChorus", "Calf MultiChorus", "Krzysztof Foltman", calf_plugins::calf_copyright_info, "ChorusPlugin" }; + +//////////////////////////////////////////////////////////////////////////// + +CALF_PORT_NAMES(compressor) = {"In L", "In R", "Out L", "Out R"}; + +const char *compressor_detection_names[] = { "RMS", "Peak" }; +const char *compressor_stereo_link_names[] = { "Average", "Maximum" }; + +CALF_PORT_PROPS(compressor) = { + { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass", "Bypass" }, + { 1, 0, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_in", "Input" }, + { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_in", "Input" }, + { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_out", "Output" }, + { 0, 0, 1, 0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_in", "0dB-In" }, + { 0, 0, 1, 0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_out", "0dB-Out" }, + { 0.125, 0.000976563, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "threshold", "Threshold" }, + { 2, 1, 20, 21, PF_FLOAT | PF_SCALE_LOG_INF | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "ratio", "Ratio" }, + { 20, 0.01, 2000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "attack", "Attack" }, + { 250, 0.01, 2000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "release", "Release" }, + { 2, 1, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "makeup", "Makeup Gain" }, + { 2.828427125, 1, 8, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "knee", "Knee" }, + { 0, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, compressor_detection_names, "detection", "Detection" }, + { 0, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, compressor_stereo_link_names, "stereo_link", "Stereo Link" }, + { 0, 0.03125, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_CTLO_REVERSE | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL| PF_PROP_GRAPH, NULL, "compression", "Reduction" }, +}; + +CALF_PLUGIN_INFO(compressor) = { 0x8502, "Compressor", "Calf Compressor", "Thor Harald Johansen", calf_plugins::calf_copyright_info, "CompressorPlugin" }; + +//////////////////////////////////////////////////////////////////////////// + +CALF_PORT_NAMES(sidechaincompressor) = {"In L", "In R", "Out L", "Out R"}; + +const char *sidechaincompressor_detection_names[] = { "RMS", "Peak" }; +const char *sidechaincompressor_stereo_link_names[] = { "Average", "Maximum" }; +const char *sidechaincompressor_mode_names[] = {"Wideband (F1:off / F2:off)", + "Deesser wide (F1:Bell / F2:HP)", + "Deesser split (F1:off / F2:HP)", + "Derumbler wide (F1:LP / F2:Bell)", + "Derumbler split (F1:LP / F2:off)", + "Weighted #1 (F1:Shelf / F2:Shelf)", + "Weighted #2 (F1:Shelf / F2:Bell)", + "Weighted #3 (F1:Bell / F2:Shelf)", + "Bandpass #1 (F1:BP / F2:off)", + "Bandpass #2 (F1:HP / F2:LP)"}; +const char *sidechaincompressor_filter_choices[] = { "12dB", "24dB", "36dB"}; + + +CALF_PORT_PROPS(sidechaincompressor) = { + { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass", "Bypass" }, + { 1, 0, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_in", "Input" }, + { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_in", "Input" }, + { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_out", "Output" }, + { 0, 0, 1, 0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_in", "0dB-In" }, + { 0, 0, 1, 0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_out", "0dB-Out" }, + { 0.125, 0.000976563, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "threshold", "Threshold" }, + { 2, 1, 20, 21, PF_FLOAT | PF_SCALE_LOG_INF | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "ratio", "Ratio" }, + { 20, 0.01, 2000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "attack", "Attack" }, + { 250, 0.01, 2000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "release", "Release" }, + { 2, 1, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "makeup", "Makeup Gain" }, + { 2.828427125, 1, 8, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "knee", "Knee" }, + { 0, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, sidechaincompressor_detection_names, "detection", "Detection" }, + { 0, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, sidechaincompressor_stereo_link_names, "stereo_link", "Stereo Link" }, + { 0, 0.03125, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_CTLO_REVERSE | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL| PF_PROP_GRAPH, NULL, "compression", "Gain Reduction" }, + { 0, 0, 9, 0, PF_ENUM | PF_CTL_COMBO, sidechaincompressor_mode_names, "sc_mode", "Sidechain Mode" }, + { 250, 10,18000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "f1_freq", "F1 Freq" }, + { 4500, 10,18000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "f2_freq", "F2 Freq" }, + { 1, 0.0625, 16, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "f1_level", "F1 Level" }, + { 1, 0.0625, 16, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "f2_level", "F2 Level" }, + { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "sc_listen", "S/C-Listen" }, + { 0, 0, 1, 0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "f1_active", "F1 Active" }, + { 0, 0, 1, 0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "f2_active", "F2 Active" }, +}; + +CALF_PLUGIN_INFO(sidechaincompressor) = { 0x8517, "Sidechaincompressor", "Calf Sidechain Compressor", "Markus Schmidt / Thor Harald Johansen", calf_plugins::calf_copyright_info, "CompressorPlugin" }; + +//////////////////////////////////////////////////////////////////////////// + +CALF_PORT_NAMES(multibandcompressor) = {"In L", "In R", "Out L", "Out R"}; + +const char *multibandcompressor_detection_names[] = { "RMS", "Peak" }; + +CALF_PORT_PROPS(multibandcompressor) = { + { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass", "Bypass" }, + { 1, 0, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_in", "Input" }, + { 1, 0, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_out", "Output" }, + { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_inL", "Input L" }, + { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_inR", "Input R" }, + { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_outL", "Output L" }, + { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_outR", "Output R" }, + { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_inL", "0dB-InL" }, + { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_inR", "0dB-InR" }, + { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_outL", "0dB-OutL" }, + { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_outR", "0dB-OutR" }, + + { 100, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "freq0", "Split 1/2" }, + { 1000, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "freq1", "Split 2/3" }, + { 6000, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "freq2", "Split 3/4" }, + + { -0.17, -0.5, 0.5, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "sep0", "S1" }, + { -0.17, -0.5, 0.5, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "sep1", "S2" }, + { -0.17, -0.5, 0.5, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "sep2", "S3" }, + + { 0.895025, 0.25, 4, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB | PF_PROP_GRAPH, NULL, "q0", "Q1" }, + { 0.895025, 0.25, 4, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB | PF_PROP_GRAPH, NULL, "q1", "Q2" }, + { 0.895025, 0.25, 4, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB | PF_PROP_GRAPH, NULL, "q2", "Q3" }, + + + { 0.0625, 0.000976563, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "threshold0", "Threshold 1" }, + { 3, 1, 20, 21, PF_FLOAT | PF_SCALE_LOG_INF | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "ratio0", "Ratio 1" }, + { 50, 0.01, 2000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "attack0", "Attack 1" }, + { 100, 0.01, 2000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "release0", "Release 1" }, + { 2, 1, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "makeup0", "Makeup 1" }, + { 2.828427125, 1, 8, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "knee0", "Knee 1" }, + { 1, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, multibandcompressor_detection_names, "detection0", "Detection 1" }, + { 1, 0.03125, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_CTLO_REVERSE | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL| PF_PROP_GRAPH, NULL, "compression0", "Gain Reduction 1" }, + { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "output0", "Output 1" }, + { 1, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass0", "Bypass 1" }, + { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "mute0", "Mute 1" }, + + + { 0.03125, 0.000976563, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "threshold1", "Threshold 2" }, + { 3, 1, 20, 21, PF_FLOAT | PF_SCALE_LOG_INF | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "ratio1", "Ratio 2" }, + { 25, 0.01, 2000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "attack1", "Attack 2" }, + { 50, 0.01, 2000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "release1", "Release 2" }, + { 2, 1, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "makeup1", "Makeup 2" }, + { 2.828427125, 1, 8, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "knee1", "Knee 2" }, + { 1, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, multibandcompressor_detection_names, "detection1", "Detection 2" }, + { 1, 0.03125, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_CTLO_REVERSE | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL| PF_PROP_GRAPH, NULL, "compression1", "Gain Reduction 2" }, + { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "output1", "Output 2" }, + { 1, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass1", "Bypass 2" }, + { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "mute1", "Mute 2" }, + + + { 0.015625, 0.000976563, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "threshold2", "Threshold 3" }, + { 3, 1, 20, 21, PF_FLOAT | PF_SCALE_LOG_INF | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "ratio2", "Ratio 3" }, + { 12.5, 0.01, 2000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "attack2", "Attack 3" }, + { 25, 0.01, 2000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "release2", "Release 3" }, + { 2, 1, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "makeup2", "Makeup 3" }, + { 2.828427125, 1, 8, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "knee2", "Knee 3" }, + { 1, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, multibandcompressor_detection_names, "detection2", "Detection 3" }, + { 1, 0.03125, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_CTLO_REVERSE | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL| PF_PROP_GRAPH, NULL, "compression2", "Gain Reduction 3" }, + { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "output2", "Output 3" }, + { 1, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass2", "Bypass 3" }, + { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "mute2", "Mute 3" }, + + + { 0.0078125, 0.000976563, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "threshold3", "Threshold 4" }, + { 3, 1, 20, 21, PF_FLOAT | PF_SCALE_LOG_INF | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "ratio3", "Ratio 4" }, + { 6.25, 0.01, 2000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "attack3", "Attack 4" }, + { 12.5, 0.01, 2000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "release3", "Release 4" }, + { 2, 1, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "makeup3", "Makeup 4" }, + { 2.828427125, 1, 8, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "knee3", "Knee 4" }, + { 1, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, multibandcompressor_detection_names, "detection3", "Detection 4" }, + { 1, 0.03125, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_CTLO_REVERSE | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL| PF_PROP_GRAPH, NULL, "compression3", "Gain Reduction 4" }, + { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "output3", "Output 4" }, + { 1, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass3", "Bypass 4" }, + { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "mute3", "Mute 4" }, +}; + +CALF_PLUGIN_INFO(multibandcompressor) = { 0x8516, "Multibandcompressor", "Calf Multiband Compressor", "Markus Schmidt / Thor Harald Johansen", calf_plugins::calf_copyright_info, "CompressorPlugin" }; + +//////////////////////////////////////////////////////////////////////////// + +CALF_PORT_NAMES(deesser) = {"In L", "In R", "Out L", "Out R"}; + +const char *deesser_detection_names[] = { "RMS", "Peak" }; +const char *deesser_mode_names[] = { "Wide", "Split" }; + + +CALF_PORT_PROPS(deesser) = { + { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass", "Bypass" }, + { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "detected", "Detected" }, + { 0, 0.03125, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_CTLO_REVERSE | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL| PF_PROP_GRAPH, NULL, "compression", "Gain Reduction" }, + { 0, 0, 1, 0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "detected_led", "Active" }, + { 0, 0, 1, 0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_out", "Out" }, + { 0, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, deesser_detection_names, "detection", "Detection" }, + { 0, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, deesser_mode_names, "mode", "Mode" }, + { 0.125, 0.000976563, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "threshold", "Threshold" }, + { 3, 1, 20, 21, PF_FLOAT | PF_SCALE_LOG_INF | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "ratio", "Ratio" }, + { 15, 1, 100, 1, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "laxity", "Laxity" }, + { 1, 1, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "makeup", "Makeup" }, + + { 6000, 10, 18000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "f1_freq", "Split" }, + { 4500, 10, 18000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "f2_freq", "Peak" }, + { 1, 0.0625, 16, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "f1_level", "Gain" }, + { 4, 0.0625, 16, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "f2_level", "Level" }, + { 1, 0.1, 100,1, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "f2_q", "Peak Q" }, + { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "sc_listen", "S/C-Listen" }, +}; + +CALF_PLUGIN_INFO(deesser) = { 0x8515, "Deesser", "Calf Deesser", "Markus Schmidt / Thor Harald Johansen", calf_plugins::calf_copyright_info, "CompressorPlugin" }; + +//////////////////////////////////////////////////////////////////////////// +// A few macros to make + +#define BYPASS_AND_LEVEL_PARAMS \ + { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass", "Bypass" }, \ + { 1, 0, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_in", "Input Gain" }, \ + { 1, 0, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_out", "Output Gain" }, + +#define METERING_PARAMS \ + { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_inL", "Meter-InL" }, \ + { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_inR", "Meter-InR" }, \ + { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_outL", "Meter-OutL" }, \ + { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_outR", "Meter-OutR" }, \ + { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_inL", "0dB-InL" }, \ + { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_inR", "0dB-InR" }, \ + { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_outL", "0dB-OutL" }, \ + { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_outR", "0dB-OutR" }, + +#define LPHP_PARAMS \ + { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "hp_active", "HP Active" }, \ + { 30, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "hp_freq", "HP Freq" }, \ + { 1, 0, 2, 0, PF_ENUM | PF_CTL_COMBO, rolloff_mode_names, "hp_mode", "HP Mode" }, \ + { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "lp_active", "LP Active" }, \ + { 18000, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "lp_freq", "LP Freq" }, \ + { 1, 0, 2, 0, PF_ENUM | PF_CTL_COMBO, rolloff_mode_names, "lp_mode", "LP Mode" }, \ + +#define SHELF_PARAMS \ + { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "ls_active", "LS Active" }, \ + { 1, 0.015625, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "ls_level", "Level L" }, \ + { 200, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "ls_freq", "Freq L" }, \ + { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "hs_active", "HS Active" }, \ + { 1, 0.015625, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "hs_level", "Level H" }, \ + { 4000, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "hs_freq", "Freq H" }, + +#define EQ_BAND_PARAMS(band, frequency) \ + { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "p" #band "_active", "F" #band " Active" }, \ + { 1, 0.015625, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "p" #band "_level", "Level " #band }, \ + { frequency, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "p" #band "_freq", "Freq " #band }, \ + { 1, 0.1, 100, 1, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "p" #band "_q", "Q " #band }, + +//////////////////////////////////////////////////////////////////////////// + +CALF_PORT_NAMES(equalizer5band) = {"In L", "In R", "Out L", "Out R"}; + +CALF_PORT_PROPS(equalizer5band) = { + BYPASS_AND_LEVEL_PARAMS + METERING_PARAMS + SHELF_PARAMS + EQ_BAND_PARAMS(1, 250) + EQ_BAND_PARAMS(2, 1000) + EQ_BAND_PARAMS(3, 2500) +}; + +CALF_PLUGIN_INFO(equalizer5band) = { 0x8511, "Equalizer5Band", "Calf Equalizer 5 Band", "Markus Schmidt", calf_plugins::calf_copyright_info, "EqualizerPlugin" }; + +////////////////////////////////////////////////////////////////////////////// + + +CALF_PORT_NAMES(equalizer8band) = {"In L", "In R", "Out L", "Out R"}; +const char *rolloff_mode_names[] = {"12dB/oct", "24dB/oct", "36dB/oct"}; + +CALF_PORT_PROPS(equalizer8band) = { + BYPASS_AND_LEVEL_PARAMS + METERING_PARAMS + LPHP_PARAMS + SHELF_PARAMS + EQ_BAND_PARAMS(1, 250) + EQ_BAND_PARAMS(2, 1000) + EQ_BAND_PARAMS(3, 2500) + EQ_BAND_PARAMS(4, 5000) +}; + +CALF_PLUGIN_INFO(equalizer8band) = { 0x8512, "Equalizer8Band", "Calf Equalizer 8 Band", "Markus Schmidt", calf_plugins::calf_copyright_info, "EqualizerPlugin" }; + +//////////////////////////////////////////////////////////////////////////// + +CALF_PORT_NAMES(equalizer12band) = {"In L", "In R", "Out L", "Out R"}; + +CALF_PORT_PROPS(equalizer12band) = { + BYPASS_AND_LEVEL_PARAMS + METERING_PARAMS + LPHP_PARAMS + SHELF_PARAMS + EQ_BAND_PARAMS(1, 60) + EQ_BAND_PARAMS(2, 120) + EQ_BAND_PARAMS(3, 250) + EQ_BAND_PARAMS(4, 500) + EQ_BAND_PARAMS(5, 1000) + EQ_BAND_PARAMS(6, 2500) + EQ_BAND_PARAMS(7, 4000) + EQ_BAND_PARAMS(8, 6000) +}; + +CALF_PLUGIN_INFO(equalizer12band) = { 0x8513, "Equalizer12Band", "Calf Equalizer 12 Band", "Markus Schmidt", calf_plugins::calf_copyright_info, "EqualizerPlugin" }; + +//////////////////////////////////////////////////////////////////////////// + +CALF_PORT_NAMES(pulsator) = {"In L", "In R", "Out L", "Out R"}; + +const char *pulsator_mode_names[] = { "Sine", "Triangle", "Square", "Saw up", "Saw down" }; + +CALF_PORT_PROPS(pulsator) = { + BYPASS_AND_LEVEL_PARAMS + METERING_PARAMS + { 0, 0, 4, 0, PF_ENUM | PF_CTL_COMBO, pulsator_mode_names, "mode", "Mode" }, + { 1, 0.01, 100, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "freq", "Frequency" }, + { 1, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "amount", "Modulation" }, + { 0.5, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "offset", "Offset L/R" }, + { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "mono", "Mono-in" }, + { 0, 0, 1, 2, PF_BOOL | PF_CTL_BUTTON , NULL, "reset", "Reset" }, +}; + +CALF_PLUGIN_INFO(pulsator) = { 0x8514, "Pulsator", "Calf Pulsator", "Markus Schmidt", calf_plugins::calf_copyright_info, "ModulationPlugin" }; + +//////////////////////////////////////////////////////////////////////////// + +CALF_PORT_NAMES(saturator) = {"In L", "In R", "Out L", "Out R"}; + +CALF_PORT_PROPS(saturator) = { + { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass", "Bypass" }, + { 1, 1, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_in", "Activation" }, + { 1, 0, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_out", "Master" }, + { 1, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB , NULL, "mix", "Mix" }, + { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_in", "Input" }, + { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_out", "Output" }, + { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_in", "0dB" }, + { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_out", "0dB" }, + + { 5, 0.1, 10, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "drive", "Saturation" }, + { 10, -10, 10, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER | PF_UNIT_COEF, NULL, "blend", "Blend" }, + { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_drive", "Drive" }, + + { 20000, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "lp_pre_freq", "Lowpass" }, + { 10, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "hp_pre_freq", "Highpass" }, + + { 20000, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "lp_post_freq", "Lowpass" }, + { 10, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "hp_post_freq", "Highpass" }, + + { 2000, 80, 8000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "p_freq", "Tone" }, + { 1, 0.0625, 16, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "p_level", "Amount" }, + { 1, 0.1, 10, 1, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "p_q", "Gradient" }, +}; + +CALF_PLUGIN_INFO(saturator) = { 0x8530, "Saturator", "Calf Saturator", "Markus Schmidt / Krzysztof Foltman", calf_plugins::calf_copyright_info, "DistortionPlugin" }; + +//////////////////////////////////////////////////////////////////////////// + +CALF_PORT_NAMES(exciter) = {"In L", "In R", "Out L", "Out R"}; + +CALF_PORT_PROPS(exciter) = { + { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass", "Bypass" }, + { 1, 0, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_in", "Input" }, + { 1, 0, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_out", "Output" }, + { 1, 0, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB | PF_PROP_NOBOUNDS, NULL, "amount", "Amount" }, + { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_in", "Input" }, + { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_out", "Output" }, + { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_in", "0dB" }, + { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_out", "0dB" }, + + { 8.5, 0.1, 10, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "drive", "Harmonics" }, + { 0, -10, 10, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER | PF_UNIT_COEF, NULL, "blend", "Blend harmonics" }, + { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_drive", "Harmonics level" }, + + { 6000, 2000, 12000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "freq", "Scope" }, + { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "listen", "Listen" }, +}; + +CALF_PLUGIN_INFO(exciter) = { 0x8531, "Exciter", "Calf Exciter", "Markus Schmidt / Krzysztof Foltman", calf_plugins::calf_copyright_info, "DistortionPlugin" }; + +//////////////////////////////////////////////////////////////////////////// + +CALF_PORT_NAMES(bassenhancer) = {"In L", "In R", "Out L", "Out R"}; + +CALF_PORT_PROPS(bassenhancer) = { + { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass", "Bypass" }, + { 1, 0, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_in", "Input" }, + { 1, 0, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_out", "Output" }, + { 1, 0, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB | PF_PROP_NOBOUNDS, NULL, "amount", "Amount" }, + { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_in", "Input" }, + { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_out", "Output" }, + { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_in", "0dB" }, + { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_out", "0dB" }, + + { 8.5, 0.1, 10, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "drive", "Harmonics" }, + { 0, -10, 10, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER | PF_UNIT_COEF, NULL, "blend", "Blend harmonics" }, + { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_drive", "Harmonics level" }, + + { 120, 10, 250, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "freq", "Scope" }, + { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "listen", "Listen" }, +}; + +CALF_PLUGIN_INFO(bassenhancer) = { 0x8532, "BassEnhancer", "Calf Bass Enhancer", "Markus Schmidt / Krzysztof Foltman", calf_plugins::calf_copyright_info, "DistortionPlugin" }; + + +//////////////////////////////////////////////////////////////////////////// + +CALF_PORT_NAMES(gate) = {"In L", "In R", "In Trigger", "Out L", "Out R"}; + +const char *gate_detection_names[] = { "RMS", "Peak" }; +const char *gate_stereo_link_names[] = { "Average", "Maximum" }; +const char *gate_weighting_names[] = { "Normal", "A-weighted", "Deesser (low)", "Deesser (med)", "Deesser (high)" }; + +CALF_PORT_PROPS(gate) = { + { 0.125, 0.000976563, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "threshold", "Threshold" }, + { 2, 1, 20, 21, PF_FLOAT | PF_SCALE_LOG_INF | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "ratio", "Ratio" }, + { 20, 1, 2000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "attack", "Attack" }, + { 250, 1, 2000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "release", "Release" }, + { 1, 1, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "makeup", "Makeup Gain" }, + { 2.828427125, 1, 8, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "knee", "Knee" }, + { 0, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, gate_detection_names, "detection", "Detection" }, + { 0, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, gate_stereo_link_names, "stereo_link", "Stereo Link" }, + { 0, 0, 4, 0, PF_ENUM | PF_CTL_COMBO, gate_weighting_names, "aweighting", "Weighting" }, + { 0, 0.03125, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL| PF_PROP_GRAPH, NULL, "gating", "Gating" }, + { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "peak", "Peak Output" }, + { 0, 0, 1, 0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip", "0dBFS" }, + { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass", "Bypass" }, + { 0.01, 0.000015849, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "range", "Max Gain Reduction" }, + { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "mono", "Mono (L only)" }, + { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "trigger", "Sidechain (Mono In)" }, + +}; + +CALF_PLUGIN_INFO(gate) = { 0x8503, "Gate", "Calf Gate", "Damien Zammit / Thor Harald Johansen", calf_plugins::calf_copyright_info, "ExpanderPlugin" }; + +//////////////////////////////////////////////////////////////////////////// + +CALF_PORT_NAMES(monosynth) = { + "Out L", "Out R", +}; + +const char *monosynth_waveform_names[] = { "Sawtooth", "Square", "Pulse", "Sine", "Triangle", "Varistep", "Skewed Saw", "Skewed Square", + "Smooth Brass", "Bass", "Dark FM", "Multiwave", "Bell FM", "Dark Pad", "DCO Saw", "DCO Maze" }; +const char *monosynth_mode_names[] = { "0\xC2\xB0 : 0\xC2\xB0", "0\xC2\xB0 : 180\xC2\xB0", "0\xC2\xB0 : 90\xC2\xB0", "90\xC2\xB0 : 90\xC2\xB0", "90\xC2\xB0 : 270\xC2\xB0", "Random" }; +const char *monosynth_legato_names[] = { "Retrig", "Legato", "Fng Retrig", "Fng Legato" }; +const char *monosynth_lfotrig_names[] = { "Retrig", "Free" }; + +const char *monosynth_filter_choices[] = { + "12dB/oct Lowpass", + "24dB/oct Lowpass", + "2x12dB/oct Lowpass", + "12dB/oct Highpass", + "Lowpass+Notch", + "Highpass+Notch", + "6dB/oct Bandpass", + "2x6dB/oct Bandpass", +}; + +CALF_PLUGIN_INFO(monosynth) = { 0x8480, "Monosynth", "Calf Monosynth", "Krzysztof Foltman", calf_plugins::calf_copyright_info, "SynthesizerPlugin" }; + +CALF_PORT_PROPS(monosynth) = { + { monosynth_metadata::wave_saw, 0, monosynth_metadata::wave_count - 1, 1, PF_ENUM | PF_CTL_COMBO | PF_PROP_GRAPH, monosynth_waveform_names, "o1_wave", "Osc1 Wave" }, + { monosynth_metadata::wave_sqr, 0, monosynth_metadata::wave_count - 1, 1, PF_ENUM | PF_CTL_COMBO | PF_PROP_GRAPH, monosynth_waveform_names, "o2_wave", "Osc2 Wave" }, + + { 0, -1, 1, 0.1, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "o1_pw", "Osc1 PW" }, + { 0, -1, 1, 0.1, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "o2_pw", "Osc2 PW" }, + + { 10, 0, 100, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "o12_detune", "O1<>2 Detune" }, + { 12, -24, 24, 0, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_SEMITONES, NULL, "o2_xpose", "Osc 2 transpose" }, + { 0, 0, 5, 0, PF_ENUM | PF_CTL_COMBO, monosynth_mode_names, "phase_mode", "Phase mode" }, + { 0.5, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "o12_mix", "O1<>2 Mix" }, + { 1, 0, 7, 0, PF_ENUM | PF_CTL_COMBO | PF_PROP_GRAPH, monosynth_filter_choices, "filter", "Filter" }, + { 33, 10,16000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "cutoff", "Cutoff" }, + { 3, 0.7, 8, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB, NULL, "res", "Resonance" }, + { 0, -2400, 2400, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "filter_sep", "Separation" }, + { 8000, -10800,10800, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "env2cutoff", "Env->Cutoff" }, + { 1, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "env2res", "Env->Res" }, + { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "env2amp", "Env->Amp" }, + + { 1, 1,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_FADER | PF_UNIT_MSEC, NULL, "adsr_a", "EG1 Attack" }, + { 350, 10,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_FADER | PF_UNIT_MSEC, NULL, "adsr_d", "EG1 Decay" }, + { 0.5, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "adsr_s", "EG1 Sustain" }, + { 0, -10000,10000, 21, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER | PF_UNIT_MSEC, NULL, "adsr_f", "EG1 Fade" }, + { 100, 10,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_FADER | PF_UNIT_MSEC, NULL, "adsr_r", "EG1 Release" }, + + { 0, 0, 2, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "key_follow", "Key Follow" }, + { 0, 0, 3, 0, PF_ENUM | PF_CTL_COMBO, monosynth_legato_names, "legato", "Legato Mode" }, + { 1, 1, 2000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "portamento", "Portamento" }, + + { 0.5, 0, 1, 0.1, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "vel2filter", "Vel->Filter" }, + { 0, 0, 1, 0.1, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "vel2amp", "Vel->Amp" }, + + { 0.5, 0, 1, 100, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_PROP_OUTPUT_GAIN, NULL, "master", "Volume" }, + + { 200, 0, 2400, 25, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "pbend_range", "PBend Range" }, + + { 5, 0.01, 20, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "lfo_rate", "LFO1 Rate" }, + { 0.5, 0, 5, 0, PF_FLOAT | PF_SCALE_QUAD | PF_CTL_KNOB | PF_UNIT_SEC, NULL, "lfo_delay", "LFO1 Delay" }, + { 0, -4800, 4800, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "lfo2filter", "LFO1->Filter" }, + { 100, 0, 1200, 0, PF_FLOAT | PF_SCALE_QUAD | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "lfo2pitch", "LFO1->Pitch" }, + { 0, 0, 1, 0.1, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "lfo2pw", "LFO1->PW" }, + { 1, 0, 1, 0.1, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "mwhl2lfo", "ModWheel->LFO1" }, + + { 1, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "scale_detune", "Scale Detune" }, + + { 0, -10800,10800, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "adsr2_cutoff", "EG2->Cutoff" }, + { 0.3, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "adsr2_res", "EG2->Res" }, + { 1, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "adsr2_amp", "EG2->Amp" }, + + { 1, 1,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_FADER | PF_UNIT_MSEC, NULL, "adsr2_a", "EG2 Attack" }, + { 100, 10,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_FADER | PF_UNIT_MSEC, NULL, "adsr2_d", "EG2 Decay" }, + { 0.5, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "adsr2_s", "EG2 Sustain" }, + { 0, -10000,10000, 21, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER | PF_UNIT_MSEC, NULL, "adsr2_f", "EG2 Fade" }, + { 50, 10,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_FADER | PF_UNIT_MSEC, NULL, "adsr2_r", "Release" }, + + { 1, 1, 16, 0, PF_FLOAT | PF_SCALE_LOG | PF_UNIT_COEF | PF_CTL_KNOB, NULL, "o1_stretch", "Osc1 Stretch" }, + { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "o1_window", "Osc1 Window" }, + + { 0, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, monosynth_lfotrig_names, "lfo1_trig", "LFO1 Trigger Mode" }, + { 0, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, monosynth_lfotrig_names, "lfo2_trig", "LFO2 Trigger Mode" }, + { 5, 0.01, 20, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "lfo2_rate", "LFO1 Rate" }, + { 0.5, 0.1, 5, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_SEC, NULL, "lfo2_delay", "LFO1 Delay" }, +}; + +//////////////////////////////////////////////////////////////////////////// + +CALF_PLUGIN_INFO(organ) = { 0x8481, "Organ", "Calf Organ", "Krzysztof Foltman", calf_plugins::calf_copyright_info, "SynthesizerPlugin" }; + +plugin_command_info *organ_metadata::get_commands() +{ + static plugin_command_info cmds[] = { + { "cmd_panic", "Panic!", "Stop all sounds and reset all controllers" }, + { NULL } + }; + return cmds; +} + +CALF_PORT_NAMES(organ) = {"Out L", "Out R"}; + +const char *organ_percussion_trigger_names[] = { "First note", "Each note", "Each, no retrig", "Polyphonic" }; + +const char *organ_wave_names[] = { + "Sin", + "S0", "S00", "S000", + "SSaw", "SSqr", "SPls", + "Saw", "Sqr", "Pls", + "S(", "Sq(", "S+", "Clvg", + "Bell", "Bell2", + "W1", "W2", "W3", "W4", "W5", "W6", "W7", "W8", "W9", + "DSaw", "DSqr", "DPls", + "P:SynStr","P:WideStr","P:Sine","P:Bell","P:Space","P:Voice","P:Hiss","P:Chant", +}; + +const char *organ_routing_names[] = { "Out", "Flt 1", "Flt 2" }; + +const char *organ_ampctl_names[] = { "None", "Direct", "Flt 1", "Flt 2", "All" }; + +const char *organ_vibrato_mode_names[] = { "None", "Direct", "Flt 1", "Flt 2", "Voice", "Global" }; + +const char *organ_filter_type_names[] = { "12dB/oct LP", "12dB/oct HP" }; + +const char *organ_filter_send_names[] = { "Output", "Filter 2" }; + +const char *organ_init_map_curve = "2\n0 1\n1 1\n"; + +CALF_PORT_PROPS(organ) = { + { 8, 0, 8, 80, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "l1", "16'" }, + { 8, 0, 8, 80, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "l2", "5 1/3'" }, + { 8, 0, 8, 80, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "l3", "8'" }, + { 0, 0, 8, 80, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "l4", "4'" }, + { 0, 0, 8, 80, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "l5", "2 2/3'" }, + { 0, 0, 8, 80, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "l6", "2'" }, + { 0, 0, 8, 80, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "l7", "1 3/5'" }, + { 0, 0, 8, 80, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "l8", "1 1/3'" }, + { 8, 0, 8, 80, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "l9", "1'" }, + + { 1, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "f1", "Freq 1" }, + { 3, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "f2", "Freq 2" }, + { 2, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "f3", "Freq 3" }, + { 4, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "f4", "Freq 4" }, + { 6, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "f5", "Freq 5" }, + { 8, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "f6", "Freq 6" }, + { 10, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "f7", "Freq 7" }, + { 12, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "f8", "Freq 8" }, + { 16, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "f9", "Freq 9" }, + + { 0, 0, organ_enums::wave_count - 1, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_wave_names, "w1", "Wave 1" }, + { 0, 0, organ_enums::wave_count - 1, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_wave_names, "w2", "Wave 2" }, + { 0, 0, organ_enums::wave_count - 1, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_wave_names, "w3", "Wave 3" }, + { 0, 0, organ_enums::wave_count - 1, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_wave_names, "w4", "Wave 4" }, + { 0, 0, organ_enums::wave_count - 1, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_wave_names, "w5", "Wave 5" }, + { 0, 0, organ_enums::wave_count - 1, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_wave_names, "w6", "Wave 6" }, + { 0, 0, organ_enums::wave_count - 1, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_wave_names, "w7", "Wave 7" }, + { 0, 0, organ_enums::wave_count - 1, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_wave_names, "w8", "Wave 8" }, + { 0, 0, organ_enums::wave_count - 1, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_wave_names, "w9", "Wave 9" }, + + { 0, -100,100, 401, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "detune1", "Detune 1" }, + { 0, -100,100, 401, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "detune2", "Detune 2" }, + { 0, -100,100, 401, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "detune3", "Detune 3" }, + { 0, -100,100, 401, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "detune4", "Detune 4" }, + { 0, -100,100, 401, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "detune5", "Detune 5" }, + { 0, -100,100, 401, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "detune6", "Detune 6" }, + { 0, -100,100, 401, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "detune7", "Detune 7" }, + { 0, -100,100, 401, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "detune8", "Detune 8" }, + { 0, -100,100, 401, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "detune9", "Detune 9" }, + + { 0, 0,360, 361, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_DEG, NULL, "phase1", "Phase 1" }, + { 0, 0,360, 361, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_DEG, NULL, "phase2", "Phase 2" }, + { 0, 0,360, 361, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_DEG, NULL, "phase3", "Phase 3" }, + { 0, 0,360, 361, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_DEG, NULL, "phase4", "Phase 4" }, + { 0, 0,360, 361, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_DEG, NULL, "phase5", "Phase 5" }, + { 0, 0,360, 361, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_DEG, NULL, "phase6", "Phase 6" }, + { 0, 0,360, 361, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_DEG, NULL, "phase7", "Phase 7" }, + { 0, 0,360, 361, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_DEG, NULL, "phase8", "Phase 8" }, + { 0, 0,360, 361, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_DEG, NULL, "phase9", "Phase 9" }, + + { 0, -1, 1, 201, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "pan1", "Pan 1" }, + { 0, -1, 1, 201, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "pan2", "Pan 2" }, + { 0, -1, 1, 201, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "pan3", "Pan 3" }, + { 0, -1, 1, 201, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "pan4", "Pan 4" }, + { 0, -1, 1, 201, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "pan5", "Pan 5" }, + { 0, -1, 1, 201, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "pan6", "Pan 6" }, + { 0, -1, 1, 201, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "pan7", "Pan 7" }, + { 0, -1, 1, 201, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "pan8", "Pan 8" }, + { 0, -1, 1, 201, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "pan9", "Pan 9" }, + + { 0, 0, 2, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_routing_names, "routing1", "Routing 1" }, + { 0, 0, 2, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_routing_names, "routing2", "Routing 2" }, + { 0, 0, 2, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_routing_names, "routing3", "Routing 3" }, + { 0, 0, 2, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_routing_names, "routing4", "Routing 4" }, + { 0, 0, 2, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_routing_names, "routing5", "Routing 5" }, + { 0, 0, 2, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_routing_names, "routing6", "Routing 6" }, + { 0, 0, 2, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_routing_names, "routing7", "Routing 7" }, + { 0, 0, 2, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_routing_names, "routing8", "Routing 8" }, + { 0, 0, 2, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_routing_names, "routing9", "Routing 9" }, + + { 96, 0, 127, 128, PF_INT | PF_CTL_KNOB | PF_UNIT_NOTE, NULL, "foldnote", "Foldover" }, + + { 200, 10, 3000, 100, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "perc_decay", "P: Carrier Decay" }, + { 0.25, 0, 1, 100, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB, NULL, "perc_level", "P: Level" }, + { 0, 0, organ_enums::wave_count_small - 1, 1, PF_ENUM | PF_CTL_COMBO, organ_wave_names, "perc_waveform", "P: Carrier Wave" }, + { 6, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "perc_harmonic", "P: Carrier Frq" }, + { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "perc_vel2amp", "P: Vel->Amp" }, + + { 200, 10, 3000, 100, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "perc_fm_decay", "P: Modulator Decay" }, + { 0, 0, 4, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "perc_fm_depth", "P: FM Depth" }, + { 0, 0, organ_enums::wave_count_small - 1, 1, PF_ENUM | PF_CTL_COMBO, organ_wave_names, "perc_fm_waveform", "P: Modulator Wave" }, + { 6, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "perc_fm_harmonic", "P: Modulator Frq" }, + { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "perc_vel2fm", "P: Vel->FM" }, + + { 0, 0, organ_enums::perctrig_count - 1, 0, PF_ENUM | PF_CTL_COMBO, organ_percussion_trigger_names, "perc_trigger", "P: Trigger" }, + { 90, 0,360, 361, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_DEG, NULL, "perc_stereo", "P: Stereo Phase" }, + + { 0, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, organ_filter_send_names, "filter_chain", "Filter 1 To" }, + { 0, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, organ_filter_type_names, "filter1_type", "Filter 1 Type" }, + { 0.1, 0, 1, 100, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_PROP_OUTPUT_GAIN | PF_PROP_GRAPH, NULL, "master", "Volume" }, + + { 2000, 20, 20000, 100, PF_FLOAT | PF_SCALE_LOG | PF_UNIT_HZ | PF_CTL_KNOB, NULL, "f1_cutoff", "F1 Cutoff" }, + { 2, 0.7, 8, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB, NULL, "f1_res", "F1 Res" }, + { 8000, -10800,10800, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "f1_env1", "F1 Env1" }, + { 0, -10800,10800, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "f1_env2", "F1 Env2" }, + { 0, -10800,10800, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "f1_env3", "F1 Env3" }, + { 0, 0, 2, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "f1_keyf", "F1 KeyFollow" }, + + { 2000, 20, 20000, 100, PF_FLOAT | PF_SCALE_LOG | PF_UNIT_HZ | PF_CTL_KNOB, NULL, "f2_cutoff", "F2 Cutoff" }, + { 2, 0.7, 8, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB, NULL, "f2_res", "F2 Res" }, + { 0, -10800,10800, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "f2_env1", "F2 Env1" }, + { 8000, -10800,10800, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "f2_env2", "F2 Env2" }, + { 0, -10800,10800, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "f2_env3", "F2 Env3" }, + { 0, 0, 2, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "f2_keyf", "F2 KeyFollow" }, + + { 1, 1,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr_a", "EG1 Attack" }, + { 350, 10,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr_d", "EG1 Decay" }, + { 0.5, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "adsr_s", "EG1 Sustain" }, + { 50, 10,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr_r", "EG1 Release" }, + { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "adsr_v", "EG1 VelMod" }, + { 0, 0, organ_enums::ampctl_count - 1, + 0, PF_INT | PF_CTL_COMBO, organ_ampctl_names, "eg1_amp_ctl", "EG1 To Amp"}, + + { 1, 1,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr2_a", "EG2 Attack" }, + { 350, 10,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr2_d", "EG2 Decay" }, + { 0.5, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "adsr2_s", "EG2 Sustain" }, + { 50, 10,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr2_r", "EG2 Release" }, + { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "adsr2_v", "EG2 VelMod" }, + { 0, 0, organ_enums::ampctl_count - 1, + 0, PF_INT | PF_CTL_COMBO, organ_ampctl_names, "eg2_amp_ctl", "EG2 To Amp"}, + + { 1, 1,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr3_a", "EG3 Attack" }, + { 350, 10,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr3_d", "EG3 Decay" }, + { 0.5, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "adsr3_s", "EG3 Sustain" }, + { 50, 10,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr3_r", "EG3 Release" }, + { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "adsr3_v", "EG3 VelMod" }, + { 0, 0, organ_enums::ampctl_count - 1, + 0, PF_INT | PF_CTL_COMBO, organ_ampctl_names, "eg3_amp_ctl", "EG3 To Amp"}, + + { 6.6, 0.01, 80, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "vib_rate", "Vib Rate" }, + { 0.5, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB , NULL, "vib_amt", "Vib Mod Amt" }, + { 0.5, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB , NULL, "vib_wet", "Vib Wet" }, + { 180, 0, 360, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_DEG, NULL, "vib_phase", "Vib Stereo" }, + { organ_enums::lfomode_global, 0, organ_enums::lfomode_count - 1, 0, PF_ENUM | PF_CTL_COMBO, organ_vibrato_mode_names, "vib_mode", "Vib Mode" }, +// { 0, 0, organ_enums::ampctl_count - 1, +// 0, PF_INT | PF_CTL_COMBO, organ_ampctl_names, "vel_amp_ctl", "Vel To Amp"}, + + { -12, -24, 24, 49, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_SEMITONES, NULL, "transpose", "Transpose" }, + { 0, -100, 100, 201, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "detune", "Detune" }, + + { 16, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "polyphony", "Polyphony" }, + + { 1, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "quad_env", "Quadratic AmpEnv" }, + + { 200, 0, 2400, 25, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "pbend_range", "PBend Range" }, + + { 80, 20, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "bass_freq", "Bass Freq" }, + { 1, 0.1, 10, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "bass_gain", "Bass Gain" }, + { 12000, 20, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "treble_freq", "Treble Freq" }, + { 1, 0.1, 10, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "treble_gain", "Treble Gain" }, + + { 0, 0, 0, 0, PF_STRING | PF_PROP_MSGCONTEXT, &organ_init_map_curve, "map_curve", "Key mapping curve" }, +}; + +//////////////////////////////////////////////////////////////////////////// + +const char *fluidsynth_init_soundfont = ""; +const char *fluidsynth_init_presetkeyset = ""; + +const char *fluidsynth_interpolation_names[] = { "None (zero-hold)", "Linear", "Cubic", "7-point" }; + +CALF_PORT_NAMES(fluidsynth) = { + "Out L", "Out R", +}; + +CALF_PLUGIN_INFO(fluidsynth) = { 0x8700, "Fluidsynth", "Calf Fluidsynth", "FluidSynth Team / Krzysztof Foltman", calf_plugins::calf_copyright_info, "SynthesizerPlugin" }; + +CALF_PORT_PROPS(fluidsynth) = { + { 0.5, 0, 1, 100, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_PROP_OUTPUT_GAIN, NULL, "master", "Volume" }, + { 2, 0, 3, 0, PF_ENUM | PF_CTL_COMBO, fluidsynth_interpolation_names, "interpolation", "Interpolation" }, + { 1, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "reverb", "Reverb" }, + { 1, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "chorus", "Chorus" }, + { 0, 0, 0, 0, PF_STRING | PF_PROP_MSGCONTEXT, &fluidsynth_init_soundfont, "soundfont", "Soundfont" }, + { 0, 0, 0, 0, PF_STRING | PF_PROP_MSGCONTEXT, &fluidsynth_init_presetkeyset, "preset_key_set", "Set Preset" }, +}; + +//////////////////////////////////////////////////////////////////////////// + +const char *wavetable_names[] = { + "Shiny1", + "Shiny2", + "Rezo", + "Metal", + "Bell", + "Blah", + "Pluck", + "Stretch", + "Stretch 2", + "Hard Sync", + "Hard Sync 2", + "Soft Sync", + "Bell 2", + "Bell 3", + "Tine", + "Tine 2", + "Clav", + "Clav 2", + "Gtr", + "Gtr 2", + "Gtr 3", + "Gtr 4", + "Gtr 5", + "Reed", + "Reed 2", + "Silver", + "Brass", + "Multi", + "Multi 2", +}; + +const char *wavetable_init_soundfont = ""; + +CALF_PORT_NAMES(wavetable) = { + "Out L", "Out R", +}; + +CALF_PLUGIN_INFO(wavetable) = { 0x8701, "Wavetable", "Calf Wavetable", "Krzysztof Foltman", calf_plugins::calf_copyright_info, "SynthesizerPlugin" }; + +CALF_PORT_PROPS(wavetable) = { + { wavetable_metadata::wt_count - 1, 0, wavetable_metadata::wt_count - 1, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, wavetable_names, "o1wave", "Osc1 Wave" }, + { 0.2, -1, 1, 0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "o1offset", "Osc1 Ctl"}, + { 0, -48, 48, 48*2+1, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_SEMITONES, NULL, "o1trans", "Osc1 Transpose" }, + { 6, -100, 100, 0, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "o1detune", "Osc1 Detune" }, + { 0.1, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "o1level", "Osc1 Level" }, + + { 0, 0, wavetable_metadata::wt_count - 1, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, wavetable_names, "o2wave", "Osc2 Wave" }, + { 0.4, -1, 1, 0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "o2offset", "Osc2 Ctl"}, + { 0, -48, 48, 48*2+1, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_SEMITONES, NULL, "o2trans", "Osc2 Transpose" }, + { -6, -100, 100, 0, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "o2detune", "Osc2 Detune" }, + { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "o2level", "Osc2 Level" }, + + { 1, 1,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr_a", "EG1 Attack" }, + { 350, 10,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr_d", "EG1 Decay" }, + { 0.5, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "adsr_s", "EG1 Sustain" }, + { 0, -10000,10000, 21, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr_f", "EG1 Fade" }, + { 50, 10,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr_r", "EG1 Release" }, + { 1, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "adsr_v", "EG1 VelMod" }, + + { 1, 1,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr2_a", "EG2 Attack" }, + { 350, 10,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr2_d", "EG2 Decay" }, + { 0.5, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "adsr2_s", "EG2 Sustain" }, + { 0, -10000,10000, 21, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr2_f", "EG2 Fade" }, + { 50, 10,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr2_r", "EG2 Release" }, + { 1, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "adsr2_v", "EG2 VelMod" }, + + { 1, 1,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr3_a", "EG3 Attack" }, + { 350, 10,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr3_d", "EG3 Decay" }, + { 0.5, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "adsr3_s", "EG3 Sustain" }, + { 0, -10000,10000, 21, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr3_f", "EG3 Fade" }, + { 50, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr3_r", "EG3 Release" }, + { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "adsr3_v", "EG3 VelMod" }, + + { 200, 0, 2400, 25, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "pbend_range", "PBend Range" }, +}; + +//////////////////////////////////////////////////////////////////////////// + +calf_plugins::plugin_registry::plugin_registry() +{ + #define PER_MODULE_ITEM(name, isSynth, jackname) plugins.push_back((new name##_metadata)); + #include +} + diff --git a/plugins/ladspa_effect/calf/src/modmatrix.cpp b/plugins/ladspa_effect/calf/src/modmatrix.cpp index cba6ced8b..2ef798aca 100644 --- a/plugins/ladspa_effect/calf/src/modmatrix.cpp +++ b/plugins/ladspa_effect/calf/src/modmatrix.cpp @@ -18,9 +18,10 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA */ -#include -#include #include +#include +#include +#include using namespace std; using namespace dsp; @@ -59,17 +60,17 @@ mod_matrix::mod_matrix(modulation_entry *_matrix, unsigned int _rows, const char matrix[i].reset(); } -const table_column_info *mod_matrix::get_table_columns(int param) +const table_column_info *mod_matrix::get_table_columns(int param) const { return table_columns; } -uint32_t mod_matrix::get_table_rows(int param) +uint32_t mod_matrix::get_table_rows(int param) const { return matrix_rows; } -std::string mod_matrix::get_cell(int param, int row, int column) +std::string mod_matrix::get_cell(int param, int row, int column) const { assert(row >= 0 && row < (int)matrix_rows); modulation_entry &slot = matrix[row]; @@ -90,7 +91,7 @@ std::string mod_matrix::get_cell(int param, int row, int column) } } -void mod_matrix::set_cell(int param, int row, int column, const std::string &src, std::string &error) +void mod_matrix::set_cell(int param, int row, int column, const std::string &src, std::string &error) const { assert(row >= 0 && row < (int)matrix_rows); modulation_entry &slot = matrix[row]; diff --git a/plugins/ladspa_effect/calf/src/modules.cpp b/plugins/ladspa_effect/calf/src/modules.cpp index 225e38712..fdfab11cc 100644 --- a/plugins/ladspa_effect/calf/src/modules.cpp +++ b/plugins/ladspa_effect/calf/src/modules.cpp @@ -1,7 +1,7 @@ -/* Calf DSP Library - * Example audio modules - parameters and LADSPA wrapper instantiation +/* Calf DSP plugin pack + * Assorted plugins * - * Copyright (C) 2001-2008 Krzysztof Foltman + * Copyright (C) 2001-2010 Krzysztof Foltman, Markus Schmidt, Thor Harald Johansen * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -18,929 +18,428 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA */ -#include +#include #include -#if USE_JACK -#include -#endif #include -#include -#include +#include +#include using namespace dsp; using namespace calf_plugins; -const char *calf_plugins::calf_copyright_info = "(C) 2001-2008 Krzysztof Foltman, license: LGPL"; +#define SET_IF_CONNECTED(name) if (params[AM::param_##name] != NULL) *params[AM::param_##name] = name; -//////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// -CALF_PORT_NAMES(flanger) = {"In L", "In R", "Out L", "Out R"}; - -CALF_PORT_PROPS(flanger) = { - { 0.1, 0.1, 10, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC | PF_PROP_GRAPH, NULL, "min_delay", "Min delay" }, - { 0.5, 0.1, 10, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "mod_depth", "Mod depth" }, - { 0.25, 0.01, 20, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "mod_rate", "Mod rate" }, - { 0.90, -0.99, 0.99, 0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "feedback", "Feedback" }, - { 0, 0, 360, 9, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_DEG, NULL, "stereo", "Stereo phase" }, - { 0, 0, 1, 2, PF_BOOL | PF_CTL_BUTTON , NULL, "reset", "Reset" }, - { 1, 0, 4, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "amount", "Amount" }, - { 1.0, 0, 4, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "dry", "Dry Amount" }, -}; - -CALF_PLUGIN_INFO(flanger) = { 0x847d, "Flanger", "Calf Flanger", "Krzysztof Foltman", calf_plugins::calf_copyright_info, "FlangerPlugin" }; - -//////////////////////////////////////////////////////////////////////////// - -CALF_PORT_NAMES(phaser) = {"In L", "In R", "Out L", "Out R"}; - -CALF_PORT_PROPS(phaser) = { - { 1000, 20, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "base_freq", "Center Freq" }, - { 4000, 0, 10800, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "mod_depth", "Mod depth" }, - { 0.25, 0.01, 20, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "mod_rate", "Mod rate" }, - { 0.25, -0.99, 0.99, 0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "feedback", "Feedback" }, - { 6, 1, 12, 12, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "stages", "# Stages" }, - { 180, 0, 360, 9, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_DEG, NULL, "stereo", "Stereo phase" }, - { 0, 0, 1, 2, PF_BOOL | PF_CTL_BUTTON , NULL, "reset", "Reset" }, - { 1, 0, 4, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "amount", "Amount" }, - { 1.0, 0, 4, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "dry", "Dry Amount" }, -}; - -CALF_PLUGIN_INFO(phaser) = { 0x8484, "Phaser", "Calf Phaser", "Krzysztof Foltman", calf_plugins::calf_copyright_info, "PhaserPlugin" }; - -//////////////////////////////////////////////////////////////////////////// - -CALF_PORT_NAMES(reverb) = {"In L", "In R", "Out L", "Out R"}; - -const char *reverb_room_sizes[] = { "Small", "Medium", "Large", "Tunnel-like", "Large/smooth", "Experimental" }; - -CALF_PORT_PROPS(reverb) = { - { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip", "0dB" }, - { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_wet", "Wet amount" }, - { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_out", "Output" }, - { 1.5, 0.4, 15.0, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_SEC, NULL, "decay_time", "Decay time" }, - { 5000, 2000,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "hf_damp", "High Frq Damp" }, - { 2, 0, 5, 0, PF_ENUM | PF_CTL_COMBO , reverb_room_sizes, "room_size", "Room size", }, - { 0.5, 0, 1, 0, PF_FLOAT | PF_CTL_KNOB | PF_SCALE_PERC, NULL, "diffusion", "Diffusion" }, - { 0.25, 0, 2, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "amount", "Wet Amount" }, - { 1.0, 0, 2, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "dry", "Dry Amount" }, - { 0, 0, 50, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "predelay", "Pre Delay" }, - { 300, 20, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "bass_cut", "Bass Cut" }, - { 5000, 20, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "treble_cut", "Treble Cut" }, -}; - -CALF_PLUGIN_INFO(reverb) = { 0x847e, "Reverb", "Calf Reverb", "Krzysztof Foltman", calf_plugins::calf_copyright_info, "ReverbPlugin" }; - -//////////////////////////////////////////////////////////////////////////// - -CALF_PORT_NAMES(filter) = {"In L", "In R", "Out L", "Out R"}; - -const char *filter_choices[] = { - "12dB/oct Lowpass", - "24dB/oct Lowpass", - "36dB/oct Lowpass", - "12dB/oct Highpass", - "24dB/oct Highpass", - "36dB/oct Highpass", - "6dB/oct Bandpass", - "12dB/oct Bandpass", - "18dB/oct Bandpass", - "6dB/oct Bandreject", - "12dB/oct Bandreject", - "18dB/oct Bandreject", -}; - -CALF_PORT_PROPS(filter) = { - { 2000, 10,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "freq", "Frequency" }, - { 0.707, 0.707, 32, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "res", "Resonance" }, - { biquad_filter_module::mode_12db_lp, - biquad_filter_module::mode_12db_lp, - biquad_filter_module::mode_count - 1, - 1, PF_ENUM | PF_CTL_COMBO, filter_choices, "mode", "Mode" }, - { 20, 5, 100, 20, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "inertia", "Inertia"}, -}; - -CALF_PLUGIN_INFO(filter) = { 0x847f, "Filter", "Calf Filter", "Krzysztof Foltman", calf_plugins::calf_copyright_info, "FilterPlugin" }; - -//////////////////////////////////////////////////////////////////////////// - -CALF_PORT_NAMES(filterclavier) = {"In L", "In R", "Out L", "Out R"}; - -CALF_PORT_PROPS(filterclavier) = { - { 0, -48, 48, 48*2+1, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_SEMITONES, NULL, "transpose", "Transpose" }, - { 0, -100, 100, 0, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "detune", "Detune" }, - { 32, 0.707, 32, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "maxres", "Max. Resonance" }, - { biquad_filter_module::mode_6db_bp, - biquad_filter_module::mode_12db_lp, - biquad_filter_module::mode_count - 1, - 1, PF_ENUM | PF_CTL_COMBO | PF_PROP_GRAPH, filter_choices, "mode", "Mode" }, - { 20, 1, 2000, 20, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "inertia", "Portamento time"} -}; - -CALF_PLUGIN_INFO(filterclavier) = { 0x849f, "Filterclavier", "Calf Filterclavier", "Krzysztof Foltman / Hans Baier", calf_plugins::calf_copyright_info, "FilterclavierPlugin" }; - -//////////////////////////////////////////////////////////////////////////// - -CALF_PORT_NAMES(vintage_delay) = {"In L", "In R", "Out L", "Out R"}; - -const char *vintage_delay_mixmodes[] = { - "Stereo", - "Ping-Pong", -}; - -const char *vintage_delay_fbmodes[] = { - "Plain", - "Tape", - "Old Tape", -}; - -CALF_PORT_PROPS(vintage_delay) = { - { 120, 30, 300, 1, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_BPM, NULL, "bpm", "Tempo" }, - { 4, 1, 16, 1, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "subdiv", "Subdivide"}, - { 3, 1, 16, 1, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "time_l", "Time L"}, - { 5, 1, 16, 1, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "time_r", "Time R"}, - { 0.5, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "feedback", "Feedback" }, - { 0.25, 0, 4, 100, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "amount", "Amount" }, - { 1, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, vintage_delay_mixmodes, "mix_mode", "Mix mode" }, - { 1, 0, 2, 0, PF_ENUM | PF_CTL_COMBO, vintage_delay_fbmodes, "medium", "Medium" }, - { 1.0, 0, 4, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "dry", "Dry Amount" }, -}; - -CALF_PLUGIN_INFO(vintage_delay) = { 0x8482, "VintageDelay", "Calf Vintage Delay", "Krzysztof Foltman", calf_plugins::calf_copyright_info, "DelayPlugin" }; - -//////////////////////////////////////////////////////////////////////////// - -CALF_PORT_NAMES(rotary_speaker) = {"In L", "In R", "Out L", "Out R"}; - -const char *rotary_speaker_speed_names[] = { "Off", "Chorale", "Tremolo", "HoldPedal", "ModWheel", "Manual" }; - -CALF_PORT_PROPS(rotary_speaker) = { - { 5, 0, 5, 1.01, PF_ENUM | PF_CTL_COMBO, rotary_speaker_speed_names, "vib_speed", "Speed Mode" }, - { 0.5, 0, 1, 0, PF_FLOAT | PF_CTL_KNOB | PF_SCALE_PERC, NULL, "spacing", "Tap Spacing" }, - { 0.5, 0, 1, 0, PF_FLOAT | PF_CTL_KNOB | PF_SCALE_PERC, NULL, "shift", "Tap Offset" }, - { 0.10, 0, 1, 0, PF_FLOAT | PF_CTL_KNOB | PF_SCALE_PERC, NULL, "mod_depth", "Mod Depth" }, - { 36, 10, 600, 0, PF_FLOAT | PF_CTL_KNOB | PF_SCALE_LOG | PF_UNIT_RPM, NULL, "treble_speed", "Treble Motor" }, - { 30, 10, 600, 0, PF_FLOAT | PF_CTL_KNOB | PF_SCALE_LOG | PF_UNIT_RPM, NULL, "bass_speed", "Bass Motor" }, - { 0.7, 0, 1, 101, PF_FLOAT | PF_CTL_KNOB | PF_SCALE_PERC, NULL, "mic_distance", "Mic Distance" }, - { 0.3, 0, 1, 101, PF_FLOAT | PF_CTL_KNOB | PF_SCALE_PERC, NULL, "reflection", "Reflection" }, - { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_l", "Low rotor" }, - { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_h", "High rotor" }, -}; - -CALF_PLUGIN_INFO(rotary_speaker) = { 0x8483, "RotarySpeaker", "Calf Rotary Speaker", "Krzysztof Foltman", calf_plugins::calf_copyright_info, "SimulationPlugin" }; - -//////////////////////////////////////////////////////////////////////////// - -CALF_PORT_NAMES(multichorus) = {"In L", "In R", "Out L", "Out R"}; - -CALF_PORT_PROPS(multichorus) = { - { 5, 0.1, 10, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC | PF_PROP_GRAPH, NULL, "min_delay", "Min delay" }, - { 6, 0.1, 10, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC| PF_PROP_GRAPH, NULL, "mod_depth", "Mod depth" }, - { 0.5, 0.01, 20, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ| PF_PROP_GRAPH, NULL, "mod_rate", "Modulation rate" }, - { 180, 0, 360, 91, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_DEG, NULL, "stereo", "Stereo phase" }, - { 4, 1, 8, 8, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "voices", "Voices"}, - { 64, 0, 360, 91, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_DEG, NULL, "vphase", "Inter-voice phase" }, - { 2, 0, 4, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "amount", "Amount" }, - { 1.0, 0, 4, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "dry", "Dry Amount" }, - { 100, 10,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "freq", "Center Frq 1" }, - { 5000, 10,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "freq2", "Center Frq 2" }, - { 0.125, 0.125, 8, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "q", "Q" }, - { 1, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "overlap", "Overlap" }, -}; - -CALF_PLUGIN_INFO(multichorus) = { 0x8501, "MultiChorus", "Calf MultiChorus", "Krzysztof Foltman", calf_plugins::calf_copyright_info, "ChorusPlugin" }; - -//////////////////////////////////////////////////////////////////////////// - -CALF_PORT_NAMES(compressor) = {"In L", "In R", "Out L", "Out R"}; - -const char *compressor_detection_names[] = { "RMS", "Peak" }; -const char *compressor_stereo_link_names[] = { "Average", "Maximum" }; -const char *compressor_weighting_names[] = { "Normal", "A-weighted", "Deesser (low)", "Deesser (med)", "Deesser (high)" }; - -CALF_PORT_PROPS(compressor) = { - { 0.125, 0.000976563, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "threshold", "Threshold" }, - { 2, 1, 20, 21, PF_FLOAT | PF_SCALE_LOG_INF | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "ratio", "Ratio" }, - { 20, 0.01, 2000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "attack", "Attack" }, - { 250, 0.01, 2000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "release", "Release" }, - { 2, 1, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "makeup", "Makeup Gain" }, - { 2.828427125, 1, 8, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "knee", "Knee" }, - { 0, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, compressor_detection_names, "detection", "Detection" }, - { 0, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, compressor_stereo_link_names, "stereo_link", "Stereo Link" }, - { 0, 0, 4, 0, PF_ENUM | PF_CTL_COMBO, compressor_weighting_names, "aweighting", "Weighting" }, - { 0, 0.03125, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_CTLO_REVERSE | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL| PF_PROP_GRAPH, NULL, "compression", "Compression" }, - { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "peak", "Peak Output" }, - { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip", "0dB" }, - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass", "Bypass" }, - { 1, 0, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "input", "Input" }, - // { 2000, 10,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "deess_freq", "Frequency" }, - // { 0.707, 0.707, 32, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "deess_res", "Q" }, -}; - -CALF_PLUGIN_INFO(compressor) = { 0x8502, "Compressor", "Calf Compressor", "Thor Harald Johansen", calf_plugins::calf_copyright_info, "CompressorPlugin" }; - -//////////////////////////////////////////////////////////////////////////// - -CALF_PORT_NAMES(sidechaincompressor) = {"In L", "In R", "Out L", "Out R"}; - -const char *sidechaincompressor_detection_names[] = { "RMS", "Peak" }; -const char *sidechaincompressor_stereo_link_names[] = { "Average", "Maximum" }; -const char *sidechaincompressor_mode_names[] = {"Wideband (F1:off / F2:off)", - "Deesser wide (F1:Bell / F2:HP)", - "Deesser split (F1:off / F2:HP)", - "Derumbler wide (F1:LP / F2:Bell)", - "Derumbler split (F1:LP / F2:off)", - "Weighted #1 (F1:Shelf / F2:Shelf)", - "Weighted #2 (F1:Shelf / F2:Bell)", - "Weighted #3 (F1:Bell / F2:Shelf)", - "Bandpass #1 (F1:BP / F2:off)", - "Bandpass #2 (F1:HP / F2:LP)"}; -const char *sidechaincompressor_filter_choices[] = { "12dB", "24dB", "36dB"}; - - -CALF_PORT_PROPS(sidechaincompressor) = { - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass", "Bypass" }, - { 1, 0, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_in", "Input" }, - { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_in", "Input" }, - { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_out", "Output" }, - { 0, 0, 1, 0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_in", "0dB" }, - { 0, 0, 1, 0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_out", "0dB" }, - { 0.125, 0.000976563, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "threshold", "Threshold" }, - { 2, 1, 20, 21, PF_FLOAT | PF_SCALE_LOG_INF | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "ratio", "Ratio" }, - { 20, 0.01, 2000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "attack", "Attack" }, - { 250, 0.01, 2000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "release", "Release" }, - { 2, 1, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "makeup", "Makeup Gain" }, - { 2.828427125, 1, 8, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "knee", "Knee" }, - { 0, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, sidechaincompressor_detection_names, "detection", "Detection" }, - { 0, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, sidechaincompressor_stereo_link_names, "stereo_link", "Stereo Link" }, - { 0, 0.03125, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_CTLO_REVERSE | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL| PF_PROP_GRAPH, NULL, "compression", "Gain Reduction" }, - { 0, 0, 9, 0, PF_ENUM | PF_CTL_COMBO, sidechaincompressor_mode_names, "sc_mode", "Sidechain Mode" }, - { 250, 10,18000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "f1_freq", "Freq" }, - { 4500, 10,18000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "f2_freq", "Freq" }, - { 1, 0.0625, 16, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "f1_level", "Level" }, - { 1, 0.0625, 16, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "f2_level", "Level" }, - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "sc_listen", "S/C-Listen" }, - { 0, 0, 1, 0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "f1_active", "active" }, - { 0, 0, 1, 0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "f2_active", "active" }, -}; - -CALF_PLUGIN_INFO(sidechaincompressor) = { 0x8502, "Sidechaincompressor", "Calf Sidechain Compressor", "Markus Schmidt / Thor Harald Johansen", calf_plugins::calf_copyright_info, "CompressorPlugin" }; - -//////////////////////////////////////////////////////////////////////////// - -CALF_PORT_NAMES(multibandcompressor) = {"In L", "In R", "Out L", "Out R"}; - -const char *multibandcompressor_detection_names[] = { "RMS", "Peak" }; - -CALF_PORT_PROPS(multibandcompressor) = { - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass", "Bypass" }, - { 1, 0, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_in", "Input" }, - { 1, 0, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_out", "Output" }, - { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_inL", "Input L" }, - { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_inR", "Input R" }, - { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_outL", "Output L" }, - { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_outR", "Output R" }, - { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_inL", "0dB" }, - { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_inR", "0dB" }, - { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_outL", "0dB" }, - { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_outR", "0dB" }, - - { 100, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "freq0", "Split 1/2" }, - { 1000, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "freq1", "Split 2/3" }, - { 6000, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "freq2", "Split 3/4" }, - - { -0.17, -0.5, 0.5, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "sep0", "S" }, - { -0.17, -0.5, 0.5, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "sep1", "S" }, - { -0.17, -0.5, 0.5, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "sep2", "S" }, - - { 0.895025, 0.25, 4, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB | PF_PROP_GRAPH, NULL, "q0", "Q" }, - { 0.895025, 0.25, 4, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB | PF_PROP_GRAPH, NULL, "q1", "Q" }, - { 0.895025, 0.25, 4, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB | PF_PROP_GRAPH, NULL, "q2", "Q" }, - - - { 0.0625, 0.000976563, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "threshold0", "Threshold" }, - { 3, 1, 20, 21, PF_FLOAT | PF_SCALE_LOG_INF | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "ratio0", "Ratio" }, - { 50, 0.01, 2000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "attack0", "Attack" }, - { 100, 0.01, 2000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "release0", "Release" }, - { 2, 1, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "makeup0", "Makeup" }, - { 2.828427125, 1, 8, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "knee0", "Knee" }, - { 1, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, multibandcompressor_detection_names, "detection0", "Detection" }, - { 1, 0.03125, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_CTLO_REVERSE | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL| PF_PROP_GRAPH, NULL, "compression0", "Gain Reduction" }, - { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "output0", "Output" }, - { 1, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass0", "Bypass" }, - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "mute0", "Mute" }, - - - { 0.03125, 0.000976563, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "threshold1", "Threshold" }, - { 3, 1, 20, 21, PF_FLOAT | PF_SCALE_LOG_INF | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "ratio1", "Ratio" }, - { 25, 0.01, 2000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "attack1", "Attack" }, - { 50, 0.01, 2000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "release1", "Release" }, - { 2, 1, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "makeup1", "Makeup" }, - { 2.828427125, 1, 8, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "knee1", "Knee" }, - { 1, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, multibandcompressor_detection_names, "detection1", "Detection" }, - { 1, 0.03125, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_CTLO_REVERSE | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL| PF_PROP_GRAPH, NULL, "compression1", "Gain Reduction" }, - { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "output1", "Output" }, - { 1, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass1", "Bypass" }, - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "mute1", "Mute" }, - - - { 0.015625, 0.000976563, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "threshold2", "Threshold" }, - { 3, 1, 20, 21, PF_FLOAT | PF_SCALE_LOG_INF | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "ratio2", "Ratio" }, - { 12.5, 0.01, 2000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "attack2", "Attack" }, - { 25, 0.01, 2000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "release2", "Release" }, - { 2, 1, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "makeup2", "Makeup" }, - { 2.828427125, 1, 8, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "knee2", "Knee" }, - { 1, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, multibandcompressor_detection_names, "detection2", "Detection" }, - { 1, 0.03125, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_CTLO_REVERSE | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL| PF_PROP_GRAPH, NULL, "compression2", "Gain Reduction" }, - { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "output2", "Output" }, - { 1, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass2", "Bypass" }, - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "mute2", "Mute" }, - - - { 0.0078125, 0.000976563, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "threshold3", "Threshold" }, - { 3, 1, 20, 21, PF_FLOAT | PF_SCALE_LOG_INF | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "ratio3", "Ratio" }, - { 6.25, 0.01, 2000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "attack3", "Attack" }, - { 12.5, 0.01, 2000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "release3", "Release" }, - { 2, 1, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "makeup3", "Makeup" }, - { 2.828427125, 1, 8, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "knee3", "Knee" }, - { 1, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, multibandcompressor_detection_names, "detection3", "Detection" }, - { 1, 0.03125, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_CTLO_REVERSE | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL| PF_PROP_GRAPH, NULL, "compression3", "Gain Reduction" }, - { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "output3", "Output" }, - { 1, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass3", "Bypass" }, - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "mute3", "Mute" }, -}; - -CALF_PLUGIN_INFO(multibandcompressor) = { 0x8502, "Multibandcompressor", "Calf Multiband Compressor", "Markus Schmidt / Thor Harald Johansen", calf_plugins::calf_copyright_info, "CompressorPlugin" }; - -//////////////////////////////////////////////////////////////////////////// - -CALF_PORT_NAMES(deesser) = {"In L", "In R", "Out L", "Out R"}; - -const char *deesser_detection_names[] = { "RMS", "Peak" }; -const char *deesser_mode_names[] = { "Wide", "Split" }; - - -CALF_PORT_PROPS(deesser) = { - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass", "Bypass" }, - { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "detected", "Detected" }, - { 0, 0.03125, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_CTLO_REVERSE | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL| PF_PROP_GRAPH, NULL, "compression", "Gain Reduction" }, - { 0, 0, 1, 0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "detected_led", "Active" }, - { 0, 0, 1, 0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_out", "Out" }, - { 0, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, deesser_detection_names, "detection", "Detection" }, - { 0, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, deesser_mode_names, "mode", "Mode" }, - { 0.125, 0.000976563, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "threshold", "Threshold" }, - { 3, 1, 20, 21, PF_FLOAT | PF_SCALE_LOG_INF | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "ratio", "Ratio" }, - { 15, 1, 100, 1, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "laxity", "Laxity" }, - { 1, 1, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "makeup", "Makeup" }, - - { 6000, 10, 18000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "f1_freq", "Split" }, - { 4500, 10, 18000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "f2_freq", "Peak" }, - { 1, 0.0625, 16, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "f1_level", "Gain" }, - { 4, 0.0625, 16, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "f2_level", "Level" }, - { 1, 0.1, 100,1, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "f2_q", "Peak Q" }, - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "sc_listen", "S/C-Listen" }, -}; - -CALF_PLUGIN_INFO(deesser) = { 0x8502, "Deesser", "Calf Deesser", "Markus Schmidt / Thor Harald Johansen", calf_plugins::calf_copyright_info, "CompressorPlugin" }; - -//////////////////////////////////////////////////////////////////////////// - -CALF_PORT_NAMES(equalizer5band) = {"In L", "In R", "Out L", "Out R"}; - -CALF_PORT_PROPS(equalizer5band) = { - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass", "Bypass" }, - { 1, 0, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_in", "Input" }, - { 1, 0, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_out", "Output" }, - { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_in", "Input" }, - { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_out", "Output" }, - { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_in", "0dB" }, - { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_out", "0dB" }, - - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "ls_active", "active" }, - { 1, 0.015625, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "ls_level", "Level" }, - { 200, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "ls_freq", "Freq" }, - - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "hs_active", "active" }, - { 1, 0.015625, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "hs_level", "Level" }, - { 4000, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "hs_freq", "Freq" }, - - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "p1_active", "active" }, - { 1, 0.015625, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "p1_level", "Level 1" }, - { 250, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "p1_freq", "Freq 1" }, - { 1, 0.1, 100, 1, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "p1_q", "Q 1" }, - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "p2_active", "active" }, - { 1, 0.015625, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "p2_level", "Level 2" }, - { 1000, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "p2_freq", "Freq 2" }, - { 1, 0.1, 100, 1, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "p2_q", "Q 2" }, - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "p3_active", "active" }, - { 1, 0.015625, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "p3_level", "Level 3" }, - { 2500, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "p3_freq", "Freq 3" }, - { 1, 0.1, 100, 1, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "p3_q", "Q 3" }, -}; - -CALF_PLUGIN_INFO(equalizer5band) = { 0x8501, "Equalizer5Band", "Calf Equalizer 5 Band", "Markus Schmidt", calf_plugins::calf_copyright_info, "EqualizerPlugin" }; - -////////////////////////////////////////////////////////////////////////////// - -CALF_PORT_NAMES(equalizer8band) = {"In L", "In R", "Out L", "Out R"}; -const char *rolloff_mode_names[] = {"12dB", "24dB", "36dB"}; - -CALF_PORT_PROPS(equalizer8band) = { - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass", "Bypass" }, - { 1, 0, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_in", "Input" }, - { 1, 0, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_out", "Output" }, - { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_inL", "L" }, - { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_inR", "R" }, - { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_outL", "L" }, - { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_outR", "R" }, - { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_inL", "0dB" }, - { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_inR", "0dB" }, - { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_outL", "0dB" }, - { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_outR", "0dB" }, - - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "hp_active", "active" }, - { 30, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "hp_freq", "Freq" }, - { 1, 0, 2, 0, PF_ENUM | PF_CTL_COMBO, rolloff_mode_names, "hp_mode", "Mode" }, - - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "lp_active", "active" }, - { 18000, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "lp_freq", "Freq" }, - { 1, 0, 2, 0, PF_ENUM | PF_CTL_COMBO, rolloff_mode_names, "lp_mode", "Mode" }, - - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "ls_active", "active" }, - { 1, 0.015625, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "ls_level", "Level" }, - { 200, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "ls_freq", "Freq" }, - - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "hs_active", "active" }, - { 1, 0.015625, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "hs_level", "Level" }, - { 4000, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "hs_freq", "Freq" }, - - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "p1_active", "active" }, - { 1, 0.015625, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "p1_level", "Level 1" }, - { 250, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "p1_freq", "Freq 1" }, - { 1, 0.1, 100, 1, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "p1_q", "Q 1" }, - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "p2_active", "active" }, - { 1, 0.015625, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "p2_level", "Level 2" }, - { 1000, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "p2_freq", "Freq 2" }, - { 1, 0.1, 100, 1, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "p2_q", "Q 2" }, - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "p3_active", "active" }, - { 1, 0.015625, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "p3_level", "Level 3" }, - { 2500, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "p3_freq", "Freq 3" }, - { 1, 0.1, 100, 1, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "p3_q", "Q 3" }, - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "p4_active", "active" }, - { 1, 0.015625, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "p4_level", "Level 4" }, - { 5000, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "p4_freq", "Freq 4" }, - { 1, 0.1, 100, 1, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "p4_q", "Q 4" }, -}; - -CALF_PLUGIN_INFO(equalizer8band) = { 0x8501, "Equalizer8Band", "Calf Equalizer 8 Band", "Markus Schmidt", calf_plugins::calf_copyright_info, "EqualizerPlugin" }; - -//////////////////////////////////////////////////////////////////////////// - -CALF_PORT_NAMES(equalizer12band) = {"In L", "In R", "Out L", "Out R"}; - -CALF_PORT_PROPS(equalizer12band) = { - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass", "Bypass" }, - { 1, 0, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_in", "Input" }, - { 1, 0, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_out", "Output" }, - { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_inL", "L" }, - { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_inR", "R" }, - { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_outL", "L" }, - { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_outR", "R" }, - { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_inL", "0dB" }, - { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_inR", "0dB" }, - { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_outL", "0dB" }, - { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_outR", "0dB" }, - - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "hp_active", "active" }, - { 30, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "hp_freq", "Freq" }, - { 1, 0, 2, 0, PF_ENUM | PF_CTL_COMBO, rolloff_mode_names, "hp_mode", "Mode" }, - - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "lp_active", "active" }, - { 18000, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "lp_freq", "Freq" }, - { 1, 0, 2, 0, PF_ENUM | PF_CTL_COMBO, rolloff_mode_names, "lp_mode", "Mode" }, - - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "ls_active", "active" }, - { 1, 0.015625, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "ls_level", "Level" }, - { 200, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "ls_freq", "Freq" }, - - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "hs_active", "active" }, - { 1, 0.015625, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "hs_level", "Level" }, - { 4000, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "hs_freq", "Freq" }, - - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "p1_active", "active" }, - { 1, 0.015625, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "p1_level", "Level 1" }, - { 60, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "p1_freq", "Freq 1" }, - { 1, 0.1, 100, 1, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "p1_q", "Q 1" }, - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "p2_active", "active" }, - { 1, 0.015625, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "p2_level", "Level 2" }, - { 120, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "p2_freq", "Freq 2" }, - { 1, 0.1, 100, 1, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "p2_q", "Q 2" }, - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "p3_active", "active" }, - { 1, 0.015625, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "p3_level", "Level 3" }, - { 250, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "p3_freq", "Freq 3" }, - { 1, 0.1, 100, 1, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "p3_q", "Q 3" }, - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "p4_active", "active" }, - { 1, 0.015625, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "p4_level", "Level 4" }, - { 500, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "p4_freq", "Freq 4" }, - { 1, 0.1, 100, 1, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "p4_q", "Q 4" }, - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "p5_active", "active" }, - { 1, 0.015625, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "p5_level", "Level 5" }, - { 1000, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "p5_freq", "Freq 5" }, - { 1, 0.1, 100, 1, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "p5_q", "Q 5" }, - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "p6_active", "active" }, - { 1, 0.015625, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "p6_level", "Level 6" }, - { 2500, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "p6_freq", "Freq 6" }, - { 1, 0.1, 100, 1, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "p6_q", "Q 6" }, - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "p7_active", "active" }, - { 1, 0.015625, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "p7_level", "Level 7" }, - { 4000, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "p7_freq", "Freq 7" }, - { 1, 0.1, 100, 1, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "p7_q", "Q 7" }, - { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "p8_active", "active" }, - { 1, 0.015625, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "p8_level", "Level 8" }, - { 6000, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "p8_freq", "Freq 8" }, - { 1, 0.1, 100, 1, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "p8_q", "Q 8" }, -}; - -CALF_PLUGIN_INFO(equalizer12band) = { 0x8501, "Equalizer12Band", "Calf Equalizer 12 Band", "Markus Schmidt", calf_plugins::calf_copyright_info, "EqualizerPlugin" }; - -//////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////// - -CALF_PORT_NAMES(monosynth) = { - "Out L", "Out R", -}; - -const char *monosynth_waveform_names[] = { "Sawtooth", "Square", "Pulse", "Sine", "Triangle", "Varistep", "Skewed Saw", "Skewed Square", - "Smooth Brass", "Bass", "Dark FM", "Multiwave", "Bell FM", "Dark Pad", "DCO Saw", "DCO Maze" }; -const char *monosynth_mode_names[] = { "0 : 0", "0 : 180", "0 : 90", "90 : 90", "90 : 270", "Random" }; -const char *monosynth_legato_names[] = { "Retrig", "Legato", "Fng Retrig", "Fng Legato" }; - -const char *monosynth_filter_choices[] = { - "12dB/oct Lowpass", - "24dB/oct Lowpass", - "2x12dB/oct Lowpass", - "12dB/oct Highpass", - "Lowpass+Notch", - "Highpass+Notch", - "6dB/oct Bandpass", - "2x6dB/oct Bandpass", -}; - -CALF_PLUGIN_INFO(monosynth) = { 0x8480, "Monosynth", "Calf Monosynth", "Krzysztof Foltman", calf_plugins::calf_copyright_info, "SynthesizerPlugin" }; - -CALF_PORT_PROPS(monosynth) = { - { monosynth_metadata::wave_saw, 0, monosynth_metadata::wave_count - 1, 1, PF_ENUM | PF_CTL_COMBO | PF_PROP_GRAPH, monosynth_waveform_names, "o1_wave", "Osc1 Wave" }, - { monosynth_metadata::wave_sqr, 0, monosynth_metadata::wave_count - 1, 1, PF_ENUM | PF_CTL_COMBO | PF_PROP_GRAPH, monosynth_waveform_names, "o2_wave", "Osc2 Wave" }, - - { 0, -1, 1, 0.1, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "o1_pw", "Osc1 PW" }, - { 0, -1, 1, 0.1, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "o2_pw", "Osc2 PW" }, - - { 10, 0, 100, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "o12_detune", "O1<>2 Detune" }, - { 12, -24, 24, 0, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_SEMITONES, NULL, "o2_xpose", "Osc 2 transpose" }, - { 0, 0, 5, 0, PF_ENUM | PF_CTL_COMBO, monosynth_mode_names, "phase_mode", "Phase mode" }, - { 0.5, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "o12_mix", "O1<>2 Mix" }, - { 1, 0, 7, 0, PF_ENUM | PF_CTL_COMBO | PF_PROP_GRAPH, monosynth_filter_choices, "filter", "Filter" }, - { 33, 10,16000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "cutoff", "Cutoff" }, - { 2, 0.7, 8, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB, NULL, "res", "Resonance" }, - { 0, -2400, 2400, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "filter_sep", "Separation" }, - { 8000, -10800,10800, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "env2cutoff", "Env->Cutoff" }, - { 1, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "env2res", "Env->Res" }, - { 1, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "env2amp", "Env->Amp" }, - - { 1, 1,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_FADER | PF_UNIT_MSEC, NULL, "adsr_a", "Attack" }, - { 350, 10,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_FADER | PF_UNIT_MSEC, NULL, "adsr_d", "Decay" }, - { 0.5, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "adsr_s", "Sustain" }, - { 0, -10000,10000, 21, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER | PF_UNIT_MSEC, NULL, "adsr_f", "Fade" }, - { 50, 10,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_FADER | PF_UNIT_MSEC, NULL, "adsr_r", "Release" }, - - { 0, 0, 2, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "key_follow", "Key Follow" }, - { 0, 0, 3, 0, PF_ENUM | PF_CTL_COMBO, monosynth_legato_names, "legato", "Legato Mode" }, - { 1, 1, 2000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "portamento", "Portamento" }, - - { 0.5, 0, 1, 0.1, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "vel2filter", "Vel->Filter" }, - { 0, 0, 1, 0.1, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "vel2amp", "Vel->Amp" }, - - { 0.5, 0, 1, 100, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_PROP_OUTPUT_GAIN, NULL, "master", "Volume" }, - - { 200, 0, 2400, 25, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "pbend_range", "PBend Range" }, - - { 5, 0.01, 20, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "lfo_rate", "LFO Rate" }, - { 0.5, 0.1, 5, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_SEC, NULL, "lfo_delay", "LFO Delay" }, - { 0, -4800, 4800, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "lfo2filter", "LFO->Filter" }, - { 100, 0, 1200, 0, PF_FLOAT | PF_SCALE_QUAD | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "lfo2pitch", "LFO->Pitch" }, - { 0, 0, 1, 0.1, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "lfo2pw", "LFO->PW" }, - { 1, 0, 1, 0.1, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "mwhl2lfo", "ModWheel->LFO" }, - - { 1, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "scale_detune", "Scale Detune" }, -}; - -//////////////////////////////////////////////////////////////////////////// - -CALF_PLUGIN_INFO(organ) = { 0x8481, "Organ", "Calf Organ", "Krzysztof Foltman", calf_plugins::calf_copyright_info, "SynthesizerPlugin" }; - -const char **organ_metadata::get_default_configure_vars() +void reverb_audio_module::activate() { - static const char *data[] = { "map_curve", "2\n0 1\n1 1\n", NULL }; - return data; + reverb.reset(); } -plugin_command_info *organ_metadata::get_commands() +void reverb_audio_module::deactivate() { - static plugin_command_info cmds[] = { - { "cmd_panic", "Panic!", "Stop all sounds and reset all controllers" }, - { NULL } - }; - return cmds; } -CALF_PORT_NAMES(organ) = {"Out L", "Out R"}; - -const char *organ_percussion_trigger_names[] = { "First note", "Each note", "Each, no retrig", "Polyphonic" }; - -const char *organ_wave_names[] = { - "Sin", - "S0", "S00", "S000", - "SSaw", "SSqr", "SPls", - "Saw", "Sqr", "Pls", - "S(", "Sq(", "S+", "Clvg", - "Bell", "Bell2", - "W1", "W2", "W3", "W4", "W5", "W6", "W7", "W8", "W9", - "DSaw", "DSqr", "DPls", - "P:SynStr","P:WideStr","P:Sine","P:Bell","P:Space","P:Voice","P:Hiss","P:Chant", -}; - -const char *organ_routing_names[] = { "Out", "Flt 1", "Flt 2" }; - -const char *organ_ampctl_names[] = { "None", "Direct", "Flt 1", "Flt 2", "All" }; - -const char *organ_vibrato_mode_names[] = { "None", "Direct", "Flt 1", "Flt 2", "Voice", "Global" }; - -const char *organ_filter_type_names[] = { "12dB/oct LP", "12dB/oct HP" }; - -const char *organ_filter_send_names[] = { "Output", "Filter 2" }; - -const char *organ_init_map_curve = "2\n0 1\n1 1\n"; - -CALF_PORT_PROPS(organ) = { - { 8, 0, 8, 80, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "l1", "16'" }, - { 8, 0, 8, 80, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "l2", "5 1/3'" }, - { 8, 0, 8, 80, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "l3", "8'" }, - { 0, 0, 8, 80, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "l4", "4'" }, - { 0, 0, 8, 80, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "l5", "2 2/3'" }, - { 0, 0, 8, 80, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "l6", "2'" }, - { 0, 0, 8, 80, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "l7", "1 3/5'" }, - { 0, 0, 8, 80, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "l8", "1 1/3'" }, - { 8, 0, 8, 80, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "l9", "1'" }, - - { 1, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "f1", "Freq 1" }, - { 3, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "f2", "Freq 2" }, - { 2, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "f3", "Freq 3" }, - { 4, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "f4", "Freq 4" }, - { 6, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "f5", "Freq 5" }, - { 8, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "f6", "Freq 6" }, - { 10, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "f7", "Freq 7" }, - { 12, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "f8", "Freq 8" }, - { 16, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "f9", "Freq 9" }, - - { 0, 0, organ_enums::wave_count - 1, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_wave_names, "w1", "Wave 1" }, - { 0, 0, organ_enums::wave_count - 1, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_wave_names, "w2", "Wave 2" }, - { 0, 0, organ_enums::wave_count - 1, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_wave_names, "w3", "Wave 3" }, - { 0, 0, organ_enums::wave_count - 1, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_wave_names, "w4", "Wave 4" }, - { 0, 0, organ_enums::wave_count - 1, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_wave_names, "w5", "Wave 5" }, - { 0, 0, organ_enums::wave_count - 1, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_wave_names, "w6", "Wave 6" }, - { 0, 0, organ_enums::wave_count - 1, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_wave_names, "w7", "Wave 7" }, - { 0, 0, organ_enums::wave_count - 1, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_wave_names, "w8", "Wave 8" }, - { 0, 0, organ_enums::wave_count - 1, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_wave_names, "w9", "Wave 9" }, - - { 0, -100,100, 401, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "detune1", "Detune 1" }, - { 0, -100,100, 401, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "detune2", "Detune 2" }, - { 0, -100,100, 401, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "detune3", "Detune 3" }, - { 0, -100,100, 401, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "detune4", "Detune 4" }, - { 0, -100,100, 401, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "detune5", "Detune 5" }, - { 0, -100,100, 401, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "detune6", "Detune 6" }, - { 0, -100,100, 401, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "detune7", "Detune 7" }, - { 0, -100,100, 401, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "detune8", "Detune 8" }, - { 0, -100,100, 401, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "detune9", "Detune 9" }, - - { 0, 0,360, 361, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_DEG, NULL, "phase1", "Phase 1" }, - { 0, 0,360, 361, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_DEG, NULL, "phase2", "Phase 2" }, - { 0, 0,360, 361, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_DEG, NULL, "phase3", "Phase 3" }, - { 0, 0,360, 361, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_DEG, NULL, "phase4", "Phase 4" }, - { 0, 0,360, 361, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_DEG, NULL, "phase5", "Phase 5" }, - { 0, 0,360, 361, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_DEG, NULL, "phase6", "Phase 6" }, - { 0, 0,360, 361, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_DEG, NULL, "phase7", "Phase 7" }, - { 0, 0,360, 361, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_DEG, NULL, "phase8", "Phase 8" }, - { 0, 0,360, 361, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_DEG, NULL, "phase9", "Phase 9" }, - - { 0, -1, 1, 201, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "pan1", "Pan 1" }, - { 0, -1, 1, 201, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "pan2", "Pan 2" }, - { 0, -1, 1, 201, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "pan3", "Pan 3" }, - { 0, -1, 1, 201, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "pan4", "Pan 4" }, - { 0, -1, 1, 201, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "pan5", "Pan 5" }, - { 0, -1, 1, 201, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "pan6", "Pan 6" }, - { 0, -1, 1, 201, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "pan7", "Pan 7" }, - { 0, -1, 1, 201, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "pan8", "Pan 8" }, - { 0, -1, 1, 201, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "pan9", "Pan 9" }, - - { 0, 0, 2, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_routing_names, "routing1", "Routing 1" }, - { 0, 0, 2, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_routing_names, "routing2", "Routing 2" }, - { 0, 0, 2, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_routing_names, "routing3", "Routing 3" }, - { 0, 0, 2, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_routing_names, "routing4", "Routing 4" }, - { 0, 0, 2, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_routing_names, "routing5", "Routing 5" }, - { 0, 0, 2, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_routing_names, "routing6", "Routing 6" }, - { 0, 0, 2, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_routing_names, "routing7", "Routing 7" }, - { 0, 0, 2, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_routing_names, "routing8", "Routing 8" }, - { 0, 0, 2, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_routing_names, "routing9", "Routing 9" }, - - { 96, 0, 127, 128, PF_INT | PF_CTL_KNOB | PF_UNIT_NOTE, NULL, "foldnote", "Foldover" }, - - { 200, 10, 3000, 100, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "perc_decay", "P: Carrier Decay" }, - { 0.25, 0, 1, 100, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB, NULL, "perc_level", "P: Level" }, - { 0, 0, organ_enums::wave_count_small - 1, 1, PF_ENUM | PF_CTL_COMBO, organ_wave_names, "perc_waveform", "P: Carrier Wave" }, - { 6, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "perc_harmonic", "P: Carrier Frq" }, - { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "perc_vel2amp", "P: Vel->Amp" }, - - { 200, 10, 3000, 100, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "perc_fm_decay", "P: Modulator Decay" }, - { 0, 0, 4, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "perc_fm_depth", "P: FM Depth" }, - { 0, 0, organ_enums::wave_count_small - 1, 1, PF_ENUM | PF_CTL_COMBO, organ_wave_names, "perc_fm_waveform", "P: Modulator Wave" }, - { 6, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "perc_fm_harmonic", "P: Modulator Frq" }, - { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "perc_vel2fm", "P: Vel->FM" }, - - { 0, 0, organ_enums::perctrig_count - 1, 0, PF_ENUM | PF_CTL_COMBO, organ_percussion_trigger_names, "perc_trigger", "P: Trigger" }, - { 90, 0,360, 361, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_DEG, NULL, "perc_stereo", "P: Stereo Phase" }, - - { 0, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, organ_filter_send_names, "filter_chain", "Filter 1 To" }, - { 0, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, organ_filter_type_names, "filter1_type", "Filter 1 Type" }, - { 0.1, 0, 1, 100, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_PROP_OUTPUT_GAIN | PF_PROP_GRAPH, NULL, "master", "Volume" }, - - { 2000, 20, 20000, 100, PF_FLOAT | PF_SCALE_LOG | PF_UNIT_HZ | PF_CTL_KNOB, NULL, "f1_cutoff", "F1 Cutoff" }, - { 2, 0.7, 8, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB, NULL, "f1_res", "F1 Res" }, - { 8000, -10800,10800, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "f1_env1", "F1 Env1" }, - { 0, -10800,10800, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "f1_env2", "F1 Env2" }, - { 0, -10800,10800, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "f1_env3", "F1 Env3" }, - { 0, 0, 2, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "f1_keyf", "F1 KeyFollow" }, - - { 2000, 20, 20000, 100, PF_FLOAT | PF_SCALE_LOG | PF_UNIT_HZ | PF_CTL_KNOB, NULL, "f2_cutoff", "F2 Cutoff" }, - { 2, 0.7, 8, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB, NULL, "f2_res", "F2 Res" }, - { 0, -10800,10800, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "f2_env1", "F2 Env1" }, - { 8000, -10800,10800, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "f2_env2", "F2 Env2" }, - { 0, -10800,10800, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "f2_env3", "F2 Env3" }, - { 0, 0, 2, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "f2_keyf", "F2 KeyFollow" }, - - { 1, 1,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr_a", "EG1 Attack" }, - { 350, 10,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr_d", "EG1 Decay" }, - { 0.5, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "adsr_s", "EG1 Sustain" }, - { 50, 10,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr_r", "EG1 Release" }, - { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "adsr_v", "EG1 VelMod" }, - { 0, 0, organ_enums::ampctl_count - 1, - 0, PF_INT | PF_CTL_COMBO, organ_ampctl_names, "eg1_amp_ctl", "EG1 To Amp"}, - - { 1, 1,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr2_a", "EG2 Attack" }, - { 350, 10,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr2_d", "EG2 Decay" }, - { 0.5, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "adsr2_s", "EG2 Sustain" }, - { 50, 10,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr2_r", "EG2 Release" }, - { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "adsr2_v", "EG2 VelMod" }, - { 0, 0, organ_enums::ampctl_count - 1, - 0, PF_INT | PF_CTL_COMBO, organ_ampctl_names, "eg2_amp_ctl", "EG2 To Amp"}, - - { 1, 1,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr3_a", "EG3 Attack" }, - { 350, 10,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr3_d", "EG3 Decay" }, - { 0.5, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "adsr3_s", "EG3 Sustain" }, - { 50, 10,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr3_r", "EG3 Release" }, - { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "adsr3_v", "EG3 VelMod" }, - { 0, 0, organ_enums::ampctl_count - 1, - 0, PF_INT | PF_CTL_COMBO, organ_ampctl_names, "eg3_amp_ctl", "EG3 To Amp"}, - - { 6.6, 0.01, 80, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "vib_rate", "Vib Rate" }, - { 0.5, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB , NULL, "vib_amt", "Vib Mod Amt" }, - { 0.5, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB , NULL, "vib_wet", "Vib Wet" }, - { 180, 0, 360, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_DEG, NULL, "vib_phase", "Vib Stereo" }, - { organ_enums::lfomode_global, 0, organ_enums::lfomode_count - 1, 0, PF_ENUM | PF_CTL_COMBO, organ_vibrato_mode_names, "vib_mode", "Vib Mode" }, -// { 0, 0, organ_enums::ampctl_count - 1, -// 0, PF_INT | PF_CTL_COMBO, organ_ampctl_names, "vel_amp_ctl", "Vel To Amp"}, - - { -12, -24, 24, 49, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_SEMITONES, NULL, "transpose", "Transpose" }, - { 0, -100, 100, 201, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "detune", "Detune" }, - - { 16, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "polyphony", "Polyphony" }, - - { 1, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "quad_env", "Quadratic AmpEnv" }, - - { 200, 0, 2400, 25, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "pbend_range", "PBend Range" }, - - { 80, 20, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "bass_freq", "Bass Freq" }, - { 1, 0.1, 10, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "bass_gain", "Bass Gain" }, - { 12000, 20, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "treble_freq", "Treble Freq" }, - { 1, 0.1, 10, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "treble_gain", "Treble Gain" }, - - { 0, 0, 0, 0, PF_STRING | PF_PROP_MSGCONTEXT, &organ_init_map_curve, "map_curve", "Key mapping curve" }, -}; - -//////////////////////////////////////////////////////////////////////////// - -const char *fluidsynth_init_soundfont = ""; - -const char *fluidsynth_interpolation_names[] = { "None (zero-hold)", "Linear", "Cubic", "7-point" }; - -CALF_PORT_NAMES(fluidsynth) = { - "Out L", "Out R", -}; - -CALF_PLUGIN_INFO(fluidsynth) = { 0x8700, "Fluidsynth", "Calf Fluidsynth", "FluidSynth Team / Krzysztof Foltman", calf_plugins::calf_copyright_info, "SynthesizerPlugin" }; - -CALF_PORT_PROPS(fluidsynth) = { - { 0.5, 0, 1, 100, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_PROP_OUTPUT_GAIN, NULL, "master", "Volume" }, - { 0, 0, 0, 0, PF_STRING | PF_PROP_MSGCONTEXT, &fluidsynth_init_soundfont, "soundfont", "Soundfont" }, - { 2, 0, 3, 0, PF_ENUM | PF_CTL_COMBO, fluidsynth_interpolation_names, "interpolation", "Interpolation" }, - { 1, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "reverb", "Reverb" }, - { 1, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "chorus", "Chorus" }, -}; - -//////////////////////////////////////////////////////////////////////////// - -const char *wavetable_names[] = { - "Shiny1", - "Shiny2", - "Rezo", - "Metal", - "Bell", - "Blah", - "Pluck", - "Stretch", - "Stretch 2", - "Hard Sync", - "Hard Sync 2", - "Soft Sync", - "Bell 2", - "Bell 3", - "Tine", - "Tine 2", - "Clav", - "Clav 2", - "Gtr", - "Gtr 2", - "Gtr 3", - "Gtr 4", - "Gtr 5", - "Reed", - "Reed 2", - "Silver", - "Brass", - "Multi", - "Multi 2", -}; - -const char *wavetable_init_soundfont = ""; - -CALF_PORT_NAMES(wavetable) = { - "Out L", "Out R", -}; - -CALF_PLUGIN_INFO(wavetable) = { 0x8701, "Wavetable", "Calf Wavetable", "Krzysztof Foltman", calf_plugins::calf_copyright_info, "SynthesizerPlugin" }; - -CALF_PORT_PROPS(wavetable) = { - { wavetable_metadata::wt_count - 1, 0, wavetable_metadata::wt_count - 1, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, wavetable_names, "o1wave", "Osc1 Wave" }, - { 0.2, -1, 1, 0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "o1offset", "Osc1 Ctl"}, - { 0, -48, 48, 48*2+1, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_SEMITONES, NULL, "o1trans", "Osc1 Transpose" }, - { 6, -100, 100, 0, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "o1detune", "Osc1 Detune" }, - { 0.1, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "o1level", "Osc1 Level" }, - - { 0, 0, wavetable_metadata::wt_count - 1, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, wavetable_names, "o2wave", "Osc2 Wave" }, - { 0.4, -1, 1, 0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "o2offset", "Osc2 Ctl"}, - { 0, -48, 48, 48*2+1, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_SEMITONES, NULL, "o2trans", "Osc2 Transpose" }, - { -6, -100, 100, 0, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "o2detune", "Osc2 Detune" }, - { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "o2level", "Osc2 Level" }, - - { 1, 1,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr_a", "EG1 Attack" }, - { 350, 10,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr_d", "EG1 Decay" }, - { 0.5, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "adsr_s", "EG1 Sustain" }, - { 0, -10000,10000, 21, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr_f", "EG1 Fade" }, - { 50, 10,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr_r", "EG1 Release" }, - { 1, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "adsr_v", "EG1 VelMod" }, - - { 1, 1,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr2_a", "EG2 Attack" }, - { 350, 10,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr2_d", "EG2 Decay" }, - { 0.5, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "adsr2_s", "EG2 Sustain" }, - { 0, -10000,10000, 21, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr2_f", "EG2 Fade" }, - { 50, 10,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr2_r", "EG2 Release" }, - { 1, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "adsr2_v", "EG2 VelMod" }, - - { 1, 1,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr3_a", "EG3 Attack" }, - { 350, 10,20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr3_d", "EG3 Decay" }, - { 0.5, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "adsr3_s", "EG3 Sustain" }, - { 0, -10000,10000, 21, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr3_f", "EG3 Fade" }, - { 50, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr3_r", "EG3 Release" }, - { 0, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "adsr3_v", "EG3 VelMod" }, - - { 200, 0, 2400, 25, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "pbend_range", "PBend Range" }, -}; - -//////////////////////////////////////////////////////////////////////////// - -void calf_plugins::get_all_plugins(std::vector &plugins) +void reverb_audio_module::set_sample_rate(uint32_t sr) { - #define PER_MODULE_ITEM(name, isSynth, jackname) plugins.push_back(new name##_metadata); - #define PER_SMALL_MODULE_ITEM(...) - #include + srate = sr; + reverb.setup(sr); + amount.set_sample_rate(sr); +} + +void reverb_audio_module::params_changed() +{ + reverb.set_type_and_diffusion(fastf2i_drm(*params[par_roomsize]), *params[par_diffusion]); + reverb.set_time(*params[par_decay]); + reverb.set_cutoff(*params[par_hfdamp]); + amount.set_inertia(*params[par_amount]); + dryamount.set_inertia(*params[par_dry]); + left_lo.set_lp(dsp::clip(*params[par_treblecut], 20.f, (float)(srate * 0.49f)), srate); + left_hi.set_hp(dsp::clip(*params[par_basscut], 20.f, (float)(srate * 0.49f)), srate); + right_lo.copy_coeffs(left_lo); + right_hi.copy_coeffs(left_hi); + predelay_amt = (int) (srate * (*params[par_predelay]) * (1.0f / 1000.0f) + 1); +} + +uint32_t reverb_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) +{ + numsamples += offset; + clip -= std::min(clip, numsamples); + for (uint32_t i = offset; i < numsamples; i++) { + float dry = dryamount.get(); + float wet = amount.get(); + stereo_sample s(ins[0][i], ins[1][i]); + stereo_sample s2 = pre_delay.process(s, predelay_amt); + + float rl = s2.left, rr = s2.right; + rl = left_lo.process(left_hi.process(rl)); + rr = right_lo.process(right_hi.process(rr)); + reverb.process(rl, rr); + outs[0][i] = dry*s.left + wet*rl; + outs[1][i] = dry*s.right + wet*rr; + meter_wet = std::max(fabs(wet*rl), fabs(wet*rr)); + meter_out = std::max(fabs(outs[0][i]), fabs(outs[1][i])); + if(outs[0][i] > 1.f or outs[1][i] > 1.f) { + clip = srate >> 3; + } + } + reverb.extra_sanitize(); + left_lo.sanitize(); + left_hi.sanitize(); + right_lo.sanitize(); + right_hi.sanitize(); + if(params[par_meter_wet] != NULL) { + *params[par_meter_wet] = meter_wet; + } + if(params[par_meter_out] != NULL) { + *params[par_meter_out] = meter_out; + } + if(params[par_clip] != NULL) { + *params[par_clip] = clip; + } + return outputs_mask; +} + +/////////////////////////////////////////////////////////////////////////////////////////////// + +vintage_delay_audio_module::vintage_delay_audio_module() +{ + old_medium = -1; + for (int i = 0; i < MAX_DELAY; i++) { + buffers[0][i] = 0.f; + buffers[1][i] = 0.f; + } +} + +void vintage_delay_audio_module::params_changed() +{ + float unit = 60.0 * srate / (*params[par_bpm] * *params[par_divide]); + deltime_l = dsp::fastf2i_drm(unit * *params[par_time_l]); + deltime_r = dsp::fastf2i_drm(unit * *params[par_time_r]); + int deltime_fb = deltime_l + deltime_r; + float fb = *params[par_feedback]; + dry.set_inertia(*params[par_dryamount]); + mixmode = dsp::fastf2i_drm(*params[par_mixmode]); + medium = dsp::fastf2i_drm(*params[par_medium]); + switch(mixmode) + { + case MIXMODE_STEREO: + fb_left.set_inertia(fb); + fb_right.set_inertia(pow(fb, *params[par_time_r] / *params[par_time_l])); + amt_left.set_inertia(*params[par_amount]); + amt_right.set_inertia(*params[par_amount]); + break; + case MIXMODE_PINGPONG: + fb_left.set_inertia(fb); + fb_right.set_inertia(fb); + amt_left.set_inertia(*params[par_amount]); + amt_right.set_inertia(*params[par_amount]); + break; + case MIXMODE_LR: + fb_left.set_inertia(fb); + fb_right.set_inertia(fb); + amt_left.set_inertia(*params[par_amount]); // L is straight 'amount' + amt_right.set_inertia(*params[par_amount] * pow(fb, 1.0 * deltime_r / deltime_fb)); // R is amount with feedback based dampening as if it ran through R/FB*100% of delay line's dampening + // deltime_l <<< deltime_r -> pow() = fb -> full delay line worth of dampening + // deltime_l >>> deltime_r -> pow() = 1 -> no dampening + break; + case MIXMODE_RL: + fb_left.set_inertia(fb); + fb_right.set_inertia(fb); + amt_left.set_inertia(*params[par_amount] * pow(fb, 1.0 * deltime_l / deltime_fb)); + amt_right.set_inertia(*params[par_amount]); + break; + } + chmix.set_inertia((1 - *params[par_width]) * 0.5); + if (medium != old_medium) + calc_filters(); +} + +void vintage_delay_audio_module::activate() +{ + bufptr = 0; + age = 0; +} + +void vintage_delay_audio_module::deactivate() +{ +} + +void vintage_delay_audio_module::set_sample_rate(uint32_t sr) +{ + srate = sr; + old_medium = -1; + amt_left.set_sample_rate(sr); amt_right.set_sample_rate(sr); + fb_left.set_sample_rate(sr); fb_right.set_sample_rate(sr); +} + +void vintage_delay_audio_module::calc_filters() +{ + // parameters are heavily influenced by gordonjcp and his tape delay unit + // although, don't blame him if it sounds bad - I've messed with them too :) + biquad_left[0].set_lp_rbj(6000, 0.707, srate); + biquad_left[1].set_bp_rbj(4500, 0.250, srate); + biquad_right[0].copy_coeffs(biquad_left[0]); + biquad_right[1].copy_coeffs(biquad_left[1]); +} + +/// Single delay line with feedback at the same tap +static inline void delayline_impl(int age, int deltime, float dry_value, const float &delayed_value, float &out, float &del, gain_smoothing &amt, gain_smoothing &fb) +{ + // if the buffer hasn't been cleared yet (after activation), pretend we've read zeros + if (age <= deltime) { + out = 0; + amt.step(); + fb.step(); + } + else + { + float delayed = delayed_value; // avoid dereferencing the pointer in 'then' branch of the if() + dsp::sanitize(delayed); + out = delayed * amt.get(); + del = dry_value + delayed * fb.get(); + } +} + +/// Single delay line with tap output +static inline void delayline2_impl(int age, int deltime, float dry_value, const float &delayed_value, const float &delayed_value_for_fb, float &out, float &del, gain_smoothing &amt, gain_smoothing &fb) +{ + if (age <= deltime) { + out = 0; + amt.step(); + fb.step(); + } + else + { + out = delayed_value * amt.get(); + del = dry_value + delayed_value_for_fb * fb.get(); + dsp::sanitize(out); + dsp::sanitize(del); + } +} + +static inline void delay_mix(float dry_left, float dry_right, float &out_left, float &out_right, float dry, float chmix) +{ + float tmp_left = lerp(out_left, out_right, chmix); + float tmp_right = lerp(out_right, out_left, chmix); + out_left = dry_left * dry + tmp_left; + out_right = dry_right * dry + tmp_right; +} + +uint32_t vintage_delay_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) +{ + uint32_t ostate = 3; // XXXKF optimize! + uint32_t end = offset + numsamples; + int orig_bufptr = bufptr; + float out_left, out_right, del_left, del_right; + + switch(mixmode) + { + case MIXMODE_STEREO: + case MIXMODE_PINGPONG: + { + int v = mixmode == MIXMODE_PINGPONG ? 1 : 0; + for(uint32_t i = offset; i < end; i++) + { + delayline_impl(age, deltime_l, ins[0][i], buffers[v][(bufptr - deltime_l) & ADDR_MASK], out_left, del_left, amt_left, fb_left); + delayline_impl(age, deltime_r, ins[1][i], buffers[1 - v][(bufptr - deltime_r) & ADDR_MASK], out_right, del_right, amt_right, fb_right); + delay_mix(ins[0][i], ins[1][i], out_left, out_right, dry.get(), chmix.get()); + + age++; + outs[0][i] = out_left; outs[1][i] = out_right; buffers[0][bufptr] = del_left; buffers[1][bufptr] = del_right; + bufptr = (bufptr + 1) & (MAX_DELAY - 1); + } + } + break; + + case MIXMODE_LR: + case MIXMODE_RL: + { + int v = mixmode == MIXMODE_RL ? 1 : 0; + int deltime_fb = deltime_l + deltime_r; + int deltime_l_corr = mixmode == MIXMODE_RL ? deltime_fb : deltime_l; + int deltime_r_corr = mixmode == MIXMODE_LR ? deltime_fb : deltime_r; + + for(uint32_t i = offset; i < end; i++) + { + delayline2_impl(age, deltime_l, ins[0][i], buffers[v][(bufptr - deltime_l_corr) & ADDR_MASK], buffers[v][(bufptr - deltime_fb) & ADDR_MASK], out_left, del_left, amt_left, fb_left); + delayline2_impl(age, deltime_r, ins[1][i], buffers[1 - v][(bufptr - deltime_r_corr) & ADDR_MASK], buffers[1-v][(bufptr - deltime_fb) & ADDR_MASK], out_right, del_right, amt_right, fb_right); + delay_mix(ins[0][i], ins[1][i], out_left, out_right, dry.get(), chmix.get()); + + age++; + outs[0][i] = out_left; outs[1][i] = out_right; buffers[0][bufptr] = del_left; buffers[1][bufptr] = del_right; + bufptr = (bufptr + 1) & (MAX_DELAY - 1); + } + } + } + if (age >= MAX_DELAY) + age = MAX_DELAY; + if (medium > 0) { + bufptr = orig_bufptr; + if (medium == 2) + { + for(uint32_t i = offset; i < end; i++) + { + buffers[0][bufptr] = biquad_left[0].process_lp(biquad_left[1].process(buffers[0][bufptr])); + buffers[1][bufptr] = biquad_right[0].process_lp(biquad_right[1].process(buffers[1][bufptr])); + bufptr = (bufptr + 1) & (MAX_DELAY - 1); + } + biquad_left[0].sanitize();biquad_right[0].sanitize(); + } else { + for(uint32_t i = offset; i < end; i++) + { + buffers[0][bufptr] = biquad_left[1].process(buffers[0][bufptr]); + buffers[1][bufptr] = biquad_right[1].process(buffers[1][bufptr]); + bufptr = (bufptr + 1) & (MAX_DELAY - 1); + } + } + biquad_left[1].sanitize();biquad_right[1].sanitize(); + + } + return ostate; +} + +/////////////////////////////////////////////////////////////////////////////////////////////// + +bool filter_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const +{ + if (!is_active) + return false; + if (index == par_cutoff && !subindex) { + context->set_line_width(1.5); + return ::get_graph(*this, subindex, data, points); + } + return false; +} + +int filter_audio_module::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) const +{ + if (fabs(inertia_cutoff.get_last() - old_cutoff) + 100 * fabs(inertia_resonance.get_last() - old_resonance) + fabs(*params[par_mode] - old_mode) > 0.1f) + { + old_cutoff = inertia_cutoff.get_last(); + old_resonance = inertia_resonance.get_last(); + old_mode = *params[par_mode]; + last_generation++; + subindex_graph = 0; + subindex_dot = INT_MAX; + subindex_gridline = INT_MAX; + } + else { + subindex_graph = 0; + subindex_dot = subindex_gridline = generation ? INT_MAX : 0; + } + if (generation == last_calculated_generation) + subindex_graph = INT_MAX; + return last_generation; +} + + +/////////////////////////////////////////////////////////////////////////////////////////////// + +filterclavier_audio_module::filterclavier_audio_module() +: filter_module_with_inertia(ins, outs, params) +, min_gain(1.0) +, max_gain(32.0) +, last_note(-1) +, last_velocity(-1) +{ +} + +void filterclavier_audio_module::params_changed() +{ + inertia_filter_module::inertia_cutoff.set_inertia( + note_to_hz(last_note + *params[par_transpose], *params[par_detune])); + + float min_resonance = param_props[par_max_resonance].min; + inertia_filter_module::inertia_resonance.set_inertia( + (float(last_velocity) / 127.0) + // 0.001: see below + * (*params[par_max_resonance] - min_resonance + 0.001) + + min_resonance); + + adjust_gain_according_to_filter_mode(last_velocity); + + inertia_filter_module::calculate_filter(); +} + +void filterclavier_audio_module::activate() +{ + inertia_filter_module::activate(); +} + +void filterclavier_audio_module::set_sample_rate(uint32_t sr) +{ + inertia_filter_module::set_sample_rate(sr); +} + +void filterclavier_audio_module::deactivate() +{ + inertia_filter_module::deactivate(); +} + + +void filterclavier_audio_module::note_on(int note, int vel) +{ + last_note = note; + last_velocity = vel; + inertia_filter_module::inertia_cutoff.set_inertia( + note_to_hz(note + *params[par_transpose], *params[par_detune])); + + float min_resonance = param_props[par_max_resonance].min; + inertia_filter_module::inertia_resonance.set_inertia( + (float(vel) / 127.0) + // 0.001: if the difference is equal to zero (which happens + // when the max_resonance knom is at minimum position + // then the filter gain doesnt seem to snap to zero on most note offs + * (*params[par_max_resonance] - min_resonance + 0.001) + + min_resonance); + + adjust_gain_according_to_filter_mode(vel); + + inertia_filter_module::calculate_filter(); +} + +void filterclavier_audio_module::note_off(int note, int vel) +{ + if (note == last_note) { + inertia_filter_module::inertia_resonance.set_inertia(param_props[par_max_resonance].min); + inertia_filter_module::inertia_gain.set_inertia(min_gain); + inertia_filter_module::calculate_filter(); + last_velocity = 0; + } +} + +void filterclavier_audio_module::adjust_gain_according_to_filter_mode(int velocity) +{ + int mode = dsp::fastf2i_drm(*params[par_mode]); + + // for bandpasses: boost gain for velocities > 0 + if ( (mode_6db_bp <= mode) && (mode <= mode_18db_bp) ) { + // gain for velocity 0: 1.0 + // gain for velocity 127: 32.0 + float mode_max_gain = max_gain; + // max_gain is right for mode_6db_bp + if (mode == mode_12db_bp) + mode_max_gain /= 6.0; + if (mode == mode_18db_bp) + mode_max_gain /= 10.5; + + inertia_filter_module::inertia_gain.set_now( + (float(velocity) / 127.0) * (mode_max_gain - min_gain) + min_gain); + } else { + inertia_filter_module::inertia_gain.set_now(min_gain); + } +} + +bool filterclavier_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const +{ + if (!is_active || index != par_mode) { + return false; + } + if (!subindex) { + context->set_line_width(1.5); + return ::get_graph(*this, subindex, data, points); + } + return false; } diff --git a/plugins/ladspa_effect/calf/src/modules_comp.cpp b/plugins/ladspa_effect/calf/src/modules_comp.cpp new file mode 100644 index 000000000..a5d58e2e5 --- /dev/null +++ b/plugins/ladspa_effect/calf/src/modules_comp.cpp @@ -0,0 +1,1592 @@ +/* Calf DSP plugin pack + * Compression related plugins + * + * Copyright (C) 2001-2010 Krzysztof Foltman, Markus Schmidt, Thor Harald Johansen and others + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include + +using namespace dsp; +using namespace calf_plugins; + +#define SET_IF_CONNECTED(name) if (params[AM::param_##name] != NULL) *params[AM::param_##name] = name; + +/// Multibandcompressor by Markus Schmidt +/// +/// This module splits the signal in four different bands +/// and sends them through multiple filters (implemented by +/// Krzysztof). They are processed by a compressing routine +/// (implemented by Thor) afterwards and summed up to the +/// final output again. +/////////////////////////////////////////////////////////////////////////////////////////////// + +multibandcompressor_audio_module::multibandcompressor_audio_module() +{ + is_active = false; + srate = 0; + // zero all displays + clip_inL = 0.f; + clip_inR = 0.f; + clip_outL = 0.f; + clip_outR = 0.f; + meter_inL = 0.f; + meter_inR = 0.f; + meter_outL = 0.f; + meter_outR = 0.f; +} + +void multibandcompressor_audio_module::activate() +{ + is_active = true; + // set all filters and strips + params_changed(); + // activate all strips + for (int j = 0; j < strips; j ++) { + strip[j].activate(); + strip[j].id = j; + } +} + +void multibandcompressor_audio_module::deactivate() +{ + is_active = false; + // deactivate all strips + for (int j = 0; j < strips; j ++) { + strip[j].deactivate(); + } +} + +void multibandcompressor_audio_module::params_changed() +{ + // set the params of all filters + if(*params[param_freq0] != freq_old[0] or *params[param_sep0] != sep_old[0] or *params[param_q0] != q_old[0]) { + lpL0.set_lp_rbj((float)(*params[param_freq0] * (1 - *params[param_sep0])), *params[param_q0], (float)srate); + lpR0.copy_coeffs(lpL0); + hpL0.set_hp_rbj((float)(*params[param_freq0] * (1 + *params[param_sep0])), *params[param_q0], (float)srate); + hpR0.copy_coeffs(hpL0); + freq_old[0] = *params[param_freq0]; + sep_old[0] = *params[param_sep0]; + q_old[0] = *params[param_q0]; + } + if(*params[param_freq1] != freq_old[1] or *params[param_sep1] != sep_old[1] or *params[param_q1] != q_old[1]) { + lpL1.set_lp_rbj((float)(*params[param_freq1] * (1 - *params[param_sep1])), *params[param_q1], (float)srate); + lpR1.copy_coeffs(lpL1); + hpL1.set_hp_rbj((float)(*params[param_freq1] * (1 + *params[param_sep1])), *params[param_q1], (float)srate); + hpR1.copy_coeffs(hpL1); + freq_old[1] = *params[param_freq1]; + sep_old[1] = *params[param_sep1]; + q_old[1] = *params[param_q1]; + } + if(*params[param_freq2] != freq_old[2] or *params[param_sep2] != sep_old[2] or *params[param_q2] != q_old[2]) { + lpL2.set_lp_rbj((float)(*params[param_freq2] * (1 - *params[param_sep2])), *params[param_q2], (float)srate); + lpR2.copy_coeffs(lpL2); + hpL2.set_hp_rbj((float)(*params[param_freq2] * (1 + *params[param_sep2])), *params[param_q2], (float)srate); + hpR2.copy_coeffs(hpL2); + freq_old[2] = *params[param_freq2]; + sep_old[2] = *params[param_sep2]; + q_old[2] = *params[param_q2]; + } + // set the params of all strips + strip[0].set_params(*params[param_attack0], *params[param_release0], *params[param_threshold0], *params[param_ratio0], *params[param_knee0], *params[param_makeup0], *params[param_detection0], 1.f, *params[param_bypass0], *params[param_mute0]); + strip[1].set_params(*params[param_attack1], *params[param_release1], *params[param_threshold1], *params[param_ratio1], *params[param_knee1], *params[param_makeup1], *params[param_detection1], 1.f, *params[param_bypass1], *params[param_mute1]); + strip[2].set_params(*params[param_attack2], *params[param_release2], *params[param_threshold2], *params[param_ratio2], *params[param_knee2], *params[param_makeup2], *params[param_detection2], 1.f, *params[param_bypass2], *params[param_mute2]); + strip[3].set_params(*params[param_attack3], *params[param_release3], *params[param_threshold3], *params[param_ratio3], *params[param_knee3], *params[param_makeup3], *params[param_detection3], 1.f, *params[param_bypass3], *params[param_mute3]); +} + +void multibandcompressor_audio_module::set_sample_rate(uint32_t sr) +{ + srate = sr; + // set srate of all strips + for (int j = 0; j < strips; j ++) { + strip[j].set_sample_rate(srate); + } +} + +#define BYPASSED_COMPRESSION(index) \ + if(params[param_compression##index] != NULL) \ + *params[param_compression##index] = 1.0; \ + if(params[param_output##index] != NULL) \ + *params[param_output##index] = 0.0; + +#define ACTIVE_COMPRESSION(index) \ + if(params[param_compression##index] != NULL) \ + *params[param_compression##index] = strip[index].get_comp_level(); \ + if(params[param_output##index] != NULL) \ + *params[param_output##index] = strip[index].get_output_level(); + +uint32_t multibandcompressor_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) +{ + bool bypass = *params[param_bypass] > 0.5f; + numsamples += offset; + for (int i = 0; i < strips; i++) + strip[i].update_curve(); + if(bypass) { + // everything bypassed + while(offset < numsamples) { + outs[0][offset] = ins[0][offset]; + outs[1][offset] = ins[1][offset]; + ++offset; + } + // displays, too + clip_inL = 0.f; + clip_inR = 0.f; + clip_outL = 0.f; + clip_outR = 0.f; + meter_inL = 0.f; + meter_inR = 0.f; + meter_outL = 0.f; + meter_outR = 0.f; + } else { + // process all strips + + // determine mute state of strips + mute[0] = *params[param_mute0] > 0.f ? true : false; + mute[1] = *params[param_mute1] > 0.f ? true : false; + mute[2] = *params[param_mute2] > 0.f ? true : false; + mute[3] = *params[param_mute3] > 0.f ? true : false; + + // let meters fall a bit + clip_inL -= std::min(clip_inL, numsamples); + clip_inR -= std::min(clip_inR, numsamples); + clip_outL -= std::min(clip_outL, numsamples); + clip_outR -= std::min(clip_outR, numsamples); + meter_inL = 0.f; + meter_inR = 0.f; + meter_outL = 0.f; + meter_outR = 0.f; + while(offset < numsamples) { + // cycle through samples + float inL = ins[0][offset]; + float inR = ins[1][offset]; + // in level + inR *= *params[param_level_in]; + inL *= *params[param_level_in]; + // out vars + float outL = 0.f; + float outR = 0.f; + for (int i = 0; i < strips; i ++) { + // cycle trough strips + if (!mute[i]) { + // strip unmuted + float left = inL; + float right = inR; + // send trough filters + switch (i) { + case 0: + left = lpL0.process(left); + right = lpR0.process(right); + lpL0.sanitize(); + lpR0.sanitize(); + break; + case 1: + left = lpL1.process(left); + right = lpR1.process(right); + left = hpL0.process(left); + right = hpR0.process(right); + lpL1.sanitize(); + lpR1.sanitize(); + hpL0.sanitize(); + hpR0.sanitize(); + break; + case 2: + left = lpL2.process(left); + right = lpR2.process(right); + left = hpL1.process(left); + right = hpR1.process(right); + lpL2.sanitize(); + lpR2.sanitize(); + hpL1.sanitize(); + hpR1.sanitize(); + break; + case 3: + left = hpL2.process(left); + right = hpR2.process(right); + hpL2.sanitize(); + hpR2.sanitize(); + break; + } + // process gain reduction + strip[i].process(left, right); + // sum up output + outL += left; + outR += right; + } else { + // strip muted + + } + + + } // process single strip + + // even out filters gain reduction + // 3dB - levelled manually (based on default sep and q settings) + outL *= 1.414213562; + outR *= 1.414213562; + + // out level + outL *= *params[param_level_out]; + outR *= *params[param_level_out]; + + // send to output + outs[0][offset] = outL; + outs[1][offset] = outR; + + // clip LED's + if(inL > 1.f) { + clip_inL = srate >> 3; + } + if(inR > 1.f) { + clip_inR = srate >> 3; + } + if(outL > 1.f) { + clip_outL = srate >> 3; + } + if(outR > 1.f) { + clip_outR = srate >> 3; + } + // set up in / out meters + if(inL > meter_inL) { + meter_inL = inL; + } + if(inR > meter_inR) { + meter_inR = inR; + } + if(outL > meter_outL) { + meter_outL = outL; + } + if(outR > meter_outR) { + meter_outR = outR; + } + // next sample + ++offset; + } // cycle trough samples + + } // process all strips (no bypass) + + // draw meters + SET_IF_CONNECTED(clip_inL); + SET_IF_CONNECTED(clip_inR); + SET_IF_CONNECTED(clip_outL); + SET_IF_CONNECTED(clip_outR); + SET_IF_CONNECTED(meter_inL); + SET_IF_CONNECTED(meter_inR); + SET_IF_CONNECTED(meter_outL); + SET_IF_CONNECTED(meter_outR); + // draw strip meters + if(bypass > 0.5f) { + BYPASSED_COMPRESSION(0) + BYPASSED_COMPRESSION(1) + BYPASSED_COMPRESSION(2) + BYPASSED_COMPRESSION(3) + } else { + ACTIVE_COMPRESSION(0) + ACTIVE_COMPRESSION(1) + ACTIVE_COMPRESSION(2) + ACTIVE_COMPRESSION(3) + } + // whatever has to be returned x) + return outputs_mask; +} + +const gain_reduction_audio_module *multibandcompressor_audio_module::get_strip_by_param_index(int index) const +{ + // let's handle by the corresponding strip + switch (index) { + case param_compression0: + return &strip[0]; + case param_compression1: + return &strip[1]; + case param_compression2: + return &strip[2]; + case param_compression3: + return &strip[3]; + } + return NULL; +} + +bool multibandcompressor_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const +{ + const gain_reduction_audio_module *m = get_strip_by_param_index(index); + if (m) + return m->get_graph(subindex, data, points, context); + return false; +} + +bool multibandcompressor_audio_module::get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context) const +{ + const gain_reduction_audio_module *m = get_strip_by_param_index(index); + if (m) + return m->get_dot(subindex, x, y, size, context); + return false; +} + +bool multibandcompressor_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const +{ + const gain_reduction_audio_module *m = get_strip_by_param_index(index); + if (m) + return m->get_gridline(subindex, pos, vertical, legend, context); + return false; +} + +int multibandcompressor_audio_module::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) const +{ + const gain_reduction_audio_module *m = get_strip_by_param_index(index); + if (m) + return m->get_changed_offsets(generation, subindex_graph, subindex_dot, subindex_gridline); + return 0; +} + +/// Compressor originally by Thor +/// +/// This module provides Thor's original compressor without any sidechain or weighting +/////////////////////////////////////////////////////////////////////////////////////////////// + +compressor_audio_module::compressor_audio_module() +{ + is_active = false; + srate = 0; + last_generation = 0; +} + +void compressor_audio_module::activate() +{ + is_active = true; + // set all filters and strips + compressor.activate(); + params_changed(); + meter_in = 0.f; + meter_out = 0.f; + clip_in = 0.f; + clip_out = 0.f; +} +void compressor_audio_module::deactivate() +{ + is_active = false; + compressor.deactivate(); +} + +void compressor_audio_module::params_changed() +{ + compressor.set_params(*params[param_attack], *params[param_release], *params[param_threshold], *params[param_ratio], *params[param_knee], *params[param_makeup], *params[param_detection], *params[param_stereo_link], *params[param_bypass], 0.f); +} + +void compressor_audio_module::set_sample_rate(uint32_t sr) +{ + srate = sr; + compressor.set_sample_rate(srate); +} + +uint32_t compressor_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) +{ + bool bypass = *params[param_bypass] > 0.5f; + numsamples += offset; + if(bypass) { + // everything bypassed + while(offset < numsamples) { + outs[0][offset] = ins[0][offset]; + outs[1][offset] = ins[1][offset]; + ++offset; + } + // displays, too + clip_in = 0.f; + clip_out = 0.f; + meter_in = 0.f; + meter_out = 0.f; + } else { + // process + + clip_in -= std::min(clip_in, numsamples); + clip_out -= std::min(clip_out, numsamples); + + compressor.update_curve(); + + while(offset < numsamples) { + // cycle through samples + float outL = 0.f; + float outR = 0.f; + float inL = ins[0][offset]; + float inR = ins[1][offset]; + // in level + inR *= *params[param_level_in]; + inL *= *params[param_level_in]; + + float leftAC = inL; + float rightAC = inR; + + compressor.process(leftAC, rightAC); + + outL = leftAC; + outR = rightAC; + + // send to output + outs[0][offset] = outL; + outs[1][offset] = outR; + + // clip LED's + if(std::max(fabs(inL), fabs(inR)) > 1.f) { + clip_in = srate >> 3; + } + if(std::max(fabs(outL), fabs(outR)) > 1.f) { + clip_out = srate >> 3; + } + // rise up out meter + meter_in = std::max(fabs(inL), fabs(inR));; + meter_out = std::max(fabs(outL), fabs(outR));; + + // next sample + ++offset; + } // cycle trough samples + } + // draw meters + SET_IF_CONNECTED(clip_in) + SET_IF_CONNECTED(clip_out) + SET_IF_CONNECTED(meter_in) + SET_IF_CONNECTED(meter_out) + // draw strip meter + if(bypass > 0.5f) { + if(params[param_compression] != NULL) { + *params[param_compression] = 1.0f; + } + } else { + if(params[param_compression] != NULL) { + *params[param_compression] = compressor.get_comp_level(); + } + } + // whatever has to be returned x) + return outputs_mask; +} +bool compressor_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const +{ + if (!is_active) + return false; + return compressor.get_graph(subindex, data, points, context); +} + +bool compressor_audio_module::get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context) const +{ + if (!is_active) + return false; + return compressor.get_dot(subindex, x, y, size, context); +} + +bool compressor_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const +{ + if (!is_active) + return false; + return compressor.get_gridline(subindex, pos, vertical, legend, context); +} + +int compressor_audio_module::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) const +{ + if (!is_active) + return false; + return compressor.get_changed_offsets(generation, subindex_graph, subindex_dot, subindex_gridline); +} + +/// Sidecain Compressor by Markus Schmidt +/// +/// This module splits the signal in a sidechain- and a process signal. +/// The sidechain is processed through Krzystofs filters and compresses +/// the process signal via Thor's compression routine afterwards. +/////////////////////////////////////////////////////////////////////////////////////////////// + +sidechaincompressor_audio_module::sidechaincompressor_audio_module() +{ + is_active = false; + srate = 0; + last_generation = 0; +} + +void sidechaincompressor_audio_module::activate() +{ + is_active = true; + // set all filters and strips + compressor.activate(); + params_changed(); + meter_in = 0.f; + meter_out = 0.f; + clip_in = 0.f; + clip_out = 0.f; +} +void sidechaincompressor_audio_module::deactivate() +{ + is_active = false; + compressor.deactivate(); +} + +sidechaincompressor_audio_module::cfloat sidechaincompressor_audio_module::h_z(const cfloat &z) const +{ + switch (sc_mode) { + default: + case WIDEBAND: + return false; + break; + case DEESSER_WIDE: + case DERUMBLER_WIDE: + case WEIGHTED_1: + case WEIGHTED_2: + case WEIGHTED_3: + case BANDPASS_2: + return f1L.h_z(z) * f2L.h_z(z); + break; + case DEESSER_SPLIT: + return f2L.h_z(z); + break; + case DERUMBLER_SPLIT: + case BANDPASS_1: + return f1L.h_z(z); + break; + } +} + +float sidechaincompressor_audio_module::freq_gain(int index, double freq, uint32_t sr) const +{ + typedef std::complex cfloat; + freq *= 2.0 * M_PI / sr; + cfloat z = 1.0 / exp(cfloat(0.0, freq)); + + return std::abs(h_z(z)); +} + +void sidechaincompressor_audio_module::params_changed() +{ + // set the params of all filters + if(*params[param_f1_freq] != f1_freq_old or *params[param_f1_level] != f1_level_old + or *params[param_f2_freq] != f2_freq_old or *params[param_f2_level] != f2_level_old + or *params[param_sc_mode] != sc_mode) { + float q = 0.707; + switch ((int)*params[param_sc_mode]) { + default: + case WIDEBAND: + f1L.set_hp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]); + f1R.copy_coeffs(f1L); + f2L.set_lp_rbj((float)*params[param_f2_freq], q, (float)srate, *params[param_f2_level]); + f2R.copy_coeffs(f2L); + f1_active = 0.f; + f2_active = 0.f; + break; + case DEESSER_WIDE: + f1L.set_peakeq_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate); + f1R.copy_coeffs(f1L); + f2L.set_hp_rbj((float)*params[param_f2_freq], q, (float)srate, *params[param_f2_level]); + f2R.copy_coeffs(f2L); + f1_active = 0.5f; + f2_active = 1.f; + break; + case DEESSER_SPLIT: + f1L.set_lp_rbj((float)*params[param_f2_freq] * (1 + 0.17), q, (float)srate); + f1R.copy_coeffs(f1L); + f2L.set_hp_rbj((float)*params[param_f2_freq] * (1 - 0.17), q, (float)srate, *params[param_f2_level]); + f2R.copy_coeffs(f2L); + f1_active = 0.f; + f2_active = 1.f; + break; + case DERUMBLER_WIDE: + f1L.set_lp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]); + f1R.copy_coeffs(f1L); + f2L.set_peakeq_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate); + f2R.copy_coeffs(f2L); + f1_active = 1.f; + f2_active = 0.5f; + break; + case DERUMBLER_SPLIT: + f1L.set_lp_rbj((float)*params[param_f1_freq] * (1 + 0.17), q, (float)srate, *params[param_f1_level]); + f1R.copy_coeffs(f1L); + f2L.set_hp_rbj((float)*params[param_f1_freq] * (1 - 0.17), q, (float)srate); + f2R.copy_coeffs(f2L); + f1_active = 1.f; + f2_active = 0.f; + break; + case WEIGHTED_1: + f1L.set_lowshelf_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate); + f1R.copy_coeffs(f1L); + f2L.set_highshelf_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate); + f2R.copy_coeffs(f2L); + f1_active = 0.5f; + f2_active = 0.5f; + break; + case WEIGHTED_2: + f1L.set_lowshelf_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate); + f1R.copy_coeffs(f1L); + f2L.set_peakeq_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate); + f2R.copy_coeffs(f2L); + f1_active = 0.5f; + f2_active = 0.5f; + break; + case WEIGHTED_3: + f1L.set_peakeq_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate); + f1R.copy_coeffs(f1L); + f2L.set_highshelf_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate); + f2R.copy_coeffs(f2L); + f1_active = 0.5f; + f2_active = 0.5f; + break; + case BANDPASS_1: + f1L.set_bp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]); + f1R.copy_coeffs(f1L); + f2L.set_hp_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate); + f2R.copy_coeffs(f2L); + f1_active = 1.f; + f2_active = 0.f; + break; + case BANDPASS_2: + f1L.set_hp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]); + f1R.copy_coeffs(f1L); + f2L.set_lp_rbj((float)*params[param_f2_freq], q, (float)srate, *params[param_f2_level]); + f2R.copy_coeffs(f2L); + f1_active = 1.f; + f2_active = 1.f; + break; + } + f1_freq_old = *params[param_f1_freq]; + f1_level_old = *params[param_f1_level]; + f2_freq_old = *params[param_f2_freq]; + f2_level_old = *params[param_f2_level]; + sc_mode = (CalfScModes)*params[param_sc_mode]; + } + // light LED's + if(params[param_f1_active] != NULL) { + *params[param_f1_active] = f1_active; + } + if(params[param_f2_active] != NULL) { + *params[param_f2_active] = f2_active; + } + // and set the compressor module + compressor.set_params(*params[param_attack], *params[param_release], *params[param_threshold], *params[param_ratio], *params[param_knee], *params[param_makeup], *params[param_detection], *params[param_stereo_link], *params[param_bypass], 0.f); +} + +void sidechaincompressor_audio_module::set_sample_rate(uint32_t sr) +{ + srate = sr; + compressor.set_sample_rate(srate); +} + +uint32_t sidechaincompressor_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) +{ + bool bypass = *params[param_bypass] > 0.5f; + numsamples += offset; + if(bypass) { + // everything bypassed + while(offset < numsamples) { + outs[0][offset] = ins[0][offset]; + outs[1][offset] = ins[1][offset]; + ++offset; + } + // displays, too + clip_in = 0.f; + clip_out = 0.f; + meter_in = 0.f; + meter_out = 0.f; + } else { + // process + + clip_in -= std::min(clip_in, numsamples); + clip_out -= std::min(clip_out, numsamples); + compressor.update_curve(); + + while(offset < numsamples) { + // cycle through samples + float outL = 0.f; + float outR = 0.f; + float inL = ins[0][offset]; + float inR = ins[1][offset]; + // in level + inR *= *params[param_level_in]; + inL *= *params[param_level_in]; + + + float leftAC = inL; + float rightAC = inR; + float leftSC = inL; + float rightSC = inR; + float leftMC = inL; + float rightMC = inR; + + switch ((int)*params[param_sc_mode]) { + default: + case WIDEBAND: + compressor.process(leftAC, rightAC); + break; + case DEESSER_WIDE: + case DERUMBLER_WIDE: + case WEIGHTED_1: + case WEIGHTED_2: + case WEIGHTED_3: + case BANDPASS_2: + leftSC = f2L.process(f1L.process(leftSC)); + rightSC = f2R.process(f1R.process(rightSC)); + leftMC = leftSC; + rightMC = rightSC; + compressor.process(leftAC, rightAC, &leftSC, &rightSC); + break; + case DEESSER_SPLIT: + leftSC = f2L.process(leftSC); + rightSC = f2R.process(rightSC); + leftMC = leftSC; + rightMC = rightSC; + compressor.process(leftSC, rightSC, &leftSC, &rightSC); + leftAC = f1L.process(leftAC); + rightAC = f1R.process(rightAC); + leftAC += leftSC; + rightAC += rightSC; + break; + case DERUMBLER_SPLIT: + leftSC = f1L.process(leftSC); + rightSC = f1R.process(rightSC); + leftMC = leftSC; + rightMC = rightSC; + compressor.process(leftSC, rightSC); + leftAC = f2L.process(leftAC); + rightAC = f2R.process(rightAC); + leftAC += leftSC; + rightAC += rightSC; + break; + case BANDPASS_1: + leftSC = f1L.process(leftSC); + rightSC = f1R.process(rightSC); + leftMC = leftSC; + rightMC = rightSC; + compressor.process(leftAC, rightAC, &leftSC, &rightSC); + break; + } + + if(*params[param_sc_listen] > 0.f) { + outL = leftMC; + outR = rightMC; + } else { + outL = leftAC; + outR = rightAC; + } + + // send to output + outs[0][offset] = outL; + outs[1][offset] = outR; + + // clip LED's + if(std::max(fabs(inL), fabs(inR)) > 1.f) { + clip_in = srate >> 3; + } + if(std::max(fabs(outL), fabs(outR)) > 1.f) { + clip_out = srate >> 3; + } + // rise up out meter + meter_in = std::max(fabs(inL), fabs(inR));; + meter_out = std::max(fabs(outL), fabs(outR));; + + // next sample + ++offset; + } // cycle trough samples + f1L.sanitize(); + f1R.sanitize(); + f2L.sanitize(); + f2R.sanitize(); + + } + // draw meters + SET_IF_CONNECTED(clip_in) + SET_IF_CONNECTED(clip_out) + SET_IF_CONNECTED(meter_in) + SET_IF_CONNECTED(meter_out) + // draw strip meter + if(bypass > 0.5f) { + if(params[param_compression] != NULL) { + *params[param_compression] = 1.0f; + } + } else { + if(params[param_compression] != NULL) { + *params[param_compression] = compressor.get_comp_level(); + } + } + // whatever has to be returned x) + return outputs_mask; +} +bool sidechaincompressor_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const +{ + if (!is_active) + return false; + if (index == param_f1_freq && !subindex) { + context->set_line_width(1.5); + return ::get_graph(*this, subindex, data, points); + } else if(index == param_compression) { + return compressor.get_graph(subindex, data, points, context); + } + return false; +} + +bool sidechaincompressor_audio_module::get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context) const +{ + if (!is_active) + return false; + if (index == param_compression) { + return compressor.get_dot(subindex, x, y, size, context); + } + return false; +} + +bool sidechaincompressor_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const +{ + if (!is_active) + return false; + if (index == param_compression) { + return compressor.get_gridline(subindex, pos, vertical, legend, context); + } else { + return get_freq_gridline(subindex, pos, vertical, legend, context); + } +// return false; +} + +int sidechaincompressor_audio_module::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) const +{ + if (!is_active) + return false; + if(index == param_compression) { + return compressor.get_changed_offsets(generation, subindex_graph, subindex_dot, subindex_gridline); + } else { + // (fabs(inertia_cutoff.get_last() - old_cutoff) + 100 * fabs(inertia_resonance.get_last() - old_resonance) + fabs(*params[par_mode] - old_mode) > 0.1f) + if (*params[param_f1_freq] != f1_freq_old1 + or *params[param_f2_freq] != f2_freq_old1 + or *params[param_f1_level] != f1_level_old1 + or *params[param_f2_level] != f2_level_old1 + or *params[param_sc_mode] !=sc_mode_old1) + { + f1_freq_old1 = *params[param_f1_freq]; + f2_freq_old1 = *params[param_f2_freq]; + f1_level_old1 = *params[param_f1_level]; + f2_level_old1 = *params[param_f2_level]; + sc_mode_old1 = (CalfScModes)*params[param_sc_mode]; + last_generation++; + subindex_graph = 0; + subindex_dot = INT_MAX; + subindex_gridline = INT_MAX; + } + else { + subindex_graph = 0; + subindex_dot = subindex_gridline = generation ? INT_MAX : 0; + } + if (generation == last_calculated_generation) + subindex_graph = INT_MAX; + return last_generation; + } + return false; +} + +/// Deesser by Markus Schmidt +/// +/// This module splits the signal in a sidechain- and a process signal. +/// The sidechain is processed through Krzystofs filters and compresses +/// the process signal via Thor's compression routine afterwards. +/////////////////////////////////////////////////////////////////////////////////////////////// + +deesser_audio_module::deesser_audio_module() +{ + is_active = false; + srate = 0; + last_generation = 0; +} + +void deesser_audio_module::activate() +{ + is_active = true; + // set all filters and strips + compressor.activate(); + params_changed(); + detected = 0.f; + detected_led = 0.f; + clip_out = 0.f; +} +void deesser_audio_module::deactivate() +{ + is_active = false; + compressor.deactivate(); +} + +void deesser_audio_module::params_changed() +{ + // set the params of all filters + if(*params[param_f1_freq] != f1_freq_old or *params[param_f1_level] != f1_level_old + or *params[param_f2_freq] != f2_freq_old or *params[param_f2_level] != f2_level_old + or *params[param_f2_q] != f2_q_old) { + float q = 0.707; + + hpL.set_hp_rbj((float)*params[param_f1_freq] * (1 - 0.17), q, (float)srate, *params[param_f1_level]); + hpR.copy_coeffs(hpL); + lpL.set_lp_rbj((float)*params[param_f1_freq] * (1 + 0.17), q, (float)srate); + lpR.copy_coeffs(lpL); + pL.set_peakeq_rbj((float)*params[param_f2_freq], *params[param_f2_q], *params[param_f2_level], (float)srate); + pR.copy_coeffs(pL); + f1_freq_old = *params[param_f1_freq]; + f1_level_old = *params[param_f1_level]; + f2_freq_old = *params[param_f2_freq]; + f2_level_old = *params[param_f2_level]; + f2_q_old = *params[param_f2_q]; + } + // and set the compressor module + compressor.set_params((float)*params[param_laxity], (float)*params[param_laxity] * 1.33, *params[param_threshold], *params[param_ratio], 2.8, *params[param_makeup], *params[param_detection], 0.f, *params[param_bypass], 0.f); +} + +void deesser_audio_module::set_sample_rate(uint32_t sr) +{ + srate = sr; + compressor.set_sample_rate(srate); +} + +uint32_t deesser_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) +{ + bool bypass = *params[param_bypass] > 0.5f; + numsamples += offset; + if(bypass) { + // everything bypassed + while(offset < numsamples) { + outs[0][offset] = ins[0][offset]; + outs[1][offset] = ins[1][offset]; + ++offset; + } + // displays, too + clip_out = 0.f; + detected = 0.f; + detected_led = 0.f; + } else { + // process + + detected_led -= std::min(detected_led, numsamples); + clip_led -= std::min(clip_led, numsamples); + compressor.update_curve(); + + while(offset < numsamples) { + // cycle through samples + float outL = 0.f; + float outR = 0.f; + float inL = ins[0][offset]; + float inR = ins[1][offset]; + + + float leftAC = inL; + float rightAC = inR; + float leftSC = inL; + float rightSC = inR; + float leftRC = inL; + float rightRC = inR; + float leftMC = inL; + float rightMC = inR; + + leftSC = pL.process(hpL.process(leftSC)); + rightSC = pR.process(hpR.process(rightSC)); + leftMC = leftSC; + rightMC = rightSC; + + switch ((int)*params[param_mode]) { + default: + case WIDE: + compressor.process(leftAC, rightAC, &leftSC, &rightSC); + break; + case SPLIT: + hpL.sanitize(); + hpR.sanitize(); + leftRC = hpL.process(leftRC); + rightRC = hpR.process(rightRC); + compressor.process(leftRC, rightRC, &leftSC, &rightSC); + leftAC = lpL.process(leftAC); + rightAC = lpR.process(rightAC); + leftAC += leftRC; + rightAC += rightRC; + break; + } + + if(*params[param_sc_listen] > 0.f) { + outL = leftMC; + outR = rightMC; + } else { + outL = leftAC; + outR = rightAC; + } + + // send to output + outs[0][offset] = outL; + outs[1][offset] = outR; + + if(std::max(fabs(leftSC), fabs(rightSC)) > *params[param_threshold]) { + detected_led = srate >> 3; + } + if(std::max(fabs(leftAC), fabs(rightAC)) > 1.f) { + clip_led = srate >> 3; + } + if(clip_led > 0) { + clip_out = 1.f; + } else { + clip_out = std::max(fabs(outL), fabs(outR)); + } + detected = std::max(fabs(leftMC), fabs(rightMC)); + + // next sample + ++offset; + } // cycle trough samples + hpL.sanitize(); + hpR.sanitize(); + lpL.sanitize(); + lpR.sanitize(); + pL.sanitize(); + pR.sanitize(); + } + // draw meters + if(params[param_detected_led] != NULL) { + *params[param_detected_led] = detected_led; + } + if(params[param_clip_out] != NULL) { + *params[param_clip_out] = clip_out; + } + if(params[param_detected] != NULL) { + *params[param_detected] = detected; + } + // draw strip meter + if(bypass > 0.5f) { + if(params[param_compression] != NULL) { + *params[param_compression] = 1.0f; + } + } else { + if(params[param_compression] != NULL) { + *params[param_compression] = compressor.get_comp_level(); + } + } + // whatever has to be returned x) + return outputs_mask; +} +bool deesser_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const +{ + if (!is_active) + return false; + if (index == param_f1_freq && !subindex) { + context->set_line_width(1.5); + return ::get_graph(*this, subindex, data, points); + } + return false; +} + +bool deesser_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const +{ + return get_freq_gridline(subindex, pos, vertical, legend, context); + +// return false; +} + +int deesser_audio_module::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) const +{ + if (!is_active) { + return false; + } else { + // (fabs(inertia_cutoff.get_last() - old_cutoff) + 100 * fabs(inertia_resonance.get_last() - old_resonance) + fabs(*params[par_mode] - old_mode) > 0.1f) + if (*params[param_f1_freq] != f1_freq_old1 + or *params[param_f2_freq] != f2_freq_old1 + or *params[param_f1_level] != f1_level_old1 + or *params[param_f2_level] != f2_level_old1 + or *params[param_f2_q] !=f2_q_old1) + { + f1_freq_old1 = *params[param_f1_freq]; + f2_freq_old1 = *params[param_f2_freq]; + f1_level_old1 = *params[param_f1_level]; + f2_level_old1 = *params[param_f2_level]; + f2_q_old1 = *params[param_f2_q]; + last_generation++; + subindex_graph = 0; + subindex_dot = INT_MAX; + subindex_gridline = INT_MAX; + } + else { + subindex_graph = 0; + subindex_dot = subindex_gridline = generation ? INT_MAX : 0; + } + if (generation == last_calculated_generation) + subindex_graph = INT_MAX; + return last_generation; + } + return false; +} + +/// Gain reduction module by Thor +/// All functions of this module are originally written +/// by Thor, while some features have been stripped (mainly stereo linking +/// and frequency correction as implemented in Sidechain Compressor above) +/// To save some CPU. +//////////////////////////////////////////////////////////////////////////////// +gain_reduction_audio_module::gain_reduction_audio_module() +{ + is_active = false; + last_generation = 0; +} + +void gain_reduction_audio_module::activate() +{ + is_active = true; + linSlope = 0.f; + meter_out = 0.f; + meter_comp = 1.f; + float l, r; + l = r = 0.f; + float byp = bypass; + bypass = 0.0; + process(l, r); + bypass = byp; +} + +void gain_reduction_audio_module::deactivate() +{ + is_active = false; +} + +void gain_reduction_audio_module::update_curve() +{ + float linThreshold = threshold; + float linKneeSqrt = sqrt(knee); + linKneeStart = linThreshold / linKneeSqrt; + adjKneeStart = linKneeStart*linKneeStart; + float linKneeStop = linThreshold * linKneeSqrt; + thres = log(linThreshold); + kneeStart = log(linKneeStart); + kneeStop = log(linKneeStop); + compressedKneeStop = (kneeStop - thres) / ratio + thres; +} + +void gain_reduction_audio_module::process(float &left, float &right, const float *det_left, const float *det_right) +{ + if(!det_left) { + det_left = &left; + } + if(!det_right) { + det_right = &right; + } + float gain = 1.f; + if(bypass < 0.5f) { + // this routine is mainly copied from thor's compressor module + // greatest sounding compressor I've heard! + bool rms = detection == 0; + bool average = stereo_link == 0; + float attack_coeff = std::min(1.f, 1.f / (attack * srate / 4000.f)); + float release_coeff = std::min(1.f, 1.f / (release * srate / 4000.f)); + + float absample = average ? (fabs(*det_left) + fabs(*det_right)) * 0.5f : std::max(fabs(*det_left), fabs(*det_right)); + if(rms) absample *= absample; + + linSlope += (absample - linSlope) * (absample > linSlope ? attack_coeff : release_coeff); + + if(linSlope > 0.f) { + gain = output_gain(linSlope, rms); + } + + left *= gain * makeup; + right *= gain * makeup; + meter_out = std::max(fabs(left), fabs(right));; + meter_comp = gain; + detected = rms ? sqrt(linSlope) : linSlope; + } +} + +float gain_reduction_audio_module::output_level(float slope) const { + return slope * output_gain(slope, false) * makeup; +} + +float gain_reduction_audio_module::output_gain(float linSlope, bool rms) const { + //this calculation is also thor's work + if(linSlope > (rms ? adjKneeStart : linKneeStart)) { + float slope = log(linSlope); + if(rms) slope *= 0.5f; + + float gain = 0.f; + float delta = 0.f; + if(IS_FAKE_INFINITY(ratio)) { + gain = thres; + delta = 0.f; + } else { + gain = (slope - thres) / ratio + thres; + delta = 1.f / ratio; + } + + if(knee > 1.f && slope < kneeStop) { + gain = hermite_interpolation(slope, kneeStart, kneeStop, kneeStart, compressedKneeStop, 1.f, delta); + } + + return exp(gain - slope); + } + + return 1.f; +} + +void gain_reduction_audio_module::set_sample_rate(uint32_t sr) +{ + srate = sr; +} +void gain_reduction_audio_module::set_params(float att, float rel, float thr, float rat, float kn, float mak, float det, float stl, float byp, float mu) +{ + // set all params + attack = att; + release = rel; + threshold = thr; + ratio = rat; + knee = kn; + makeup = mak; + detection = det; + stereo_link = stl; + bypass = byp; + mute = mu; + if(mute > 0.f) { + meter_out = 0.f; + meter_comp = 1.f; + } +} +float gain_reduction_audio_module::get_output_level() { + // returns output level (max(left, right)) + return meter_out; +} +float gain_reduction_audio_module::get_comp_level() { + // returns amount of compression + return meter_comp; +} + +bool gain_reduction_audio_module::get_graph(int subindex, float *data, int points, cairo_iface *context) const +{ + if (!is_active) + return false; + if (subindex > 1) // 1 + return false; + for (int i = 0; i < points; i++) + { + float input = dB_grid_inv(-1.0 + i * 2.0 / (points - 1)); + if (subindex == 0) + data[i] = dB_grid(input); + else { + float output = output_level(input); + data[i] = dB_grid(output); + } + } + if (subindex == (bypass > 0.5f ? 1 : 0) or mute > 0.1f) + context->set_source_rgba(0.35, 0.4, 0.2, 0.3); + else { + context->set_source_rgba(0.35, 0.4, 0.2, 1); + context->set_line_width(1.5); + } + return true; +} + +bool gain_reduction_audio_module::get_dot(int subindex, float &x, float &y, int &size, cairo_iface *context) const +{ + if (!is_active) + return false; + if (!subindex) + { + if(bypass > 0.5f or mute > 0.f) { + return false; + } else { + bool rms = detection == 0; + float det = rms ? sqrt(detected) : detected; + x = 0.5 + 0.5 * dB_grid(det); + y = dB_grid(bypass > 0.5f or mute > 0.f ? det : output_level(det)); + return true; + } + } + return false; +} + +bool gain_reduction_audio_module::get_gridline(int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const +{ + bool tmp; + vertical = (subindex & 1) != 0; + bool result = get_freq_gridline(subindex >> 1, pos, tmp, legend, context, false); + if (result && vertical) { + if ((subindex & 4) && !legend.empty()) { + legend = ""; + } + else { + size_t pos = legend.find(" dB"); + if (pos != std::string::npos) + legend.erase(pos); + } + pos = 0.5 + 0.5 * pos; + } + return result; +} + +int gain_reduction_audio_module::get_changed_offsets(int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) const +{ + subindex_graph = 0; + subindex_dot = 0; + subindex_gridline = generation ? INT_MAX : 0; + + if (fabs(threshold-old_threshold) + fabs(ratio - old_ratio) + fabs(knee - old_knee) + fabs(makeup - old_makeup) + fabs(detection - old_detection) + fabs(bypass - old_bypass) + fabs(mute - old_mute) > 0.000001f) + { + old_threshold = threshold; + old_ratio = ratio; + old_knee = knee; + old_makeup = makeup; + old_detection = detection; + old_bypass = bypass; + old_mute = mute; + last_generation++; + } + + if (generation == last_generation) + subindex_graph = 2; + return last_generation; +} + + + +/////////////////////////////////////////////////////////////////////////////////////////////// + +gate_audio_module::gate_audio_module() +{ + is_active = false; + srate = 0; + last_generation = 0; +} + +void gate_audio_module::activate() +{ + is_active = true; + linSlope = 0.f; + peak = 0.f; + clip = 0.f; +} + +void gate_audio_module::deactivate() +{ + is_active = false; +} + +void gate_audio_module::set_sample_rate(uint32_t sr) +{ + srate = sr; + awL.set(sr); + awR.set(sr); +} + +bool gate_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const +{ + if (!is_active) + return false; + if (subindex > 1) // 1 + return false; + for (int i = 0; i < points; i++) + { + float input = dB_grid_inv(-1.0 + i * 2.0 / (points - 1)); + float output = output_level(input); + if (subindex == 0) + data[i] = dB_grid(input); + else + data[i] = dB_grid(output); + } + if (subindex == (*params[param_bypass] > 0.f ? 1 : 0)) + context->set_source_rgba(0.35, 0.4, 0.2, 0.3); + else { + context->set_source_rgba(0.35, 0.4, 0.2, 1); + context->set_line_width(1.5); + } + return true; +} + +bool gate_audio_module::get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context) const +{ + if (!is_active) + return false; + if (!subindex) + { + bool rms = *params[param_detection] == 0; + float det = rms ? sqrt(detected) : detected; + x = 0.5 + 0.5 * dB_grid(det); + y = dB_grid(*params[param_bypass] > 0.f ? det : output_level(det)); + return *params[param_bypass] > 0.f ? false : true; + } + return false; +} + +bool gate_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const +{ + bool tmp; + vertical = (subindex & 1) != 0; + bool result = get_freq_gridline(subindex >> 1, pos, tmp, legend, context, false); + if (result && vertical) { + if ((subindex & 4) && !legend.empty()) { + legend = ""; + } + else { + size_t pos = legend.find(" dB"); + if (pos != std::string::npos) + legend.erase(pos); + } + pos = 0.5 + 0.5 * pos; + } + return result; +} + +uint32_t gate_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) +{ + bool bypass = *params[param_bypass] > 0.f; + + if(bypass) { + int count = numsamples * sizeof(float); + memcpy(outs[0], ins[0], count); + memcpy(outs[1], ins[1], count); + + if(params[param_gating] != NULL) { + *params[param_gating] = 1.f; + } + + if(params[param_clip] != NULL) { + *params[param_clip] = 0.f; + } + + if(params[param_peak] != NULL) { + *params[param_peak] = 0.f; + } + + return inputs_mask; + } + + bool rms = *params[param_detection] == 0; + bool average = *params[param_stereo_link] == 0; + int aweighting = fastf2i_drm(*params[param_aweighting]); + float linThreshold = *params[param_threshold]; + if (rms) + linThreshold = linThreshold * linThreshold; + ratio = *params[param_ratio]; + float attack = *params[param_attack]; + float attack_coeff = std::min(1.f, 1.f / (attack * srate / 4000.f)); + float release = *params[param_release]; + float release_coeff = std::min(1.f, 1.f / (release * srate / 4000.f)); + makeup = *params[param_makeup]; + knee = *params[param_knee]; + + range = *params[param_range]; + + float linKneeSqrt = sqrt(knee); + linKneeStart = linThreshold / linKneeSqrt; + adjKneeStart = linKneeStart*linKneeStart; + linKneeStop = linThreshold * linKneeSqrt; + + threshold = log(linThreshold); + kneeStart = log(linKneeStart); + kneeStop = log(linKneeStop); + compressedKneeStop = (kneeStop - threshold) / ratio + threshold; + + if (aweighting >= 2) + { + bpL.set_highshelf_rbj(5000, 0.707, 10 << (aweighting - 2), srate); + bpR.copy_coeffs(bpL); + bpL.sanitize(); + bpR.sanitize(); + } + + numsamples += offset; + + float gating = 1.f; + + peak -= peak * 5.f * numsamples / srate; + + clip -= std::min(clip, numsamples); + float left; + float right; + + while(offset < numsamples) { + if(*params[param_trigger]) { + left = ins[2][offset]; // Use sidechain to trigger input + right = left; // (mono sidechain) + } else { + left = ins[0][offset]; + right = ins[1][offset]; + } + + if(aweighting == 1) { + left = awL.process(left); + right = awR.process(right); + } + else if(aweighting >= 2) { + left = bpL.process(left); + right = bpR.process(right); + } + + float absample = average ? (fabs(left) + fabs(right)) * 0.5f : std::max(fabs(left), fabs(right)); + if(rms) absample *= absample; + + linSlope += (absample - linSlope) * (absample > linSlope ? attack_coeff : release_coeff); + + float gain = 1.f; + + if(linSlope > 0.f) { + gain = output_gain(linSlope, rms); + } + + gating = gain; + gain *= makeup; + + float outL = ins[0][offset] * gain; + float outR = ins[1][offset] * gain; + + outs[0][offset] = outL; + outs[1][offset] = outR; + + ++offset; + + float maxLR = std::max(fabs(outL), fabs(outR)); + + if(maxLR > 1.f) clip = srate >> 3; /* blink clip LED for 125 ms */ + + if(maxLR > peak) { + peak = maxLR; + } + } + + detected = linSlope; + + if(params[param_gating] != NULL) { + *params[param_gating] = gating; + } + + if(params[param_clip] != NULL) { + *params[param_clip] = clip; + } + + if(params[param_peak] != NULL) { + *params[param_peak] = peak; + } + + return inputs_mask; +} + +int gate_audio_module::get_changed_offsets(int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) const +{ + subindex_graph = 0; + subindex_dot = 0; + subindex_gridline = generation ? INT_MAX : 0; + + if (fabs(range-old_range) + fabs(threshold-old_threshold) + fabs(ratio - old_ratio) + fabs(knee - old_knee) + fabs( makeup - old_makeup) + fabs( *params[param_bypass] - old_bypass) > 0.01f) + { + old_range = range; + old_threshold = threshold; + old_ratio = ratio; + old_knee = knee; + old_makeup = makeup; + old_bypass = *params[param_bypass]; + old_trigger = *params[param_trigger]; + old_mono = *params[param_mono]; + last_generation++; + } + old_trigger = *params[param_trigger]; + + if (generation == last_generation) + subindex_graph = 2; + return last_generation; +} diff --git a/plugins/ladspa_effect/calf/src/modules_dist.cpp b/plugins/ladspa_effect/calf/src/modules_dist.cpp new file mode 100644 index 000000000..aba40fc74 --- /dev/null +++ b/plugins/ladspa_effect/calf/src/modules_dist.cpp @@ -0,0 +1,738 @@ +/* Calf DSP plugin pack + * Distortion related plugins + * + * Copyright (C) 2001-2010 Krzysztof Foltman, Markus Schmidt, Thor Harald Johansen and others + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include + +using namespace dsp; +using namespace calf_plugins; + +#define SET_IF_CONNECTED(name) if (params[AM::param_##name] != NULL) *params[AM::param_##name] = name; + +/// Saturator Band by Markus Schmidt +/// +/// This module is based on Krzysztof's filters and Tom Szilagyi's distortion routine. +/// It provides a blendable saturation stage followed by a highpass, a lowpass and a peak filter +/////////////////////////////////////////////////////////////////////////////////////////////// + +saturator_audio_module::saturator_audio_module() +{ + is_active = false; + srate = 0; + clip_in = 0.f; + clip_out = 0.f; + meter_in = 0.f; + meter_out = 0.f; + meter_drive = 0.f; +} + +void saturator_audio_module::activate() +{ + is_active = true; + // set all filters + params_changed(); +} +void saturator_audio_module::deactivate() +{ + is_active = false; +} + +void saturator_audio_module::params_changed() +{ + // set the params of all filters + if(*params[param_lp_pre_freq] != lp_pre_freq_old) { + lp[0][0].set_lp_rbj(*params[param_lp_pre_freq], 0.707, (float)srate); + if(in_count > 1 && out_count > 1) + lp[1][0].copy_coeffs(lp[0][0]); + lp[0][1].copy_coeffs(lp[0][0]); + if(in_count > 1 && out_count > 1) + lp[1][1].copy_coeffs(lp[0][0]); + lp_pre_freq_old = *params[param_lp_pre_freq]; + } + if(*params[param_hp_pre_freq] != hp_pre_freq_old) { + hp[0][0].set_hp_rbj(*params[param_hp_pre_freq], 0.707, (float)srate); + if(in_count > 1 && out_count > 1) + hp[1][0].copy_coeffs(hp[0][0]); + hp[0][1].copy_coeffs(hp[0][0]); + if(in_count > 1 && out_count > 1) + hp[1][1].copy_coeffs(hp[0][0]); + hp_pre_freq_old = *params[param_hp_pre_freq]; + } + if(*params[param_lp_post_freq] != lp_post_freq_old) { + lp[0][2].set_lp_rbj(*params[param_lp_post_freq], 0.707, (float)srate); + if(in_count > 1 && out_count > 1) + lp[1][2].copy_coeffs(lp[0][2]); + lp[0][3].copy_coeffs(lp[0][2]); + if(in_count > 1 && out_count > 1) + lp[1][3].copy_coeffs(lp[0][2]); + lp_post_freq_old = *params[param_lp_post_freq]; + } + if(*params[param_hp_post_freq] != hp_post_freq_old) { + hp[0][2].set_hp_rbj(*params[param_hp_post_freq], 0.707, (float)srate); + if(in_count > 1 && out_count > 1) + hp[1][2].copy_coeffs(hp[0][2]); + hp[0][3].copy_coeffs(hp[0][2]); + if(in_count > 1 && out_count > 1) + hp[1][3].copy_coeffs(hp[0][2]); + hp_post_freq_old = *params[param_hp_post_freq]; + } + if(*params[param_p_freq] != p_freq_old or *params[param_p_level] != p_level_old or *params[param_p_q] != p_q_old) { + p[0].set_peakeq_rbj((float)*params[param_p_freq], (float)*params[param_p_q], (float)*params[param_p_level], (float)srate); + if(in_count > 1 && out_count > 1) + p[1].copy_coeffs(p[0]); + p_freq_old = *params[param_p_freq]; + p_level_old = *params[param_p_level]; + p_q_old = *params[param_p_q]; + } + // set distortion + dist[0].set_params(*params[param_blend], *params[param_drive]); + if(in_count > 1 && out_count > 1) + dist[1].set_params(*params[param_blend], *params[param_drive]); +} + +void saturator_audio_module::set_sample_rate(uint32_t sr) +{ + srate = sr; + dist[0].set_sample_rate(sr); + if(in_count > 1 && out_count > 1) + dist[1].set_sample_rate(sr); +} + +uint32_t saturator_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) +{ + bool bypass = *params[param_bypass] > 0.5f; + numsamples += offset; + if(bypass) { + // everything bypassed + while(offset < numsamples) { + if(in_count > 1 && out_count > 1) { + outs[0][offset] = ins[0][offset]; + outs[1][offset] = ins[1][offset]; + } else if(in_count > 1) { + outs[0][offset] = (ins[0][offset] + ins[1][offset]) / 2; + } else if(out_count > 1) { + outs[0][offset] = ins[0][offset]; + outs[1][offset] = ins[0][offset]; + } else { + outs[0][offset] = ins[0][offset]; + } + ++offset; + } + // displays, too + clip_in = 0.f; + clip_out = 0.f; + meter_in = 0.f; + meter_out = 0.f; + meter_drive = 0.f; + } else { + + clip_in -= std::min(clip_in, numsamples); + clip_out -= std::min(clip_out, numsamples); + meter_in = 0.f; + meter_out = 0.f; + meter_drive = 0.f; + float in_avg[2] = {0.f, 0.f}; + float out_avg[2] = {0.f, 0.f}; + float tube_avg = 0.f; + // process + while(offset < numsamples) { + // cycle through samples + float out[2], in[2] = {0.f, 0.f}; + float maxIn, maxOut = 0.f; + int c = 0; + + if(in_count > 1 && out_count > 1) { + // stereo in/stereo out + // handle full stereo + in[0] = ins[0][offset]; + in[1] = ins[1][offset]; + c = 2; + } else { + // in and/or out mono + // handle mono + in[0] = ins[0][offset]; + in[1] = in[0]; + c = 1; + } + + float proc[2]; + proc[0] = in[0] * *params[param_level_in]; + proc[1] = in[1] * *params[param_level_in]; + + for (int i = 0; i < c; ++i) { + // all pre filters in chain + proc[i] = lp[i][1].process(lp[i][0].process(proc[i])); + proc[i] = hp[i][1].process(hp[i][0].process(proc[i])); + + // get average for display purposes before... + in_avg[i] += fabs(pow(proc[i], 2.f)); + + // ...saturate... + proc[i] = dist[i].process(proc[i]); + + // ...and get average after... + out_avg[i] += fabs(pow(proc[i], 2.f)); + + // tone control + proc[i] = p[i].process(proc[i]); + + // all post filters in chain + proc[i] = lp[i][2].process(lp[i][3].process(proc[i])); + proc[i] = hp[i][2].process(hp[i][3].process(proc[i])); + + //subtract gain + proc[i] /= *params[param_level_in]; + } + + if(in_count > 1 && out_count > 1) { + // full stereo + out[0] = ((proc[0] * *params[param_mix]) + in[0] * (1 - *params[param_mix])) * *params[param_level_out]; + outs[0][offset] = out[0]; + out[1] = ((proc[1] * *params[param_mix]) + in[1] * (1 - *params[param_mix])) * *params[param_level_out]; + outs[1][offset] = out[1]; + maxIn = std::max(fabs(in[0]), fabs(in[1])); + maxOut = std::max(fabs(out[0]), fabs(out[1])); + } else if(out_count > 1) { + // mono -> pseudo stereo + out[0] = ((proc[0] * *params[param_mix]) + in[0] * (1 - *params[param_mix])) * *params[param_level_out]; + outs[0][offset] = out[0]; + out[1] = out[0]; + outs[1][offset] = out[1]; + maxOut = fabs(out[0]); + maxIn = fabs(in[0]); + } else { + // stereo -> mono + // or full mono + out[0] = ((proc[0] * *params[param_mix]) + in[0] * (1 - *params[param_mix])) * *params[param_level_out]; + outs[0][offset] = out[0]; + maxIn = fabs(in[0]); + maxOut = fabs(out[0]); + } + + if(maxIn > 1.f) { + clip_in = srate >> 3; + } + if(maxOut > 1.f) { + clip_out = srate >> 3; + } + // set up in / out meters + if(maxIn > meter_in) { + meter_in = maxIn; + } + if(maxOut > meter_out) { + meter_out = maxOut; + } + + // next sample + ++offset; + } // cycle trough samples + + tube_avg = (sqrt(std::max(out_avg[0], out_avg[1])) / numsamples) - (sqrt(std::max(in_avg[0], in_avg[1])) / numsamples); + meter_drive = (5.0f * fabs(tube_avg) * (float(*params[param_blend]) + 30.0f)); + // printf("out:%.6f in: %.6f avg: %.6f drv: %.3f\n", sqrt(std::max(out_avg[0], out_avg[1])) / numsamples, sqrt(std::max(in_avg[0], in_avg[1])) / numsamples, tube_avg, meter_drive); + // clean up + lp[0][0].sanitize(); + lp[1][0].sanitize(); + lp[0][1].sanitize(); + lp[1][1].sanitize(); + lp[0][2].sanitize(); + lp[1][2].sanitize(); + lp[0][3].sanitize(); + lp[1][3].sanitize(); + hp[0][0].sanitize(); + hp[1][0].sanitize(); + hp[0][1].sanitize(); + hp[1][1].sanitize(); + hp[0][2].sanitize(); + hp[1][2].sanitize(); + hp[0][3].sanitize(); + hp[1][3].sanitize(); + p[0].sanitize(); + p[1].sanitize(); + } + // draw meters + if(params[param_clip_in] != NULL) { + *params[param_clip_in] = clip_in; + } + if(params[param_clip_out] != NULL) { + *params[param_clip_out] = clip_out; + } + + if(params[param_meter_in] != NULL) { + *params[param_meter_in] = meter_in; + } + if(params[param_meter_out] != NULL) { + *params[param_meter_out] = meter_out; + } + if(params[param_meter_drive] != NULL) { + *params[param_meter_drive] = meter_drive; + } + // whatever has to be returned x) + return outputs_mask; +} + +/// Exciter by Markus Schmidt +/// +/// This module is based on Krzysztof's filters and Tom Szilagyi's distortion routine. +/// It provides a blendable saturation stage followed by a highpass, a lowpass and a peak filter +/////////////////////////////////////////////////////////////////////////////////////////////// + +exciter_audio_module::exciter_audio_module() +{ + is_active = false; + srate = 0; + clip_in = 0.f; + clip_out = 0.f; + meter_in = 0.f; + meter_out = 0.f; + meter_drive = 0.f; +} + +void exciter_audio_module::activate() +{ + is_active = true; + // set all filters + params_changed(); +} + +void exciter_audio_module::deactivate() +{ + is_active = false; +} + +void exciter_audio_module::params_changed() +{ + // set the params of all filters + if(*params[param_freq] != freq_old) { + hp[0][0].set_hp_rbj(*params[param_freq], 0.707, (float)srate); + hp[0][1].copy_coeffs(hp[0][0]); + hp[0][2].copy_coeffs(hp[0][0]); + hp[0][3].copy_coeffs(hp[0][0]); + if(in_count > 1 && out_count > 1) { + hp[1][0].copy_coeffs(hp[0][0]); + hp[1][1].copy_coeffs(hp[0][0]); + hp[1][2].copy_coeffs(hp[0][0]); + hp[1][3].copy_coeffs(hp[0][0]); + } + freq_old = *params[param_freq]; + } + // set distortion + dist[0].set_params(*params[param_blend], *params[param_drive]); + if(in_count > 1 && out_count > 1) + dist[1].set_params(*params[param_blend], *params[param_drive]); +} + +void exciter_audio_module::set_sample_rate(uint32_t sr) +{ + srate = sr; + dist[0].set_sample_rate(sr); + if(in_count > 1 && out_count > 1) + dist[1].set_sample_rate(sr); +} + +uint32_t exciter_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) +{ + bool bypass = *params[param_bypass] > 0.5f; + numsamples += offset; + if(bypass) { + // everything bypassed + while(offset < numsamples) { + if(in_count > 1 && out_count > 1) { + outs[0][offset] = ins[0][offset]; + outs[1][offset] = ins[1][offset]; + } else if(in_count > 1) { + outs[0][offset] = (ins[0][offset] + ins[1][offset]) / 2; + } else if(out_count > 1) { + outs[0][offset] = ins[0][offset]; + outs[1][offset] = ins[0][offset]; + } else { + outs[0][offset] = ins[0][offset]; + } + ++offset; + } + // displays, too + clip_in = 0.f; + clip_out = 0.f; + meter_in = 0.f; + meter_out = 0.f; + meter_drive = 0.f; + } else { + + clip_in -= std::min(clip_in, numsamples); + clip_out -= std::min(clip_out, numsamples); + meter_in = 0.f; + meter_out = 0.f; + meter_drive = 0.f; + + // process + while(offset < numsamples) { + // cycle through samples + float out[2], in[2] = {0.f, 0.f}; + float maxIn, maxOut, maxDrive = 0.f; + int c = 0; + + if(in_count > 1 && out_count > 1) { + // stereo in/stereo out + // handle full stereo + in[0] = ins[0][offset]; + in[0] *= *params[param_level_in]; + in[1] = ins[1][offset]; + in[1] *= *params[param_level_in]; + c = 2; + } else { + // in and/or out mono + // handle mono + in[0] = ins[0][offset]; + in[0] *= *params[param_level_in]; + in[1] = in[0]; + c = 1; + } + + float proc[2]; + proc[0] = in[0]; + proc[1] = in[1]; + + for (int i = 0; i < c; ++i) { + // all pre filters in chain + proc[i] = hp[i][1].process(hp[i][0].process(proc[i])); + + // saturate + proc[i] = dist[i].process(proc[i]); + + // all post filters in chain + proc[i] = hp[i][2].process(hp[i][3].process(proc[i])); + } + + if(in_count > 1 && out_count > 1) { + // full stereo + if(*params[param_listen] > 0.f) + out[0] = proc[0] * *params[param_amount] * *params[param_level_out]; + else + out[0] = (proc[0] * *params[param_amount] + in[0]) * *params[param_level_out]; + outs[0][offset] = out[0]; + if(*params[param_listen] > 0.f) + out[1] = proc[1] * *params[param_amount] * *params[param_level_out]; + else + out[1] = (proc[1] * *params[param_amount] + in[1]) * *params[param_level_out]; + outs[1][offset] = out[1]; + maxIn = std::max(fabs(in[0]), fabs(in[1])); + maxOut = std::max(fabs(out[0]), fabs(out[1])); + maxDrive = std::max(dist[0].get_distortion_level() * *params[param_amount], + dist[1].get_distortion_level() * *params[param_amount]); + } else if(out_count > 1) { + // mono -> pseudo stereo + if(*params[param_listen] > 0.f) + out[0] = proc[0] * *params[param_amount] * *params[param_level_out]; + else + out[0] = (proc[0] * *params[param_amount] + in[0]) * *params[param_level_out]; + outs[0][offset] = out[0]; + out[1] = out[0]; + outs[1][offset] = out[1]; + maxOut = fabs(out[0]); + maxIn = fabs(in[0]); + maxDrive = dist[0].get_distortion_level() * *params[param_amount]; + } else { + // stereo -> mono + // or full mono + if(*params[param_listen] > 0.f) + out[0] = proc[0] * *params[param_amount] * *params[param_level_out]; + else + out[0] = (proc[0] * *params[param_amount] + in[0]) * *params[param_level_out]; + outs[0][offset] = out[0]; + maxIn = fabs(in[0]); + maxOut = fabs(out[0]); + maxDrive = dist[0].get_distortion_level() * *params[param_amount]; + } + + if(maxIn > 1.f) { + clip_in = srate >> 3; + } + if(maxOut > 1.f) { + clip_out = srate >> 3; + } + // set up in / out meters + if(maxIn > meter_in) { + meter_in = maxIn; + } + if(maxOut > meter_out) { + meter_out = maxOut; + } + if(maxDrive > meter_drive) { + meter_drive = maxDrive; + } + + // next sample + ++offset; + } // cycle trough samples + // clean up + hp[0][0].sanitize(); + hp[1][0].sanitize(); + hp[0][1].sanitize(); + hp[1][1].sanitize(); + hp[0][2].sanitize(); + hp[1][2].sanitize(); + hp[0][3].sanitize(); + hp[1][3].sanitize(); + } + // draw meters + if(params[param_clip_in] != NULL) { + *params[param_clip_in] = clip_in; + } + if(params[param_clip_out] != NULL) { + *params[param_clip_out] = clip_out; + } + + if(params[param_meter_in] != NULL) { + *params[param_meter_in] = meter_in; + } + if(params[param_meter_out] != NULL) { + *params[param_meter_out] = meter_out; + } + if(params[param_meter_drive] != NULL) { + *params[param_meter_drive] = meter_drive; + } + // whatever has to be returned x) + return outputs_mask; +} + +/// Bass Enhancer by Markus Schmidt +/// +/// This module is based on Krzysztof's filters and Tom's distortion routine. +/// It sends the signal through a lowpass, saturates it and sends it through a lowpass again +/////////////////////////////////////////////////////////////////////////////////////////////// + +bassenhancer_audio_module::bassenhancer_audio_module() +{ + is_active = false; + srate = 0; + clip_in = 0.f; + clip_out = 0.f; + meter_in = 0.f; + meter_out = 0.f; + meter_drive = 0.f; +} + +void bassenhancer_audio_module::activate() +{ + is_active = true; + // set all filters + params_changed(); +} +void bassenhancer_audio_module::deactivate() +{ + is_active = false; +} + +void bassenhancer_audio_module::params_changed() +{ + // set the params of all filters + if(*params[param_freq] != freq_old) { + lp[0][0].set_lp_rbj(*params[param_freq], 0.707, (float)srate); + lp[0][1].copy_coeffs(lp[0][0]); + lp[0][2].copy_coeffs(lp[0][0]); + lp[0][3].copy_coeffs(lp[0][0]); + if(in_count > 1 && out_count > 1) { + lp[1][0].copy_coeffs(lp[0][0]); + lp[1][1].copy_coeffs(lp[0][0]); + lp[1][2].copy_coeffs(lp[0][0]); + lp[1][3].copy_coeffs(lp[0][0]); + } + freq_old = *params[param_freq]; + } + // set distortion + dist[0].set_params(*params[param_blend], *params[param_drive]); + if(in_count > 1 && out_count > 1) + dist[1].set_params(*params[param_blend], *params[param_drive]); +} + +void bassenhancer_audio_module::set_sample_rate(uint32_t sr) +{ + srate = sr; + dist[0].set_sample_rate(sr); + if(in_count > 1 && out_count > 1) + dist[1].set_sample_rate(sr); +} + +uint32_t bassenhancer_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) +{ + bool bypass = *params[param_bypass] > 0.5f; + numsamples += offset; + if(bypass) { + // everything bypassed + while(offset < numsamples) { + if(in_count > 1 && out_count > 1) { + outs[0][offset] = ins[0][offset]; + outs[1][offset] = ins[1][offset]; + } else if(in_count > 1) { + outs[0][offset] = (ins[0][offset] + ins[1][offset]) / 2; + } else if(out_count > 1) { + outs[0][offset] = ins[0][offset]; + outs[1][offset] = ins[0][offset]; + } else { + outs[0][offset] = ins[0][offset]; + } + ++offset; + } + // displays, too + clip_in = 0.f; + clip_out = 0.f; + meter_in = 0.f; + meter_out = 0.f; + meter_drive = 0.f; + } else { + + clip_in -= std::min(clip_in, numsamples); + clip_out -= std::min(clip_out, numsamples); + meter_in = 0.f; + meter_out = 0.f; + meter_drive = 0.f; + + // process + while(offset < numsamples) { + // cycle through samples + float out[2], in[2] = {0.f, 0.f}; + float maxIn, maxOut, maxDrive = 0.f; + int c = 0; + + if(in_count > 1 && out_count > 1) { + // stereo in/stereo out + // handle full stereo + in[0] = ins[0][offset]; + in[0] *= *params[param_level_in]; + in[1] = ins[1][offset]; + in[1] *= *params[param_level_in]; + c = 2; + } else { + // in and/or out mono + // handle mono + in[0] = ins[0][offset]; + in[0] *= *params[param_level_in]; + in[1] = in[0]; + c = 1; + } + + float proc[2]; + proc[0] = in[0]; + proc[1] = in[1]; + + for (int i = 0; i < c; ++i) { + // all pre filters in chain + proc[i] = lp[i][1].process(lp[i][0].process(proc[i])); + + // saturate + proc[i] = dist[i].process(proc[i]); + + // all post filters in chain + proc[i] = lp[i][2].process(lp[i][3].process(proc[i])); + } + + if(in_count > 1 && out_count > 1) { + // full stereo + if(*params[param_listen] > 0.f) + out[0] = proc[0] * *params[param_amount] * *params[param_level_out]; + else + out[0] = (proc[0] * *params[param_amount] + in[0]) * *params[param_level_out]; + outs[0][offset] = out[0]; + if(*params[param_listen] > 0.f) + out[1] = proc[1] * *params[param_amount] * *params[param_level_out]; + else + out[1] = (proc[1] * *params[param_amount] + in[1]) * *params[param_level_out]; + outs[1][offset] = out[1]; + maxIn = std::max(fabs(in[0]), fabs(in[1])); + maxOut = std::max(fabs(out[0]), fabs(out[1])); + maxDrive = std::max(dist[0].get_distortion_level() * *params[param_amount], + dist[1].get_distortion_level() * *params[param_amount]); + } else if(out_count > 1) { + // mono -> pseudo stereo + if(*params[param_listen] > 0.f) + out[0] = proc[0] * *params[param_amount] * *params[param_level_out]; + else + out[0] = (proc[0] * *params[param_amount] + in[0]) * *params[param_level_out]; + outs[0][offset] = out[0]; + out[1] = out[0]; + outs[1][offset] = out[1]; + maxOut = fabs(out[0]); + maxIn = fabs(in[0]); + maxDrive = dist[0].get_distortion_level() * *params[param_amount]; + } else { + // stereo -> mono + // or full mono + if(*params[param_listen] > 0.f) + out[0] = proc[0] * *params[param_amount] * *params[param_level_out]; + else + out[0] = (proc[0] * *params[param_amount] + in[0]) * *params[param_level_out]; + outs[0][offset] = out[0]; + maxIn = fabs(in[0]); + maxOut = fabs(out[0]); + maxDrive = dist[0].get_distortion_level() * *params[param_amount]; + } + + if(maxIn > 1.f) { + clip_in = srate >> 3; + } + if(maxOut > 1.f) { + clip_out = srate >> 3; + } + // set up in / out meters + if(maxIn > meter_in) { + meter_in = maxIn; + } + if(maxOut > meter_out) { + meter_out = maxOut; + } + if(maxDrive > meter_drive) { + meter_drive = maxDrive; + } + + // next sample + ++offset; + } // cycle trough samples + // clean up + lp[0][0].sanitize(); + lp[1][0].sanitize(); + lp[0][1].sanitize(); + lp[1][1].sanitize(); + lp[0][2].sanitize(); + lp[1][2].sanitize(); + lp[0][3].sanitize(); + lp[1][3].sanitize(); + } + // draw meters + if(params[param_clip_in] != NULL) { + *params[param_clip_in] = clip_in; + } + if(params[param_clip_out] != NULL) { + *params[param_clip_out] = clip_out; + } + + if(params[param_meter_in] != NULL) { + *params[param_meter_in] = meter_in; + } + if(params[param_meter_out] != NULL) { + *params[param_meter_out] = meter_out; + } + if(params[param_meter_drive] != NULL) { + *params[param_meter_drive] = meter_drive; + } + // whatever has to be returned x) + return outputs_mask; +} diff --git a/plugins/ladspa_effect/calf/src/modules_dsp.cpp b/plugins/ladspa_effect/calf/src/modules_dsp.cpp deleted file mode 100644 index 5258c0475..000000000 --- a/plugins/ladspa_effect/calf/src/modules_dsp.cpp +++ /dev/null @@ -1,2951 +0,0 @@ -/* Calf DSP Library - * Example audio modules - DSP code - * - * Copyright (C) 2001-2008 Krzysztof Foltman - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this program; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA - */ -#include -#include -#include -#if USE_JACK -#include -#endif -#include -#include -#include - -using namespace dsp; -using namespace calf_plugins; - -/// convert amplitude value to normalized grid-ish value (0dB = 0.5, 30dB = 1.0, -30 dB = 0.0, -60dB = -0.5, -90dB = -1.0) -static inline float dB_grid(float amp) -{ - return log(amp) * (1.0 / log(256.0)) + 0.4; -} - -template -static bool get_graph(Fx &fx, int subindex, float *data, int points) -{ - for (int i = 0; i < points; i++) - { - typedef std::complex cfloat; - double freq = 20.0 * pow (20000.0 / 20.0, i * 1.0 / points); - data[i] = dB_grid(fx.freq_gain(subindex, freq, fx.srate)); - } - return true; -} - -/// convert normalized grid-ish value back to amplitude value -static inline float dB_grid_inv(float pos) -{ - return pow(256.0, pos - 0.4); -} - -static void set_channel_color(cairo_iface *context, int channel) -{ - if (channel & 1) - context->set_source_rgba(0.35, 0.4, 0.2, 1); - else - context->set_source_rgba(0.35, 0.4, 0.2, 0.5); - context->set_line_width(1.5); -} - -static bool get_freq_gridline(int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context, bool use_frequencies = true) -{ - if (subindex < 0 ) - return false; - if (use_frequencies) - { - if (subindex < 28) - { - vertical = true; - if (subindex == 9) legend = "100 Hz"; - if (subindex == 18) legend = "1 kHz"; - if (subindex == 27) legend = "10 kHz"; - float freq = 100; - if (subindex < 9) - freq = 10 * (subindex + 1); - else if (subindex < 18) - freq = 100 * (subindex - 9 + 1); - else if (subindex < 27) - freq = 1000 * (subindex - 18 + 1); - else - freq = 10000 * (subindex - 27 + 1); - pos = log(freq / 20.0) / log(1000); - if (!legend.empty()) - context->set_source_rgba(0, 0, 0, 0.2); - else - context->set_source_rgba(0, 0, 0, 0.1); - return true; - } - subindex -= 28; - } - if (subindex >= 32) - return false; - float gain = 16.0 / (1 << subindex); - pos = dB_grid(gain); - if (pos < -1) - return false; - if (subindex != 4) - context->set_source_rgba(0, 0, 0, subindex & 1 ? 0.1 : 0.2); - if (!(subindex & 1)) - { - std::stringstream ss; - ss << (24 - 6 * subindex) << " dB"; - legend = ss.str(); - } - vertical = false; - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -bool frequency_response_line_graph::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) -{ - return get_freq_gridline(subindex, pos, vertical, legend, context); -} - -int frequency_response_line_graph::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) -{ - subindex_graph = 0; - subindex_dot = 0; - subindex_gridline = generation ? INT_MAX : 0; - return 1; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -void flanger_audio_module::activate() { - left.reset(); - right.reset(); - last_r_phase = *params[par_stereo] * (1.f / 360.f); - left.reset_phase(0.f); - right.reset_phase(last_r_phase); - is_active = true; -} - -void flanger_audio_module::set_sample_rate(uint32_t sr) { - srate = sr; - left.setup(sr); - right.setup(sr); -} - -void flanger_audio_module::deactivate() { - is_active = false; -} - -bool flanger_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) -{ - if (!is_active) - return false; - if (index == par_delay && subindex < 2) - { - set_channel_color(context, subindex); - return ::get_graph(*this, subindex, data, points); - } - return false; -} - -float flanger_audio_module::freq_gain(int subindex, float freq, float srate) -{ - return (subindex ? right : left).freq_gain(freq, srate); -} - -/////////////////////////////////////////////////////////////////////////////////////////////// - -void phaser_audio_module::set_sample_rate(uint32_t sr) -{ - srate = sr; - left.setup(sr); - right.setup(sr); -} - -void phaser_audio_module::activate() -{ - is_active = true; - left.reset(); - right.reset(); - last_r_phase = *params[par_stereo] * (1.f / 360.f); - left.reset_phase(0.f); - right.reset_phase(last_r_phase); -} - -void phaser_audio_module::deactivate() -{ - is_active = false; -} - -bool phaser_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) -{ - if (!is_active) - return false; - if (subindex < 2) - { - set_channel_color(context, subindex); - return ::get_graph(*this, subindex, data, points); - } - return false; -} - -float phaser_audio_module::freq_gain(int subindex, float freq, float srate) -{ - return (subindex ? right : left).freq_gain(freq, srate); -} - -bool phaser_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) -{ - return get_freq_gridline(subindex, pos, vertical, legend, context); -} - -/////////////////////////////////////////////////////////////////////////////////////////////// - -void reverb_audio_module::activate() -{ - reverb.reset(); -} - -void reverb_audio_module::deactivate() -{ -} - -void reverb_audio_module::set_sample_rate(uint32_t sr) -{ - srate = sr; - reverb.setup(sr); - amount.set_sample_rate(sr); -} - -/////////////////////////////////////////////////////////////////////////////////////////////// - -bool filter_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) -{ - if (!is_active) - return false; - if (index == par_cutoff && !subindex) { - context->set_line_width(1.5); - return ::get_graph(*this, subindex, data, points); - } - return false; -} - -int filter_audio_module::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) -{ - if (fabs(inertia_cutoff.get_last() - old_cutoff) + 100 * fabs(inertia_resonance.get_last() - old_resonance) + fabs(*params[par_mode] - old_mode) > 0.1f) - { - old_cutoff = inertia_cutoff.get_last(); - old_resonance = inertia_resonance.get_last(); - old_mode = *params[par_mode]; - last_generation++; - subindex_graph = 0; - subindex_dot = INT_MAX; - subindex_gridline = INT_MAX; - } - else { - subindex_graph = 0; - subindex_dot = subindex_gridline = generation ? INT_MAX : 0; - } - if (generation == last_calculated_generation) - subindex_graph = INT_MAX; - return last_generation; -} - - -/////////////////////////////////////////////////////////////////////////////////////////////// - -bool filterclavier_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) -{ - if (!is_active || index != par_mode) { - return false; - } - if (!subindex) { - context->set_line_width(1.5); - return ::get_graph(*this, subindex, data, points); - } - return false; -} - -/////////////////////////////////////////////////////////////////////////////////////////////// - -rotary_speaker_audio_module::rotary_speaker_audio_module() -{ - mwhl_value = hold_value = 0.f; - phase_h = phase_l = 0.f; - aspeed_l = 1.f; - aspeed_h = 1.f; - dspeed = 0.f; -} - -void rotary_speaker_audio_module::set_sample_rate(uint32_t sr) -{ - srate = sr; - setup(); -} - -void rotary_speaker_audio_module::setup() -{ - crossover1l.set_lp_rbj(800.f, 0.7, (float)srate); - crossover1r.set_lp_rbj(800.f, 0.7, (float)srate); - crossover2l.set_hp_rbj(800.f, 0.7, (float)srate); - crossover2r.set_hp_rbj(800.f, 0.7, (float)srate); -} - -void rotary_speaker_audio_module::activate() -{ - phase_h = phase_l = 0.f; - maspeed_h = maspeed_l = 0.f; - setup(); -} - -void rotary_speaker_audio_module::deactivate() -{ -} - -void rotary_speaker_audio_module::control_change(int ctl, int val) -{ - if (vibrato_mode == 3 && ctl == 64) - { - hold_value = val / 127.f; - set_vibrato(); - return; - } - if (vibrato_mode == 4 && ctl == 1) - { - mwhl_value = val / 127.f; - set_vibrato(); - return; - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////// - -void multichorus_audio_module::activate() -{ - is_active = true; - params_changed(); -} - -void multichorus_audio_module::deactivate() -{ - is_active = false; -} - -void multichorus_audio_module::set_sample_rate(uint32_t sr) { - srate = sr; - left.setup(sr); - right.setup(sr); -} - -bool multichorus_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) -{ - if (!is_active) - return false; - int nvoices = (int)*params[par_voices]; - if (index == par_delay && subindex < 3) - { - if (subindex < 2) - set_channel_color(context, subindex); - else { - context->set_source_rgba(0.35, 0.4, 0.2); - context->set_line_width(1.0); - } - return ::get_graph(*this, subindex, data, points); - } - if (index == par_rate && subindex < nvoices) { - sine_multi_lfo &lfo = left.lfo; - for (int i = 0; i < points; i++) { - float phase = i * 2 * M_PI / points; - // original -65536 to 65535 value - float orig = subindex * lfo.voice_offset + ((lfo.voice_depth >> (30-13)) * 65536.0 * (0.95 * sin(phase) + 1)/ 8192.0) - 65536; - // scale to -1..1 - data[i] = orig / 65536.0; - } - return true; - } - return false; -} - -bool multichorus_audio_module::get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context) -{ - int voice = subindex >> 1; - int nvoices = (int)*params[par_voices]; - if ((index != par_rate && index != par_depth) || voice >= nvoices) - return false; - - float unit = (1 - *params[par_overlap]); - float scw = 1 + unit * (nvoices - 1); - set_channel_color(context, subindex); - sine_multi_lfo &lfo = (subindex & 1 ? right : left).lfo; - if (index == par_rate) - { - x = (double)(lfo.phase + lfo.vphase * voice) / 4096.0; - y = 0.95 * sin(x * 2 * M_PI); - y = (voice * unit + (y + 1) / 2) / scw * 2 - 1; - } - else - { - double ph = (double)(lfo.phase + lfo.vphase * voice) / 4096.0; - x = 0.5 + 0.5 * sin(ph * 2 * M_PI); - y = subindex & 1 ? -0.75 : 0.75; - x = (voice * unit + x) / scw; - } - return true; -} - -bool multichorus_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) -{ - if (index == par_rate && !subindex) - { - pos = 0; - vertical = false; - return true; - } - if (index == par_delay) - return get_freq_gridline(subindex, pos, vertical, legend, context); - return false; -} - -float multichorus_audio_module::freq_gain(int subindex, float freq, float srate) -{ - if (subindex == 2) - return *params[par_amount] * left.post.freq_gain(freq, srate); - return (subindex ? right : left).freq_gain(freq, srate); -} - -/////////////////////////////////////////////////////////////////////////////////////////////// - -compressor_audio_module::compressor_audio_module() -{ - is_active = false; - srate = 0; - last_generation = 0; -} - -void compressor_audio_module::activate() -{ - is_active = true; - linSlope = 0.f; - peak = 0.f; - clip = 0.f; -} - -void compressor_audio_module::deactivate() -{ - is_active = false; -} - -void compressor_audio_module::set_sample_rate(uint32_t sr) -{ - srate = sr; - awL.set(sr); - awR.set(sr); -} - -bool compressor_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) -{ - if (!is_active) - return false; - if (subindex > 1) // 1 - return false; - for (int i = 0; i < points; i++) - { - float input = dB_grid_inv(-1.0 + i * 2.0 / (points - 1)); - float output = output_level(input); - if (subindex == 0) - data[i] = dB_grid(input); - else - data[i] = dB_grid(output); - } - if (subindex == (*params[param_bypass] > 0.5f ? 1 : 0)) - context->set_source_rgba(0.35, 0.4, 0.2, 0.3); - else { - context->set_source_rgba(0.35, 0.4, 0.2, 1); - context->set_line_width(2); - } - return true; -} - -bool compressor_audio_module::get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context) -{ - if (!is_active) - return false; - if (!subindex) - { - bool rms = *params[param_detection] == 0; - float det = rms ? sqrt(detected) : detected; - x = 0.5 + 0.5 * dB_grid(det); - y = dB_grid(*params[param_bypass] > 0.5f ? det : output_level(det)); - return *params[param_bypass] > 0.5f ? false : true; - } - return false; -} - -bool compressor_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) -{ - bool tmp; - vertical = (subindex & 1) != 0; - bool result = get_freq_gridline(subindex >> 1, pos, tmp, legend, context, false); - if (result && vertical) { - if ((subindex & 4) && !legend.empty()) { - legend = ""; - } - else { - size_t pos = legend.find(" dB"); - if (pos != std::string::npos) - legend.erase(pos); - } - pos = 0.5 + 0.5 * pos; - } - return result; -} - -// In case of doubt: this function is written by Thor. I just moved it to this file, damaging -// the output of "git annotate" in the process. -uint32_t compressor_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) -{ - bool bypass = *params[param_bypass] > 0.5f; - - if(bypass) { - numsamples += offset; - while(offset < numsamples) { - outs[0][offset] = ins[0][offset]; - outs[1][offset] = ins[1][offset]; - ++offset; - } - - if(params[param_compression] != NULL) { - *params[param_compression] = 1.f; - } - - if(params[param_clip] != NULL) { - *params[param_clip] = 0.f; - } - - if(params[param_peak] != NULL) { - *params[param_peak] = 0.f; - } - - return inputs_mask; - } - - bool rms = *params[param_detection] == 0; - bool average = *params[param_stereo_link] == 0; - int aweighting = fastf2i_drm(*params[param_aweighting]); - float linThreshold = *params[param_threshold]; - ratio = *params[param_ratio]; - float attack = *params[param_attack]; - float attack_coeff = std::min(1.f, 1.f / (attack * srate / 4000.f)); - float release = *params[param_release]; - float release_coeff = std::min(1.f, 1.f / (release * srate / 4000.f)); - makeup = *params[param_makeup]; - knee = *params[param_knee]; - - float linKneeSqrt = sqrt(knee); - linKneeStart = linThreshold / linKneeSqrt; - adjKneeStart = linKneeStart*linKneeStart; - float linKneeStop = linThreshold * linKneeSqrt; - - threshold = log(linThreshold); - kneeStart = log(linKneeStart); - kneeStop = log(linKneeStop); - compressedKneeStop = (kneeStop - threshold) / ratio + threshold; - - if (aweighting >= 2) - { - bpL.set_highshelf_rbj(5000, 0.707, 10 << (aweighting - 2), srate); - bpR.copy_coeffs(bpL); - bpL.sanitize(); - bpR.sanitize(); - } - - numsamples += offset; - - float compression = 1.f; - peak = 0.f; - clip -= std::min(clip, numsamples); - - while(offset < numsamples) { - float left = ins[0][offset] * *params[param_input]; - float right = ins[1][offset] * *params[param_input]; - - if(aweighting == 1) { - left = awL.process(left); - right = awR.process(right); - } - else if(aweighting >= 2) { - left = bpL.process(left); - right = bpR.process(right); - } - - float absample = average ? (fabs(left) + fabs(right)) * 0.5f : std::max(fabs(left), fabs(right)); - if(rms) absample *= absample; - - linSlope += (absample - linSlope) * (absample > linSlope ? attack_coeff : release_coeff); - - float gain = 1.f; - - if(linSlope > 0.f) { - gain = output_gain(linSlope, rms); - } - - compression = gain; - gain *= makeup; - - float outL = ins[0][offset] * gain * *params[param_input]; - float outR = ins[1][offset] * gain * *params[param_input]; - - outs[0][offset] = outL; - outs[1][offset] = outR; - - ++offset; - - float maxLR = std::max(fabs(outL), fabs(outR)); - if(maxLR > peak) - peak = maxLR; - - if(peak > 1.f) clip = srate >> 3; /* blink clip LED for 125 ms */ - } - - detected = linSlope; - - if(params[param_compression] != NULL) { - *params[param_compression] = compression; - } - - if(params[param_clip] != NULL) { - *params[param_clip] = clip; - } - - if(params[param_peak] != NULL) { - *params[param_peak] = peak; - } - - return inputs_mask; -} - - -/// Multibandcompressor by Markus Schmidt -/// -/// This module splits the signal in four different bands -/// and sends them through multiple filters (implemented by -/// Krzysztof). They are processed by a compressing routine -/// (implemented by Thor) afterwards and summed up to the -/// final output again. -/////////////////////////////////////////////////////////////////////////////////////////////// - -multibandcompressor_audio_module::multibandcompressor_audio_module() -{ - is_active = false; - srate = 0; - // zero all displays - clip_inL = 0.f; - clip_inR = 0.f; - clip_outL = 0.f; - clip_outR = 0.f; - meter_inL = 0.f; - meter_inR = 0.f; - meter_outL = 0.f; - meter_outR = 0.f; -} - -void multibandcompressor_audio_module::activate() -{ - is_active = true; - // set all filters and strips - params_changed(); - // activate all strips - for (int j = 0; j < strips; j ++) { - strip[j].activate(); - strip[j].id = j; - } -} - -void multibandcompressor_audio_module::deactivate() -{ - is_active = false; - // deactivate all strips - for (int j = 0; j < strips; j ++) { - strip[j].deactivate(); - } -} - -void multibandcompressor_audio_module::params_changed() -{ - // set the params of all filters - if(*params[param_freq0] != freq_old[0] or *params[param_sep0] != sep_old[0] or *params[param_q0] != q_old[0]) { - lpL0.set_lp_rbj((float)(*params[param_freq0] * (1 - *params[param_sep0])), *params[param_q0], (float)srate); - lpR0.copy_coeffs(lpL0); - hpL0.set_hp_rbj((float)(*params[param_freq0] * (1 + *params[param_sep0])), *params[param_q0], (float)srate); - hpR0.copy_coeffs(hpL0); - freq_old[0] = *params[param_freq0]; - sep_old[0] = *params[param_sep2]; - q_old[0] = *params[param_q2]; - } - if(*params[param_freq1] != freq_old[1] or *params[param_sep1] != sep_old[1] or *params[param_q1] != q_old[1]) { - lpL1.set_lp_rbj((float)(*params[param_freq1] * (1 - *params[param_sep1])), *params[param_q1], (float)srate); - lpR1.copy_coeffs(lpL1); - hpL1.set_hp_rbj((float)(*params[param_freq1] * (1 + *params[param_sep1])), *params[param_q1], (float)srate); - hpR1.copy_coeffs(hpL1); - freq_old[1] = *params[param_freq1]; - sep_old[1] = *params[param_sep2]; - q_old[1] = *params[param_q2]; - } - if(*params[param_freq2] != freq_old[2] or *params[param_sep2] != sep_old[2] or *params[param_q2] != q_old[2]) { - lpL2.set_lp_rbj((float)(*params[param_freq2] * (1 - *params[param_sep2])), *params[param_q2], (float)srate); - lpR2.copy_coeffs(lpL2); - hpL2.set_hp_rbj((float)(*params[param_freq2] * (1 + *params[param_sep2])), *params[param_q2], (float)srate); - hpR2.copy_coeffs(hpL2); - freq_old[2] = *params[param_freq2]; - sep_old[2] = *params[param_sep2]; - q_old[2] = *params[param_q2]; - } - // set the params of all strips - for (int j = 0; j < strips; j ++) { - switch (j) { - case 0: - strip[j].set_params(*params[param_attack0], *params[param_release0], *params[param_threshold0], *params[param_ratio0], *params[param_knee0], *params[param_makeup0], *params[param_detection0], 1.f, *params[param_bypass0], *params[param_mute0]); - break; - case 1: - strip[j].set_params(*params[param_attack1], *params[param_release1], *params[param_threshold1], *params[param_ratio1], *params[param_knee1], *params[param_makeup1], *params[param_detection1], 1.f, *params[param_bypass1], *params[param_mute1]); - break; - case 2: - strip[j].set_params(*params[param_attack2], *params[param_release2], *params[param_threshold2], *params[param_ratio2], *params[param_knee2], *params[param_makeup2], *params[param_detection2], 1.f, *params[param_bypass2], *params[param_mute2]); - break; - case 3: - strip[j].set_params(*params[param_attack3], *params[param_release3], *params[param_threshold3], *params[param_ratio3], *params[param_knee3], *params[param_makeup3], *params[param_detection3], 1.f, *params[param_bypass3], *params[param_mute3]); - break; - } - } -} - -void multibandcompressor_audio_module::set_sample_rate(uint32_t sr) -{ - srate = sr; - // set srate of all strips - for (int j = 0; j < strips; j ++) { - strip[j].set_sample_rate(srate); - } -} - -uint32_t multibandcompressor_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) -{ - bool bypass = *params[param_bypass] > 0.5f; - numsamples += offset; - if(bypass) { - // everything bypassed - while(offset < numsamples) { - outs[0][offset] = ins[0][offset]; - outs[1][offset] = ins[1][offset]; - ++offset; - } - // displays, too - clip_inL = 0.f; - clip_inR = 0.f; - clip_outL = 0.f; - clip_outR = 0.f; - meter_inL = 0.f; - meter_inR = 0.f; - meter_outL = 0.f; - meter_outR = 0.f; - } else { - // process all strips - - // determine mute state of strips - mute[0] = *params[param_mute0] > 0.f ? true : false; - mute[1] = *params[param_mute1] > 0.f ? true : false; - mute[2] = *params[param_mute2] > 0.f ? true : false; - mute[3] = *params[param_mute3] > 0.f ? true : false; - - // let meters fall a bit - clip_inL -= std::min(clip_inL, numsamples); - clip_inR -= std::min(clip_inR, numsamples); - clip_outL -= std::min(clip_outL, numsamples); - clip_outR -= std::min(clip_outR, numsamples); - meter_inL = 0.f; - meter_inR = 0.f; - meter_outL = 0.f; - meter_outR = 0.f; - while(offset < numsamples) { - // cycle through samples - float inL = ins[0][offset]; - float inR = ins[1][offset]; - // in level - inR *= *params[param_level_in]; - inL *= *params[param_level_in]; - // out vars - float outL = 0.f; - float outR = 0.f; - for (int i = 0; i < strips; i ++) { - // cycle trough strips - if (!mute[i]) { - // strip unmuted - float left = inL; - float right = inR; - // send trough filters - switch (i) { - case 0: - left = lpL0.process(left); - right = lpR0.process(right); - lpL0.sanitize(); - lpR0.sanitize(); - break; - case 1: - left = lpL1.process(left); - right = lpR1.process(right); - left = hpL0.process(left); - right = hpR0.process(right); - lpL1.sanitize(); - lpR1.sanitize(); - hpL0.sanitize(); - hpR0.sanitize(); - break; - case 2: - left = lpL2.process(left); - right = lpR2.process(right); - left = hpL1.process(left); - right = hpR1.process(right); - lpL2.sanitize(); - lpR2.sanitize(); - hpL1.sanitize(); - hpR1.sanitize(); - break; - case 3: - left = hpL2.process(left); - right = hpR2.process(right); - hpL2.sanitize(); - hpR2.sanitize(); - break; - } - // process gain reduction - strip[i].process(left, right); - // sum up output - outL += left; - outR += right; - } else { - // strip muted - - } - - - } // process single strip - - // even out filters gain reduction - // 3dB - levelled manually (based on default sep and q settings) - outL *= 1.414213562; - outR *= 1.414213562; - - // out level - outL *= *params[param_level_out]; - outR *= *params[param_level_out]; - - // send to output - outs[0][offset] = outL; - outs[1][offset] = outR; - - // clip LED's - if(inL > 1.f) { - clip_inL = srate >> 3; - } - if(inR > 1.f) { - clip_inR = srate >> 3; - } - if(outL > 1.f) { - clip_outL = srate >> 3; - } - if(outR > 1.f) { - clip_outR = srate >> 3; - } - // set up in / out meters - if(inL > meter_inL) { - meter_inL = inL; - } - if(inR > meter_inR) { - meter_inR = inR; - } - if(outL > meter_outL) { - meter_outL = outL; - } - if(outR > meter_outR) { - meter_outR = outR; - } - // next sample - ++offset; - } // cycle trough samples - - } // process all strips (no bypass) - - // draw meters - if(params[param_clip_inL] != NULL) { - *params[param_clip_inL] = clip_inL; - } - if(params[param_clip_inR] != NULL) { - *params[param_clip_inR] = clip_inR; - } - if(params[param_clip_outL] != NULL) { - *params[param_clip_outL] = clip_outL; - } - if(params[param_clip_outR] != NULL) { - *params[param_clip_outR] = clip_outR; - } - - if(params[param_meter_inL] != NULL) { - *params[param_meter_inL] = meter_inL; - } - if(params[param_meter_inR] != NULL) { - *params[param_meter_inR] = meter_inR; - } - if(params[param_meter_outL] != NULL) { - *params[param_meter_outL] = meter_outL; - } - if(params[param_meter_outR] != NULL) { - *params[param_meter_outR] = meter_outR; - } - // draw strip meters - if(bypass > 0.5f) { - if(params[param_compression0] != NULL) { - *params[param_compression0] = 1.0f; - } - if(params[param_compression1] != NULL) { - *params[param_compression1] = 1.0f; - } - if(params[param_compression2] != NULL) { - *params[param_compression2] = 1.0f; - } - if(params[param_compression3] != NULL) { - *params[param_compression3] = 1.0f; - } - - if(params[param_output0] != NULL) { - *params[param_output0] = 0.0f; - } - if(params[param_output1] != NULL) { - *params[param_output1] = 0.0f; - } - if(params[param_output2] != NULL) { - *params[param_output2] = 0.0f; - } - if(params[param_output3] != NULL) { - *params[param_output3] = 0.0f; - } - } else { - if(params[param_compression0] != NULL) { - *params[param_compression0] = strip[0].get_comp_level(); - } - if(params[param_compression1] != NULL) { - *params[param_compression1] = strip[1].get_comp_level(); - } - if(params[param_compression2] != NULL) { - *params[param_compression2] = strip[2].get_comp_level(); - } - if(params[param_compression3] != NULL) { - *params[param_compression3] = strip[3].get_comp_level(); - } - - if(params[param_output0] != NULL) { - *params[param_output0] = strip[0].get_output_level(); - } - if(params[param_output1] != NULL) { - *params[param_output1] = strip[1].get_output_level(); - } - if(params[param_output2] != NULL) { - *params[param_output2] = strip[2].get_output_level(); - } - if(params[param_output3] != NULL) { - *params[param_output3] = strip[3].get_output_level(); - } - } - // whatever has to be returned x) - return outputs_mask; -} -bool multibandcompressor_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) -{ - // let's handle by the corresponding strip - switch (index) { - case param_compression0: - return strip[0].get_graph(subindex, data, points, context); - break; - case param_compression1: - return strip[1].get_graph(subindex, data, points, context); - break; - case param_compression2: - return strip[2].get_graph(subindex, data, points, context); - break; - case param_compression3: - return strip[3].get_graph(subindex, data, points, context); - break; - } - return false; -} - -bool multibandcompressor_audio_module::get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context) -{ - // let's handle by the corresponding strip - switch (index) { - case param_compression0: - return strip[0].get_dot(subindex, x, y, size, context); - break; - case param_compression1: - return strip[1].get_dot(subindex, x, y, size, context); - break; - case param_compression2: - return strip[2].get_dot(subindex, x, y, size, context); - break; - case param_compression3: - return strip[3].get_dot(subindex, x, y, size, context); - break; - } - return false; -} - -bool multibandcompressor_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) -{ - // let's handle by the corresponding strip - switch (index) { - case param_compression0: - return strip[0].get_gridline(subindex, pos, vertical, legend, context); - break; - case param_compression1: - return strip[1].get_gridline(subindex, pos, vertical, legend, context); - break; - case param_compression2: - return strip[2].get_gridline(subindex, pos, vertical, legend, context); - break; - case param_compression3: - return strip[3].get_gridline(subindex, pos, vertical, legend, context); - break; - } - return false; -} - -int multibandcompressor_audio_module::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) -{ - // let's handle by the corresponding strip - switch (index) { - case param_compression0: - return strip[0].get_changed_offsets(generation, subindex_graph, subindex_dot, subindex_gridline); - break; - case param_compression1: - return strip[1].get_changed_offsets(generation, subindex_graph, subindex_dot, subindex_gridline); - break; - case param_compression2: - return strip[2].get_changed_offsets(generation, subindex_graph, subindex_dot, subindex_gridline); - break; - case param_compression3: - return strip[3].get_changed_offsets(generation, subindex_graph, subindex_dot, subindex_gridline); - break; - } - return 0; -} - -/// Sidecain Compressor by Markus Schmidt -/// -/// This module splits the signal in a sidechain- and a process signal. -/// The sidechain is processed through Krzystofs filters and compresses -/// the process signal via Thor's compression routine afterwards. -/////////////////////////////////////////////////////////////////////////////////////////////// - -sidechaincompressor_audio_module::sidechaincompressor_audio_module() -{ - is_active = false; - srate = 0; - last_generation = 0; -} - -void sidechaincompressor_audio_module::activate() -{ - is_active = true; - // set all filters and strips - compressor.activate(); - params_changed(); - meter_in = 0.f; - meter_out = 0.f; - clip_in = 0.f; - clip_out = 0.f; -} -void sidechaincompressor_audio_module::deactivate() -{ - is_active = false; - compressor.deactivate(); -} - -void sidechaincompressor_audio_module::params_changed() -{ - // set the params of all filters - if(*params[param_f1_freq] != f1_freq_old or *params[param_f1_level] != f1_level_old - or *params[param_f2_freq] != f2_freq_old or *params[param_f2_level] != f2_level_old - or *params[param_sc_mode] != sc_mode) { - float q = 0.707; - switch ((int)*params[param_sc_mode]) { - default: - case WIDEBAND: - f1L.set_hp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]); - f1R.copy_coeffs(f1L); - f2L.set_lp_rbj((float)*params[param_f2_freq], q, (float)srate, *params[param_f2_level]); - f2R.copy_coeffs(f2L); - f1_active = 0.f; - f2_active = 0.f; - break; - case DEESSER_WIDE: - f1L.set_peakeq_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate); - f1R.copy_coeffs(f1L); - f2L.set_hp_rbj((float)*params[param_f2_freq], q, (float)srate, *params[param_f2_level]); - f2R.copy_coeffs(f2L); - f1_active = 0.5f; - f2_active = 1.f; - break; - case DEESSER_SPLIT: - f1L.set_lp_rbj((float)*params[param_f2_freq] * (1 + 0.17), q, (float)srate); - f1R.copy_coeffs(f1L); - f2L.set_hp_rbj((float)*params[param_f2_freq] * (1 - 0.17), q, (float)srate, *params[param_f2_level]); - f2R.copy_coeffs(f2L); - f1_active = 0.f; - f2_active = 1.f; - break; - case DERUMBLER_WIDE: - f1L.set_lp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]); - f1R.copy_coeffs(f1L); - f2L.set_peakeq_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate); - f2R.copy_coeffs(f2L); - f1_active = 1.f; - f2_active = 0.5f; - break; - case DERUMBLER_SPLIT: - f1L.set_lp_rbj((float)*params[param_f1_freq] * (1 + 0.17), q, (float)srate, *params[param_f1_level]); - f1R.copy_coeffs(f1L); - f2L.set_hp_rbj((float)*params[param_f1_freq] * (1 - 0.17), q, (float)srate); - f2R.copy_coeffs(f2L); - f1_active = 1.f; - f2_active = 0.f; - break; - case WEIGHTED_1: - f1L.set_lowshelf_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate); - f1R.copy_coeffs(f1L); - f2L.set_highshelf_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate); - f2R.copy_coeffs(f2L); - f1_active = 0.5f; - f2_active = 0.5f; - break; - case WEIGHTED_2: - f1L.set_lowshelf_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate); - f1R.copy_coeffs(f1L); - f2L.set_peakeq_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate); - f2R.copy_coeffs(f2L); - f1_active = 0.5f; - f2_active = 0.5f; - break; - case WEIGHTED_3: - f1L.set_peakeq_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate); - f1R.copy_coeffs(f1L); - f2L.set_highshelf_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate); - f2R.copy_coeffs(f2L); - f1_active = 0.5f; - f2_active = 0.5f; - break; - case BANDPASS_1: - f1L.set_bp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]); - f1R.copy_coeffs(f1L); - f2L.set_hp_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate); - f2R.copy_coeffs(f2L); - f1_active = 1.f; - f2_active = 0.f; - break; - case BANDPASS_2: - f1L.set_hp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]); - f1R.copy_coeffs(f1L); - f2L.set_lp_rbj((float)*params[param_f2_freq], q, (float)srate, *params[param_f2_level]); - f2R.copy_coeffs(f2L); - f1_active = 1.f; - f2_active = 1.f; - break; - } - f1_freq_old = *params[param_f1_freq]; - f1_level_old = *params[param_f1_level]; - f2_freq_old = *params[param_f2_freq]; - f2_level_old = *params[param_f2_level]; - sc_mode = (CalfScModes)*params[param_sc_mode]; - } - // light LED's - if(params[param_f1_active] != NULL) { - *params[param_f1_active] = f1_active; - } - if(params[param_f2_active] != NULL) { - *params[param_f2_active] = f2_active; - } - // and set the compressor module - compressor.set_params(*params[param_attack], *params[param_release], *params[param_threshold], *params[param_ratio], *params[param_knee], *params[param_makeup], *params[param_detection], *params[param_stereo_link], *params[param_bypass], 0.f); -} - -void sidechaincompressor_audio_module::set_sample_rate(uint32_t sr) -{ - srate = sr; - compressor.set_sample_rate(srate); -} - -uint32_t sidechaincompressor_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) -{ - bool bypass = *params[param_bypass] > 0.5f; - numsamples += offset; - if(bypass) { - // everything bypassed - while(offset < numsamples) { - outs[0][offset] = ins[0][offset]; - outs[1][offset] = ins[1][offset]; - ++offset; - } - // displays, too - clip_in = 0.f; - clip_out = 0.f; - meter_in = 0.f; - meter_out = 0.f; - } else { - // process - - clip_in -= std::min(clip_in, numsamples); - clip_out -= std::min(clip_out, numsamples); - - while(offset < numsamples) { - // cycle through samples - float outL = 0.f; - float outR = 0.f; - float inL = ins[0][offset]; - float inR = ins[1][offset]; - // in level - inR *= *params[param_level_in]; - inL *= *params[param_level_in]; - - - float leftAC = inL; - float rightAC = inR; - float leftSC = inL; - float rightSC = inR; - float leftMC = inL; - float rightMC = inR; - - switch ((int)*params[param_sc_mode]) { - default: - case WIDEBAND: - compressor.process(leftAC, rightAC, leftSC, rightSC); - break; - case DEESSER_WIDE: - case DERUMBLER_WIDE: - case WEIGHTED_1: - case WEIGHTED_2: - case WEIGHTED_3: - case BANDPASS_2: - leftSC = f2L.process(f1L.process(leftSC)); - rightSC = f2R.process(f1R.process(rightSC)); - leftMC = leftSC; - rightMC = rightSC; - compressor.process(leftAC, rightAC, leftSC, rightSC); - break; - case DEESSER_SPLIT: - leftSC = f2L.process(leftSC); - rightSC = f2R.process(rightSC); - leftMC = leftSC; - rightMC = rightSC; - compressor.process(leftSC, rightSC, leftSC, rightSC); - leftAC = f1L.process(leftAC); - rightAC = f1R.process(rightAC); - leftAC += leftSC; - rightAC += rightSC; - break; - case DERUMBLER_SPLIT: - leftSC = f1L.process(leftSC); - rightSC = f1R.process(rightSC); - leftMC = leftSC; - rightMC = rightSC; - compressor.process(leftSC, rightSC, leftSC, rightSC); - leftAC = f2L.process(leftAC); - rightAC = f2R.process(rightAC); - leftAC += leftSC; - rightAC += rightSC; - break; - case BANDPASS_1: - leftSC = f1L.process(leftSC); - rightSC = f1R.process(rightSC); - leftMC = leftSC; - rightMC = rightSC; - compressor.process(leftAC, rightAC, leftSC, rightSC); - break; - } - - if(*params[param_sc_listen] > 0.f) { - outL = leftMC; - outR = rightMC; - } else { - outL = leftAC; - outR = rightAC; - } - - // send to output - outs[0][offset] = outL; - outs[1][offset] = outR; - - // clip LED's - if(std::max(fabs(inL), fabs(inR)) > 1.f) { - clip_in = srate >> 3; - } - if(std::max(fabs(outL), fabs(outR)) > 1.f) { - clip_out = srate >> 3; - } - // rise up out meter - meter_in = std::max(fabs(inL), fabs(inR));; - meter_out = std::max(fabs(outL), fabs(outR));; - - // next sample - ++offset; - } // cycle trough samples - f1L.sanitize(); - f1R.sanitize(); - f2L.sanitize(); - f2R.sanitize(); - - } - // draw meters - if(params[param_clip_in] != NULL) { - *params[param_clip_in] = clip_in; - } - if(params[param_clip_out] != NULL) { - *params[param_clip_out] = clip_out; - } - if(params[param_meter_in] != NULL) { - *params[param_meter_in] = meter_in; - } - if(params[param_meter_out] != NULL) { - *params[param_meter_out] = meter_out; - } - // draw strip meter - if(bypass > 0.5f) { - if(params[param_compression] != NULL) { - *params[param_compression] = 1.0f; - } - } else { - if(params[param_compression] != NULL) { - *params[param_compression] = compressor.get_comp_level(); - } - } - // whatever has to be returned x) - return outputs_mask; -} -bool sidechaincompressor_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) -{ - if (!is_active) - return false; - if (index == param_f1_freq && !subindex) { - context->set_line_width(1.5); - return ::get_graph(*this, subindex, data, points); - } else if(index == param_compression) { - return compressor.get_graph(subindex, data, points, context); - } - return false; -} - -bool sidechaincompressor_audio_module::get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context) -{ - if (!is_active) - return false; - if (index == param_compression) { - return compressor.get_dot(subindex, x, y, size, context); - } - return false; -} - -bool sidechaincompressor_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) -{ - if (!is_active) - return false; - if (index == param_compression) { - return compressor.get_gridline(subindex, pos, vertical, legend, context); - } else { - return get_freq_gridline(subindex, pos, vertical, legend, context); - } -// return false; -} - -int sidechaincompressor_audio_module::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) -{ - if (!is_active) - return false; - if(index == param_compression) { - return compressor.get_changed_offsets(generation, subindex_graph, subindex_dot, subindex_gridline); - } else { - // (fabs(inertia_cutoff.get_last() - old_cutoff) + 100 * fabs(inertia_resonance.get_last() - old_resonance) + fabs(*params[par_mode] - old_mode) > 0.1f) - if (*params[param_f1_freq] != f1_freq_old1 - or *params[param_f2_freq] != f2_freq_old1 - or *params[param_f1_level] != f1_level_old1 - or *params[param_f2_level] != f2_level_old1 - or *params[param_sc_mode] !=sc_mode_old1) - { - f1_freq_old1 = *params[param_f1_freq]; - f2_freq_old1 = *params[param_f2_freq]; - f1_level_old1 = *params[param_f1_level]; - f2_level_old1 = *params[param_f2_level]; - sc_mode_old1 = (CalfScModes)*params[param_sc_mode]; - last_generation++; - subindex_graph = 0; - subindex_dot = INT_MAX; - subindex_gridline = INT_MAX; - } - else { - subindex_graph = 0; - subindex_dot = subindex_gridline = generation ? INT_MAX : 0; - } - if (generation == last_calculated_generation) - subindex_graph = INT_MAX; - return last_generation; - } - return false; -} - -/// Deesser by Markus Schmidt -/// -/// This module splits the signal in a sidechain- and a process signal. -/// The sidechain is processed through Krzystofs filters and compresses -/// the process signal via Thor's compression routine afterwards. -/////////////////////////////////////////////////////////////////////////////////////////////// - -deesser_audio_module::deesser_audio_module() -{ - is_active = false; - srate = 0; - last_generation = 0; -} - -void deesser_audio_module::activate() -{ - is_active = true; - // set all filters and strips - compressor.activate(); - params_changed(); - detected = 0.f; - detected_led = 0.f; - clip_out = 0.f; -} -void deesser_audio_module::deactivate() -{ - is_active = false; - compressor.deactivate(); -} - -void deesser_audio_module::params_changed() -{ - // set the params of all filters - if(*params[param_f1_freq] != f1_freq_old or *params[param_f1_level] != f1_level_old - or *params[param_f2_freq] != f2_freq_old or *params[param_f2_level] != f2_level_old - or *params[param_f2_q] != f2_q_old) { - float q = 0.707; - - hpL.set_hp_rbj((float)*params[param_f1_freq] * (1 - 0.17), q, (float)srate, *params[param_f1_level]); - hpR.copy_coeffs(hpL); - lpL.set_lp_rbj((float)*params[param_f1_freq] * (1 + 0.17), q, (float)srate); - lpR.copy_coeffs(lpL); - pL.set_peakeq_rbj((float)*params[param_f2_freq], *params[param_f2_q], *params[param_f2_level], (float)srate); - pR.copy_coeffs(pL); - f1_freq_old = *params[param_f1_freq]; - f1_level_old = *params[param_f1_level]; - f2_freq_old = *params[param_f2_freq]; - f2_level_old = *params[param_f2_level]; - f2_q_old = *params[param_f2_q]; - } - // and set the compressor module - compressor.set_params((float)*params[param_laxity], (float)*params[param_laxity] * 1.33, *params[param_threshold], *params[param_ratio], 2.8, *params[param_makeup], *params[param_detection], 0.f, *params[param_bypass], 0.f); -} - -void deesser_audio_module::set_sample_rate(uint32_t sr) -{ - srate = sr; - compressor.set_sample_rate(srate); -} - -uint32_t deesser_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) -{ - bool bypass = *params[param_bypass] > 0.5f; - numsamples += offset; - if(bypass) { - // everything bypassed - while(offset < numsamples) { - outs[0][offset] = ins[0][offset]; - outs[1][offset] = ins[1][offset]; - ++offset; - } - // displays, too - clip_out = 0.f; - detected = 0.f; - detected_led = 0.f; - } else { - // process - - detected_led -= std::min(detected_led, numsamples); - clip_led -= std::min(clip_led, numsamples); - - while(offset < numsamples) { - // cycle through samples - float outL = 0.f; - float outR = 0.f; - float inL = ins[0][offset]; - float inR = ins[1][offset]; - - - float leftAC = inL; - float rightAC = inR; - float leftSC = inL; - float rightSC = inR; - float leftRC = inL; - float rightRC = inR; - float leftMC = inL; - float rightMC = inR; - - leftSC = pL.process(hpL.process(leftSC)); - rightSC = pR.process(hpR.process(rightSC)); - leftMC = leftSC; - rightMC = rightSC; - - switch ((int)*params[param_mode]) { - default: - case WIDE: - compressor.process(leftAC, rightAC, leftSC, rightSC); - break; - case SPLIT: - hpL.sanitize(); - hpR.sanitize(); - leftRC = hpL.process(leftRC); - rightRC = hpR.process(rightRC); - compressor.process(leftRC, rightRC, leftSC, rightSC); - leftAC = lpL.process(leftAC); - rightAC = lpR.process(rightAC); - leftAC += leftRC; - rightAC += rightRC; - break; - } - - if(*params[param_sc_listen] > 0.f) { - outL = leftMC; - outR = rightMC; - } else { - outL = leftAC; - outR = rightAC; - } - - // send to output - outs[0][offset] = outL; - outs[1][offset] = outR; - - if(std::max(fabs(leftSC), fabs(rightSC)) > *params[param_threshold]) { - detected_led = srate >> 3; - } - if(std::max(fabs(leftAC), fabs(rightAC)) > 1.f) { - clip_led = srate >> 3; - } - if(clip_led > 0) { - clip_out = 1.f; - } else { - clip_out = std::max(fabs(outL), fabs(outR)); - } - detected = std::max(fabs(leftMC), fabs(rightMC)); - - // next sample - ++offset; - } // cycle trough samples - hpL.sanitize(); - hpR.sanitize(); - lpL.sanitize(); - lpR.sanitize(); - pL.sanitize(); - pR.sanitize(); - } - // draw meters - if(params[param_detected_led] != NULL) { - *params[param_detected_led] = detected_led; - } - if(params[param_clip_out] != NULL) { - *params[param_clip_out] = clip_out; - } - if(params[param_detected] != NULL) { - *params[param_detected] = detected; - } - // draw strip meter - if(bypass > 0.5f) { - if(params[param_compression] != NULL) { - *params[param_compression] = 1.0f; - } - } else { - if(params[param_compression] != NULL) { - *params[param_compression] = compressor.get_comp_level(); - } - } - // whatever has to be returned x) - return outputs_mask; -} -bool deesser_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) -{ - if (!is_active) - return false; - if (index == param_f1_freq && !subindex) { - context->set_line_width(1.5); - return ::get_graph(*this, subindex, data, points); - } - return false; -} - -bool deesser_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) -{ - return get_freq_gridline(subindex, pos, vertical, legend, context); - -// return false; -} - -int deesser_audio_module::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) -{ - if (!is_active) { - return false; - } else { - // (fabs(inertia_cutoff.get_last() - old_cutoff) + 100 * fabs(inertia_resonance.get_last() - old_resonance) + fabs(*params[par_mode] - old_mode) > 0.1f) - if (*params[param_f1_freq] != f1_freq_old1 - or *params[param_f2_freq] != f2_freq_old1 - or *params[param_f1_level] != f1_level_old1 - or *params[param_f2_level] != f2_level_old1 - or *params[param_f2_q] !=f2_q_old1) - { - f1_freq_old1 = *params[param_f1_freq]; - f2_freq_old1 = *params[param_f2_freq]; - f1_level_old1 = *params[param_f1_level]; - f2_level_old1 = *params[param_f2_level]; - f2_q_old1 = *params[param_f2_q]; - last_generation++; - subindex_graph = 0; - subindex_dot = INT_MAX; - subindex_gridline = INT_MAX; - } - else { - subindex_graph = 0; - subindex_dot = subindex_gridline = generation ? INT_MAX : 0; - } - if (generation == last_calculated_generation) - subindex_graph = INT_MAX; - return last_generation; - } - return false; -} - -/// Gain reduction module by Thor -/// All functions of this module are originally written -/// by Thor, while some features have been stripped (mainly stereo linking -/// and frequency correction as implemented in Sidechain Compressor above) -/// To save some CPU. -//////////////////////////////////////////////////////////////////////////////// -gain_reduction_audio_module::gain_reduction_audio_module() -{ - is_active = false; - last_generation = 0; -} - -void gain_reduction_audio_module::activate() -{ - is_active = true; - linSlope = 0.f; - meter_out = 0.f; - meter_comp = 1.f; - float l, r; - l = r = 0.f; - float byp = bypass; - bypass = 0.0; - process(l, r); - bypass = byp; -} - -void gain_reduction_audio_module::deactivate() -{ - is_active = false; -} - -void gain_reduction_audio_module::process(float &left, float &right, float det_left, float det_right) -{ - if(!det_left) { - det_left = left; - } - if(!det_right) { - det_right = right; - } - float gain = 1.f; - if(bypass < 0.5f) { - // this routine is mainly copied from thor's compressor module - // greatest sounding compressor I've heard! - bool rms = detection == 0; - bool average = stereo_link == 0; - float linThreshold = threshold; - float attack_coeff = std::min(1.f, 1.f / (attack * srate / 4000.f)); - float release_coeff = std::min(1.f, 1.f / (release * srate / 4000.f)); - float linKneeSqrt = sqrt(knee); - linKneeStart = linThreshold / linKneeSqrt; - adjKneeStart = linKneeStart*linKneeStart; - float linKneeStop = linThreshold * linKneeSqrt; - thres = log(linThreshold); - kneeStart = log(linKneeStart); - kneeStop = log(linKneeStop); - compressedKneeStop = (kneeStop - thres) / ratio + thres; - - float absample = average ? (fabs(det_left) + fabs(det_right)) * 0.5f : std::max(fabs(det_left), fabs(det_right)); - if(rms) absample *= absample; - - linSlope += (absample - linSlope) * (absample > linSlope ? attack_coeff : release_coeff); - - if(linSlope > 0.f) { - gain = output_gain(linSlope, rms); - } - - left *= gain * makeup; - right *= gain * makeup; - meter_out = std::max(fabs(left), fabs(right));; - meter_comp = gain; - detected = rms ? sqrt(linSlope) : linSlope; - } -} - -float gain_reduction_audio_module::output_level(float slope) { - return slope * output_gain(slope, false) * makeup; -} - -float gain_reduction_audio_module::output_gain(float linSlope, bool rms) { - //this calculation is also thor's work - if(linSlope > (rms ? adjKneeStart : linKneeStart)) { - float slope = log(linSlope); - if(rms) slope *= 0.5f; - - float gain = 0.f; - float delta = 0.f; - if(IS_FAKE_INFINITY(ratio)) { - gain = thres; - delta = 0.f; - } else { - gain = (slope - thres) / ratio + thres; - delta = 1.f / ratio; - } - - if(knee > 1.f && slope < kneeStop) { - gain = hermite_interpolation(slope, kneeStart, kneeStop, kneeStart, compressedKneeStop, 1.f, delta); - } - - return exp(gain - slope); - } - - return 1.f; -} - -void gain_reduction_audio_module::set_sample_rate(uint32_t sr) -{ - srate = sr; -} -void gain_reduction_audio_module::set_params(float att, float rel, float thr, float rat, float kn, float mak, float det, float stl, float byp, float mu) -{ - // set all params - attack = att; - release = rel; - threshold = thr; - ratio = rat; - knee = kn; - makeup = mak; - detection = det; - stereo_link = stl; - bypass = byp; - mute = mu; - if(mute > 0.f) { - meter_out = 0.f; - meter_comp = 1.f; - } -} -float gain_reduction_audio_module::get_output_level() { - // returns output level (max(left, right)) - return meter_out; -} -float gain_reduction_audio_module::get_comp_level() { - // returns amount of compression - return meter_comp; -} - -bool gain_reduction_audio_module::get_graph(int subindex, float *data, int points, cairo_iface *context) -{ - if (!is_active) - return false; - if (subindex > 1) // 1 - return false; - for (int i = 0; i < points; i++) - { - float input = dB_grid_inv(-1.0 + i * 2.0 / (points - 1)); - if (subindex == 0) - data[i] = dB_grid(input); - else { - float output = output_level(input); - data[i] = dB_grid(output); - } - } - if (subindex == (bypass > 0.5f ? 1 : 0) or mute > 0.1f) - context->set_source_rgba(0.35, 0.4, 0.2, 0.3); - else { - context->set_source_rgba(0.35, 0.4, 0.2, 1); - context->set_line_width(1.5); - } - return true; -} - -bool gain_reduction_audio_module::get_dot(int subindex, float &x, float &y, int &size, cairo_iface *context) -{ - if (!is_active) - return false; - if (!subindex) - { - if(bypass > 0.5f or mute > 0.f) { - return false; - } else { - bool rms = detection == 0; - float det = rms ? sqrt(detected) : detected; - x = 0.5 + 0.5 * dB_grid(det); - y = dB_grid(bypass > 0.5f or mute > 0.f ? det : output_level(det)); - return true; - } - } - return false; -} - -bool gain_reduction_audio_module::get_gridline(int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) -{ - bool tmp; - vertical = (subindex & 1) != 0; - bool result = get_freq_gridline(subindex >> 1, pos, tmp, legend, context, false); - if (result && vertical) { - if ((subindex & 4) && !legend.empty()) { - legend = ""; - } - else { - size_t pos = legend.find(" dB"); - if (pos != std::string::npos) - legend.erase(pos); - } - pos = 0.5 + 0.5 * pos; - } - return result; -} - -int gain_reduction_audio_module::get_changed_offsets(int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) -{ - subindex_graph = 0; - subindex_dot = 0; - subindex_gridline = generation ? INT_MAX : 0; - - if (fabs(threshold-old_threshold) + fabs(ratio - old_ratio) + fabs(knee - old_knee) + fabs(makeup - old_makeup) + fabs(detection - old_detection) + fabs(bypass - old_bypass) + fabs(mute - old_mute) > 0.000001f) - { - old_threshold = threshold; - old_ratio = ratio; - old_knee = knee; - old_makeup = makeup; - old_detection = detection; - old_bypass = bypass; - old_mute = mute; - last_generation++; - } - - if (generation == last_generation) - subindex_graph = 2; - return last_generation; -} - -/// Equalizer 12 Band by Markus Schmidt -/// -/// This module is based on Krzysztof's filters. It provides a couple -/// of different chained filters. -/////////////////////////////////////////////////////////////////////////////////////////////// - -equalizer12band_audio_module::equalizer12band_audio_module() -{ - is_active = false; - srate = 0; - last_generation = 0; - clip_inL = 0.f; - clip_inR = 0.f; - clip_outL = 0.f; - clip_outR = 0.f; - meter_inL = 0.f; - meter_inR = 0.f; - meter_outL = 0.f; - meter_outR = 0.f; -} - -void equalizer12band_audio_module::activate() -{ - is_active = true; - // set all filters - params_changed(); -} -void equalizer12band_audio_module::deactivate() -{ - is_active = false; -} - -void equalizer12band_audio_module::params_changed() -{ - // set the params of all filters - if(*params[param_hp_freq] != hp_freq_old) { - hpL[0].set_hp_rbj(*params[param_hp_freq], 0.707, (float)srate, 1.0); - hpL[1].copy_coeffs(hpL[0]); - hpL[2].copy_coeffs(hpL[0]); - hpR[0].copy_coeffs(hpL[0]); - hpR[1].copy_coeffs(hpL[0]); - hpR[2].copy_coeffs(hpL[0]); - hp_freq_old = *params[param_hp_freq]; - } - if(*params[param_lp_freq] != lp_freq_old) { - lpL[0].set_lp_rbj(*params[param_lp_freq], 0.707, (float)srate, 1.0); - lpL[1].copy_coeffs(lpL[0]); - lpL[2].copy_coeffs(lpL[0]); - lpR[0].copy_coeffs(lpL[0]); - lpR[1].copy_coeffs(lpL[0]); - lpR[2].copy_coeffs(lpL[0]); - lp_freq_old = *params[param_lp_freq]; - } - if(*params[param_ls_freq] != ls_freq_old or *params[param_ls_level] != ls_level_old) { - lsL.set_lowshelf_rbj(*params[param_ls_freq], 0.707, *params[param_ls_level], (float)srate); - lsR.copy_coeffs(lsL); - ls_level_old = *params[param_ls_level]; - ls_freq_old = *params[param_ls_freq]; - } - if(*params[param_hs_freq] != hs_freq_old or *params[param_hs_level] != hs_level_old) { - hsL.set_highshelf_rbj(*params[param_hs_freq], 0.707, *params[param_hs_level], (float)srate); - hsR.copy_coeffs(hsL); - hs_level_old = *params[param_hs_level]; - hs_freq_old = *params[param_hs_freq]; - } - if(*params[param_p1_freq] != p_freq_old[0] or *params[param_p1_level] != p_level_old[0] or *params[param_p1_q] != p_q_old[0]) { - pL[0].set_peakeq_rbj((float)*params[param_p1_freq], *params[param_p1_q], *params[param_p1_level], (float)srate); - pR[0].copy_coeffs(pL[0]); - p_freq_old[0] = *params[param_p1_freq]; - p_level_old[0] = *params[param_p1_level]; - p_q_old[0] = *params[param_p1_q]; - } - if(*params[param_p2_freq] != p_freq_old[1] or *params[param_p2_level] != p_level_old[1] or *params[param_p2_q] != p_q_old[1]) { - pL[1].set_peakeq_rbj((float)*params[param_p2_freq], *params[param_p2_q], *params[param_p2_level], (float)srate); - pR[1].copy_coeffs(pL[1]); - p_freq_old[1] = *params[param_p2_freq]; - p_level_old[1] = *params[param_p2_level]; - p_q_old[1] = *params[param_p2_q]; - } - if(*params[param_p3_freq] != p_freq_old[2] or *params[param_p3_level] != p_level_old[2] or *params[param_p3_q] != p_q_old[2]) { - pL[2].set_peakeq_rbj((float)*params[param_p3_freq], *params[param_p3_q], *params[param_p3_level], (float)srate); - pR[2].copy_coeffs(pL[2]); - p_freq_old[2] = *params[param_p3_freq]; - p_level_old[2] = *params[param_p3_level]; - p_q_old[2] = *params[param_p3_q]; - } - if(*params[param_p4_freq] != p_freq_old[3] or *params[param_p4_level] != p_level_old[3] or *params[param_p4_q] != p_q_old[3]) { - pL[3].set_peakeq_rbj((float)*params[param_p4_freq], *params[param_p4_q], *params[param_p4_level], (float)srate); - pR[3].copy_coeffs(pL[3]); - p_freq_old[3] = *params[param_p4_freq]; - p_level_old[3] = *params[param_p4_level]; - p_q_old[3] = *params[param_p4_q]; - } - if(*params[param_p5_freq] != p_freq_old[4] or *params[param_p5_level] != p_level_old[4] or *params[param_p5_q] != p_q_old[4]) { - pL[4].set_peakeq_rbj((float)*params[param_p5_freq], *params[param_p5_q], *params[param_p5_level], (float)srate); - pR[4].copy_coeffs(pL[4]); - p_freq_old[4] = *params[param_p5_freq]; - p_level_old[4] = *params[param_p5_level]; - p_q_old[4] = *params[param_p5_q]; - } - if(*params[param_p6_freq] != p_freq_old[5] or *params[param_p6_level] != p_level_old[5] or *params[param_p6_q] != p_q_old[5]) { - pL[5].set_peakeq_rbj((float)*params[param_p6_freq], *params[param_p6_q], *params[param_p6_level], (float)srate); - pR[5].copy_coeffs(pL[5]); - p_freq_old[5] = *params[param_p6_freq]; - p_level_old[5] = *params[param_p6_level]; - p_q_old[5] = *params[param_p6_q]; - } - if(*params[param_p7_freq] != p_freq_old[6] or *params[param_p7_level] != p_level_old[6] or *params[param_p7_q] != p_q_old[6]) { - pL[6].set_peakeq_rbj((float)*params[param_p7_freq], *params[param_p7_q], *params[param_p7_level], (float)srate); - pR[6].copy_coeffs(pL[6]); - p_freq_old[6] = *params[param_p7_freq]; - p_level_old[6] = *params[param_p7_level]; - p_q_old[6] = *params[param_p7_q]; - } - if(*params[param_p8_freq] != p_freq_old[7] or *params[param_p8_level] != p_level_old[7] or *params[param_p8_q] != p_q_old[7]) { - pL[7].set_peakeq_rbj((float)*params[param_p8_freq], *params[param_p8_q], *params[param_p8_level], (float)srate); - pR[7].copy_coeffs(pL[7]); - p_freq_old[7] = *params[param_p8_freq]; - p_level_old[7] = *params[param_p8_level]; - p_q_old[7] = *params[param_p8_q]; - } -} - -void equalizer12band_audio_module::set_sample_rate(uint32_t sr) -{ - srate = sr; -} - -uint32_t equalizer12band_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) -{ - bool bypass = *params[param_bypass] > 0.5f; - numsamples += offset; - if(bypass) { - // everything bypassed - while(offset < numsamples) { - outs[0][offset] = ins[0][offset]; - outs[1][offset] = ins[1][offset]; - ++offset; - } - // displays, too - clip_inL = 0.f; - clip_inR = 0.f; - clip_outL = 0.f; - clip_outR = 0.f; - meter_inL = 0.f; - meter_inR = 0.f; - meter_outL = 0.f; - meter_outR = 0.f; - } else { - - clip_inL -= std::min(clip_inL, numsamples); - clip_inR -= std::min(clip_inR, numsamples); - clip_outL -= std::min(clip_outL, numsamples); - clip_outR -= std::min(clip_outR, numsamples); - meter_inL = 0.f; - meter_inR = 0.f; - meter_outL = 0.f; - meter_outR = 0.f; - - // process - while(offset < numsamples) { - // cycle through samples - float outL = 0.f; - float outR = 0.f; - float inL = ins[0][offset]; - float inR = ins[1][offset]; - // in level - inR *= *params[param_level_in]; - inL *= *params[param_level_in]; - - float procL = inL; - float procR = inR; - - // all filters in chain - if(*params[param_hp_active] > 0.f) { - switch((int)*params[param_hp_mode]) { - case MODE12DB: - procL = hpL[0].process(procL); - procR = hpR[0].process(procR); - break; - case MODE24DB: - procL = hpL[1].process(hpL[0].process(procL)); - procR = hpR[1].process(hpR[0].process(procR)); - break; - case MODE36DB: - procL = hpL[2].process(hpL[1].process(hpL[0].process(procL))); - procR = hpR[2].process(hpR[1].process(hpR[0].process(procR))); - break; - } - } - if(*params[param_lp_active] > 0.f) { - switch((int)*params[param_lp_mode]) { - case MODE12DB: - procL = lpL[0].process(procL); - procR = lpR[0].process(procR); - break; - case MODE24DB: - procL = lpL[1].process(lpL[0].process(procL)); - procR = lpR[1].process(lpR[0].process(procR)); - break; - case MODE36DB: - procL = lpL[2].process(lpL[1].process(lpL[0].process(procL))); - procR = lpR[2].process(lpR[1].process(lpR[0].process(procR))); - break; - } - } - if(*params[param_ls_active] > 0.f) { - procL = lsL.process(procL); - procR = lsR.process(procR); - } - if(*params[param_hs_active] > 0.f) { - procL = hsL.process(procL); - procR = hsR.process(procR); - } - if(*params[param_p1_active] > 0.f) { - procL = pL[0].process(procL); - procR = pR[0].process(procR); - } - if(*params[param_p2_active] > 0.f) { - procL = pL[1].process(procL); - procR = pR[1].process(procR); - } - if(*params[param_p3_active] > 0.f) { - procL = pL[2].process(procL); - procR = pR[2].process(procR); - } - if(*params[param_p4_active] > 0.f) { - procL = pL[3].process(procL); - procR = pR[3].process(procR); - } - if(*params[param_p5_active] > 0.f) { - procL = pL[4].process(procL); - procR = pR[4].process(procR); - } - if(*params[param_p6_active] > 0.f) { - procL = pL[5].process(procL); - procR = pR[5].process(procR); - } - if(*params[param_p7_active] > 0.f) { - procL = pL[6].process(procL); - procR = pR[6].process(procR); - } - if(*params[param_p8_active] > 0.f) { - procL = pL[7].process(procL); - procR = pR[7].process(procR); - } - - outL = procL * *params[param_level_out]; - outR = procR * *params[param_level_out]; - - // send to output - outs[0][offset] = outL; - outs[1][offset] = outR; - - // clip LED's - if(inL > 1.f) { - clip_inL = srate >> 3; - } - if(inR > 1.f) { - clip_inR = srate >> 3; - } - if(outL > 1.f) { - clip_outL = srate >> 3; - } - if(outR > 1.f) { - clip_outR = srate >> 3; - } - // set up in / out meters - if(inL > meter_inL) { - meter_inL = inL; - } - if(inR > meter_inR) { - meter_inR = inR; - } - if(outL > meter_outL) { - meter_outL = outL; - } - if(outR > meter_outR) { - meter_outR = outR; - } - - // next sample - ++offset; - } // cycle trough samples - // clean up - for(int i = 0; i < 3; ++i) { - hpL[i].sanitize(); - hpR[i].sanitize(); - lpL[i].sanitize(); - lpR[i].sanitize(); - } - lsL.sanitize(); - hsR.sanitize(); - for(int i = 0; i < 8; ++i) { - pL[i].sanitize(); - pR[i].sanitize(); - } - } - // draw meters - if(params[param_clip_inL] != NULL) { - *params[param_clip_inL] = clip_inL; - } - if(params[param_clip_inR] != NULL) { - *params[param_clip_inR] = clip_inR; - } - if(params[param_clip_outL] != NULL) { - *params[param_clip_outL] = clip_outL; - } - if(params[param_clip_outR] != NULL) { - *params[param_clip_outR] = clip_outR; - } - - if(params[param_meter_inL] != NULL) { - *params[param_meter_inL] = meter_inL; - } - if(params[param_meter_inR] != NULL) { - *params[param_meter_inR] = meter_inR; - } - if(params[param_meter_outL] != NULL) { - *params[param_meter_outL] = meter_outL; - } - if(params[param_meter_outR] != NULL) { - *params[param_meter_outR] = meter_outR; - } - // whatever has to be returned x) - return outputs_mask; -} -bool equalizer12band_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) -{ - if (!is_active) - return false; - if (index == param_p1_freq && !subindex) { - context->set_line_width(1.5); - return ::get_graph(*this, subindex, data, points); - } - return false; -} - -bool equalizer12band_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) -{ - if (!is_active) { - return false; - } else { - return get_freq_gridline(subindex, pos, vertical, legend, context); - } -} - -int equalizer12band_audio_module::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) -{ - if (!is_active) { - return false; - } else { - if (*params[param_hp_freq] != hp_freq_old1 - or *params[param_hp_mode] != hp_mode_old1 - or *params[param_lp_freq] != lp_freq_old1 - or *params[param_lp_mode] != lp_mode_old1 - - or *params[param_ls_freq] != ls_freq_old1 - or *params[param_ls_level] != ls_level_old1 - or *params[param_hs_freq] != hs_freq_old1 - or *params[param_hs_level] != hs_level_old1 - - or *params[param_p1_freq] != p_freq_old1[0] - or *params[param_p1_level] != p_level_old1[0] - or *params[param_p1_q] != p_q_old1[0] - - or *params[param_p2_freq] != p_freq_old1[1] - or *params[param_p2_level] != p_level_old1[1] - or *params[param_p2_q] != p_q_old1[1] - - or *params[param_p3_freq] != p_freq_old1[2] - or *params[param_p3_level] != p_level_old1[2] - or *params[param_p3_q] != p_q_old1[2] - - or *params[param_p4_freq] != p_freq_old1[3] - or *params[param_p4_level] != p_level_old1[3] - or *params[param_p4_q] != p_q_old1[3] - - or *params[param_p5_freq] != p_freq_old1[4] - or *params[param_p5_level] != p_level_old1[4] - or *params[param_p5_q] != p_q_old1[4] - - or *params[param_p6_freq] != p_freq_old1[5] - or *params[param_p6_level] != p_level_old1[5] - or *params[param_p6_q] != p_q_old1[5] - - or *params[param_p7_freq] != p_freq_old1[6] - or *params[param_p7_level] != p_level_old1[6] - or *params[param_p7_q] != p_q_old1[6] - - or *params[param_p8_freq] != p_freq_old1[7] - or *params[param_p8_level] != p_level_old1[7] - or *params[param_p8_q] != p_q_old1[7]) - { - - hp_freq_old1 = *params[param_hp_freq]; - hp_mode_old1 = *params[param_hp_mode]; - lp_freq_old1 = *params[param_lp_freq]; - lp_mode_old1 = *params[param_lp_mode]; - - ls_freq_old1 = *params[param_ls_freq]; - ls_level_old1 = *params[param_ls_level]; - hs_freq_old1 = *params[param_hs_freq]; - hs_level_old1 = *params[param_hs_level]; - - p_freq_old1[0] = *params[param_p1_freq]; - p_level_old1[0] = *params[param_p1_level]; - p_q_old1[0] = *params[param_p1_q]; - - p_freq_old1[1] = *params[param_p2_freq]; - p_level_old1[1] = *params[param_p2_level]; - p_q_old1[1] = *params[param_p2_q]; - - p_freq_old1[2] = *params[param_p3_freq]; - p_level_old1[2] = *params[param_p3_level]; - p_q_old1[2] = *params[param_p3_q]; - - p_freq_old1[3] = *params[param_p4_freq]; - p_level_old1[3] = *params[param_p4_level]; - p_q_old1[3] = *params[param_p4_q]; - - p_freq_old1[4] = *params[param_p5_freq]; - p_level_old1[4] = *params[param_p5_level]; - p_q_old1[4] = *params[param_p5_q]; - - p_freq_old1[5] = *params[param_p6_freq]; - p_level_old1[5] = *params[param_p6_level]; - p_q_old1[5] = *params[param_p6_q]; - - p_freq_old1[6] = *params[param_p7_freq]; - p_level_old1[6] = *params[param_p7_level]; - p_q_old1[6] = *params[param_p7_q]; - - p_freq_old1[7] = *params[param_p8_freq]; - p_level_old1[7] = *params[param_p8_level]; - p_q_old1[7] = *params[param_p8_q]; - - last_generation++; - subindex_graph = 0; - subindex_dot = INT_MAX; - subindex_gridline = INT_MAX; - } - else { - subindex_graph = 0; - subindex_dot = subindex_gridline = generation ? INT_MAX : 0; - } - if (generation == last_calculated_generation) - subindex_graph = INT_MAX; - return last_generation; - } - return false; -} - -/// Equalizer 8 Band by Markus Schmidt -/// -/// This module is based on Krzysztof's filters. It provides a couple -/// of different chained filters. -/////////////////////////////////////////////////////////////////////////////////////////////// - -equalizer8band_audio_module::equalizer8band_audio_module() -{ - is_active = false; - srate = 0; - last_generation = 0; - clip_inL = 0.f; - clip_inR = 0.f; - clip_outL = 0.f; - clip_outR = 0.f; - meter_inL = 0.f; - meter_inR = 0.f; - meter_outL = 0.f; - meter_outR = 0.f; -} - -void equalizer8band_audio_module::activate() -{ - is_active = true; - // set all filters - params_changed(); -} -void equalizer8band_audio_module::deactivate() -{ - is_active = false; -} - -void equalizer8band_audio_module::params_changed() -{ - // set the params of all filters - if(*params[param_hp_freq] != hp_freq_old) { - hpL[0].set_hp_rbj(*params[param_hp_freq], 0.707, (float)srate, 1.0); - hpL[1].copy_coeffs(hpL[0]); - hpL[2].copy_coeffs(hpL[0]); - hpR[0].copy_coeffs(hpL[0]); - hpR[1].copy_coeffs(hpL[0]); - hpR[2].copy_coeffs(hpL[0]); - hp_freq_old = *params[param_hp_freq]; - } - if(*params[param_lp_freq] != lp_freq_old) { - lpL[0].set_lp_rbj(*params[param_lp_freq], 0.707, (float)srate, 1.0); - lpL[1].copy_coeffs(lpL[0]); - lpL[2].copy_coeffs(lpL[0]); - lpR[0].copy_coeffs(lpL[0]); - lpR[1].copy_coeffs(lpL[0]); - lpR[2].copy_coeffs(lpL[0]); - lp_freq_old = *params[param_lp_freq]; - } - if(*params[param_ls_freq] != ls_freq_old or *params[param_ls_level] != ls_level_old) { - lsL.set_lowshelf_rbj(*params[param_ls_freq], 0.707, *params[param_ls_level], (float)srate); - lsR.copy_coeffs(lsL); - ls_level_old = *params[param_ls_level]; - ls_freq_old = *params[param_ls_freq]; - } - if(*params[param_hs_freq] != hs_freq_old or *params[param_hs_level] != hs_level_old) { - hsL.set_highshelf_rbj(*params[param_hs_freq], 0.707, *params[param_hs_level], (float)srate); - hsR.copy_coeffs(hsL); - hs_level_old = *params[param_hs_level]; - hs_freq_old = *params[param_hs_freq]; - } - if(*params[param_p1_freq] != p_freq_old[0] or *params[param_p1_level] != p_level_old[0] or *params[param_p1_q] != p_q_old[0]) { - pL[0].set_peakeq_rbj((float)*params[param_p1_freq], *params[param_p1_q], *params[param_p1_level], (float)srate); - pR[0].copy_coeffs(pL[0]); - p_freq_old[0] = *params[param_p1_freq]; - p_level_old[0] = *params[param_p1_level]; - p_q_old[0] = *params[param_p1_q]; - } - if(*params[param_p2_freq] != p_freq_old[1] or *params[param_p2_level] != p_level_old[1] or *params[param_p2_q] != p_q_old[1]) { - pL[1].set_peakeq_rbj((float)*params[param_p2_freq], *params[param_p2_q], *params[param_p2_level], (float)srate); - pR[1].copy_coeffs(pL[1]); - p_freq_old[1] = *params[param_p2_freq]; - p_level_old[1] = *params[param_p2_level]; - p_q_old[1] = *params[param_p2_q]; - } - if(*params[param_p3_freq] != p_freq_old[2] or *params[param_p3_level] != p_level_old[2] or *params[param_p3_q] != p_q_old[2]) { - pL[2].set_peakeq_rbj((float)*params[param_p3_freq], *params[param_p3_q], *params[param_p3_level], (float)srate); - pR[2].copy_coeffs(pL[2]); - p_freq_old[2] = *params[param_p3_freq]; - p_level_old[2] = *params[param_p3_level]; - p_q_old[2] = *params[param_p3_q]; - } - if(*params[param_p4_freq] != p_freq_old[3] or *params[param_p4_level] != p_level_old[3] or *params[param_p4_q] != p_q_old[3]) { - pL[3].set_peakeq_rbj((float)*params[param_p4_freq], *params[param_p4_q], *params[param_p4_level], (float)srate); - pR[3].copy_coeffs(pL[3]); - p_freq_old[3] = *params[param_p4_freq]; - p_level_old[3] = *params[param_p4_level]; - p_q_old[3] = *params[param_p4_q]; - } -} - -void equalizer8band_audio_module::set_sample_rate(uint32_t sr) -{ - srate = sr; -} - -uint32_t equalizer8band_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) -{ - bool bypass = *params[param_bypass] > 0.5f; - numsamples += offset; - if(bypass) { - // everything bypassed - while(offset < numsamples) { - outs[0][offset] = ins[0][offset]; - outs[1][offset] = ins[1][offset]; - ++offset; - } - // displays, too - clip_inL = 0.f; - clip_inR = 0.f; - clip_outL = 0.f; - clip_outR = 0.f; - meter_inL = 0.f; - meter_inR = 0.f; - meter_outL = 0.f; - meter_outR = 0.f; - } else { - - clip_inL -= std::min(clip_inL, numsamples); - clip_inR -= std::min(clip_inR, numsamples); - clip_outL -= std::min(clip_outL, numsamples); - clip_outR -= std::min(clip_outR, numsamples); - meter_inL = 0.f; - meter_inR = 0.f; - meter_outL = 0.f; - meter_outR = 0.f; - - // process - while(offset < numsamples) { - // cycle through samples - float outL = 0.f; - float outR = 0.f; - float inL = ins[0][offset]; - float inR = ins[1][offset]; - // in level - inR *= *params[param_level_in]; - inL *= *params[param_level_in]; - - float procL = inL; - float procR = inR; - - // all filters in chain - if(*params[param_hp_active] > 0.f) { - switch((int)*params[param_hp_mode]) { - case MODE12DB: - procL = hpL[0].process(procL); - procR = hpR[0].process(procR); - break; - case MODE24DB: - procL = hpL[1].process(hpL[0].process(procL)); - procR = hpR[1].process(hpR[0].process(procR)); - break; - case MODE36DB: - procL = hpL[2].process(hpL[1].process(hpL[0].process(procL))); - procR = hpR[2].process(hpR[1].process(hpR[0].process(procR))); - break; - } - } - if(*params[param_lp_active] > 0.f) { - switch((int)*params[param_lp_mode]) { - case MODE12DB: - procL = lpL[0].process(procL); - procR = lpR[0].process(procR); - break; - case MODE24DB: - procL = lpL[1].process(lpL[0].process(procL)); - procR = lpR[1].process(lpR[0].process(procR)); - break; - case MODE36DB: - procL = lpL[2].process(lpL[1].process(lpL[0].process(procL))); - procR = lpR[2].process(lpR[1].process(lpR[0].process(procR))); - break; - } - } - if(*params[param_ls_active] > 0.f) { - procL = lsL.process(procL); - procR = lsR.process(procR); - } - if(*params[param_hs_active] > 0.f) { - procL = hsL.process(procL); - procR = hsR.process(procR); - } - if(*params[param_p1_active] > 0.f) { - procL = pL[0].process(procL); - procR = pR[0].process(procR); - } - if(*params[param_p2_active] > 0.f) { - procL = pL[1].process(procL); - procR = pR[1].process(procR); - } - if(*params[param_p3_active] > 0.f) { - procL = pL[2].process(procL); - procR = pR[2].process(procR); - } - if(*params[param_p4_active] > 0.f) { - procL = pL[3].process(procL); - procR = pR[3].process(procR); - } - - outL = procL * *params[param_level_out]; - outR = procR * *params[param_level_out]; - - // send to output - outs[0][offset] = outL; - outs[1][offset] = outR; - - // clip LED's - if(inL > 1.f) { - clip_inL = srate >> 3; - } - if(inR > 1.f) { - clip_inR = srate >> 3; - } - if(outL > 1.f) { - clip_outL = srate >> 3; - } - if(outR > 1.f) { - clip_outR = srate >> 3; - } - // set up in / out meters - if(inL > meter_inL) { - meter_inL = inL; - } - if(inR > meter_inR) { - meter_inR = inR; - } - if(outL > meter_outL) { - meter_outL = outL; - } - if(outR > meter_outR) { - meter_outR = outR; - } - - // next sample - ++offset; - } // cycle trough samples - // clean up - for(int i = 0; i < 3; ++i) { - hpL[i].sanitize(); - hpR[i].sanitize(); - lpL[i].sanitize(); - lpR[i].sanitize(); - } - lsL.sanitize(); - hsR.sanitize(); - for(int i = 0; i < 4; ++i) { - pL[i].sanitize(); - pR[i].sanitize(); - } - } - // draw meters - if(params[param_clip_inL] != NULL) { - *params[param_clip_inL] = clip_inL; - } - if(params[param_clip_inR] != NULL) { - *params[param_clip_inR] = clip_inR; - } - if(params[param_clip_outL] != NULL) { - *params[param_clip_outL] = clip_outL; - } - if(params[param_clip_outR] != NULL) { - *params[param_clip_outR] = clip_outR; - } - - if(params[param_meter_inL] != NULL) { - *params[param_meter_inL] = meter_inL; - } - if(params[param_meter_inR] != NULL) { - *params[param_meter_inR] = meter_inR; - } - if(params[param_meter_outL] != NULL) { - *params[param_meter_outL] = meter_outL; - } - if(params[param_meter_outR] != NULL) { - *params[param_meter_outR] = meter_outR; - } - // whatever has to be returned x) - return outputs_mask; -} -bool equalizer8band_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) -{ - if (!is_active) - return false; - if (index == param_p1_freq && !subindex) { - context->set_line_width(1.5); - return ::get_graph(*this, subindex, data, points); - } - return false; -} - -bool equalizer8band_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) -{ - if (!is_active) { - return false; - } else { - return get_freq_gridline(subindex, pos, vertical, legend, context); - } -} - -int equalizer8band_audio_module::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) -{ - if (!is_active) { - return false; - } else { - if (*params[param_hp_freq] != hp_freq_old1 - or *params[param_hp_mode] != hp_mode_old1 - or *params[param_lp_freq] != lp_freq_old1 - or *params[param_lp_mode] != lp_mode_old1 - - or *params[param_ls_freq] != ls_freq_old1 - or *params[param_ls_level] != ls_level_old1 - or *params[param_hs_freq] != hs_freq_old1 - or *params[param_hs_level] != hs_level_old1 - - or *params[param_p1_freq] != p_freq_old1[0] - or *params[param_p1_level] != p_level_old1[0] - or *params[param_p1_q] != p_q_old1[0] - - or *params[param_p2_freq] != p_freq_old1[1] - or *params[param_p2_level] != p_level_old1[1] - or *params[param_p2_q] != p_q_old1[1] - - or *params[param_p3_freq] != p_freq_old1[2] - or *params[param_p3_level] != p_level_old1[2] - or *params[param_p3_q] != p_q_old1[2] - - or *params[param_p4_freq] != p_freq_old1[3] - or *params[param_p4_level] != p_level_old1[3] - or *params[param_p4_q] != p_q_old1[3]) - { - - hp_freq_old1 = *params[param_hp_freq]; - hp_mode_old1 = *params[param_hp_mode]; - lp_freq_old1 = *params[param_lp_freq]; - lp_mode_old1 = *params[param_lp_mode]; - - ls_freq_old1 = *params[param_ls_freq]; - ls_level_old1 = *params[param_ls_level]; - hs_freq_old1 = *params[param_hs_freq]; - hs_level_old1 = *params[param_hs_level]; - - p_freq_old1[0] = *params[param_p1_freq]; - p_level_old1[0] = *params[param_p1_level]; - p_q_old1[0] = *params[param_p1_q]; - - p_freq_old1[1] = *params[param_p2_freq]; - p_level_old1[1] = *params[param_p2_level]; - p_q_old1[1] = *params[param_p2_q]; - - p_freq_old1[2] = *params[param_p3_freq]; - p_level_old1[2] = *params[param_p3_level]; - p_q_old1[2] = *params[param_p3_q]; - - p_freq_old1[3] = *params[param_p4_freq]; - p_level_old1[3] = *params[param_p4_level]; - p_q_old1[3] = *params[param_p4_q]; - - last_generation++; - subindex_graph = 0; - subindex_dot = INT_MAX; - subindex_gridline = INT_MAX; - } - else { - subindex_graph = 0; - subindex_dot = subindex_gridline = generation ? INT_MAX : 0; - } - if (generation == last_calculated_generation) - subindex_graph = INT_MAX; - return last_generation; - } - return false; -} - -/// Equalizer 5 Band by Markus Schmidt -/// -/// This module is based on Krzysztof's filters. It provides a couple -/// of different chained filters. -/////////////////////////////////////////////////////////////////////////////////////////////// - -equalizer5band_audio_module::equalizer5band_audio_module() -{ - is_active = false; - srate = 0; - last_generation = 0; - clip_in = 0.f; - clip_out = 0.f; - meter_in = 0.f; - meter_out = 0.f; -} - -void equalizer5band_audio_module::activate() -{ - is_active = true; - // set all filters - params_changed(); -} -void equalizer5band_audio_module::deactivate() -{ - is_active = false; -} - -void equalizer5band_audio_module::params_changed() -{ - // set the params of all filters - if(*params[param_ls_freq] != ls_freq_old or *params[param_ls_level] != ls_level_old) { - lsL.set_lowshelf_rbj(*params[param_ls_freq], 0.707, *params[param_ls_level], (float)srate); - lsR.copy_coeffs(lsL); - ls_level_old = *params[param_ls_level]; - ls_freq_old = *params[param_ls_freq]; - } - if(*params[param_hs_freq] != hs_freq_old or *params[param_hs_level] != hs_level_old) { - hsL.set_highshelf_rbj(*params[param_hs_freq], 0.707, *params[param_hs_level], (float)srate); - hsR.copy_coeffs(hsL); - hs_level_old = *params[param_hs_level]; - hs_freq_old = *params[param_hs_freq]; - } - if(*params[param_p1_freq] != p_freq_old[0] or *params[param_p1_level] != p_level_old[0] or *params[param_p1_q] != p_q_old[0]) { - pL[0].set_peakeq_rbj((float)*params[param_p1_freq], *params[param_p1_q], *params[param_p1_level], (float)srate); - pR[0].copy_coeffs(pL[0]); - p_freq_old[0] = *params[param_p1_freq]; - p_level_old[0] = *params[param_p1_level]; - p_q_old[0] = *params[param_p1_q]; - } - if(*params[param_p2_freq] != p_freq_old[1] or *params[param_p2_level] != p_level_old[1] or *params[param_p2_q] != p_q_old[1]) { - pL[1].set_peakeq_rbj((float)*params[param_p2_freq], *params[param_p2_q], *params[param_p2_level], (float)srate); - pR[1].copy_coeffs(pL[1]); - p_freq_old[1] = *params[param_p2_freq]; - p_level_old[1] = *params[param_p2_level]; - p_q_old[1] = *params[param_p2_q]; - } - if(*params[param_p3_freq] != p_freq_old[2] or *params[param_p3_level] != p_level_old[2] or *params[param_p3_q] != p_q_old[2]) { - pL[2].set_peakeq_rbj((float)*params[param_p3_freq], *params[param_p3_q], *params[param_p3_level], (float)srate); - pR[2].copy_coeffs(pL[2]); - p_freq_old[2] = *params[param_p3_freq]; - p_level_old[2] = *params[param_p3_level]; - p_q_old[2] = *params[param_p3_q]; - } -} - -void equalizer5band_audio_module::set_sample_rate(uint32_t sr) -{ - srate = sr; -} - -uint32_t equalizer5band_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) -{ - bool bypass = *params[param_bypass] > 0.5f; - numsamples += offset; - if(bypass) { - // everything bypassed - while(offset < numsamples) { - outs[0][offset] = ins[0][offset]; - outs[1][offset] = ins[1][offset]; - ++offset; - } - // displays, too - clip_in = 0.f; - clip_out = 0.f; - meter_in = 0.f; - meter_out = 0.f; - } else { - - clip_in -= std::min(clip_in, numsamples); - clip_out -= std::min(clip_out, numsamples); - meter_in = 0.f; - meter_out = 0.f; - - // process - while(offset < numsamples) { - // cycle through samples - float outL = 0.f; - float outR = 0.f; - float inL = ins[0][offset]; - float inR = ins[1][offset]; - // in level - inR *= *params[param_level_in]; - inL *= *params[param_level_in]; - - float procL = inL; - float procR = inR; - - // all filters in chain - if(*params[param_ls_active] > 0.f) { - procL = lsL.process(procL); - procR = lsR.process(procR); - } - if(*params[param_hs_active] > 0.f) { - procL = hsL.process(procL); - procR = hsR.process(procR); - } - if(*params[param_p1_active] > 0.f) { - procL = pL[0].process(procL); - procR = pR[0].process(procR); - } - if(*params[param_p2_active] > 0.f) { - procL = pL[1].process(procL); - procR = pR[1].process(procR); - } - if(*params[param_p3_active] > 0.f) { - procL = pL[2].process(procL); - procR = pR[2].process(procR); - } - - outL = procL * *params[param_level_out]; - outR = procR * *params[param_level_out]; - - // send to output - outs[0][offset] = outL; - outs[1][offset] = outR; - - // clip LED's - float maxIn = std::max(fabs(inL), fabs(inR)); - float maxOut = std::max(fabs(outL), fabs(outR)); - - if(maxIn > 1.f) { - clip_in = srate >> 3; - } - if(maxOut > 1.f) { - clip_out = srate >> 3; - } - // set up in / out meters - if(maxIn > meter_in) { - meter_in = maxIn; - } - if(maxOut > meter_out) { - meter_out = maxOut; - } - - // next sample - ++offset; - } // cycle trough samples - // clean up - lsL.sanitize(); - hsR.sanitize(); - for(int i = 0; i < 3; ++i) { - pL[i].sanitize(); - pR[i].sanitize(); - } - } - // draw meters - if(params[param_clip_in] != NULL) { - *params[param_clip_in] = clip_in; - } - if(params[param_clip_out] != NULL) { - *params[param_clip_out] = clip_out; - } - - if(params[param_meter_in] != NULL) { - *params[param_meter_in] = meter_in; - } - if(params[param_meter_out] != NULL) { - *params[param_meter_out] = meter_out; - } - // whatever has to be returned x) - return outputs_mask; -} -bool equalizer5band_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) -{ - if (!is_active) - return false; - if (index == param_p1_freq && !subindex) { - context->set_line_width(1.5); - return ::get_graph(*this, subindex, data, points); - } - return false; -} - -bool equalizer5band_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) -{ - if (!is_active) { - return false; - } else { - return get_freq_gridline(subindex, pos, vertical, legend, context); - } -} - -int equalizer5band_audio_module::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) -{ - if (!is_active) { - return false; - } else { - if (*params[param_ls_freq] != ls_freq_old1 - or *params[param_ls_level] != ls_level_old1 - or *params[param_hs_freq] != hs_freq_old1 - or *params[param_hs_level] != hs_level_old1 - - or *params[param_p1_freq] != p_freq_old1[0] - or *params[param_p1_level] != p_level_old1[0] - or *params[param_p1_q] != p_q_old1[0] - - or *params[param_p2_freq] != p_freq_old1[1] - or *params[param_p2_level] != p_level_old1[1] - or *params[param_p2_q] != p_q_old1[1] - - or *params[param_p3_freq] != p_freq_old1[2] - or *params[param_p3_level] != p_level_old1[2] - or *params[param_p3_q] != p_q_old1[2]) - { - - ls_freq_old1 = *params[param_ls_freq]; - ls_level_old1 = *params[param_ls_level]; - hs_freq_old1 = *params[param_hs_freq]; - hs_level_old1 = *params[param_hs_level]; - - p_freq_old1[0] = *params[param_p1_freq]; - p_level_old1[0] = *params[param_p1_level]; - p_q_old1[0] = *params[param_p1_q]; - - p_freq_old1[1] = *params[param_p2_freq]; - p_level_old1[1] = *params[param_p2_level]; - p_q_old1[1] = *params[param_p2_q]; - - p_freq_old1[2] = *params[param_p3_freq]; - p_level_old1[2] = *params[param_p3_level]; - p_q_old1[2] = *params[param_p3_q]; - - last_generation++; - subindex_graph = 0; - subindex_dot = INT_MAX; - subindex_gridline = INT_MAX; - } - else { - subindex_graph = 0; - subindex_dot = subindex_gridline = generation ? INT_MAX : 0; - } - if (generation == last_calculated_generation) - subindex_graph = INT_MAX; - return last_generation; - } - return false; -} diff --git a/plugins/ladspa_effect/calf/src/modules_eq.cpp b/plugins/ladspa_effect/calf/src/modules_eq.cpp new file mode 100644 index 000000000..d4ea0bcc4 --- /dev/null +++ b/plugins/ladspa_effect/calf/src/modules_eq.cpp @@ -0,0 +1,381 @@ +/* Calf DSP plugin pack + * Equalization related plugins + * + * Copyright (C) 2001-2010 Krzysztof Foltman, Markus Schmidt, Thor Harald Johansen and others + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include + +using namespace dsp; +using namespace calf_plugins; + +#define SET_IF_CONNECTED(name) if (params[AM::param_##name] != NULL) *params[AM::param_##name] = name; + +/// Equalizer 12 Band by Markus Schmidt +/// +/// This module is based on Krzysztof's filters. It provides a couple +/// of different chained filters. +/////////////////////////////////////////////////////////////////////////////////////////////// + +template +equalizerNband_audio_module::equalizerNband_audio_module() +{ + is_active = false; + srate = 0; + last_generation = 0; + clip_inL = clip_inR = clip_outL = clip_outR = 0.f; + meter_inL = meter_inR = meter_outL = meter_outR = 0.f; +} + +template +void equalizerNband_audio_module::activate() +{ + is_active = true; + // set all filters + params_changed(); +} + +template +void equalizerNband_audio_module::deactivate() +{ + is_active = false; +} + +static inline void copy_lphp(biquad_d2 filters[3][2]) +{ + for (int i = 0; i < 3; i++) + for (int j = 0; j < 2; j++) + if (i || j) + filters[i][j].copy_coeffs(filters[0][0]); +} + +template +void equalizerNband_audio_module::params_changed() +{ + // set the params of all filters + + // lp/hp first (if available) + if (has_lphp) + { + hp_mode = (CalfEqMode)(int)*params[AM::param_hp_mode]; + lp_mode = (CalfEqMode)(int)*params[AM::param_lp_mode]; + + float hpfreq = *params[AM::param_hp_freq], lpfreq = *params[AM::param_lp_freq]; + + if(hpfreq != hp_freq_old) { + hp[0][0].set_hp_rbj(hpfreq, 0.707, (float)srate, 1.0); + copy_lphp(hp); + hp_freq_old = hpfreq; + } + if(lpfreq != lp_freq_old) { + lp[0][0].set_lp_rbj(lpfreq, 0.707, (float)srate, 1.0); + copy_lphp(lp); + lp_freq_old = lpfreq; + } + } + + // then shelves + float hsfreq = *params[AM::param_hs_freq], hslevel = *params[AM::param_hs_level]; + float lsfreq = *params[AM::param_ls_freq], lslevel = *params[AM::param_ls_level]; + + if(lsfreq != ls_freq_old or lslevel != ls_level_old) { + lsL.set_lowshelf_rbj(lsfreq, 0.707, lslevel, (float)srate); + lsR.copy_coeffs(lsL); + ls_level_old = lslevel; + ls_freq_old = lsfreq; + } + if(hsfreq != hs_freq_old or hslevel != hs_level_old) { + hsL.set_highshelf_rbj(hsfreq, 0.707, hslevel, (float)srate); + hsR.copy_coeffs(hsL); + hs_level_old = hslevel; + hs_freq_old = hsfreq; + } + for (int i = 0; i < AM::PeakBands; i++) + { + int offset = i * params_per_band; + float freq = *params[AM::param_p1_freq + offset]; + float level = *params[AM::param_p1_level + offset]; + float q = *params[AM::param_p1_q + offset]; + if(freq != p_freq_old[i] or level != p_level_old[i] or q != p_q_old[i]) { + pL[i].set_peakeq_rbj(freq, q, level, (float)srate); + pR[i].copy_coeffs(pL[i]); + p_freq_old[i] = freq; + p_level_old[i] = level; + p_q_old[i] = q; + } + } +} + +template +inline void equalizerNband_audio_module::process_hplp(float &left, float &right) +{ + if (!has_lphp) + return; + if (*params[AM::param_lp_active] > 0.f) + { + switch(lp_mode) + { + case MODE12DB: + left = lp[0][0].process(left); + right = lp[0][1].process(right); + break; + case MODE24DB: + left = lp[1][0].process(lp[0][0].process(left)); + right = lp[1][1].process(lp[0][1].process(right)); + break; + case MODE36DB: + left = lp[2][0].process(lp[1][0].process(lp[0][0].process(left))); + right = lp[2][1].process(lp[1][1].process(lp[0][1].process(right))); + break; + } + } + if (*params[AM::param_hp_active] > 0.f) + { + switch(hp_mode) + { + case MODE12DB: + left = hp[0][0].process(left); + right = hp[0][1].process(right); + break; + case MODE24DB: + left = hp[1][0].process(hp[0][0].process(left)); + right = hp[1][1].process(hp[0][1].process(right)); + break; + case MODE36DB: + left = hp[2][0].process(hp[1][0].process(hp[0][0].process(left))); + right = hp[2][1].process(hp[1][1].process(hp[0][1].process(right))); + break; + } + } +} + +template +uint32_t equalizerNband_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) +{ + bool bypass = *params[AM::param_bypass] > 0.f; + numsamples += offset; + if(bypass) { + // everything bypassed + while(offset < numsamples) { + outs[0][offset] = ins[0][offset]; + outs[1][offset] = ins[1][offset]; + ++offset; + } + // displays, too + clip_inL = clip_inR = clip_outL = clip_outR = 0.f; + meter_inL = meter_inR = meter_outL = meter_outR = 0.f; + } else { + + clip_inL -= std::min(clip_inL, numsamples); + clip_inR -= std::min(clip_inR, numsamples); + clip_outL -= std::min(clip_outL, numsamples); + clip_outR -= std::min(clip_outR, numsamples); + meter_inL = 0.f; + meter_inR = 0.f; + meter_outL = 0.f; + meter_outR = 0.f; + + // process + while(offset < numsamples) { + // cycle through samples + float outL = 0.f; + float outR = 0.f; + float inL = ins[0][offset]; + float inR = ins[1][offset]; + // in level + inR *= *params[AM::param_level_in]; + inL *= *params[AM::param_level_in]; + + float procL = inL; + float procR = inR; + + // all filters in chain + process_hplp(procL, procR); + if(*params[AM::param_ls_active] > 0.f) { + procL = lsL.process(procL); + procR = lsR.process(procR); + } + if(*params[AM::param_hs_active] > 0.f) { + procL = hsL.process(procL); + procR = hsR.process(procR); + } + for (int i = 0; i < AM::PeakBands; i++) + { + if(*params[AM::param_p1_active + i * params_per_band] > 0.f) { + procL = pL[i].process(procL); + procR = pR[i].process(procR); + } + } + + outL = procL * *params[AM::param_level_out]; + outR = procR * *params[AM::param_level_out]; + + // send to output + outs[0][offset] = outL; + outs[1][offset] = outR; + + // clip LED's + if(inL > 1.f) { + clip_inL = srate >> 3; + } + if(inR > 1.f) { + clip_inR = srate >> 3; + } + if(outL > 1.f) { + clip_outL = srate >> 3; + } + if(outR > 1.f) { + clip_outR = srate >> 3; + } + // set up in / out meters + if(inL > meter_inL) { + meter_inL = inL; + } + if(inR > meter_inR) { + meter_inR = inR; + } + if(outL > meter_outL) { + meter_outL = outL; + } + if(outR > meter_outR) { + meter_outR = outR; + } + + // next sample + ++offset; + } // cycle trough samples + // clean up + for(int i = 0; i < 3; ++i) { + hp[i][0].sanitize(); + hp[i][1].sanitize(); + lp[i][0].sanitize(); + lp[i][1].sanitize(); + } + lsL.sanitize(); + hsR.sanitize(); + for(int i = 0; i < AM::PeakBands; ++i) { + pL[i].sanitize(); + pR[i].sanitize(); + } + } + // draw meters + SET_IF_CONNECTED(clip_inL) + SET_IF_CONNECTED(clip_inR) + SET_IF_CONNECTED(clip_outL) + SET_IF_CONNECTED(clip_outR) + SET_IF_CONNECTED(meter_inL) + SET_IF_CONNECTED(meter_inR) + SET_IF_CONNECTED(meter_outL) + SET_IF_CONNECTED(meter_outR) + // whatever has to be returned x) + return outputs_mask; +} + +template +bool equalizerNband_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const +{ + if (!is_active) + return false; + if (index == AM::param_p1_freq && !subindex) { + context->set_line_width(1.5); + return ::get_graph(*this, subindex, data, points); + } + return false; +} + +template +bool equalizerNband_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const +{ + if (!is_active) { + return false; + } else { + return get_freq_gridline(subindex, pos, vertical, legend, context); + } +} + +template +int equalizerNband_audio_module::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) const +{ + if (!is_active) { + return false; + } else { + bool changed = false; + for (int i = 0; i < graph_param_count && !changed; i++) + { + if (*params[AM::first_graph_param + i] != old_params_for_graph[i]) + changed = true; + } + if (changed) + { + for (int i = 0; i < graph_param_count; i++) + old_params_for_graph[i] = *params[AM::first_graph_param + i]; + + last_generation++; + subindex_graph = 0; + subindex_dot = INT_MAX; + subindex_gridline = INT_MAX; + } + else { + subindex_graph = 0; + subindex_dot = subindex_gridline = generation ? INT_MAX : 0; + } + if (generation == last_calculated_generation) + subindex_graph = INT_MAX; + return last_generation; + } + return false; +} + +static inline float adjusted_lphp_gain(const float *const *params, int param_active, int param_mode, const biquad_d2 &filter, float freq, float srate) +{ + if(*params[param_active] > 0.f) { + float gain = filter.freq_gain(freq, srate); + switch((int)*params[param_mode]) { + case MODE12DB: + return gain; + case MODE24DB: + return gain * gain; + case MODE36DB: + return gain * gain * gain; + } + } + return 1; +} + +template +float equalizerNband_audio_module::freq_gain(int index, double freq, uint32_t sr) const +{ + float ret = 1.f; + if (use_hplp) + { + ret *= adjusted_lphp_gain(params, AM::param_hp_active, AM::param_hp_mode, hp[0][0], freq, (float)sr); + ret *= adjusted_lphp_gain(params, AM::param_lp_active, AM::param_lp_mode, lp[0][0], freq, (float)sr); + } + ret *= (*params[AM::param_ls_active] > 0.f) ? lsL.freq_gain(freq, sr) : 1; + ret *= (*params[AM::param_hs_active] > 0.f) ? hsL.freq_gain(freq, sr) : 1; + for (int i = 0; i < PeakBands; i++) + ret *= (*params[AM::param_p1_active + i * params_per_band] > 0.f) ? pL[i].freq_gain(freq, (float)sr) : 1; + return ret; +} + +template class equalizerNband_audio_module; +template class equalizerNband_audio_module; +template class equalizerNband_audio_module; + diff --git a/plugins/ladspa_effect/calf/src/modules_mod.cpp b/plugins/ladspa_effect/calf/src/modules_mod.cpp new file mode 100644 index 000000000..f9716c21a --- /dev/null +++ b/plugins/ladspa_effect/calf/src/modules_mod.cpp @@ -0,0 +1,736 @@ +/* Calf DSP plugin pack + * Modulation effect plugins + * + * Copyright (C) 2001-2010 Krzysztof Foltman, Markus Schmidt, Thor Harald Johansen and others + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include + +using namespace dsp; +using namespace calf_plugins; + +#define SET_IF_CONNECTED(name) if (params[AM::param_##name] != NULL) *params[AM::param_##name] = name; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void flanger_audio_module::activate() { + left.reset(); + right.reset(); + last_r_phase = *params[par_stereo] * (1.f / 360.f); + left.reset_phase(0.f); + right.reset_phase(last_r_phase); + is_active = true; +} + +void flanger_audio_module::set_sample_rate(uint32_t sr) { + srate = sr; + left.setup(sr); + right.setup(sr); +} + +void flanger_audio_module::deactivate() { + is_active = false; +} + +bool flanger_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const +{ + if (!is_active) + return false; + if (index == par_delay && subindex < 2) + { + set_channel_color(context, subindex); + return ::get_graph(*this, subindex, data, points); + } + return false; +} + +float flanger_audio_module::freq_gain(int subindex, float freq, float srate) const +{ + return (subindex ? right : left).freq_gain(freq, srate); +} + +void flanger_audio_module::params_changed() +{ + float dry = *params[par_dryamount]; + float wet = *params[par_amount]; + float rate = *params[par_rate]; // 0.01*pow(1000.0f,*params[par_rate]); + float min_delay = *params[par_delay] / 1000.0; + float mod_depth = *params[par_depth] / 1000.0; + float fb = *params[par_fb]; + left.set_dry(dry); right.set_dry(dry); + left.set_wet(wet); right.set_wet(wet); + left.set_rate(rate); right.set_rate(rate); + left.set_min_delay(min_delay); right.set_min_delay(min_delay); + left.set_mod_depth(mod_depth); right.set_mod_depth(mod_depth); + left.set_fb(fb); right.set_fb(fb); + float r_phase = *params[par_stereo] * (1.f / 360.f); + clear_reset = false; + if (*params[par_reset] >= 0.5) { + clear_reset = true; + left.reset_phase(0.f); + right.reset_phase(r_phase); + } else { + if (fabs(r_phase - last_r_phase) > 0.0001f) { + right.phase = left.phase; + right.inc_phase(r_phase); + last_r_phase = r_phase; + } + } +} + +void flanger_audio_module::params_reset() +{ + if (clear_reset) { + *params[par_reset] = 0.f; + clear_reset = false; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////// + +phaser_audio_module::phaser_audio_module() +: left(MaxStages, x1vals[0], y1vals[0]) +, right(MaxStages, x1vals[1], y1vals[1]) +{ + is_active = false; +} + +void phaser_audio_module::set_sample_rate(uint32_t sr) +{ + srate = sr; + left.setup(sr); + right.setup(sr); +} + +void phaser_audio_module::activate() +{ + is_active = true; + left.reset(); + right.reset(); + last_r_phase = *params[par_stereo] * (1.f / 360.f); + left.reset_phase(0.f); + right.reset_phase(last_r_phase); +} + +void phaser_audio_module::deactivate() +{ + is_active = false; +} + +bool phaser_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const +{ + if (!is_active) + return false; + if (subindex < 2) + { + set_channel_color(context, subindex); + return ::get_graph(*this, subindex, data, points); + } + return false; +} + +float phaser_audio_module::freq_gain(int subindex, float freq, float srate) const +{ + return (subindex ? right : left).freq_gain(freq, srate); +} + +bool phaser_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const +{ + return get_freq_gridline(subindex, pos, vertical, legend, context); +} + +void phaser_audio_module::params_changed() +{ + float dry = *params[par_dryamount]; + float wet = *params[par_amount]; + float rate = *params[par_rate]; // 0.01*pow(1000.0f,*params[par_rate]); + float base_frq = *params[par_freq]; + float mod_depth = *params[par_depth]; + float fb = *params[par_fb]; + int stages = (int)*params[par_stages]; + left.set_dry(dry); right.set_dry(dry); + left.set_wet(wet); right.set_wet(wet); + left.set_rate(rate); right.set_rate(rate); + left.set_base_frq(base_frq); right.set_base_frq(base_frq); + left.set_mod_depth(mod_depth); right.set_mod_depth(mod_depth); + left.set_fb(fb); right.set_fb(fb); + left.set_stages(stages); right.set_stages(stages); + float r_phase = *params[par_stereo] * (1.f / 360.f); + clear_reset = false; + if (*params[par_reset] >= 0.5) { + clear_reset = true; + left.reset_phase(0.f); + right.reset_phase(r_phase); + } else { + if (fabs(r_phase - last_r_phase) > 0.0001f) { + right.phase = left.phase; + right.inc_phase(r_phase); + last_r_phase = r_phase; + } + } +} + +void phaser_audio_module::params_reset() +{ + if (clear_reset) { + *params[par_reset] = 0.f; + clear_reset = false; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////// + +rotary_speaker_audio_module::rotary_speaker_audio_module() +{ + mwhl_value = hold_value = 0.f; + phase_h = phase_l = 0.f; + aspeed_l = 1.f; + aspeed_h = 1.f; + dspeed = 0.f; +} + +void rotary_speaker_audio_module::set_sample_rate(uint32_t sr) +{ + srate = sr; + setup(); +} + +void rotary_speaker_audio_module::setup() +{ + crossover1l.set_lp_rbj(800.f, 0.7, (float)srate); + crossover1r.set_lp_rbj(800.f, 0.7, (float)srate); + crossover2l.set_hp_rbj(800.f, 0.7, (float)srate); + crossover2r.set_hp_rbj(800.f, 0.7, (float)srate); +} + +void rotary_speaker_audio_module::activate() +{ + phase_h = phase_l = 0.f; + maspeed_h = maspeed_l = 0.f; + setup(); +} + +void rotary_speaker_audio_module::deactivate() +{ +} + +void rotary_speaker_audio_module::control_change(int ctl, int val) +{ + if (vibrato_mode == 3 && ctl == 64) + { + hold_value = val / 127.f; + set_vibrato(); + return; + } + if (vibrato_mode == 4 && ctl == 1) + { + mwhl_value = val / 127.f; + set_vibrato(); + return; + } +} + +void rotary_speaker_audio_module::params_changed() +{ + set_vibrato(); +} + +void rotary_speaker_audio_module::set_vibrato() +{ + vibrato_mode = fastf2i_drm(*params[par_speed]); + // manual vibrato - do not recalculate speeds as they're not used anyway + if (vibrato_mode == 5) + return; + if (!vibrato_mode) + dspeed = -1; + else { + float speed = vibrato_mode - 1; + if (vibrato_mode == 3) + speed = hold_value; + if (vibrato_mode == 4) + speed = mwhl_value; + dspeed = (speed < 0.5f) ? 0 : 1; + } + update_speed(); +} + +/// Convert RPM speed to delta-phase +uint32_t rotary_speaker_audio_module::rpm2dphase(float rpm) +{ + return (uint32_t)((rpm / (60.0 * srate)) * (1 << 30)) << 2; +} + +/// Set delta-phase variables based on current calculated (and interpolated) RPM speed +void rotary_speaker_audio_module::update_speed() +{ + float speed_h = aspeed_h >= 0 ? (48 + (400-48) * aspeed_h) : (48 * (1 + aspeed_h)); + float speed_l = aspeed_l >= 0 ? 40 + (342-40) * aspeed_l : (40 * (1 + aspeed_l)); + dphase_h = rpm2dphase(speed_h); + dphase_l = rpm2dphase(speed_l); +} + +void rotary_speaker_audio_module::update_speed_manual(float delta) +{ + float ts = *params[par_treblespeed]; + float bs = *params[par_bassspeed]; + incr_towards(maspeed_h, ts, delta * 200, delta * 200); + incr_towards(maspeed_l, bs, delta * 200, delta * 200); + dphase_h = rpm2dphase(maspeed_h); + dphase_l = rpm2dphase(maspeed_l); +} + +/// map a ramp [int] to a sinusoid-like function [0, 65536] +static inline int pseudo_sine_scl(int counter) +{ + // premature optimization is a root of all evil; it can be done with integers only - but later :) + double v = counter * (1.0 / (65536.0 * 32768.0)); + return (int) (32768 + 32768 * (v - v*v*v) * (1.0 / 0.3849)); +} + +/// Increase or decrease aspeed towards raspeed, with required negative and positive rate +inline bool rotary_speaker_audio_module::incr_towards(float &aspeed, float raspeed, float delta_decc, float delta_acc) +{ + if (aspeed < raspeed) { + aspeed = std::min(raspeed, aspeed + delta_acc); + return true; + } + else if (aspeed > raspeed) + { + aspeed = std::max(raspeed, aspeed - delta_decc); + return true; + } + return false; +} + +uint32_t rotary_speaker_audio_module::process(uint32_t offset, uint32_t nsamples, uint32_t inputs_mask, uint32_t outputs_mask) +{ + int shift = (int)(300000 * (*params[par_shift])), pdelta = (int)(300000 * (*params[par_spacing])); + int md = (int)(100 * (*params[par_moddepth])); + float mix = 0.5 * (1.0 - *params[par_micdistance]); + float mix2 = *params[par_reflection]; + float mix3 = mix2 * mix2; + for (unsigned int i = 0; i < nsamples; i++) { + float in_l = ins[0][i + offset], in_r = ins[1][i + offset]; + float in_mono = 0.5f * (in_l + in_r); + + int xl = pseudo_sine_scl(phase_l), yl = pseudo_sine_scl(phase_l + 0x40000000); + int xh = pseudo_sine_scl(phase_h), yh = pseudo_sine_scl(phase_h + 0x40000000); + // printf("%d %d %d\n", shift, pdelta, shift + pdelta + 20 * xl); + meter_l = xl; + meter_h = xh; + // float out_hi_l = in_mono - delay.get_interp_1616(shift + md * xh) + delay.get_interp_1616(shift + md * 65536 + pdelta - md * yh) - delay.get_interp_1616(shift + md * 65536 + pdelta + pdelta - md * xh); + // float out_hi_r = in_mono + delay.get_interp_1616(shift + md * 65536 - md * yh) - delay.get_interp_1616(shift + pdelta + md * xh) + delay.get_interp_1616(shift + pdelta + pdelta + md * yh); + float out_hi_l = in_mono + delay.get_interp_1616(shift + md * xh) - mix2 * delay.get_interp_1616(shift + md * 65536 + pdelta - md * yh) + mix3 * delay.get_interp_1616(shift + md * 65536 + pdelta + pdelta - md * xh); + float out_hi_r = in_mono + delay.get_interp_1616(shift + md * 65536 - md * yh) - mix2 * delay.get_interp_1616(shift + pdelta + md * xh) + mix3 * delay.get_interp_1616(shift + pdelta + pdelta + md * yh); + + float out_lo_l = in_mono + delay.get_interp_1616(shift + md * xl); // + delay.get_interp_1616(shift + md * 65536 + pdelta - md * yl); + float out_lo_r = in_mono + delay.get_interp_1616(shift + md * yl); // - delay.get_interp_1616(shift + pdelta + md * yl); + + out_hi_l = crossover2l.process(out_hi_l); // sanitize(out_hi_l); + out_hi_r = crossover2r.process(out_hi_r); // sanitize(out_hi_r); + out_lo_l = crossover1l.process(out_lo_l); // sanitize(out_lo_l); + out_lo_r = crossover1r.process(out_lo_r); // sanitize(out_lo_r); + + float out_l = out_hi_l + out_lo_l; + float out_r = out_hi_r + out_lo_r; + + float mic_l = out_l + mix * (out_r - out_l); + float mic_r = out_r + mix * (out_l - out_r); + + outs[0][i + offset] = mic_l * 0.5f; + outs[1][i + offset] = mic_r * 0.5f; + delay.put(in_mono); + phase_l += dphase_l; + phase_h += dphase_h; + } + crossover1l.sanitize(); + crossover1r.sanitize(); + crossover2l.sanitize(); + crossover2r.sanitize(); + float delta = nsamples * 1.0 / srate; + if (vibrato_mode == 5) + update_speed_manual(delta); + else + { + bool u1 = incr_towards(aspeed_l, dspeed, delta * 0.2, delta * 0.14); + bool u2 = incr_towards(aspeed_h, dspeed, delta, delta * 0.5); + if (u1 || u2) + set_vibrato(); + } + if(params[par_meter_l] != NULL) { + *params[par_meter_l] = (float)meter_l / 65536.0; + } + if(params[par_meter_h] != NULL) { + *params[par_meter_h] = (float)meter_h / 65536.0; + } + return outputs_mask; +} + +/////////////////////////////////////////////////////////////////////////////////////////////// + +multichorus_audio_module::multichorus_audio_module() +{ + is_active = false; + last_r_phase = -1; +} + +void multichorus_audio_module::activate() +{ + is_active = true; + params_changed(); +} + +void multichorus_audio_module::deactivate() +{ + is_active = false; +} + +void multichorus_audio_module::set_sample_rate(uint32_t sr) { + srate = sr; + left.setup(sr); + right.setup(sr); +} + +bool multichorus_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const +{ + if (!is_active) + return false; + int nvoices = (int)*params[par_voices]; + if (index == par_delay && subindex < 3) + { + if (subindex < 2) + set_channel_color(context, subindex); + else { + context->set_source_rgba(0.35, 0.4, 0.2); + context->set_line_width(1.0); + } + return ::get_graph(*this, subindex, data, points); + } + if (index == par_rate && subindex < nvoices) { + const sine_multi_lfo &lfo = left.lfo; + for (int i = 0; i < points; i++) { + float phase = i * 2 * M_PI / points; + // original -65536 to 65535 value + float orig = subindex * lfo.voice_offset + ((lfo.voice_depth >> (30-13)) * 65536.0 * (0.95 * sin(phase) + 1)/ 8192.0) - 65536; + // scale to -1..1 + data[i] = orig / 65536.0; + } + return true; + } + return false; +} + +bool multichorus_audio_module::get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context) const +{ + int voice = subindex >> 1; + int nvoices = (int)*params[par_voices]; + if ((index != par_rate && index != par_depth) || voice >= nvoices) + return false; + + float unit = (1 - *params[par_overlap]); + float scw = 1 + unit * (nvoices - 1); + set_channel_color(context, subindex); + const sine_multi_lfo &lfo = (subindex & 1 ? right : left).lfo; + if (index == par_rate) + { + x = (double)(lfo.phase + lfo.vphase * voice) / 4096.0; + y = 0.95 * sin(x * 2 * M_PI); + y = (voice * unit + (y + 1) / 2) / scw * 2 - 1; + } + else + { + double ph = (double)(lfo.phase + lfo.vphase * voice) / 4096.0; + x = 0.5 + 0.5 * sin(ph * 2 * M_PI); + y = subindex & 1 ? -0.75 : 0.75; + x = (voice * unit + x) / scw; + } + return true; +} + +bool multichorus_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const +{ + if (index == par_rate && !subindex) + { + pos = 0; + vertical = false; + return true; + } + if (index == par_delay) + return get_freq_gridline(subindex, pos, vertical, legend, context); + return false; +} + +float multichorus_audio_module::freq_gain(int subindex, float freq, float srate) const +{ + if (subindex == 2) + return *params[par_amount] * left.post.freq_gain(freq, srate); + return (subindex ? right : left).freq_gain(freq, srate); +} + +void multichorus_audio_module::params_changed() +{ + // delicious copy-pasta from flanger module - it'd be better to keep it common or something + float dry = *params[par_dryamount]; + float wet = *params[par_amount]; + float rate = *params[par_rate]; + float min_delay = *params[par_delay] / 1000.0; + float mod_depth = *params[par_depth] / 1000.0; + float overlap = *params[par_overlap]; + left.set_dry(dry); right.set_dry(dry); + left.set_wet(wet); right.set_wet(wet); + left.set_rate(rate); right.set_rate(rate); + left.set_min_delay(min_delay); right.set_min_delay(min_delay); + left.set_mod_depth(mod_depth); right.set_mod_depth(mod_depth); + int voices = (int)*params[par_voices]; + left.lfo.set_voices(voices); right.lfo.set_voices(voices); + left.lfo.set_overlap(overlap);right.lfo.set_overlap(overlap); + float vphase = *params[par_vphase] * (1.f / 360.f); + left.lfo.vphase = right.lfo.vphase = vphase * (4096 / std::max(voices - 1, 1)); + float r_phase = *params[par_stereo] * (1.f / 360.f); + if (fabs(r_phase - last_r_phase) > 0.0001f) { + right.lfo.phase = left.lfo.phase; + right.lfo.phase += chorus_phase(r_phase * 4096); + last_r_phase = r_phase; + } + left.post.f1.set_bp_rbj(*params[par_freq], *params[par_q], srate); + left.post.f2.set_bp_rbj(*params[par_freq2], *params[par_q], srate); + right.post.f1.copy_coeffs(left.post.f1); + right.post.f2.copy_coeffs(left.post.f2); +} + +uint32_t multichorus_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) +{ + left.process(outs[0] + offset, ins[0] + offset, numsamples); + right.process(outs[1] + offset, ins[1] + offset, numsamples); + return outputs_mask; // XXXKF allow some delay after input going blank +} + +/// Pulsator by Markus Schmidt +/// +/// This module provides a couple +/// of different LFO's for modulating the level of a signal. +/////////////////////////////////////////////////////////////////////////////////////////////// + +pulsator_audio_module::pulsator_audio_module() +{ + is_active = false; + srate = 0; +// last_generation = 0; + clip_inL = 0.f; + clip_inR = 0.f; + clip_outL = 0.f; + clip_outR = 0.f; + meter_inL = 0.f; + meter_inR = 0.f; + meter_outL = 0.f; + meter_outR = 0.f; +} + +void pulsator_audio_module::activate() +{ + is_active = true; + lfoL.activate(); + lfoR.activate(); + params_changed(); +} +void pulsator_audio_module::deactivate() +{ + is_active = false; + lfoL.deactivate(); + lfoR.deactivate(); +} + +void pulsator_audio_module::params_changed() +{ + lfoL.set_params(*params[param_freq], *params[param_mode], 0.f, srate, *params[param_amount]); + lfoR.set_params(*params[param_freq], *params[param_mode], *params[param_offset], srate, *params[param_amount]); + clear_reset = false; + if (*params[param_reset] >= 0.5) { + clear_reset = true; + lfoL.set_phase(0.f); + lfoR.set_phase(0.f); + } +} + +void pulsator_audio_module::set_sample_rate(uint32_t sr) +{ + srate = sr; +} + +uint32_t pulsator_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) +{ + bool bypass = *params[param_bypass] > 0.5f; + uint32_t samples = numsamples + offset; + if(bypass) { + // everything bypassed + while(offset < samples) { + outs[0][offset] = ins[0][offset]; + outs[1][offset] = ins[1][offset]; + ++offset; + } + // displays, too + clip_inL = 0.f; + clip_inR = 0.f; + clip_outL = 0.f; + clip_outR = 0.f; + meter_inL = 0.f; + meter_inR = 0.f; + meter_outL = 0.f; + meter_outR = 0.f; + + // LFO's should go on + lfoL.advance(numsamples); + lfoR.advance(numsamples); + + } else { + + clip_inL -= std::min(clip_inL, numsamples); + clip_inR -= std::min(clip_inR, numsamples); + clip_outL -= std::min(clip_outL, numsamples); + clip_outR -= std::min(clip_outR, numsamples); + meter_inL = 0.f; + meter_inR = 0.f; + meter_outL = 0.f; + meter_outR = 0.f; + + // process + while(offset < samples) { + // cycle through samples + float outL = 0.f; + float outR = 0.f; + float inL = ins[0][offset]; + float inR = ins[1][offset]; + // in level + inR *= *params[param_level_in]; + inL *= *params[param_level_in]; + + if(*params[param_mono] > 0.5) { + inL = (inL + inR) * 0.5; + inR = inL; + } + float procL = inL; + float procR = inR; + + procL *= (lfoL.get_value() * 0.5 + *params[param_amount] / 2); + procR *= (lfoR.get_value() * 0.5 + *params[param_amount] / 2); + + outL = procL + inL * (1 - *params[param_amount]); + outR = procR + inR * (1 - *params[param_amount]); + + outL *= *params[param_level_out]; + outR *= *params[param_level_out]; + + // send to output + outs[0][offset] = outL; + outs[1][offset] = outR; + + // clip LED's + if(inL > 1.f) { + clip_inL = srate >> 3; + } + if(inR > 1.f) { + clip_inR = srate >> 3; + } + if(outL > 1.f) { + clip_outL = srate >> 3; + } + if(outR > 1.f) { + clip_outR = srate >> 3; + } + // set up in / out meters + if(inL > meter_inL) { + meter_inL = inL; + } + if(inR > meter_inR) { + meter_inR = inR; + } + if(outL > meter_outL) { + meter_outL = outL; + } + if(outR > meter_outR) { + meter_outR = outR; + } + + // next sample + ++offset; + + // advance lfo's + lfoL.advance(1); + lfoR.advance(1); + } // cycle trough samples + } + // draw meters + SET_IF_CONNECTED(clip_inL) + SET_IF_CONNECTED(clip_inR) + SET_IF_CONNECTED(clip_outL) + SET_IF_CONNECTED(clip_outR) + SET_IF_CONNECTED(meter_inL) + SET_IF_CONNECTED(meter_inR) + SET_IF_CONNECTED(meter_outL) + SET_IF_CONNECTED(meter_outR) + // whatever has to be returned x) + return outputs_mask; +} + +bool pulsator_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const +{ + if (!is_active) { + return false; + } else if(index == param_freq) { + if(subindex == 0) { + context->set_source_rgba(0.35, 0.4, 0.2, 1); + return lfoL.get_graph(data, points, context); + } + if(subindex == 1) { + context->set_source_rgba(0.35, 0.4, 0.2, 0.5); + return lfoR.get_graph(data, points, context); + } + } + return false; +} + +bool pulsator_audio_module::get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context) const +{ + if (!is_active) { + return false; + } else if(index == param_freq) { + if(subindex == 0) { + context->set_source_rgba(0.35, 0.4, 0.2, 1); + return lfoL.get_dot(x, y, size, context); + } + if(subindex == 1) { + context->set_source_rgba(0.35, 0.4, 0.2, 0.5); + return lfoR.get_dot(x, y, size, context); + } + return false; + } + return false; +} + +bool pulsator_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const +{ + if (index == param_freq && !subindex) + { + pos = 0; + vertical = false; + return true; + } + return false; +} diff --git a/plugins/ladspa_effect/calf/src/modules_small.cpp b/plugins/ladspa_effect/calf/src/modules_small.cpp deleted file mode 100644 index 24e141819..000000000 --- a/plugins/ladspa_effect/calf/src/modules_small.cpp +++ /dev/null @@ -1,1916 +0,0 @@ -/* Calf DSP Library - * Small modules for modular synthesizers - * - * Copyright (C) 2001-2008 Krzysztof Foltman - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this program; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef ENABLE_EXPERIMENTAL - -#if USE_LV2 -#define LV2_SMALL_WRAPPER(mod, name) static calf_plugins::lv2_small_wrapper lv2_small_##mod(name); -#else -#define LV2_SMALL_WRAPPER(...) -#endif - -#define SMALL_WRAPPERS(mod, name) LV2_SMALL_WRAPPER(mod, name) - -#if USE_LV2 - -using namespace calf_plugins; -using namespace dsp; -using namespace std; - -template LV2_Descriptor lv2_small_wrapper::descriptor; -template uint32_t lv2_small_wrapper::poly_port_types; - -namespace small_plugins -{ - -class filter_base: public null_small_audio_module -{ -public: - enum { in_signal, in_cutoff, in_resonance, in_count }; - enum { out_signal, out_count}; - float *ins[in_count]; - float *outs[out_count]; - static void port_info(plugin_info_iface *pii) - { - pii->audio_port("in", "In").input(); - pii->control_port("cutoff", "Cutoff", 1000).input().log_range(20, 20000); - pii->control_port("res", "Resonance", 0.707).input().log_range(0.707, 20); - pii->audio_port("out", "Out").output(); - } - dsp::biquad_d1 filter; - - void activate() { - filter.reset(); - } - inline void process_inner(uint32_t count) { - for (uint32_t i = 0; i < count; i++) - outs[out_signal][i] = filter.process(ins[in_signal][i]); - filter.sanitize(); - } -}; - -class lp_filter_audio_module: public filter_base -{ -public: - inline void process(uint32_t count) { - filter.set_lp_rbj(clip(*ins[in_cutoff], 0.0001, 0.48 * srate), *ins[in_resonance], srate); - process_inner(count); - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("lowpass12", "12dB/oct RBJ Lowpass", "lv2:LowpassPlugin"); - port_info(pii); - } -}; - -class hp_filter_audio_module: public filter_base -{ -public: - inline void process(uint32_t count) { - filter.set_hp_rbj(clip(*ins[in_cutoff], 0.0001, 0.48 * srate), *ins[in_resonance], srate); - process_inner(count); - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("highpass12", "12dB/oct RBJ Highpass", "lv2:HighpassPlugin"); - port_info(pii); - } -}; - -class bp_filter_audio_module: public filter_base -{ -public: - inline void process(uint32_t count) { - filter.set_bp_rbj(clip(*ins[in_cutoff], 0.0001, 0.48 * srate), *ins[in_resonance], srate); - process_inner(count); - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("bandpass6", "6dB/oct RBJ Bandpass", "lv2:BandpassPlugin"); - port_info(pii); - } -}; - -class br_filter_audio_module: public filter_base -{ -public: - inline void process(uint32_t count) { - filter.set_br_rbj(clip(*ins[in_cutoff], 0.0001, 0.48 * srate), *ins[in_resonance], srate); - process_inner(count); - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("notch6", "6dB/oct RBJ Bandpass", "lv2:FilterPlugin"); - port_info(pii); - } -}; - -class onepole_filter_base: public null_small_audio_module -{ -public: - enum { in_signal, in_cutoff, in_count }; - enum { out_signal, out_count}; - float *ins[in_count]; - float *outs[out_count]; - dsp::onepole filter; - static parameter_properties param_props[]; - - static void port_info(plugin_info_iface *pii) - { - pii->audio_port("In", "in").input(); - pii->control_port("Cutoff", "cutoff", 1000).input().log_range(20, 20000); - pii->audio_port("Out", "out").output(); - } - /// do not export mode and inertia as CVs, as those are settings and not parameters - void activate() { - filter.reset(); - } -}; - -class onepole_lp_filter_audio_module: public onepole_filter_base -{ -public: - void process(uint32_t count) { - filter.set_lp(clip(*ins[in_cutoff], 0.0001, 0.48 * srate), srate); - for (uint32_t i = 0; i < count; i++) - outs[0][i] = filter.process_lp(ins[0][i]); - filter.sanitize(); - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("lowpass6", "6dB/oct Lowpass Filter", "lv2:LowpassPlugin"); - port_info(pii); - } -}; - -class onepole_hp_filter_audio_module: public onepole_filter_base -{ -public: - void process(uint32_t count) { - filter.set_hp(clip(*ins[in_cutoff], 0.0001, 0.48 * srate), srate); - for (uint32_t i = 0; i < count; i++) - outs[0][i] = filter.process_hp(ins[0][i]); - filter.sanitize(); - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("highpass6", "6dB/oct Highpass Filter", "lv2:HighpassPlugin"); - port_info(pii); - } -}; - -class onepole_ap_filter_audio_module: public onepole_filter_base -{ -public: - void process(uint32_t count) { - filter.set_ap(clip(*ins[in_cutoff], 0.0001, 0.48 * srate), srate); - for (uint32_t i = 0; i < count; i++) - outs[0][i] = filter.process_ap(ins[0][i]); - filter.sanitize(); - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("allpass", "1-pole 1-zero Allpass Filter", "lv2:AllpassPlugin"); - port_info(pii); - } -}; - -/// This works for 1 or 2 operands only... -template -class audio_operator_audio_module: public small_audio_module_base -{ -public: - static void port_info(plugin_info_iface *pii) - { - if (Inputs == 1) - pii->audio_port("in", "In", "").input(); - else - { - pii->audio_port("in_1", "In 1", "").input(); - pii->audio_port("in_2", "In 2", "").input(); - } - pii->audio_port("out", "Out", "").output(); - } -}; - -class min_audio_module: public audio_operator_audio_module<2> -{ -public: - void process(uint32_t count) { - for (uint32_t i = 0; i < count; i++) - outs[0][i] = std::min(ins[0][i], ins[1][i]); - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("min", "Minimum (A)", "kf:MathOperatorPlugin", "min"); - port_info(pii); - } -}; - -class max_audio_module: public audio_operator_audio_module<2> -{ -public: - void process(uint32_t count) { - for (uint32_t i = 0; i < count; i++) - outs[0][i] = std::max(ins[0][i], ins[1][i]); - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("max", "Maximum (A)", "kf:MathOperatorPlugin", "max"); - port_info(pii); - } -}; - -class minus_audio_module: public audio_operator_audio_module<2> -{ -public: - void process(uint32_t count) { - for (uint32_t i = 0; i < count; i++) - outs[0][i] = ins[0][i] - ins[1][i]; - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("minus", "Subtract (A)", "kf:MathOperatorPlugin", "-"); - port_info(pii); - } -}; - -class mul_audio_module: public audio_operator_audio_module<2> -{ -public: - void process(uint32_t count) { - for (uint32_t i = 0; i < count; i++) - outs[0][i] = ins[0][i] * ins[1][i]; - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("mul", "Multiply (A)", "kf:MathOperatorPlugin", "*"); - port_info(pii); - } -}; - -class neg_audio_module: public audio_operator_audio_module<1> -{ -public: - void process(uint32_t count) { - for (uint32_t i = 0; i < count; i++) - outs[0][i] = -ins[0][i]; - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("neg", "Negative (A)", "kf:MathOperatorPlugin", "-"); - port_info(pii); - } -}; - -template struct polymorphic_process; - -template struct polymorphic_process -{ - static inline void run(float **ins, float **outs, uint32_t count, uint32_t poly_port_types) { - if (poly_port_types < 2) // control to control or audio to control - *outs[0] = T::process_single(*ins[0]); - else if (poly_port_types == 2) { - outs[0][0] = T::process_single(ins[0][0]); // same as above, but the index might not be 0 in later versions - for (uint32_t i = 1; i < count; i++) - outs[0][i] = outs[0][0]; - } - else { // audio to audio - for (uint32_t i = 0; i < count; i++) - outs[0][i] = T::process_single(ins[0][i]); - } - }; -}; - -template struct polymorphic_process -{ - static inline void run(float **ins, float **outs, uint32_t count, uint32_t poly_port_types) { - poly_port_types &= ~1; - if (poly_port_types < 4) // any to control - *outs[0] = T::process_single(*ins[0], *ins[1]); - else if (poly_port_types == 4) { // control+control to audio - outs[0][0] = T::process_single(*ins[0], *ins[1]); // same as above, but the index might not be 0 in later versions - for (uint32_t i = 1; i < count; i++) - outs[0][i] = outs[0][0]; - } - else { // {control+audio or audio+control or audio+audio} to audio - // use masks to force 0 for index for control ports - uint32_t mask1 = null_small_audio_module::port_audio_mask(0, poly_port_types); - uint32_t mask2 = null_small_audio_module::port_audio_mask(1, poly_port_types); - for (uint32_t i = 0; i < count; i++) - outs[0][i] = T::process_single(ins[0][i & mask1], ins[1][i & mask2]); - } - }; -}; - -/// This works for 1 or 2 operands only... -template -class control_operator_audio_module: public small_audio_module_base -{ -public: - using small_audio_module_base::ins; - using small_audio_module_base::outs; - using small_audio_module_base::poly_port_types; - static void port_info(plugin_info_iface *pii, control_port_info_iface *cports[Inputs + 1], float in1 = 0, float in2 = 0) - { - int idx = 0; - if (Inputs == 1) - cports[idx++] = &pii->control_port("in", "In", in1, "").polymorphic().poly_audio().input(); - else - { - cports[idx++] = &pii->control_port("in_1", "In 1", in1, "").polymorphic().poly_audio().input(); - cports[idx++] = &pii->control_port("in_2", "In 2", in2, "").polymorphic().poly_audio().input(); - } - cports[idx++] = &pii->control_port("out", "Out", 0, "").poly_audio().output(); - } - - template inline void do_process(uint32_t count) { - polymorphic_process::run(ins, outs, count, poly_port_types); - } -}; - -class minus_c_audio_module: public control_operator_audio_module<2> -{ -public: - static inline float process_single(float x, float y) { - return x - y; - } - void process(uint32_t count) { - do_process(count); - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("minus_c", "Subtract (C)", "kf:MathOperatorPlugin", "-"); - control_port_info_iface *cports[3]; - port_info(pii, cports); - } -}; - -class mul_c_audio_module: public control_operator_audio_module<2> -{ -public: - static inline float process_single(float x, float y) { - return x * y; - } - void process(uint32_t count) { - do_process(count); - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("mul_c", "Multiply (C)", "kf:MathOperatorPlugin", "*"); - control_port_info_iface *cports[3]; - port_info(pii, cports); - } -}; - -class neg_c_audio_module: public control_operator_audio_module<1> -{ -public: - static inline float process_single(float x) { - return -x; - } - void process(uint32_t count) { - do_process(count); - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("neg_c", "Negative (C)", "kf:MathOperatorPlugin", "-"); - control_port_info_iface *cports[2]; - port_info(pii, cports); - } -}; - -class min_c_audio_module: public control_operator_audio_module<2> -{ -public: - static inline float process_single(float x, float y) { - return std::min(x, y); - } - void process(uint32_t count) { - do_process(count); - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("min_c", "Minimum (C)", "kf:MathOperatorPlugin", "min"); - control_port_info_iface *cports[3]; - port_info(pii, cports); - } -}; - -class max_c_audio_module: public control_operator_audio_module<2> -{ -public: - static inline float process_single(float x, float y) { - return std::max(x, y); - } - void process(uint32_t count) { - do_process(count); - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("max_c", "Maximum (C)", "kf:MathOperatorPlugin", "max"); - control_port_info_iface *cports[3]; - port_info(pii, cports); - } -}; - -class less_c_audio_module: public control_operator_audio_module<2> -{ -public: - static inline float process_single(float x, float y) { - return x < y; - } - void process(uint32_t count) { - do_process(count); - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("less_c", "Less than (C)", "kf:MathOperatorPlugin", "<"); - control_port_info_iface *cports[2]; - port_info(pii, cports); - cports[2]->toggle(); - } -}; - -class level2edge_c_audio_module: public control_operator_audio_module<1> -{ -public: - bool last_value; - void activate() { - last_value = false; - } - void process(uint32_t count) { - *outs[0] = (*ins[0] > 0 && !last_value) ? 1.f : 0.f; - last_value = *ins[0] > 0; - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("level2edge_c", "Level to edge (C)", "kf:BooleanPlugin"); - control_port_info_iface *cports[2]; - port_info(pii, cports); - cports[0]->toggle(); - cports[1]->toggle().trigger(); - } -}; - -class int_c_audio_module: public control_operator_audio_module<1> -{ -public: - static inline float process_single(float x) { - return (int)x; - } - void process(uint32_t count) { - do_process(count); - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("int_c", "Integer value (C)", "kf:IntegerPlugin"); - control_port_info_iface *cports[2]; - port_info(pii, cports); - cports[0]->integer(); - cports[1]->integer(); - } -}; - -class bitwise_op_c_module_base: public control_operator_audio_module<2> -{ -public: - static void port_info(plugin_info_iface *pii) - { - pii->control_port("in_1", "In 1", 0, "").polymorphic().poly_audio().integer().input(); - pii->control_port("in_2", "In 2", 0, "").polymorphic().poly_audio().integer().input(); - pii->control_port("out", "Out", 0, "").polymorphic().poly_audio().integer().output(); - } -}; -class bit_and_c_audio_module: public bitwise_op_c_module_base -{ -public: - static inline float process_single(float x, float y) { - return ((int)x) & ((int)y); - } - void process(uint32_t count) { - do_process(count); - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("bit_and_c", "Bitwise AND (C)", "kf:IntegerPlugin"); - port_info(pii); - } -}; - -class bit_or_c_audio_module: public bitwise_op_c_module_base -{ -public: - static inline float process_single(float x, float y) { - return ((int)x) | ((int)y); - } - void process(uint32_t count) { - do_process(count); - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("bit_or_c", "Bitwise OR (C)", "kf:IntegerPlugin"); - port_info(pii); - } -}; - -class bit_xor_c_audio_module: public bitwise_op_c_module_base -{ -public: - static inline float process_single(float x, float y) { - return ((int)x) ^ ((int)y); - } - void process(uint32_t count) { - do_process(count); - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("bit_xor_c", "Bitwise XOR (C)", "kf:IntegerPlugin"); - port_info(pii); - } -}; - -class flipflop_c_audio_module: public control_operator_audio_module<1> -{ -public: - bool last_value, output; - void activate() { - last_value = false; - output = false; - } - void process(uint32_t count) { - if (*ins[0] > 0 && !last_value) - output = !output; - *outs[0] = output ? 1.f : 0.f; - last_value = *ins[0] > 0; - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("flipflop_c", "T Flip-Flop (C)", "kf:BooleanPlugin"); - control_port_info_iface *cports[2]; - port_info(pii, cports); - cports[0]->toggle().trigger(); - cports[1]->toggle(); - } -}; - -class logical_and_c_audio_module: public control_operator_audio_module<2> -{ -public: - static inline float process_single(float x, float y) { - return (x > 0 && y > 0) ? 1.f : 0.f; - } - void process(uint32_t count) { - do_process(count); - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("logical_and_c", "Logical AND (C)", "kf:BooleanPlugin", "&&"); - control_port_info_iface *cports[3]; - port_info(pii, cports); - cports[0]->toggle(); - cports[1]->toggle(); - cports[2]->toggle(); - } -}; - -class logical_or_c_audio_module: public control_operator_audio_module<2> -{ -public: - static inline float process_single(float x, float y) { - return (x > 0 || y > 0) ? 1.f : 0.f; - } - void process(uint32_t count) { - do_process(count); - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("logical_or_c", "Logical OR (C)", "kf:BooleanPlugin", "||"); - control_port_info_iface *cports[3]; - port_info(pii, cports); - cports[0]->toggle(); - cports[1]->toggle(); - cports[2]->toggle(); - } -}; - -class logical_xor_c_audio_module: public control_operator_audio_module<2> -{ -public: - static inline float process_single(float x, float y) { - return ((x > 0) != (y > 0)) ? 1.f : 0.f; - } - void process(uint32_t count) { - do_process(count); - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("logical_xor_c", "Logical XOR (C)", "kf:BooleanPlugin", "xor"); - control_port_info_iface *cports[3]; - port_info(pii, cports); - cports[0]->toggle(); - cports[1]->toggle(); - cports[2]->toggle(); - } -}; - -class logical_not_c_audio_module: public control_operator_audio_module<1> -{ -public: - static inline float process_single(float x) { - return (x <= 0) ? 1.f : 0.f; - } - void process(uint32_t count) { - do_process(count); - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("logical_not_c", "Logical NOT (C)", "kf:BooleanPlugin", "!"); - control_port_info_iface *cports[2]; - port_info(pii, cports); - cports[0]->toggle(); - cports[1]->toggle(); - } -}; - -/// converter of trigger signals from audio to control rate -class trigger_a2c_audio_module: public null_small_audio_module -{ -public: - enum { in_count = 1, out_count = 1 }; - float *ins[in_count]; - float *outs[out_count]; - void process(uint32_t count) { - for (uint32_t i = 0; i < count; i++) - { - if (ins[0][i] > 0) - { - *outs[0] = 1.f; - return; - } - } - *outs[0] = 0.f; - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("trigger_a2c", "Audio-to-control OR", "kf:BooleanPlugin", "ta2c"); - pii->audio_port("in", "In").input(); - pii->control_port("out", "Out", 0.f).output().toggle(); - } -}; - -/// Monostable multivibrator like 74121 or 74123, with reset input, progress output (0 to 1), "finished" signal, configurable to allow or forbid retriggering. -class timer_c_audio_module: public null_small_audio_module -{ -public: - enum { in_trigger, in_time, in_reset, in_allow_retrig, in_count }; - enum { out_running, out_finished, out_progress, out_count }; - float *ins[in_count]; - float *outs[out_count]; - bool running, finished, old_trigger; - double state; - - void activate() - { - state = 0.f; - running = false; - finished = false; - old_trigger = false; - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("timer_c", "Timer (C)", "lv2:UtilityPlugin"); - pii->control_port("trigger", "Trigger", 0.f).input().toggle().trigger(); - pii->control_port("time", "Time", 0.f).input(); - pii->control_port("reset", "Reset", 0).input().toggle(); - pii->control_port("allow_retrig", "Allow retrig", 0).input().toggle(); - pii->control_port("running", "Running", 0.f).output().toggle(); - pii->control_port("finished", "Finished", 0.f).output().toggle(); - pii->control_port("progress", "Progress", 0.f).output().lin_range(0, 1); - } - void process(uint32_t count) - { - // This is a branch city, which is definitely a bad thing. - // Perhaps I'll add a bunch of __builtin_expect hints some day, but somebody would have to start using it first. - if (*ins[in_reset] > 0) - { - state = 0.0; - running = finished = false; - } - else - if (!old_trigger && *ins[in_trigger] > 0 && (!running || *ins[in_allow_retrig] > 0)) - { - state = 0.0; - running = true; - finished = false; - } - else - if (running) - { - float rate = (1.0 / std::max(0.0000001f, *ins[in_time])); - state += rate * odsr * count; - if (state >= 1.0) - { - running = false; - finished = true; - state = 1.0; - } - } - old_trigger = *ins[in_trigger] > 0; - *outs[out_running] = running ? 1.f : 0.f; - *outs[out_finished] = finished ? 1.f : 0.f; - *outs[out_progress] = state; - } -}; - -/// 4-input priority multiplexer - without inertia. Outputs the first input if gate_1 is true, else second input if gate_2 is true, else... else "Else" input -class prio_mux_c_audio_module: public null_small_audio_module -{ -public: - enum { in_in1, in_gate1, in_in2, in_gate2, in_in3, in_gate3, in_in4, in_gate4, in_else, in_count }; - enum { out_value, out_count }; - float *ins[in_count]; - float *outs[out_count]; - - static void plugin_info(plugin_info_iface *pii) - { - pii->names("prio_mux_c", "Priority Multiplexer (C)", "kf:BooleanPlugin"); - for (int i = 1; i <= 4; i++) - { - stringstream numb; - numb << i; - string num = numb.str(); - pii->control_port("in_"+num, "In "+num, 0.f).input(); - pii->control_port("gate_"+num, "Gate "+num, 0.f).input().toggle(); - } - pii->control_port("in_else", "Else", 0.f).input(); - pii->control_port("out", "Out", 0.f).output(); - } - void process(uint32_t count) - { - for (int i = 0; i < 4; i++) - { - if (*ins[i * 2 + in_gate1] > 0) - { - *outs[out_value] = *ins[i * 2 + in_in1]; - return; - } - } - *outs[out_value] = *ins[in_else]; - } -}; - -/// 8-input priority encoder - outputs the index of the first port whose value is >0. 'Any' output is set whenever any of gates is set (which tells -/// apart no inputs set and 0th input set). -template -class prio_enc_c_audio_module: public null_small_audio_module -{ -public: - enum { in_gate1, in_count = in_gate1 + N}; - enum { out_value, out_any, out_count }; - float *ins[in_count]; - float *outs[out_count]; - - static void plugin_info(plugin_info_iface *pii) - { - char buf[32], buf2[64]; - sprintf(buf, "prio_enc%d_c", N); - sprintf(buf2, "%d-input Priority Encoder (C)", N); - pii->names(buf, buf2, "kf:IntegerPlugin"); - for (int i = 0; i < N; i++) - { - stringstream numb; - numb << i; - string num = numb.str(); - pii->control_port("gate_"+num, "Gate "+num, 0.f).input().toggle(); - } - pii->control_port("out", "Out", -1).output().integer(); - pii->control_port("any", "Any", -1).output().toggle(); - } - void process(uint32_t count) - { - for (int i = 0; i < N; i++) - { - if (*ins[in_gate1 + i] > 0) - { - *outs[out_value] = i; - *outs[out_any] = 1; - return; - } - } - *outs[out_value] = 0; - *outs[out_any] = 0; - } -}; - -typedef prio_enc_c_audio_module<8> prio_enc8_c_audio_module; - -/// 8-input integer multiplexer, outputs the input selected by ((int)select input & 7) -template -class mux_c_audio_module: public null_small_audio_module -{ -public: - enum { in_select, in_in1, in_count = in_in1 + N}; - enum { out_value, out_count }; - float *ins[in_count]; - float *outs[out_count]; - - static void plugin_info(plugin_info_iface *pii) - { - char buf[32], buf2[64]; - sprintf(buf, "mux%d_c", N); - sprintf(buf2, "%d-input Multiplexer (C)", N); - pii->names(buf, buf2, "kf:IntegerPlugin"); - pii->control_port("select", "Select", 0.f).input().integer().lin_range(0, N - 1); - for (int i = 0; i < N; i++) - { - stringstream numb; - numb << i; - string num = numb.str(); - pii->control_port("in_"+num, "In "+num, 0.f).input(); - } - pii->control_port("out", "Out", -1).output(); - } - void process(uint32_t count) - { - *outs[out_value] = *ins[in_in1 + ((N - 1) & (int)*ins[in_select])]; - } -}; - -typedef mux_c_audio_module<4> mux4_c_audio_module; -typedef mux_c_audio_module<8> mux8_c_audio_module; -typedef mux_c_audio_module<16> mux16_c_audio_module; - -/// Linear-to-exponential mapper -class map_lin2exp_audio_module: public null_small_audio_module -{ -public: - enum { in_signal, in_from_min, in_from_max, in_to_min, in_to_max, in_count }; - enum { out_signal, out_count }; - float *ins[in_count]; - float *outs[out_count]; - - static void plugin_info(plugin_info_iface *pii) - { - pii->names("lin2exp", "Lin-Exp Mapper", "lv2:UtilityPlugin"); - pii->control_port("in", "In", 0.f).input(); - pii->control_port("from_min", "Min (from)", 0).input(); - pii->control_port("from_max", "Max (from)", 1).input(); - pii->control_port("to_min", "Min (to)", 20).input(); - pii->control_port("to_max", "Max (to)", 20000).input(); - pii->control_port("out", "Out", 0.f).output(); - } - void process(uint32_t count) - { - float normalized = (*ins[in_signal] - *ins[in_from_min]) / (*ins[in_from_max] - *ins[in_from_min]); - *outs[out_signal] = *ins[in_to_min] * pow(*ins[in_to_max] / *ins[in_to_min], normalized); - } -}; - -/// Schmitt trigger - http://en.wikipedia.org/wiki/Schmitt_trigger - also outputs a change signal (positive spike whenever output value is changed) -class schmitt_c_audio_module: public null_small_audio_module -{ -public: - enum { in_signal, in_low, in_high, in_count }; - enum { out_signal, out_change, out_count }; - float *ins[in_count]; - float *outs[out_count]; - bool state; - - void activate() - { - state = false; - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("schmitt_c", "Schmitt Trigger (C)", "kf:BooleanPlugin"); - pii->control_port("in", "In", 0.f).input(); - pii->control_port("low", "Low threshold", 0).input(); - pii->control_port("high", "High threshold", 0.5).input(); - pii->control_port("out", "Out", 0.f).output(); - pii->control_port("change", "Change", 0.f).output(); - } - void process(uint32_t count) - { - float value = *ins[in_signal]; - bool new_state = state; - if (value <= *ins[in_low]) - new_state = false; - if (value >= *ins[in_high]) - new_state = true; - *outs[out_signal] = new_state ? 1.f : 0.f; - *outs[out_change] = (new_state != state) ? 1.f : 0.f; - state = new_state; - } -}; - -/// Stateless 'between' operator (lo <= in <= hi) -class between_c_audio_module: public null_small_audio_module -{ -public: - enum { in_signal, in_low, in_high, in_count }; - enum { out_signal, out_count }; - float *ins[in_count]; - float *outs[out_count]; - - static void plugin_info(plugin_info_iface *pii) - { - pii->names("between_c", "Between (C)", "kf:MathOperatorPlugin"); - pii->control_port("in", "In", 0.f).input(); - pii->control_port("low", "Low threshold", 0).input(); - pii->control_port("high", "High threshold", 1).input(); - pii->control_port("out", "Out", 0.f).output(); - } - void process(uint32_t count) - { - float value = *ins[in_signal]; - *outs[out_signal] = (value >= *ins[in_low] && value <= *ins[in_high]) ? 1.f : 0.f; - } -}; - -/// Clip to range -class clip_c_audio_module: public null_small_audio_module -{ -public: - enum { in_signal, in_min, in_max, in_count }; - enum { out_signal, out_count }; - float *ins[in_count]; - float *outs[out_count]; - - static void plugin_info(plugin_info_iface *pii) - { - pii->names("clip_c", "Clip (C)", "kf:MathOperatorPlugin", "clip"); - pii->control_port("in", "In", 0.f).input(); - pii->control_port("min", "Min", 0).input(); - pii->control_port("max", "Max", 1).input(); - pii->control_port("out", "Out", 0.f).output(); - } - void process(uint32_t count) - { - float value = *ins[in_signal]; - *outs[out_signal] = std::min(*ins[in_max], std::max(value, *ins[in_min])); - } -}; - -/// Two input control crossfader -class crossfader2_c_audio_module: public null_small_audio_module -{ -public: - enum { in_a, in_b, in_ctl, in_count }; - enum { out_value, out_count }; - float *ins[in_count]; - float *outs[out_count]; - - static void plugin_info(plugin_info_iface *pii) - { - pii->names("crossfader2_c", "2-in crossfader (C)", "kf:MathOperatorPlugin", "xfC"); - pii->control_port("in_a", "In A", 0.f).input(); - pii->control_port("in_b", "In B", 0).input(); - pii->control_port("mix", "B in mix", 0.5).input(); - pii->control_port("out", "Out", 0.f).output(); - } - void process(uint32_t count) - { - *outs[out_value] = *ins[in_a] + (*ins[in_b] - *ins[in_a]) * dsp::clip(*ins[in_ctl], 0.f, 1.f); - } -}; - -/// 2-input multiplexer (if-then-else) -class ifthenelse_c_audio_module: public null_small_audio_module -{ -public: - enum { in_if, in_then, in_else, in_count }; - enum { out_value, out_count }; - float *ins[in_count]; - float *outs[out_count]; - - static void plugin_info(plugin_info_iface *pii) - { - pii->names("ifthenelse_c", "If-Then-Else (C)", "kf:BooleanPlugin", "if"); - pii->control_port("if", "If", 0.f).input().toggle(); - pii->control_port("then", "Then", 0).input(); - pii->control_port("else", "Else", 0).input(); - pii->control_port("out", "Out", 0.f).output(); - } - void process(uint32_t count) - { - *outs[out_value] = *ins[in_if] > 0 ? *ins[in_then] : *ins[in_else]; - } -}; - -/// Integer counter with definable ranges -class counter_c_audio_module: public null_small_audio_module -{ -public: - enum { in_clock, in_min, in_max, in_steps, in_reset, in_count }; - enum { out_value, out_carry, out_count }; - float *ins[in_count]; - float *outs[out_count]; - bool state; - int value; - - void activate() - { - state = false; - value = 0; - } - - static void plugin_info(plugin_info_iface *pii) - { - pii->names("counter_c", "Counter (C)", "kf:IntegerPlugin", "cnt"); - pii->control_port("clock", "Clock", 0.f).input().toggle().trigger(); - pii->control_port("min", "Min", 0).input(); - pii->control_port("max", "Max", 15).input(); - pii->control_port("steps", "Steps", 16).input().integer(); - pii->control_port("reset", "Reset", 0).input().toggle(); - pii->control_port("out", "Out", 0.f).output(); - pii->control_port("carry", "Carry", 0.f).output().toggle().trigger(); - } - void process(uint32_t count) - { - // Yes, this is slower than it should be. I will bother optimizing it when someone starts actually using it. - if (*ins[in_reset] > 0 || *ins[in_steps] < 2.0) - { - state = false; - value = 0; - *outs[out_value] = *ins[in_min]; - *outs[out_carry] = 0.f; - return; - } - *outs[out_carry] = 0; - if (!state && *ins[in_clock] > 0) - { - value++; - state = true; - if (value >= (int)*ins[in_steps]) - { - value = 0; - *outs[out_carry] = 1; - } - } - else - state = *ins[in_clock] > 0; - *outs[out_value] = *ins[in_min] + (*ins[in_max] - *ins[in_min]) * value / (int)(*ins[in_steps] - 1); - } -}; - -/// Two input audio crossfader -class crossfader2_a_audio_module: public null_small_audio_module -{ -public: - enum { in_a, in_b, in_ctl, in_count }; - enum { out_value, out_count }; - float *ins[in_count]; - float *outs[out_count]; - - static void plugin_info(plugin_info_iface *pii) - { - pii->names("crossfader2_a", "2-in crossfader (A)", "kf:MathOperatorPlugin", "xfA"); - pii->audio_port("in_a", "In A").input(); - pii->audio_port("in_b", "In B").input(); - pii->audio_port("mix", "B in mix").input(); - pii->audio_port("out", "Out").output(); - } - void process(uint32_t count) - { - for (uint32_t i = 0; i < count; i++) - outs[out_value][i] = ins[in_a][i] + (ins[in_b][i] - ins[in_a][i]) * dsp::clip(ins[in_ctl][i], 0.f, 1.f); - } -}; - -/// Base class for LFOs with frequency and reset inputs -class freq_phase_lfo_base: public small_audio_module_base<2, 1> -{ -public: - enum { in_freq, in_reset }; - double phase; - inline void activate() - { - phase = 0; - } - static void port_info(plugin_info_iface *pii) - { - pii->control_port("freq", "Frequency", 1).input().log_range(0.02, 100); - pii->control_port("reset", "Reset", 0).input().toggle(); - pii->control_port("out", "Out", 0).output(); - } - inline void check_inputs() - { - if (*ins[in_reset]) - phase = 0; - } - inline void advance(uint32_t count) - { - phase += count * *ins[in_freq] * odsr; - if (phase >= 1.0) - phase = fmod(phase, 1.0); - } -}; - -class square_lfo_audio_module: public freq_phase_lfo_base -{ -public: - void process(uint32_t count) - { - check_inputs(); - *outs[0] = (phase < 0.5) ? -1 : +1; - advance(count); - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("square_lfo", "Square LFO", "lv2:OscillatorPlugin"); - port_info(pii); - } -}; - -class saw_lfo_audio_module: public freq_phase_lfo_base -{ -public: - void process(uint32_t count) - { - check_inputs(); - *outs[0] = -1 + 2 * phase; - advance(count); - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("saw_lfo", "Saw LFO", "lv2:OscillatorPlugin"); - port_info(pii); - } -}; - -class pulse_lfo_audio_module: public freq_phase_lfo_base -{ -public: - inline void activate() - { - phase = 1.0; - } - void process(uint32_t count) - { - check_inputs(); - double oldphase = phase; - advance(count); - *outs[0] = (phase < oldphase) ? 1.f : 0.f; - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("pulse_lfo", "Pulse LFO", "lv2:OscillatorPlugin"); - port_info(pii); - } -}; - -#define SMALL_OSC_TABLE_BITS 12 - -class freq_only_osc_base_common: public null_small_audio_module -{ -public: - typedef waveform_family waves_type; - enum { in_freq, in_count }; - enum { out_signal, out_count}; - enum { wave_size = 1 << SMALL_OSC_TABLE_BITS }; - float *ins[in_count]; - float *outs[out_count]; - waves_type *waves; - waveform_oscillator osc; - - /// Fill the array with the original, non-bandlimited, waveform - virtual void get_original_waveform(float data[wave_size]) = 0; - /// This function needs to be virtual to ensure a separate wave family for each class (but not each instance) - virtual waves_type *get_waves() = 0; - void activate() { - waves = get_waves(); - } - void process(uint32_t count) - { - osc.set_freq_odsr(*ins[in_freq], odsr); - osc.waveform = waves->get_level(osc.phasedelta); - if (osc.waveform) - { - for (uint32_t i = 0; i < count; i++) - outs[out_signal][i] = osc.get(); - } - else - dsp::zero(outs[out_signal], count); - } - static void port_info(plugin_info_iface *pii) - { - pii->control_port("freq", "Frequency", 440).input().log_range(20, 20000); - pii->audio_port("out", "Out").output(); - } - /// Generate a wave family (bandlimit levels) from the original wave - waves_type *create_waves() { - waves_type *ptr = new waves_type; - float source[wave_size]; - get_original_waveform(source); - bandlimiter bl; - ptr->make(bl, source); - return ptr; - } -}; - -template -class freq_only_osc_base: public freq_only_osc_base_common -{ - virtual waves_type *get_waves() { - static waves_type *waves = NULL; - if (!waves) - waves = create_waves(); - return waves; - } -}; - -class square_osc_audio_module: public freq_only_osc_base -{ -public: - virtual void get_original_waveform(float data[wave_size]) { - for (int i = 0; i < wave_size; i++) - data[i] = (i < wave_size / 2) ? +1 : -1; - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("squareosc", "Square Oscillator", "lv2:OscillatorPlugin"); - port_info(pii); - } -}; - -class saw_osc_audio_module: public freq_only_osc_base -{ -public: - virtual void get_original_waveform(float data[wave_size]) { - for (int i = 0; i < wave_size; i++) - data[i] = (i * 2.0 / wave_size) - 1; - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("sawosc", "Saw Oscillator", "lv2:OscillatorPlugin"); - port_info(pii); - } -}; - -class print_c_audio_module: public small_audio_module_base<1, 0> -{ -public: - static void plugin_info(plugin_info_iface *pii) - { - pii->names("print_c", "Print To Console (C)", "lv2:UtilityPlugin"); - pii->control_port("in", "In", 0).input(); - } - void process(uint32_t) - { - printf("%f\n", *ins[0]); - } -}; - -class print_e_audio_module: public small_audio_module_base<1, 0> -{ -public: - static void plugin_info(plugin_info_iface *pii) - { - pii->names("print_e", "Print To Console (E)", "lv2:UtilityPlugin"); - pii->event_port("in", "In").input(); - } - void dump(LV2_Event_Buffer *event_data) - { - event_port_read_iterator ei(event_data); - while(ei) - { - const lv2_event &event = *ei++; - printf("Event at %d.%d, type %d, size %d:", event.frames, event.subframes, (int)event.type, (int)event.size); - uint32_t size = std::min((uint16_t)16, event.size); - - for (uint32_t j = 0; j < size; j++) - printf(" %02X", (uint32_t)event.data[j]); - if (event.size > size) - printf("...\n"); - else - printf("\n"); - } - } - void process(uint32_t) - { - LV2_Event_Buffer *event_data = (LV2_Event_Buffer *)ins[0]; - dump(event_data); - } -}; - -class print_em_audio_module: public print_e_audio_module -{ -public: - LV2_Event_Buffer *events; - static void plugin_info(plugin_info_iface *pii) - { - pii->names("print_em", "Print To Console (EM)", "lv2:UtilityPlugin"); - pii->lv2_ttl("lv2:requiredFeature ;"); - pii->lv2_ttl("lv2:requiredFeature lv2ctx:MessageContext ;"); - pii->lv2_ttl("lv2ctx:requiredContext lv2ctx:MessageContext ;"); - pii->event_port("in", "In").input().lv2_ttl("lv2ctx:context lv2ctx:MessageContext ;"); - } - void process(uint32_t) - { - } - static uint32_t message_run(LV2_Handle instance, const void *valid_inputs, void *outputs_written) - { - print_em_audio_module *self = (print_em_audio_module *)instance; - if (lv2_contexts_port_is_valid(valid_inputs, 0)) - { - printf("message_run (events = %p, count = %d)\n", self->events, self->events->event_count); - self->dump(self->events); - } - return 0; - } - static void message_connect_port(LV2_Handle instance, uint32_t port, void* data) - { - print_em_audio_module *self = (print_em_audio_module *)instance; - printf("message_connect_port %d -> %p\n", port, data); - assert(!port); - self->events = (LV2_Event_Buffer *)data; - } - static inline const void *ext_data(const char *URI) { - static LV2MessageContext ctx_ext_data = { message_run, message_connect_port }; - printf("URI=%s\n", URI); - if (!strcmp(URI, LV2_CONTEXT_MESSAGE)) - { - return &ctx_ext_data; - } - return NULL; - } -}; - -class copy_em_audio_module: public small_audio_module_base<0, 0> -{ -public: - LV2_Event_Buffer *events_in, *events_out; - static void plugin_info(plugin_info_iface *pii) - { - pii->names("copy_em", "Message pass-through (EM)", "lv2:UtilityPlugin"); - pii->lv2_ttl("lv2:requiredFeature lv2ctx:MessageContext ;"); - pii->lv2_ttl("lv2:requiredFeature ;"); - pii->lv2_ttl("lv2:requiredContext lv2ctx:MessageContext ;"); - pii->event_port("in", "In").input().lv2_ttl("lv2ctx:context lv2ctx:MessageContext ;"); - pii->event_port("out", "Out").output().lv2_ttl("lv2ctx:context lv2ctx:MessageContext ;"); - } - void process(uint32_t) - { - } - static uint32_t message_run(LV2_Handle instance, const void *valid_inputs, void *outputs_written) - { - copy_em_audio_module *self = (copy_em_audio_module *)instance; - return self->message_run(valid_inputs, outputs_written); - } - uint32_t message_run(const void *inputs_written, void *outputs_written) - { - if (lv2_contexts_port_is_valid(inputs_written, 0)) - { - event_port_read_iterator ri(events_in); - event_port_write_iterator wi(events_out); - if (events_in->size > events_out->capacity) - { - printf("Buffer capacity exceeded!\n"); - return false; - } - while(ri) - { - const lv2_event &event = *ri++; - *wi++ = event; - } - if (events_in->event_count != 0) - { - lv2_contexts_set_port_valid(outputs_written, 1); - return 1; - } - } - lv2_contexts_unset_port_valid(outputs_written, 1); - return 0; - } - static void message_connect_port(LV2_Handle instance, uint32_t port, void* data) - { - copy_em_audio_module *self = (copy_em_audio_module *)instance; - printf("message_connect_port %d -> %p\n", port, data); - if (port == 0) self->events_in = (LV2_Event_Buffer *)data; - if (port == 1) self->events_out = (LV2_Event_Buffer *)data; - } - static inline const void *ext_data(const char *URI) { - static LV2MessageContext ctx_ext_data = { message_run, message_connect_port }; - if (!strcmp(URI, LV2_CONTEXT_MESSAGE)) - { - printf("URI=%s\n", URI); - return &ctx_ext_data; - } - return NULL; - } -}; - -template -class miditypefilter_m_audio_module: public midi_mixin > -{ -public: - static inline void extra_inputs(plugin_info_iface *pii) - { - } - static inline const char *plugin_symbol() { return Range::strings()[0]; } - static inline const char *plugin_name() { return Range::strings()[1]; } - static inline const char *port_symbol() { return Range::strings()[2]; } - static inline const char *port_name() { return Range::strings()[3]; } - static void plugin_info(plugin_info_iface *pii) - { - pii->names(Range::plugin_symbol(), Range::plugin_name(), "kf:MIDIPlugin"); - pii->event_port("in", "In").input(); - Range::extra_inputs(pii); - pii->event_port(Range::port_symbol(), Range::port_name()).output(); - pii->event_port("others", "Others").output(); - } - void process(uint32_t) - { - event_port_read_iterator ri((LV2_Event_Buffer *)this->ins[0]); - event_port_write_iterator wi((LV2_Event_Buffer *)this->outs[0]); - event_port_write_iterator wi2((LV2_Event_Buffer *)this->outs[1]); - while(ri) - { - const lv2_event &event = *ri++; - if (event.type == this->midi_event_type && event.size && Range::is_in_range(event.data, this->ins)) - *wi++ = event; - else - *wi2++ = event; - } - } -}; - -class notefilter_m_audio_module: public miditypefilter_m_audio_module -{ -public: - static inline bool is_in_range(const uint8_t *data, float **) { return data[0] >= 0x80 && data[0] <= 0x9F; } - static inline const char **strings() { static const char *s[] = { "notefilter_m", "Note Filter", "note", "Note" }; return s;} -}; - -class pcfilter_m_audio_module: public miditypefilter_m_audio_module -{ -public: - static inline bool is_in_range(const uint8_t *data, float **) { return data[0] >= 0xA0 && data[0] <= 0xAF; } - static inline const char **strings() { static const char *s[] = { "pcfilter_m", "Program Change Filter", "pc", "PC" }; return s;} -}; - -class ccfilter_m_audio_module: public miditypefilter_m_audio_module -{ -public: - static inline bool is_in_range(const uint8_t *data, float **) { return data[0] >= 0xB0 && data[0] <= 0xBF; } - static inline const char **strings() { static const char *s[] = { "ccfilter_m", "Control Change Filter", "cc", "CC" }; return s;} -}; - -class pressurefilter_m_audio_module: public miditypefilter_m_audio_module -{ -public: - static inline bool is_in_range(const uint8_t *data, float **) { return data[0] >= 0xC0 && data[0] <= 0xDF; } - static inline const char **strings() { static const char *s[] = { "pressurefilter_m", "Pressure Filter", "pressure", "Pressure" }; return s;} -}; - -class pitchbendfilter_m_audio_module: public miditypefilter_m_audio_module -{ -public: - static inline bool is_in_range(const uint8_t *data, float **) { return data[0] >= 0xE0 && data[0] <= 0xEF; } - static inline const char **strings() { static const char *s[] = { "pitchbendfilter_m", "Pitch Bend Filter", "pbend", "Pitch Bend" }; return s;} -}; - -class systemfilter_m_audio_module: public miditypefilter_m_audio_module -{ -public: - static inline bool is_in_range(const uint8_t *data, float **) { return data[0] >= 0xF0; } - static inline const char **strings() { static const char *s[] = { "systemfilter_m", "System Msg Filter", "system", "System" }; return s;} -}; - -class channelfilter_m_audio_module: public miditypefilter_m_audio_module -{ -public: - static inline void extra_inputs(plugin_info_iface *pii) - { - pii->control_port("min", "Min Channel", 1).input().integer().lin_range(1, 16); - pii->control_port("max", "Max Channel", 16).input().integer().lin_range(1, 16); - } - static inline bool is_in_range(const uint8_t *data, float **ins) { - int chnl = 1 + (data[0] & 0xF); - return data[0] < 0xF0 && chnl >= *ins[1] && chnl <= *ins[2]; - } - static inline const char **strings() { static const char *s[] = { "channelfilter_m", "Channel Range Filter", "range", "Range" }; return s;} -}; - -class keyfilter_m_audio_module: public miditypefilter_m_audio_module -{ -public: - static inline void extra_inputs(plugin_info_iface *pii) - { - pii->control_port("min", "Min Note", 0).input().integer().lin_range(0, 127); - pii->control_port("max", "Max Note", 127).input().integer().lin_range(0, 127); - } - static inline bool is_in_range(const uint8_t *data, float **ins) { - // XXXKF doesn't handle polyphonic aftertouch - return (data[0] >= 0x80 && data[0] <= 0x9F) && data[0] >= *ins[1] && data[1] <= *ins[2]; - } - static inline const char **strings() { static const char *s[] = { "keyfilter_m", "Key Range Filter", "range", "Range" }; return s;} -}; - -class key_less_than_m_audio_module: public miditypefilter_m_audio_module -{ -public: - static inline void extra_inputs(plugin_info_iface *pii) - { - pii->control_port("threshold", "Threshold", 60).input().integer().lin_range(0, 128); - } - static inline bool is_in_range(const uint8_t *data, float **ins) { - // XXXKF doesn't handle polyphonic aftertouch - return (data[0] >= 0x80 && data[0] <= 0x9F) && data[1] < *ins[1]; - } - static inline const char **strings() { static const char *s[] = { "key_less_than_m", "Key Less-Than Filter", "less", "Less" }; return s;} -}; - -class channel_less_than_m_audio_module: public miditypefilter_m_audio_module -{ -public: - static inline void extra_inputs(plugin_info_iface *pii) - { - pii->control_port("threshold", "Threshold", 10).input().integer().lin_range(1, 16); - } - static inline bool is_in_range(const uint8_t *data, float **ins) { - // XXXKF doesn't handle polyphonic aftertouch - return (data[0] < 0xF0) && (1 + (data[0] & 0xF)) < *ins[1]; - } - static inline const char **strings() { static const char *s[] = { "channel_less_than_m", "Channel Less-Than Filter", "less", "Less" }; return s;} -}; - -class transpose_m_audio_module: public midi_mixin > -{ -public: - static void plugin_info(plugin_info_iface *pii) - { - pii->names("transpose_m", "Transpose", "kf:MIDIPlugin"); - pii->event_port("in", "In").input(); - pii->control_port("transpose", "Transpose", 12).input().integer(); - pii->event_port("out", "Out").output(); - } - void process(uint32_t) - { - event_port_read_iterator ri((LV2_Event_Buffer *)ins[0]); - event_port_write_iterator wi((LV2_Event_Buffer *)outs[0]); - while(ri) - { - const lv2_event &event = *ri++; - if (event.type == this->midi_event_type && event.size == 3 && (event.data[0] >= 0x80 && event.data[0] <= 0x9F)) - { - int new_note = event.data[1] + (int)*ins[1]; - // ignore out-of-range notes - if (new_note >= 0 && new_note <= 127) - { - // it is not possible to create copies here because they are variable length and would "nicely" overwrite the stack - // so write the original event instead, and then modify the pitch - *wi = event; - wi->data[1] = new_note; - wi++; - } - } - else - *wi++ = event; - } - } -}; - -class setchannel_m_audio_module: public midi_mixin > -{ -public: - static void plugin_info(plugin_info_iface *pii) - { - pii->names("setchannel_m", "Set Channel", "kf:MIDIPlugin"); - pii->event_port("in", "In").input(); - pii->control_port("channel", "Channel", 1).input().integer().lin_range(1, 16); - pii->event_port("out", "Out").output(); - } - void process(uint32_t) - { - event_port_read_iterator ri((LV2_Event_Buffer *)ins[0]); - event_port_write_iterator wi((LV2_Event_Buffer *)outs[0]); - while(ri) - { - const lv2_event &event = *ri++; - if (event.type == this->midi_event_type && (event.data[0] >= 0x80 && event.data[0] <= 0xEF)) - { - *wi = event; - // modify channel number in the first byte - wi->data[0] = (wi->data[0] & 0xF0) | (((int)*ins[1] - 1) & 0xF); - wi++; - } - else - *wi++ = event; - } - } -}; - -class eventmerge_e_audio_module: public event_mixin > -{ -public: - static void plugin_info(plugin_info_iface *pii) - { - pii->names("eventmerge_e", "Event Merge (E)", "lv2:UtilityPlugin"); - pii->event_port("in_1", "In 1").input(); - pii->event_port("in_2", "In 2").input(); - pii->event_port("out", "Out").output(); - } - void process(uint32_t) - { - event_port_merge_iterator ri((const LV2_Event_Buffer *)ins[0], (const LV2_Event_Buffer *)ins[1]); - event_port_write_iterator wi((LV2_Event_Buffer *)outs[0]); - while(ri) - *wi++ = *ri++; - } -}; - -class print_a_audio_module: public small_audio_module_base<1, 0> -{ -public: - static void plugin_info(plugin_info_iface *pii) - { - pii->names("print_a", "Print To Console (A)", "lv2:UtilityPlugin"); - pii->audio_port("in", "In").input(); - } - void process(uint32_t) - { - printf("%f\n", *ins[0]); - } -}; - -template -class quadpower_base: public null_small_audio_module -{ -public: - enum { in_value, in_factor, in_count , out_count = 4 }; - float *ins[in_count]; - float *outs[out_count]; - - static void plugin_info(plugin_info_iface *pii) - { - const char *names[8] = {"xa", "x*a^1", "xaa", "x*a^2", "xaaa", "x*a^3", "xaaaa", "x*a^4" }; - if (audio) - pii->names("quadpower_a", "Quad Power (A)", "kf:MathOperatorPlugin"); - else - pii->names("quadpower_c", "Quad Power (C)", "kf:MathOperatorPlugin"); - if (audio) - pii->audio_port("x", "x").input(); - else - pii->control_port("x", "x", 1).input(); - pii->control_port("a", "a", 1).input(); - for (int i = 0; i < 8; i += 2) - if (audio) - pii->audio_port(names[i], names[i+1]).output(); - else - pii->control_port(names[i], names[i+1], 0).output(); - } -}; - -class quadpower_a_audio_module: public quadpower_base -{ -public: - void process(uint32_t count) - { - float a = *ins[in_factor]; - for (uint32_t i = 0; i < count; i++) - { - float x = ins[in_value][i]; - outs[0][i] = x * a; - outs[1][i] = x * a * a; - outs[2][i] = x * a * a * a; - outs[3][i] = x * a * a * a * a; - } - } -}; - -class quadpower_c_audio_module: public quadpower_base -{ -public: - void process(uint32_t) - { - float x = *ins[in_value]; - float a = *ins[in_factor]; - *outs[0] = x * a; - *outs[1] = x * a * a; - *outs[2] = x * a * a * a; - *outs[3] = x * a * a * a * a; - } -}; - -template -class inertia_c_module_base: public small_audio_module_base<3, 1> -{ -public: - enum { in_value, in_inertia, in_immediate }; - bool reset; - inertia state; - inertia_c_module_base() - : state(Ramp(1)) - {} - void activate() - { - reset = true; - } - static void port_info(plugin_info_iface *pii) - { - pii->control_port("in", "In", 0).input(); - pii->control_port("time", "Inertia time", 100).input(); - pii->control_port("reset", "Reset", 0).input().toggle().trigger(); - pii->control_port("out", "Out", 0).output(); - } - void process(uint32_t count) - { - float value = *ins[in_value]; - if (reset || *ins[in_immediate] > 0) - { - *outs[0] = value; - state.set_now(value); - reset = false; - } - else - { - if (value != state.get_last()) - { - state.ramp.set_length(dsp::clip((int)(srate * 0.001 * *ins[in_inertia]), 1, 10000000)); - } - state.set_inertia(value); - *outs[0] = state.get_last(); - if (count) - state.step_many(count); - } - } -}; - -class linear_inertia_c_audio_module: public inertia_c_module_base -{ -public: - static void plugin_info(plugin_info_iface *pii) - { - pii->names("linear_inertia_c", "Linear Inertia (C)", "lv2:FilterPlugin"); - port_info(pii); - } -}; - -class exp_inertia_c_audio_module: public inertia_c_module_base -{ -public: - static void plugin_info(plugin_info_iface *pii) - { - pii->names("exp_inertia_c", "Exponential Inertia (C)", "lv2:FilterPlugin"); - port_info(pii); - } -}; - -class sample_hold_base: public small_audio_module_base<2, 1> -{ -public: - enum { in_value, in_gate }; - static void port_info(plugin_info_iface *pii, const char *clock_symbol, const char *clock_name) - { - pii->control_port("in", "In", 0).input(); - pii->control_port(clock_symbol, clock_name, 0).input().toggle().trigger(); - pii->control_port("out", "Out", 0).output(); - } -}; - -class sample_hold_edge_c_audio_module: public sample_hold_base -{ -public: - bool prev_clock; - float value; - void activate() - { - prev_clock = false; - value = 0; - } - void process(uint32_t count) - { - if (!prev_clock && *ins[in_gate] > 0) - value = *ins[in_value]; - prev_clock = *ins[in_gate] > 0; - *outs[0] = value; - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("sample_hold_edge", "Sample&Hold (Edge, C)", "lv2:UtilityPlugin"); - port_info(pii, "clock", "Clock"); - } -}; - -class sample_hold_level_c_audio_module: public sample_hold_base -{ -public: - float value; - void activate() - { - value = 0; - } - void process(uint32_t count) - { - if (*ins[in_gate] > 0) - value = *ins[in_value]; - *outs[0] = value; - } - static void plugin_info(plugin_info_iface *pii) - { - pii->names("sample_hold_level", "Sample&Hold (Level, C)", "lv2:UtilityPlugin"); - port_info(pii, "gate", "Gate"); - } -}; - -class msgread_e_audio_module: public message_mixin > -{ -public: - uint32_t set_float_msg, float_type; - static void plugin_info(plugin_info_iface *pii) - { - pii->names("msgread_e", "Msg Read", "lv2:UtilityPlugin"); - pii->has_gui(); - pii->event_port("in", "In").input(); - pii->control_port("out", "Out", 0).output(); - } - virtual void map_uris() - { - message_mixin >::map_uris(); - set_float_msg = map_uri("http://lv2plug.in/ns/dev/msg", "http://foltman.com/garbage/setFloat"); - float_type = map_uri("http://lv2plug.in/ns/dev/types", "http://lv2plug.in/ns/dev/types#float"); - } - void process(uint32_t count) - { - event_port_read_iterator ri((const LV2_Event_Buffer *)ins[0]); - while(ri) - { - const lv2_event *event = &*ri++; - if (event->type == message_event_type) - { - struct payload { - uint32_t selector; - uint32_t serial_no; - uint32_t data_size; - uint32_t parg_count; - uint32_t data_type; - float data_value; - uint32_t narg_count; - }; - const payload *p = (const payload *)event->data; - if (p->selector == set_float_msg) { - assert(p->parg_count == 1); - assert(p->data_size == 16); - assert(p->data_type == float_type); - *outs[0] = p->data_value; - assert(p->narg_count == 0); // this is just for testing - passing - } - } - } - } -}; - -}; - -#define PER_SMALL_MODULE_ITEM(name, id) SMALL_WRAPPERS(name, id) -#include - -const LV2_Descriptor *calf_plugins::lv2_small_descriptor(uint32_t index) -{ - #define PER_SMALL_MODULE_ITEM(name, id) if (!(index--)) return &::lv2_small_##name.descriptor; - #include - return NULL; -} -#endif -#endif - -void calf_plugins::get_all_small_plugins(plugin_list_info_iface *iface) -{ -#if USE_LV2 - #define PER_SMALL_MODULE_ITEM(name, id) { plugin_info_iface *pii = &iface->plugin(id); small_plugins::name##_audio_module::plugin_info(pii); pii->finalize(); } - #include -#endif -} - diff --git a/plugins/ladspa_effect/calf/src/monosynth.cpp b/plugins/ladspa_effect/calf/src/monosynth.cpp index 33b24f3ae..d5c77c16f 100644 --- a/plugins/ladspa_effect/calf/src/monosynth.cpp +++ b/plugins/ladspa_effect/calf/src/monosynth.cpp @@ -18,12 +18,6 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA */ -#include -#include -#include -#if USE_JACK -#include -#endif #include #include @@ -38,8 +32,10 @@ static const char *monosynth_mod_src_names[] = { "Velocity", "Pressure", "ModWheel", - "Envelope", - "LFO", + "Envelope 1", + "Envelope 2", + "LFO 1", + "LFO 2", NULL }; @@ -53,6 +49,7 @@ static const char *monosynth_mod_dest_names[] = { "O2: Detune [ct]", "O1: PW (%)", "O2: PW (%)", + "O1: Stretch", NULL }; @@ -68,7 +65,6 @@ void monosynth_audio_module::activate() { running = false; output_pos = 0; queue_note_on = -1; - stop_count = 0; inertia_pitchbend.set_now(1.f); lfo_bend = 1.0; modwheel_value = 0.f; @@ -79,6 +75,7 @@ void monosynth_audio_module::activate() { filter2.reset(); stack.clear(); last_pwshift1 = last_pwshift2 = 0; + last_stretch1 = 65536; } waveform_family *monosynth_audio_module::waves; @@ -204,7 +201,7 @@ void monosynth_audio_module::precalculate_waves(progress_report_iface *reporter) } -bool monosynth_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) +bool monosynth_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const { monosynth_audio_module::precalculate_waves(NULL); // printf("get_graph %d %p %d wave1=%d wave2=%d\n", index, data, points, wave1, wave2); @@ -225,8 +222,25 @@ bool monosynth_audio_module::get_graph(int index, int subindex, float *data, int if (wave == wave_sqr) wave = wave_saw; float *waveform = waves[wave].original; + float rnd_start = 1 - *params[par_window1] * 0.5f; + float scl = rnd_start < 1.0 ? 1.f / (1 - rnd_start) : 0.f; for (int i = 0; i < points; i++) - data[i] = (sign * waveform[i * S / points] + waveform[(i * S / points + shift) & (S - 1)]) / (sign == -1 ? 1 : 2); + { + int pos = i * S / points; + float r = 1; + if (index == par_wave1) + { + float ph = i * 1.0 / points; + if (ph < 0.5f) + ph = 1.f - ph; + ph = (ph - rnd_start) * scl; + if (ph < 0) + ph = 0; + r = 1.0 - ph * ph; + pos = int(pos * 1.0 * last_stretch1 / 65536.0 ) % S; + } + data[i] = r * (sign * waveform[pos] + waveform[(pos + shift) & (S - 1)]) / (sign == -1 ? 1 : 2); + } return true; } if (index == par_filtertype) { @@ -239,7 +253,7 @@ bool monosynth_audio_module::get_graph(int index, int subindex, float *data, int typedef complex cfloat; double freq = 20.0 * pow (20000.0 / 20.0, i * 1.0 / points); - dsp::biquad_d1_lerp &f = subindex ? filter2 : filter; + const dsp::biquad_d1_lerp &f = subindex ? filter2 : filter; float level = f.freq_gain(freq, srate); if (!is_stereo_filter()) level *= filter2.freq_gain(freq, srate); @@ -252,19 +266,24 @@ bool monosynth_audio_module::get_graph(int index, int subindex, float *data, int return get_static_graph(index, subindex, *params[index], data, points, context); } -void monosynth_audio_module::calculate_buffer_oscs(float lfo) +void monosynth_audio_module::calculate_buffer_oscs(float lfo1) { int flag1 = (wave1 == wave_sqr); int flag2 = (wave2 == wave_sqr); + int32_t shift1 = last_pwshift1; int32_t shift2 = last_pwshift2; - int32_t shift_target1 = (int32_t)(0x78000000 * dsp::clip11(*params[par_pw1] + lfo * *params[par_lfopw] + 0.01f * moddest[moddest_o1pw])); - int32_t shift_target2 = (int32_t)(0x78000000 * dsp::clip11(*params[par_pw2] + lfo * *params[par_lfopw] + 0.01f * moddest[moddest_o2pw])); + int32_t stretch1 = last_stretch1; + int32_t shift_target1 = (int32_t)(0x78000000 * dsp::clip11(*params[par_pw1] + lfo1 * *params[par_lfopw] + 0.01f * moddest[moddest_o1pw])); + int32_t shift_target2 = (int32_t)(0x78000000 * dsp::clip11(*params[par_pw2] + lfo1 * *params[par_lfopw] + 0.01f * moddest[moddest_o2pw])); + int32_t stretch_target1 = (int32_t)(65536 * dsp::clip(*params[par_stretch1] + 0.01f * moddest[moddest_o1stretch], 1.f, 16.f)); int32_t shift_delta1 = ((shift_target1 >> 1) - (last_pwshift1 >> 1)) >> (step_shift - 1); int32_t shift_delta2 = ((shift_target2 >> 1) - (last_pwshift2 >> 1)) >> (step_shift - 1); - last_lfov = lfo; + int32_t stretch_delta1 = ((stretch_target1 >> 1) - (last_stretch1 >> 1)) >> (step_shift - 1); last_pwshift1 = shift_target1; last_pwshift2 = shift_target2; + last_stretch1 = stretch_target1; + lookup_waveforms(); shift1 += (flag1 << 31); shift2 += (flag2 << 31); @@ -274,14 +293,25 @@ void monosynth_audio_module::calculate_buffer_oscs(float lfo) float cur_xfade = last_xfade; float xfade_step = (new_xfade - cur_xfade) * (1.0 / step_size); + float rnd_start = 1 - *params[par_window1] * 0.5f; + float scl = rnd_start < 1.0 ? 1.f / (1 - rnd_start) : 0.f; + for (uint32_t i = 0; i < step_size; i++) { - float osc1val = osc1.get_phaseshifted(shift1, mix1); - float osc2val = osc2.get_phaseshifted(shift2, mix2); - float wave = osc1val + (osc2val - osc1val) * cur_xfade; - buffer[i] = wave; + //buffer[i] = lerp(osc1.get_phaseshifted(shift1, mix1), osc2.get_phaseshifted(shift2, mix2), cur_xfade); + float o1phase = osc1.phase / (65536.0 * 65536.0); + if (o1phase < 0.5) + o1phase = 1 - o1phase; + o1phase = (o1phase - rnd_start) * scl; + if (o1phase < 0) + o1phase = 0; + float r = 1.0 - o1phase * o1phase; + buffer[i] = lerp(r * osc1.get_phasedist(stretch1, shift1, mix1), osc2.get_phaseshifted(shift2, mix2), cur_xfade); + osc1.advance(); + osc2.advance(); shift1 += shift_delta1; shift2 += shift_delta2; + stretch1 += stretch_delta1; cur_xfade += xfade_step; } last_xfade = new_xfade; @@ -320,16 +350,15 @@ void monosynth_audio_module::calculate_buffer_stereo() for (uint32_t i = 0; i < step_size; i++) { float wave1 = buffer[i] * fgain; - float wave2 = phaseshifter.process_ap(wave1); buffer[i] = fgain * filter.process(wave1); - buffer2[i] = fgain * filter2.process(wave2); + buffer2[i] = fgain * filter2.process(wave1); fgain += fgain_delta; } } void monosynth_audio_module::lookup_waveforms() { - osc1.waveform = waves[wave1 == wave_sqr ? wave_saw : wave1].get_level(osc1.phasedelta); + osc1.waveform = waves[wave1 == wave_sqr ? wave_saw : wave1].get_level((uint32_t)(((uint64_t)osc1.phasedelta) * last_stretch1 >> 16)); osc2.waveform = waves[wave2 == wave_sqr ? wave_saw : wave2].get_level(osc2.phasedelta); if (!osc1.waveform) osc1.waveform = silence; if (!osc2.waveform) osc2.waveform = silence; @@ -340,7 +369,8 @@ void monosynth_audio_module::lookup_waveforms() void monosynth_audio_module::delayed_note_on() { force_fadeout = false; - stop_count = 0; + fadeout.reset_soft(); + fadeout2.reset_soft(); porta_time = 0.f; start_freq = freq; target_freq = freq = 440 * pow(2.0, (queue_note_on - 69) / 12.0); @@ -349,10 +379,11 @@ void monosynth_audio_module::delayed_note_on() fltctl = 1.0 + (queue_vel - 1.0) * *params[par_vel2filter]; set_frequency(); lookup_waveforms(); - lfo_clock = 0.f; + bool starting = false; if (!running) { + starting = true; if (legato >= 2) porta_time = -1.f; last_xfade = xfade; @@ -360,7 +391,10 @@ void monosynth_audio_module::delayed_note_on() osc2.reset(); filter.reset(); filter2.reset(); - lfo.reset(); + if (*params[par_lfo1trig] <= 0) + lfo1.reset(); + if (*params[par_lfo2trig] <= 0) + lfo2.reset(); switch((int)*params[par_oscmode]) { case 1: @@ -384,19 +418,20 @@ void monosynth_audio_module::delayed_note_on() default: break; } - envelope.note_on(); running = true; } if (legato >= 2 && !gate) porta_time = -1.f; gate = true; stopping = false; - if (!(legato & 1) || envelope.released()) { - envelope.note_on(); - } - envelope.advance(); + if (starting || !(legato & 1) || envelope1.released()) + envelope1.note_on(); + if (starting || !(legato & 1) || envelope2.released()) + envelope2.note_on(); + envelope1.advance(); + envelope2.advance(); queue_note_on = -1; - float modsrc[modsrc_count] = { 1, velocity, inertia_pressure.get_last(), modwheel_value, 0, 0.5+0.5*last_lfov}; + float modsrc[modsrc_count] = { 1, velocity, inertia_pressure.get_last(), modwheel_value, envelope1.value, envelope2.value, 0.5+0.5*lfo1.last, 0.5+0.5*lfo2.last}; calculate_modmatrix(moddest, moddest_count, modsrc); } @@ -404,27 +439,32 @@ void monosynth_audio_module::set_sample_rate(uint32_t sr) { srate = sr; crate = sr / step_size; odcr = (float)(1.0 / crate); - phaseshifter.set_ap(1000.f, sr); fgain = 0.f; fgain_delta = 0.f; inertia_cutoff.ramp.set_length(crate / 30); // 1/30s inertia_pitchbend.ramp.set_length(crate / 30); // 1/30s + master.set_sample_rate(sr); } void monosynth_audio_module::calculate_step() { if (queue_note_on != -1) delayed_note_on(); - else if (stopping) + else + if (stopping || !running) { running = false; - dsp::zero(buffer, step_size); - if (is_stereo_filter()) - dsp::zero(buffer2, step_size); - envelope.advance(); + envelope1.advance(); + envelope2.advance(); + lfo1.get(); + lfo2.get(); + float modsrc[modsrc_count] = { 1, velocity, inertia_pressure.get_last(), modwheel_value, envelope1.value, envelope2.value, 0.5+0.5*lfo1.last, 0.5+0.5*lfo2.last}; + calculate_modmatrix(moddest, moddest_count, modsrc); + last_stretch1 = (int32_t)(65536 * dsp::clip(*params[par_stretch1] + 0.01f * moddest[moddest_o1stretch], 1.f, 16.f)); return; } - lfo.set_freq(*params[par_lforate], crate); + lfo1.set_freq(*params[par_lforate], crate); + lfo2.set_freq(*params[par_lfo2rate], crate); float porta_total_time = *params[par_portamento] * 0.001f; if (porta_total_time >= 0.00101f && porta_time >= 0) { @@ -439,30 +479,34 @@ void monosynth_audio_module::calculate_step() porta_time += odcr; } } - float lfov = lfo.get() * std::min(1.0f, lfo_clock / *params[par_lfodelay]); - lfov = lfov * dsp::lerp(1.f, modwheel_value, *params[par_mwhl_lfo]); + float lfov1 = lfo1.get() * std::min(1.0f, lfo_clock / *params[par_lfodelay]); + lfov1 = lfov1 * dsp::lerp(1.f, modwheel_value, *params[par_mwhl_lfo]); + float lfov2 = lfo2.get() * std::min(1.0f, lfo_clock / *params[par_lfo2delay]); lfo_clock += odcr; if (fabs(*params[par_lfopitch]) > small_value()) - lfo_bend = pow(2.0f, *params[par_lfopitch] * lfov * (1.f / 1200.0f)); + lfo_bend = pow(2.0f, *params[par_lfopitch] * lfov1 * (1.f / 1200.0f)); inertia_pitchbend.step(); set_frequency(); - envelope.advance(); - float env = envelope.value; + envelope1.advance(); + envelope2.advance(); + float env1 = envelope1.value, env2 = envelope2.value; + float aenv1 = envelope1.get_amp_value(), aenv2 = envelope2.get_amp_value(); // mod matrix // this should be optimized heavily; I think I'll do it when MIDI in Ardour 3 gets stable :> - float modsrc[modsrc_count] = { 1, velocity, inertia_pressure.get(), modwheel_value, env, 0.5+0.5*lfov}; + float modsrc[modsrc_count] = { 1, velocity, inertia_pressure.get(), modwheel_value, env1, env2, 0.5+0.5*lfov1, 0.5+0.5*lfov2}; calculate_modmatrix(moddest, moddest_count, modsrc); inertia_cutoff.set_inertia(*params[par_cutoff]); - cutoff = inertia_cutoff.get() * pow(2.0f, (lfov * *params[par_lfofilter] + env * fltctl * *params[par_envmod] + moddest[moddest_cutoff]) * (1.f / 1200.f)); + cutoff = inertia_cutoff.get() * pow(2.0f, (lfov1 * *params[par_lfofilter] + env1 * fltctl * *params[par_env1tocutoff] + env2 * fltctl * *params[par_env2tocutoff] + moddest[moddest_cutoff]) * (1.f / 1200.f)); if (*params[par_keyfollow] > 0.01f) cutoff *= pow(freq / 264.f, *params[par_keyfollow]); cutoff = dsp::clip(cutoff , 10.f, 18000.f); float resonance = *params[par_resonance]; - float e2r = *params[par_envtores]; - float e2a = *params[par_envtoamp]; - resonance = resonance * (1 - e2r) + (0.7 + (resonance - 0.7) * env * env) * e2r + moddest[moddest_resonance]; + float e2r1 = *params[par_env1tores]; + resonance = resonance * (1 - e2r1) + (0.7 + (resonance - 0.7) * env1 * env1) * e2r1; + float e2r2 = *params[par_env2tores]; + resonance = resonance * (1 - e2r2) + (0.7 + (resonance - 0.7) * env2 * env2) * e2r2 + moddest[moddest_resonance]; float cutoff2 = dsp::clip(cutoff * separation, 10.f, 18000.f); float newfgain = 0.f; if (filter_type != last_filter_type) @@ -514,13 +558,18 @@ void monosynth_audio_module::calculate_step() newfgain = ampctl; break; } - float aenv = env; - if (*params[par_envtoamp] > 0.f) - newfgain *= 1.0 - (1.0 - aenv) * e2a; + float e2a1 = *params[par_env1toamp]; + float e2a2 = *params[par_env2toamp]; + if (e2a1 > 0.f) + newfgain *= aenv1; + if (e2a2 > 0.f) + newfgain *= aenv2; if (moddest[moddest_attenuation] != 0.f) newfgain *= dsp::clip(1 - moddest[moddest_attenuation] * moddest[moddest_attenuation], 0.f, 1.f); fgain_delta = (newfgain - fgain) * (1.0 / step_size); - calculate_buffer_oscs(lfov); + calculate_buffer_oscs(lfov1); + lfo1.last = lfov1; + lfo2.last = lfov2; switch(filter_type) { case flt_lp24: @@ -538,17 +587,42 @@ void monosynth_audio_module::calculate_step() calculate_buffer_stereo(); break; } - if ((envelope.state == adsr::STOP && !gate) || force_fadeout || (envelope.state == adsr::RELEASE && *params[par_envtoamp] <= 0.f)) + apply_fadeout(); +} + +void monosynth_audio_module::apply_fadeout() +{ + if (fadeout.undoing) { - enum { ramp = step_size * 4 }; - for (int i = 0; i < step_size; i++) - buffer[i] *= (ramp - i - stop_count) * (1.0f / ramp); + fadeout.process(buffer2, step_size); if (is_stereo_filter()) - for (int i = 0; i < step_size; i++) - buffer2[i] *= (ramp - i - stop_count) * (1.0f / ramp); - stop_count += step_size; - if (stop_count >= ramp) - stopping = true; + fadeout2.process(buffer2, step_size); + } + else + { + // stop the sound if the amplitude envelope is not running (if there's any) + bool aenv1_on = *params[par_env1toamp] > 0.f, aenv2_on = *params[par_env2toamp] > 0.f; + + bool do_fadeout = force_fadeout; + + // if there's no amplitude envelope at all, the fadeout starts at key release + if (!aenv1_on && !aenv2_on && !gate) + do_fadeout = true; + // if ENV1 modulates amplitude, the fadeout will start on ENV1 end too + if (aenv1_on && envelope1.state == adsr::STOP) + do_fadeout = true; + // if ENV2 modulates amplitude, the fadeout will start on ENV2 end too + if (aenv2_on && envelope2.state == adsr::STOP) + do_fadeout = true; + + if (do_fadeout || fadeout.undoing || fadeout2.undoing) + { + fadeout.process(buffer, step_size); + if (is_stereo_filter()) + fadeout2.process(buffer2, step_size); + if (fadeout.done) + stopping = true; + } } } @@ -573,14 +647,16 @@ void monosynth_audio_module::note_off(int note, int vel) porta_time = 0; set_frequency(); if (!(legato & 1)) { - envelope.note_on(); + envelope1.note_on(); + envelope2.note_on(); stopping = false; running = true; } return; } gate = false; - envelope.note_off(); + envelope1.note_off(); + envelope2.note_off(); } } @@ -607,7 +683,8 @@ void monosynth_audio_module::control_change(int controller, int value) case 123: // all notes off gate = false; queue_note_on = -1; - envelope.note_off(); + envelope1.note_off(); + envelope2.note_off(); stack.clear(); break; } @@ -618,7 +695,8 @@ void monosynth_audio_module::deactivate() gate = false; running = false; stopping = false; - envelope.reset(); + envelope1.reset(); + envelope2.reset(); stack.clear(); } @@ -640,9 +718,9 @@ void monosynth_audio_module::set_frequency() void monosynth_audio_module::params_changed() { float sf = 0.001f; - envelope.set(*params[par_attack] * sf, *params[par_decay] * sf, std::min(0.999f, *params[par_sustain]), *params[par_release] * sf, srate / step_size, *params[par_fade] * sf); + envelope1.set(*params[par_env1attack] * sf, *params[par_env1decay] * sf, std::min(0.999f, *params[par_env1sustain]), *params[par_env1release] * sf, srate / step_size, *params[par_env1fade] * sf); + envelope2.set(*params[par_env2attack] * sf, *params[par_env2decay] * sf, std::min(0.999f, *params[par_env2sustain]), *params[par_env2release] * sf, srate / step_size, *params[par_env2fade] * sf); filter_type = dsp::fastf2i_drm(*params[par_filtertype]); - decay_factor = odcr * 1000.0 / *params[par_decay]; separation = pow(2.0, *params[par_cutoffsep] / 1200.0); wave1 = dsp::clip(dsp::fastf2i_drm(*params[par_wave1]), 0, (int)wave_count - 1); wave2 = dsp::clip(dsp::fastf2i_drm(*params[par_wave2]), 0, (int)wave_count - 1); @@ -659,34 +737,33 @@ void monosynth_audio_module::params_changed() uint32_t monosynth_audio_module::process(uint32_t offset, uint32_t nsamples, uint32_t inputs_mask, uint32_t outputs_mask) { - if (!running && queue_note_on == -1) { - for (uint32_t i = 0; i < nsamples / step_size; i++) - envelope.advance(); - return 0; - } uint32_t op = offset; uint32_t op_end = offset + nsamples; + int had_data = 0; while(op < op_end) { - if (output_pos == 0) { - if (running || queue_note_on != -1) - calculate_step(); - else { - envelope.advance(); - dsp::zero(buffer, step_size); - } - } + if (output_pos == 0) + calculate_step(); if(op < op_end) { uint32_t ip = output_pos; uint32_t len = std::min(step_size - output_pos, op_end - op); - if (is_stereo_filter()) - for(uint32_t i = 0 ; i < len; i++) { - float vol = master.get(); - outs[0][op + i] = buffer[ip + i] * vol, - outs[1][op + i] = buffer2[ip + i] * vol; - } - else - for(uint32_t i = 0 ; i < len; i++) - outs[0][op + i] = outs[1][op + i] = buffer[ip + i] * master.get(); + if (running) + { + had_data = 3; + if (is_stereo_filter()) + for(uint32_t i = 0 ; i < len; i++) { + float vol = master.get(); + outs[0][op + i] = buffer[ip + i] * vol; + outs[1][op + i] = buffer2[ip + i] * vol; + } + else + for(uint32_t i = 0 ; i < len; i++) + outs[0][op + i] = outs[1][op + i] = buffer[ip + i] * master.get(); + } + else + { + dsp::zero(&outs[0][op], len); + dsp::zero(&outs[1][op], len); + } op += len; output_pos += len; if (output_pos == step_size) @@ -694,6 +771,6 @@ uint32_t monosynth_audio_module::process(uint32_t offset, uint32_t nsamples, uin } } - return 3; + return had_data; } diff --git a/plugins/ladspa_effect/calf/src/organ.cpp b/plugins/ladspa_effect/calf/src/organ.cpp index 3d1b7eed1..b28cbaaa1 100644 --- a/plugins/ladspa_effect/calf/src/organ.cpp +++ b/plugins/ladspa_effect/calf/src/organ.cpp @@ -18,15 +18,10 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA */ +#include -#include -#include -#include -#if USE_JACK -#include -#endif #include -#include +#include #include using namespace std; @@ -35,7 +30,50 @@ using namespace calf_plugins; ////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool organ_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) +organ_audio_module::organ_audio_module() +: drawbar_organ(&par_values) +{ + var_map_curve = "2\n0 1\n1 1\n"; // XXXKF hacky bugfix +} + +void organ_audio_module::activate() +{ + setup(srate); + panic_flag = false; +} + +void organ_audio_module::post_instantiate() +{ + dsp::organ_voice_base::precalculate_waves(progress_report); +} + + +uint32_t organ_audio_module::process(uint32_t offset, uint32_t nsamples, uint32_t inputs_mask, uint32_t outputs_mask) +{ + float *o[2] = { outs[0] + offset, outs[1] + offset }; + if (panic_flag) + { + control_change(120, 0); // stop all sounds + control_change(121, 0); // reset all controllers + panic_flag = false; + } + render_separate(o, nsamples); + return 3; +} + +void organ_audio_module::params_changed() { + for (int i = 0; i < param_count - var_count; i++) + ((float *)&par_values)[i] = *params[i]; + + unsigned int old_poly = polyphony_limit; + polyphony_limit = dsp::clip(dsp::fastf2i_drm(*params[par_polyphony]), 1, 32); + if (polyphony_limit < old_poly) + trim_voices(); + + update_params(); +} + +bool organ_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const { if (index == par_master) { organ_voice_base::precalculate_waves(progress_report); @@ -74,6 +112,13 @@ bool organ_audio_module::get_graph(int index, int subindex, float *data, int poi return false; } +uint32_t organ_audio_module::message_run(const void *valid_inputs, void *output_ports) +{ + // silence a default printf (which is kind of a warning about unhandled message_run) + return 0; +} + + //////////////////////////////////////////////////////////////////////////// organ_voice_base::small_wave_family (*organ_voice_base::waves)[organ_voice_base::wave_count_small]; @@ -192,6 +237,12 @@ static void padsynth(bandlimiter blSrc, bandlimiterreport_progress(floor(progress / totalwaves), "Precalculating large waveforms"); } } while(0) +void organ_voice_base::update_pitch() +{ + float phase = dsp::midi_note_to_phase(note, 100 * parameters->global_transpose + parameters->global_detune, sample_rate_ref); + dpphase.set((long int) (phase * parameters->percussion_harmonic * parameters->pitch_bend)); + moddphase.set((long int) (phase * parameters->percussion_fm_harmonic * parameters->pitch_bend)); +} void organ_voice_base::precalculate_waves(progress_report_iface *reporter) { @@ -502,6 +553,17 @@ void organ_voice_base::render_percussion_to(float (*buf)[2], int nsamples) } } +void organ_voice_base::perc_reset() +{ + pphase = 0; + modphase = 0; + dpphase = 0; + moddphase = 0; + note = -1; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////// + void organ_vibrato::reset() { for (int i = 0; i < VibratoSize; i++) @@ -549,6 +611,8 @@ void organ_vibrato::process(organ_parameters *parameters, float (*data)[2], unsi } } +////////////////////////////////////////////////////////////////////////////////////////////////////// + void organ_voice::update_pitch() { organ_voice_base::update_pitch(); @@ -730,8 +794,64 @@ void organ_voice::render_block() { if (use_percussion()) render_percussion_to(output_buffer, BlockSize); + } +void organ_voice::note_on(int note, int vel) +{ + stolen = false; + finishing = false; + perc_released = false; + released = false; + reset(); + this->note = note; + const float sf = 0.001f; + for (int i = 0; i < EnvCount; i++) + { + organ_parameters::organ_env_parameters &p = parameters->envs[i]; + envs[i].set(sf * p.attack, sf * p.decay, p.sustain, sf * p.release, sample_rate / BlockSize); + envs[i].note_on(); + } + update_pitch(); + velocity = vel * 1.0 / 127.0; + amp.set(1.0f); + perc_note_on(note, vel); +} + +void organ_voice::note_off(int /* vel */) +{ + // reset age to 0 (because decay will turn from exponential to linear, necessary because of error cumulation prevention) + perc_released = true; + if (pamp.get_active()) + { + pamp.reinit(); + } + rel_age_const = pamp.get() * ((1.0/44100.0)/0.03); + for (int i = 0; i < EnvCount; i++) + envs[i].note_off(); +} + +void organ_voice::steal() +{ + perc_released = true; + finishing = true; + stolen = true; +} + +void organ_voice::reset() +{ + inertia_pitchbend.ramp.set_length(sample_rate / (BlockSize * 30)); // 1/30s + vibrato.reset(); + phase = 0; + for (int i = 0; i < FilterCount; i++) + { + filterL[i].reset(); + filterR[i].reset(); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + void drawbar_organ::update_params() { parameters->perc_decay_const = dsp::decay::calc_exp_constant(1.0 / 1024.0, 0.001 * parameters->percussion_time * sample_rate); @@ -745,6 +865,42 @@ void drawbar_organ::update_params() parameters->foldvalue = (int)(dphase); } +dsp::voice *drawbar_organ::alloc_voice() +{ + block_voice *v = new block_voice(); + v->parameters = parameters; + return v; +} + +void drawbar_organ::percussion_note_on(int note, int vel) +{ + percussion.perc_note_on(note, vel); +} + +void drawbar_organ::setup(int sr) +{ + basic_synth::setup(sr); + percussion.setup(sr); + parameters->cutoff = 0; + params_changed(); + global_vibrato.reset(); +} + +bool drawbar_organ::check_percussion() { + switch(dsp::fastf2i_drm(parameters->percussion_trigger)) + { + case organ_voice_base::perctrig_first: + return active_voices.empty(); + case organ_voice_base::perctrig_each: + default: + return true; + case organ_voice_base::perctrig_eachplus: + return !percussion.get_noticable(); + case organ_voice_base::perctrig_polyphonic: + return false; + } +} + void drawbar_organ::pitch_bend(int amt) { parameters->pitch_bend = pow(2.0, (amt * parameters->pitch_bend_range) / (1200.0 * 8192.0)); diff --git a/plugins/ladspa_effect/calf/src/plugin.cpp b/plugins/ladspa_effect/calf/src/plugin.cpp index 2887904d1..9a4b97615 100644 --- a/plugins/ladspa_effect/calf/src/plugin.cpp +++ b/plugins/ladspa_effect/calf/src/plugin.cpp @@ -1,7 +1,7 @@ -/* Calf DSP Library - * Example audio modules - LADSPA/DSSI/LV2 wrapper instantiation +/* Calf DSP plugin pack + * LADSPA/DSSI/LV2 wrapper instantiation for all plugins * - * Copyright (C) 2001-2008 Krzysztof Foltman + * Copyright (C) 2001-2010 Krzysztof Foltman * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -18,36 +18,467 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA */ +#include #include #include #include +#include #include -#include +#include +#include +#include +#include +#include +#include using namespace calf_plugins; +using namespace osctl; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #if USE_LADSPA -template -LADSPA_Descriptor ladspa_wrapper::descriptor; -template -LADSPA_Descriptor ladspa_wrapper::descriptor_for_dssi; +ladspa_instance::ladspa_instance(audio_module_iface *_module, ladspa_plugin_metadata_set *_ladspa, int sample_rate) +{ + module = _module; + metadata = module->get_metadata_iface(); + ladspa = _ladspa; + + module->get_port_arrays(ins, outs, params); + + activate_flag = true; +#if USE_DSSI + feedback_sender = NULL; +#endif + + module->set_sample_rate(sample_rate); + module->post_instantiate(); +} + +float ladspa_instance::get_param_value(int param_no) +{ + // XXXKF hack + if (param_no >= ladspa->real_param_count) + return 0; + return *params[param_no]; +} + +void ladspa_instance::set_param_value(int param_no, float value) +{ + // XXXKF hack + if (param_no >= ladspa->real_param_count) + return; + *params[param_no] = value; +} + +bool ladspa_instance::activate_preset(int bank, int program) +{ + return false; +} + +/// LADSPA run function - does set sample rate / activate logic when it's run first time after activation +void ladspa_instance::run(unsigned long SampleCount) +{ + if (activate_flag) + { + module->activate(); + activate_flag = false; + } + module->params_changed(); + module->process_slice(0, SampleCount); +} #if USE_DSSI -template -DSSI_Descriptor ladspa_wrapper::dssi_descriptor; +void ladspa_instance::run_synth(unsigned long SampleCount, snd_seq_event_t *Events, unsigned long EventCount) +{ + if (activate_flag) + { + module->activate(); + activate_flag = false; + } + module->params_changed(); + + uint32_t offset = 0; + for (uint32_t e = 0; e < EventCount; e++) + { + uint32_t timestamp = Events[e].time.tick; + if (timestamp != offset) + module->process_slice(offset, timestamp); + process_dssi_event(Events[e]); + offset = timestamp; + } + if (offset != SampleCount) + module->process_slice(offset, SampleCount); +} -template -DSSI_Program_Descriptor ladspa_wrapper::dssi_default_program; - -template -std::vector *ladspa_wrapper::presets; - -template -std::vector *ladspa_wrapper::preset_descs; #endif + +char *ladspa_instance::configure(const char *key, const char *value) +{ +#if USE_DSSI + if (!strcmp(key, "OSC:FEEDBACK_URI")) + { + const line_graph_iface *lgi = dynamic_cast(metadata); + //if (!lgi) + // return NULL; + if (*value) + { + if (feedback_sender) { + delete feedback_sender; + feedback_sender = NULL; + } + feedback_sender = new dssi_feedback_sender(value, lgi); + feedback_sender->add_graphs(metadata->get_param_props(0), metadata->get_param_count()); + } + else + { + if (feedback_sender) { + delete feedback_sender; + feedback_sender = NULL; + } + } + return NULL; + } + else + if (!strcmp(key, "OSC:UPDATE")) + { + if (feedback_sender) + feedback_sender->update(); + return NULL; + } + else + if (!strcmp(key, "OSC:SEND_STATUS")) + { + if (!feedback_sender) + return NULL; + struct status_gatherer: public send_updates_iface + { + osc_inline_typed_strstream str; + void send_status(const char *key, const char *value) + { + str << key << value; + } + } sg; + int serial = atoi(value); + serial = module->send_status_updates(&sg, serial); + sg.str << (uint32_t)serial; + feedback_sender->client->send("/status_data", sg.str); + return NULL; + } + else #endif + if (!strcmp(key, "ExecCommand")) + { + if (*value) + { + execute(atoi(value)); + } + return NULL; + } + return module->configure(key, value); +} + +template +ladspa_plugin_metadata_set ladspa_wrapper::output; + +#if USE_DSSI + +/// Utility function: handle MIDI event (only handles a subset in this version) +void ladspa_instance::process_dssi_event(snd_seq_event_t &event) +{ + switch(event.type) { + case SND_SEQ_EVENT_NOTEON: + module->note_on(event.data.note.note, event.data.note.velocity); + break; + case SND_SEQ_EVENT_NOTEOFF: + module->note_off(event.data.note.note, event.data.note.velocity); + break; + case SND_SEQ_EVENT_PGMCHANGE: + module->program_change(event.data.control.value); + break; + case SND_SEQ_EVENT_CONTROLLER: + module->control_change(event.data.control.param, event.data.control.value); + break; + case SND_SEQ_EVENT_PITCHBEND: + module->pitch_bend(event.data.control.value); + break; + case SND_SEQ_EVENT_CHANPRESS: + module->channel_pressure(event.data.control.value); + break; + } +} +#endif + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// LADSPA callbacks + +/// LADSPA activate function (note that at this moment the ports are not set) +static void cb_activate(LADSPA_Handle Instance) +{ + ((ladspa_instance *)(Instance))->activate_flag = true; +} + +/// LADSPA run function - does set sample rate / activate logic when it's run first time after activation +static void cb_run(LADSPA_Handle Instance, unsigned long SampleCount) { + ((ladspa_instance *)(Instance))->run(SampleCount); +} + +/// LADSPA port connection function +static void cb_connect(LADSPA_Handle Instance, unsigned long port, LADSPA_Data *DataLocation) +{ + ladspa_instance *const mod = (ladspa_instance *)Instance; + + int first_out = mod->ladspa->input_count; + int first_param = first_out + mod->ladspa->output_count; + int ladspa_port_count = first_param + mod->ladspa->real_param_count; + + if ((int)port < first_out) + mod->ins[port] = DataLocation; + else if ((int)port < first_param) + mod->outs[port - first_out] = DataLocation; + else if ((int)port < ladspa_port_count) { + int i = port - first_param; + mod->params[i] = DataLocation; + *mod->params[i] = mod->metadata->get_param_props(i)->def_value; + } +} + + +/// LADSPA deactivate function +static void cb_deactivate(LADSPA_Handle Instance) { + ((ladspa_instance *)(Instance))->module->deactivate(); +} + +/// LADSPA cleanup (delete instance) function +static void cb_cleanup(LADSPA_Handle Instance) { + delete ((ladspa_instance *)(Instance)); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// DSSI callbacks + +#if USE_DSSI +/// DSSI "run synth" function, same as run() except it allows for event delivery +static void cb_run_synth(LADSPA_Handle Instance, unsigned long SampleCount, + snd_seq_event_t *Events, unsigned long EventCount) { + ((ladspa_instance *)(Instance))->run_synth(SampleCount, Events, EventCount); +} + +/// DSSI configure function (named properties) +static char *cb_configure(LADSPA_Handle Instance, + const char *Key, + const char *Value) +{ + return ((ladspa_instance *)(Instance))->configure(Key, Value); +} + +/// DSSI get program descriptor function; for 0, it returns the default program (from parameter properties table), for others, it uses global or user preset +static const DSSI_Program_Descriptor *cb_get_program(LADSPA_Handle Instance, unsigned long index) +{ + ladspa_plugin_metadata_set *ladspa = ((ladspa_instance *)(Instance))->ladspa; + if (index > ladspa->presets->size()) + return NULL; + if (index) + return &(*ladspa->preset_descs)[index - 1]; + return &ladspa->dssi_default_program; +} + +/// DSSI select program function; for 0, it sets the defaults, for others, it sets global or user preset +static void cb_select_program(LADSPA_Handle Instance, unsigned long Bank, unsigned long Program) +{ + ladspa_instance *mod = (ladspa_instance *)Instance; + ladspa_plugin_metadata_set *ladspa = mod->ladspa; + unsigned int no = (Bank << 7) + Program - 1; + // printf("no = %d presets = %p:%d\n", no, presets, presets->size()); + if (no == -1U) { + int rpc = ladspa->real_param_count; + for (int i =0 ; i < rpc; i++) + *mod->params[i] = mod->metadata->get_param_props(i)->def_value; + return; + } + if (no >= ladspa->presets->size()) + return; + plugin_preset &p = (*ladspa->presets)[no]; + // printf("activating preset %s\n", p.name.c_str()); + p.activate(mod); +} + +#endif + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +ladspa_plugin_metadata_set::ladspa_plugin_metadata_set() +{ + metadata = NULL; + memset(&descriptor, 0, sizeof(descriptor)); + +#if USE_DSSI + presets = NULL; + preset_descs = NULL; + memset(&descriptor_for_dssi, 0, sizeof(descriptor_for_dssi)); + memset(&dssi_descriptor, 0, sizeof(dssi_descriptor)); +#endif +} + +void ladspa_plugin_metadata_set::prepare(const plugin_metadata_iface *md, LADSPA_Handle (*cb_instantiate)(const struct _LADSPA_Descriptor * Descriptor, unsigned long sample_rate)) +{ + metadata = md; + + input_count = md->get_input_count(); + output_count = md->get_output_count(); + param_count = md->get_param_count(); // XXXKF ladspa_instance::real_param_count(); + real_param_count = 0; + while(real_param_count < md->get_param_count() && (metadata->get_param_props(real_param_count)->flags & PF_TYPEMASK) < PF_STRING) + real_param_count++; + + const ladspa_plugin_info &plugin_info = md->get_plugin_info(); + descriptor.UniqueID = plugin_info.unique_id; + descriptor.Label = plugin_info.label; + descriptor.Name = strdup((std::string(plugin_info.name) + " LADSPA").c_str()); + descriptor.Maker = plugin_info.maker; + descriptor.Copyright = plugin_info.copyright; + descriptor.Properties = md->is_rt_capable() ? LADSPA_PROPERTY_HARD_RT_CAPABLE : 0; + descriptor.PortCount = input_count + output_count + real_param_count; + descriptor.PortNames = new char *[descriptor.PortCount]; + descriptor.PortDescriptors = new LADSPA_PortDescriptor[descriptor.PortCount]; + descriptor.PortRangeHints = new LADSPA_PortRangeHint[descriptor.PortCount]; + int i; + for (i = 0; i < input_count + output_count; i++) + { + LADSPA_PortRangeHint &prh = ((LADSPA_PortRangeHint *)descriptor.PortRangeHints)[i]; + ((int *)descriptor.PortDescriptors)[i] = i < input_count ? LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO + : LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO; + prh.HintDescriptor = 0; + ((const char **)descriptor.PortNames)[i] = md->get_port_names()[i]; + } + for (; i < input_count + output_count + real_param_count; i++) + { + LADSPA_PortRangeHint &prh = ((LADSPA_PortRangeHint *)descriptor.PortRangeHints)[i]; + const parameter_properties &pp = *md->get_param_props(i - input_count - output_count); + ((int *)descriptor.PortDescriptors)[i] = + LADSPA_PORT_CONTROL | (pp.flags & PF_PROP_OUTPUT ? LADSPA_PORT_OUTPUT : LADSPA_PORT_INPUT); + prh.HintDescriptor = LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW; + ((const char **)descriptor.PortNames)[i] = pp.name; + prh.LowerBound = pp.min; + prh.UpperBound = pp.max; + switch(pp.flags & PF_TYPEMASK) { + case PF_BOOL: + prh.HintDescriptor |= LADSPA_HINT_TOGGLED; + prh.HintDescriptor &= ~(LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW); + break; + case PF_INT: + case PF_ENUM: + prh.HintDescriptor |= LADSPA_HINT_INTEGER; + break; + default: { + int defpt = (int)(100 * (pp.def_value - pp.min) / (pp.max - pp.min)); + if ((pp.flags & PF_SCALEMASK) == PF_SCALE_LOG) + defpt = (int)(100 * log(pp.def_value / pp.min) / log(pp.max / pp.min)); + if (defpt < 12) + prh.HintDescriptor |= LADSPA_HINT_DEFAULT_MINIMUM; + else if (defpt < 37) + prh.HintDescriptor |= LADSPA_HINT_DEFAULT_LOW; + else if (defpt < 63) + prh.HintDescriptor |= LADSPA_HINT_DEFAULT_MIDDLE; + else if (defpt < 88) + prh.HintDescriptor |= LADSPA_HINT_DEFAULT_HIGH; + else + prh.HintDescriptor |= LADSPA_HINT_DEFAULT_MAXIMUM; + } + } + if (pp.def_value == 0 || pp.def_value == 1 || pp.def_value == 100 || pp.def_value == 440 ) { + prh.HintDescriptor &= ~LADSPA_HINT_DEFAULT_MASK; + if (pp.def_value == 1) + prh.HintDescriptor |= LADSPA_HINT_DEFAULT_1; + else if (pp.def_value == 100) + prh.HintDescriptor |= LADSPA_HINT_DEFAULT_100; + else if (pp.def_value == 440) + prh.HintDescriptor |= LADSPA_HINT_DEFAULT_440; + else + prh.HintDescriptor |= LADSPA_HINT_DEFAULT_0; + } + switch(pp.flags & PF_SCALEMASK) { + case PF_SCALE_LOG: + prh.HintDescriptor |= LADSPA_HINT_LOGARITHMIC; + break; + } + } + descriptor.ImplementationData = this; + descriptor.instantiate = cb_instantiate; + descriptor.connect_port = cb_connect; + descriptor.activate = cb_activate; + descriptor.run = cb_run; + descriptor.run_adding = NULL; + descriptor.set_run_adding_gain = NULL; + descriptor.deactivate = cb_deactivate; + descriptor.cleanup = cb_cleanup; + prepare_dssi(); +} + +void ladspa_plugin_metadata_set::prepare_dssi() +{ +#if USE_DSSI + const ladspa_plugin_info &plugin_info = metadata->get_plugin_info(); + memcpy(&descriptor_for_dssi, &descriptor, sizeof(descriptor)); + descriptor_for_dssi.Name = strdup((std::string(plugin_info.name) + " DSSI").c_str()); + memset(&dssi_descriptor, 0, sizeof(dssi_descriptor)); + dssi_descriptor.DSSI_API_Version = 1; + dssi_descriptor.LADSPA_Plugin = &descriptor_for_dssi; + dssi_descriptor.configure = cb_configure; + dssi_descriptor.get_program = cb_get_program; + dssi_descriptor.select_program = cb_select_program; + if (metadata->get_midi()) + dssi_descriptor.run_synth = cb_run_synth; + + presets = new std::vector; + preset_descs = new std::vector; + + preset_list plist_tmp, plist; + plist.load_defaults(true); + plist_tmp.load_defaults(false); + plist.presets.insert(plist.presets.end(), plist_tmp.presets.begin(), plist_tmp.presets.end()); + + // XXXKF this assumes that plugin name in preset is case-insensitive equal to plugin label + // if I forget about this, I'll be in a deep trouble + dssi_default_program.Bank = 0; + dssi_default_program.Program = 0; + dssi_default_program.Name = "default"; + + int pos = 1; + for (unsigned int i = 0; i < plist.presets.size(); i++) + { + plugin_preset &pp = plist.presets[i]; + if (strcasecmp(pp.plugin.c_str(), descriptor.Label)) + continue; + DSSI_Program_Descriptor pd; + pd.Bank = pos >> 7; + pd.Program = pos++; + pd.Name = pp.name.c_str(); + preset_descs->push_back(pd); + presets->push_back(pp); + } +#endif +} + +ladspa_plugin_metadata_set::~ladspa_plugin_metadata_set() +{ + delete []descriptor.PortNames; + delete []descriptor.PortDescriptors; + delete []descriptor.PortRangeHints; +#if USE_DSSI + if (presets) + presets->clear(); + if (preset_descs) + preset_descs->clear(); + delete presets; + delete preset_descs; +#endif +} + +#endif + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////// #if USE_LV2 // instantiate descriptor templates @@ -61,11 +492,7 @@ const LV2_Descriptor *lv2_descriptor(uint32_t index) { #define PER_MODULE_ITEM(name, isSynth, jackname) if (!(index--)) return &lv2_wrapper::get().descriptor; #include -#ifdef ENABLE_EXPERIMENTAL - return lv2_small_descriptor(index); -#else return NULL; -#endif } }; @@ -99,3 +526,17 @@ const DSSI_Descriptor *dssi_descriptor(unsigned long Index) #endif +#if USE_JACK + +extern "C" { + +audio_module_iface *create_calf_plugin_by_name(const char *effect_name) +{ + #define PER_MODULE_ITEM(name, isSynth, jackname) if (!strcasecmp(effect_name, jackname)) return new name##_audio_module; + #include + return NULL; +} + +} + +#endif diff --git a/plugins/ladspa_effect/calf/src/synth.cpp b/plugins/ladspa_effect/calf/src/synth.cpp index 633650e31..fcda18b22 100644 --- a/plugins/ladspa_effect/calf/src/synth.cpp +++ b/plugins/ladspa_effect/calf/src/synth.cpp @@ -18,12 +18,6 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA */ -#include -#include -#if USE_JACK -#include -#endif -#include #include using namespace dsp; @@ -176,8 +170,6 @@ void basic_synth::control_change(int ctl, int val) } } if (ctl == 123 || ctl == 120) { // all notes off, all sounds off - vector notes; - notes.reserve(128); if (ctl == 120) { // for "all sounds off", automatically release hold and sostenuto pedal control_change(66, 0); control_change(64, 0); diff --git a/plugins/ladspa_effect/calf/src/utils.cpp b/plugins/ladspa_effect/calf/src/utils.cpp index 338587f2c..d661c914f 100644 --- a/plugins/ladspa_effect/calf/src/utils.cpp +++ b/plugins/ladspa_effect/calf/src/utils.cpp @@ -17,10 +17,10 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA */ -#include -#include +#include #include #include +#include #include using namespace std; @@ -69,6 +69,11 @@ std::string xml_escape(const std::string &src) return dest; } +std::string to_xml_attr(const std::string &key, const std::string &value) +{ + return " " + key + "=\"" + xml_escape(value) + "\""; +} + std::string load_file(const std::string &src) { std::string str; @@ -129,4 +134,22 @@ std::string indent(const std::string &src, const std::string &indent) return dest; } +////////////////////////////////////////////////////////////////////////////////// + +file_exception::file_exception(const std::string &f) +: message(strerror(errno)) +, filename(f) +, container(filename + ":" + message) +{ + text = container.c_str(); +} + +file_exception::file_exception(const std::string &f, const std::string &t) +: message(t) +, filename(f) +, container(filename + ":" + message) +{ + text = container.c_str(); +} + } diff --git a/plugins/lb302/lb302.cpp b/plugins/lb302/lb302.cpp index 5e231413b..5097a3d7d 100644 --- a/plugins/lb302/lb302.cpp +++ b/plugins/lb302/lb302.cpp @@ -977,7 +977,7 @@ void lb302SynthView::modelChanged() extern "C" { -// neccessary for getting instance out of shared lib +// necessary for getting instance out of shared lib Plugin * PLUGIN_EXPORT lmms_plugin_main( Model *, void * _data ) { diff --git a/plugins/lb303/lb303.cpp b/plugins/lb303/lb303.cpp index 5c43aff37..269b53393 100644 --- a/plugins/lb303/lb303.cpp +++ b/plugins/lb303/lb303.cpp @@ -829,7 +829,7 @@ void lb303SynthView::modelChanged() extern "C" { -// neccessary for getting instance out of shared lib +// necessary for getting instance out of shared lib Plugin * PLUGIN_EXPORT lmms_plugin_main( Model *, void * _data ) { diff --git a/plugins/lv2_browser/lv2_browser.cpp b/plugins/lv2_browser/lv2_browser.cpp index 34e45e686..71e2c1062 100644 --- a/plugins/lv2_browser/lv2_browser.cpp +++ b/plugins/lv2_browser/lv2_browser.cpp @@ -59,7 +59,7 @@ Plugin::Descriptor PLUGIN_EXPORT lv2browser_plugin_descriptor = } ; -// neccessary for getting instance out of shared lib +// necessary for getting instance out of shared lib Plugin * PLUGIN_EXPORT lmms_plugin_main( Model * _parent, void * _data ) { return new lv2Browser; diff --git a/plugins/midi_import/MidiImport.cpp b/plugins/midi_import/MidiImport.cpp index f2e62b058..375920ca9 100644 --- a/plugins/midi_import/MidiImport.cpp +++ b/plugins/midi_import/MidiImport.cpp @@ -569,7 +569,7 @@ void MidiImport::error() extern "C" { -// neccessary for getting instance out of shared lib +// necessary for getting instance out of shared lib Plugin * PLUGIN_EXPORT lmms_plugin_main( Model *, void * _data ) { return new MidiImport( QString::fromUtf8( diff --git a/plugins/organic/organic.cpp b/plugins/organic/organic.cpp index 48d254334..e3e3d7c1b 100644 --- a/plugins/organic/organic.cpp +++ b/plugins/organic/organic.cpp @@ -563,7 +563,7 @@ void OscillatorObject::updateDetuning() extern "C" { -// neccessary for getting instance out of shared lib +// necessary for getting instance out of shared lib Plugin * PLUGIN_EXPORT lmms_plugin_main( Model *, void * _data ) { return( new organicInstrument( static_cast( _data ) ) ); diff --git a/plugins/papu/papu_instrument.cpp b/plugins/papu/papu_instrument.cpp index a5c8b0f9f..d49807d2a 100644 --- a/plugins/papu/papu_instrument.cpp +++ b/plugins/papu/papu_instrument.cpp @@ -732,7 +732,7 @@ void papuInstrumentView::modelChanged() extern "C" { -// neccessary for getting instance out of shared lib +// necessary for getting instance out of shared lib Plugin * PLUGIN_EXPORT lmms_plugin_main( Model *, void * _data ) { return( new papuInstrument( diff --git a/plugins/peak_controller_effect/peak_controller_effect.cpp b/plugins/peak_controller_effect/peak_controller_effect.cpp index b12177956..9ab9b0cdc 100644 --- a/plugins/peak_controller_effect/peak_controller_effect.cpp +++ b/plugins/peak_controller_effect/peak_controller_effect.cpp @@ -148,7 +148,7 @@ bool PeakControllerEffect::processAudioBuffer( sampleFrame * _buf, extern "C" { -// neccessary for getting instance out of shared lib +// necessary for getting instance out of shared lib Plugin * PLUGIN_EXPORT lmms_plugin_main( Model * _parent, void * _data ) { return new PeakControllerEffect( _parent, diff --git a/plugins/sf2_player/sf2_player.cpp b/plugins/sf2_player/sf2_player.cpp index 56479236d..cab2bd919 100644 --- a/plugins/sf2_player/sf2_player.cpp +++ b/plugins/sf2_player/sf2_player.cpp @@ -2,7 +2,7 @@ * sf2_player.cpp - a soundfont2 player using fluidSynth * * Copyright (c) 2008 Paul Giblock - * Copyright (c) 2009 Tobias Doerffel + * Copyright (c) 2009-2010 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -53,7 +53,7 @@ static const char * __supportedExts[] = extern "C" { -Plugin::Descriptor sf2player_plugin_descriptor = +Plugin::Descriptor PLUGIN_EXPORT sf2player_plugin_descriptor = { STRINGIFY( PLUGIN_NAME ), "Sf2 Player", @@ -636,6 +636,7 @@ void sf2Instrument::playNote( notePlayHandle * _n, sampleFrame * ) SF2PluginData * pluginData = static_cast( _n->m_pluginData ); +#ifdef SOMEONE_FIXED_PER_NOTE_PANNING if( pluginData->fluidVoice && pluginData->lastPanning != _n->getPanning() ) { @@ -650,6 +651,7 @@ void sf2Instrument::playNote( notePlayHandle * _n, sampleFrame * ) pluginData->lastPanning = _n->getPanning(); } +#endif const float currentVelocity = _n->volumeLevel( tfp ) * 127; if( pluginData->fluidVoice && @@ -1106,8 +1108,8 @@ void sf2InstrumentView::showPatchDialog() extern "C" { -// neccessary for getting instance out of shared lib -Plugin * lmms_plugin_main( Model *, void * _data ) +// necessary for getting instance out of shared lib +Plugin * PLUGIN_EXPORT lmms_plugin_main( Model *, void * _data ) { return new sf2Instrument( static_cast( _data ) ); } diff --git a/plugins/sid/sid_instrument.cpp b/plugins/sid/sid_instrument.cpp index 8769b9e0a..4a51a314d 100644 --- a/plugins/sid/sid_instrument.cpp +++ b/plugins/sid/sid_instrument.cpp @@ -815,7 +815,7 @@ void sidInstrumentView::modelChanged() extern "C" { -// neccessary for getting instance out of shared lib +// necessary for getting instance out of shared lib Plugin * PLUGIN_EXPORT lmms_plugin_main( Model *, void * _data ) { return( new sidInstrument( diff --git a/plugins/spectrum_analyzer/spectrum_analyzer.cpp b/plugins/spectrum_analyzer/spectrum_analyzer.cpp index 7e3686d44..5ce6c067f 100644 --- a/plugins/spectrum_analyzer/spectrum_analyzer.cpp +++ b/plugins/spectrum_analyzer/spectrum_analyzer.cpp @@ -1,8 +1,8 @@ /* * spectrum_analyzer.cpp - spectrum analyzer plugin * - * Copyright (c) 2008-2009 Tobias Doerffel - * + * Copyright (c) 2008-2010 Tobias Doerffel + * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * * This program is free software; you can redistribute it and/or @@ -82,6 +82,11 @@ bool spectrumAnalyzer::processAudioBuffer( sampleFrame * _buf, return( false ); } + if( !m_saControls.isViewVisible() ) + { + return true; + } + fpp_t f = 0; if( _frames > FFT_BUFFER_SIZE ) { @@ -163,7 +168,7 @@ bool spectrumAnalyzer::processAudioBuffer( sampleFrame * _buf, extern "C" { -// neccessary for getting instance out of shared lib +// necessary for getting instance out of shared lib Plugin * PLUGIN_EXPORT lmms_plugin_main( Model * _parent, void * _data ) { return( new spectrumAnalyzer( _parent, diff --git a/plugins/stereo_enhancer/stereo_enhancer.cpp b/plugins/stereo_enhancer/stereo_enhancer.cpp index 5b6b5386c..b9c75b3fe 100644 --- a/plugins/stereo_enhancer/stereo_enhancer.cpp +++ b/plugins/stereo_enhancer/stereo_enhancer.cpp @@ -163,7 +163,7 @@ void stereoEnhancerEffect::clearMyBuffer() extern "C" { -// neccessary for getting instance out of shared lib +// necessary for getting instance out of shared lib Plugin * PLUGIN_EXPORT lmms_plugin_main( Model * _parent, void * _data ) { return( new stereoEnhancerEffect( _parent, diff --git a/plugins/stereo_matrix/stereo_matrix.cpp b/plugins/stereo_matrix/stereo_matrix.cpp index 246763eff..b484d99ae 100644 --- a/plugins/stereo_matrix/stereo_matrix.cpp +++ b/plugins/stereo_matrix/stereo_matrix.cpp @@ -112,7 +112,7 @@ bool stereoMatrixEffect::processAudioBuffer( sampleFrame * _buf, extern "C" { -// neccessary for getting instance out of shared lib +// necessary for getting instance out of shared lib Plugin * PLUGIN_EXPORT lmms_plugin_main( Model * _parent, void * _data ) { return( new stereoMatrixEffect( _parent, diff --git a/plugins/stk/mallets/mallets.cpp b/plugins/stk/mallets/mallets.cpp index d4d21222a..b03267b2e 100644 --- a/plugins/stk/mallets/mallets.cpp +++ b/plugins/stk/mallets/mallets.cpp @@ -2,7 +2,8 @@ * mallets.cpp - tuned instruments that one would bang upon * * Copyright (c) 2006-2008 Danny McRae - * + * Copyright (c) 2009-2010 Tobias Doerffel + * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * * This program is free software; you can redistribute it and/or @@ -41,7 +42,7 @@ extern "C" { -Plugin::Descriptor malletsstk_plugin_descriptor = +Plugin::Descriptor PLUGIN_EXPORT malletsstk_plugin_descriptor = { STRINGIFY( PLUGIN_NAME ), "Mallets", @@ -654,8 +655,8 @@ malletsSynth::malletsSynth( const StkFloat _pitch, extern "C" { -// neccessary for getting instance out of shared lib -Plugin * lmms_plugin_main( Model *, void * _data ) +// necessary for getting instance out of shared lib +Plugin * PLUGIN_EXPORT lmms_plugin_main( Model *, void * _data ) { return new malletsInstrument( static_cast( _data ) ); } diff --git a/plugins/stk/mallets/mallets.h b/plugins/stk/mallets/mallets.h index 937d6686c..f40d89152 100644 --- a/plugins/stk/mallets/mallets.h +++ b/plugins/stk/mallets/mallets.h @@ -36,6 +36,12 @@ #include "note_play_handle.h" #include "led_checkbox.h" +// As of Stk 4.4 all classes and types have been moved to the namespace "stk". +// However in older versions this namespace does not exist, therefore declare it +// so this plugin builds with all versions of Stk. +namespace stk { } ; +using namespace stk; + class malletsSynth { diff --git a/plugins/triple_oscillator/TripleOscillator.cpp b/plugins/triple_oscillator/TripleOscillator.cpp index c550a57fb..a025546cf 100644 --- a/plugins/triple_oscillator/TripleOscillator.cpp +++ b/plugins/triple_oscillator/TripleOscillator.cpp @@ -865,7 +865,7 @@ void TripleOscillatorView::modelChanged() extern "C" { -// neccessary for getting instance out of shared lib +// necessary for getting instance out of shared lib Plugin * PLUGIN_EXPORT lmms_plugin_main( Model *, void * _data ) { return new TripleOscillator( static_cast( _data ) ); diff --git a/plugins/vestige/vestige.cpp b/plugins/vestige/vestige.cpp index 3b6fb056b..99a4c0116 100644 --- a/plugins/vestige/vestige.cpp +++ b/plugins/vestige/vestige.cpp @@ -51,7 +51,7 @@ static const char * __supportedExts[] = extern "C" { -Plugin::Descriptor vestige_plugin_descriptor = +Plugin::Descriptor PLUGIN_EXPORT vestige_plugin_descriptor = { STRINGIFY( PLUGIN_NAME ), "VeSTige", @@ -360,6 +360,11 @@ void VestigeInstrumentView::openPlugin() engine::getMixer()->lock(); m_vi->loadFile( ofd.selectedFiles()[0] ); engine::getMixer()->unlock(); + if( m_vi->m_plugin && m_vi->m_plugin->pluginWidget() ) + { + m_vi->m_plugin->pluginWidget()->setWindowIcon( + PLUGIN_NAME::getIconPixmap( "logo" ) ); + } } } @@ -448,8 +453,8 @@ void VestigeInstrumentView::paintEvent( QPaintEvent * ) extern "C" { -// neccessary for getting instance out of shared lib -Plugin * lmms_plugin_main( Model *, void * _data ) +// necessary for getting instance out of shared lib +Plugin * PLUGIN_EXPORT lmms_plugin_main( Model *, void * _data ) { return new vestigeInstrument( static_cast( _data ) ); } diff --git a/plugins/vibed/vibed.cpp b/plugins/vibed/vibed.cpp index f6630ec58..9ce83afb0 100644 --- a/plugins/vibed/vibed.cpp +++ b/plugins/vibed/vibed.cpp @@ -241,7 +241,7 @@ void vibed::loadSettings( const QDomElement & _this ) float * shp = 0; base64::decode( _this.attribute( "graph" + QString::number( i ) ), - (char * *) &shp, + &shp, &size ); // TODO: check whether size == 128 * sizeof( float ), // otherwise me might and up in a segfault @@ -543,7 +543,7 @@ vibedView::vibedView( Instrument * _instrument, m_stringSelector->setAccessibleName( tr( "String" ) ); m_stringSelector->setWhatsThis( tr( "The String selector is used to choose which string the controls are " -"editting. A Vibed instrument can contain up to nine independently " +"editing. A Vibed instrument can contain up to nine independently " "vibrating strings. The LED in the lower right corner of the " "waveform editor indicates whether the selected string is active." ) ); @@ -779,7 +779,7 @@ void vibedView::displayHelp() extern "C" { -// neccessary for getting instance out of shared lib +// necessary for getting instance out of shared lib Plugin * PLUGIN_EXPORT lmms_plugin_main( Model *, void * _data ) { return( new vibed( static_cast( _data ) ) ); diff --git a/plugins/vst_base/remote_vst_plugin.cpp b/plugins/vst_base/remote_vst_plugin.cpp index 0f9ba6c23..1da5a6a65 100644 --- a/plugins/vst_base/remote_vst_plugin.cpp +++ b/plugins/vst_base/remote_vst_plugin.cpp @@ -104,7 +104,7 @@ class RemoteVstPlugin; RemoteVstPlugin * __plugin = NULL; -DWORD __GuiThreadID = NULL; +DWORD __GuiThreadID = 0; @@ -813,7 +813,7 @@ void RemoteVstPlugin::saveChunkToFile( const std::string & _file ) void RemoteVstPlugin::loadChunkFromFile( const std::string & _file, int _len ) { - char buf[_len]; + char * buf = NULL; void * chunk = NULL; // various plugins need this in order to not crash when setting @@ -823,7 +823,8 @@ void RemoteVstPlugin::loadChunkFromFile( const std::string & _file, int _len ) // allocated buffer big enough? if( _len > actualLen ) { - // no, manually try our local buffer + // no, then manually allocate a buffer + buf = new char[_len]; chunk = buf; } @@ -831,6 +832,8 @@ void RemoteVstPlugin::loadChunkFromFile( const std::string & _file, int _len ) read( fd, chunk, _len ); close( fd ); pluginDispatch( 24, 0, _len, chunk ); + + delete[] buf; } diff --git a/plugins/vst_base/vst_base.cpp b/plugins/vst_base/vst_base.cpp index 51460fe19..f5ae7571f 100644 --- a/plugins/vst_base/vst_base.cpp +++ b/plugins/vst_base/vst_base.cpp @@ -2,7 +2,7 @@ * vst_base.cpp - VST-base-code to be used by any LMMS plugins dealing with VST- * plugins * - * Copyright (c) 2006-2009 Tobias Doerffel + * Copyright (c) 2006-2010 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -31,7 +31,7 @@ extern "C" { -Plugin::Descriptor vstbase_plugin_descriptor = +Plugin::Descriptor PLUGIN_EXPORT vstbase_plugin_descriptor = { STRINGIFY( PLUGIN_NAME ), "VST Base", diff --git a/plugins/vst_effect/VstEffect.cpp b/plugins/vst_effect/VstEffect.cpp index 02283851c..2ada8ca14 100644 --- a/plugins/vst_effect/VstEffect.cpp +++ b/plugins/vst_effect/VstEffect.cpp @@ -1,7 +1,7 @@ /* * VstEffect.cpp - class for handling VST effect plugins * - * Copyright (c) 2006-2009 Tobias Doerffel + * Copyright (c) 2006-2010 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -35,7 +35,7 @@ extern "C" { -Plugin::Descriptor vsteffect_plugin_descriptor = +Plugin::Descriptor PLUGIN_EXPORT vsteffect_plugin_descriptor = { STRINGIFY( PLUGIN_NAME ), "VST Effect", @@ -174,8 +174,8 @@ void VstEffect::closePlugin() extern "C" { -// neccessary for getting instance out of shared lib -Plugin * lmms_plugin_main( Model * _parent, void * _data ) +// necessary for getting instance out of shared lib +Plugin * PLUGIN_EXPORT lmms_plugin_main( Model * _parent, void * _data ) { return new VstEffect( _parent, static_cast( diff --git a/plugins/zynaddsubfx/CMakeLists.txt b/plugins/zynaddsubfx/CMakeLists.txt index 32ebbf801..2da4bd7ac 100644 --- a/plugins/zynaddsubfx/CMakeLists.txt +++ b/plugins/zynaddsubfx/CMakeLists.txt @@ -88,12 +88,24 @@ ENDIF(LMMS_BUILD_WIN32) BUILD_PLUGIN(zynaddsubfx ZynAddSubFx.cpp ZynAddSubFx.h MOCFILES ZynAddSubFx.h EMBEDDED_RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.png) TARGET_LINK_LIBRARIES(zynaddsubfx ZynAddSubFxCore) +IF(WIN32) + SET(WINRC "${CMAKE_CURRENT_BINARY_DIR}/zynaddsubfxrc.obj") + ADD_CUSTOM_COMMAND(OUTPUT ${WINRC} + COMMAND ${WINDRES} + -I${CMAKE_CURRENT_SOURCE_DIR} + -o${CMAKE_CURRENT_BINARY_DIR}/zynaddsubfxrc.obj + -i${CMAKE_CURRENT_BINARY_DIR}/zynaddsubfx.rc + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/zynaddsubfx.rc) +ENDIF(WIN32) SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${PLUGIN_DIR}") SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) -ADD_EXECUTABLE(RemoteZynAddSubFx RemoteZynAddSubFx.cpp ${ZYN_SRC_GUI}) +ADD_EXECUTABLE(RemoteZynAddSubFx RemoteZynAddSubFx.cpp ${ZYN_SRC_GUI} ${WINRC}) INSTALL(TARGETS RemoteZynAddSubFx RUNTIME DESTINATION ${PLUGIN_DIR}) -TARGET_LINK_LIBRARIES(RemoteZynAddSubFx -L${CMAKE_CURRENT_BINARY_DIR} -lZynAddSubFxCore ${CMAKE_CURRENT_BINARY_DIR}/fltk/bin/libfltk.a) +IF(LMMS_BUILD_LINUX) + SET(FONTCONFIG_LIBS -lfontconfig) +ENDIF(LMMS_BUILD_LINUX) +TARGET_LINK_LIBRARIES(RemoteZynAddSubFx -lpthread ${FONTCONFIG_LIBS} -L${CMAKE_CURRENT_BINARY_DIR} -lZynAddSubFxCore ${CMAKE_CURRENT_BINARY_DIR}/fltk/bin/libfltk.a) ADD_DEPENDENCIES(RemoteZynAddSubFx ZynAddSubFxCore) # link system libraries when on win32 diff --git a/plugins/zynaddsubfx/ChangeLog b/plugins/zynaddsubfx/ChangeLog index d0edbdc86..fb680430a 100644 --- a/plugins/zynaddsubfx/ChangeLog +++ b/plugins/zynaddsubfx/ChangeLog @@ -94,7 +94,7 @@ Programul incepe sa fie controlabil de Interfata 02 Aug 2002 - Inlaturat o eroare stupida care facea ca sa se seteze valorile EnvelopeParams la -1 (scria din Master:: prea mult) 03 Aug 2002 - Terminata interfata pentru ADnoteParameters.GlobalPars - Adaugat inca un parametru la lfo (continous LFO) care faca ca LFO-ul sa nu inceapa la fiecare NoteOn + Adaugat inca un parametru la lfo (continuous LFO) care faca ca LFO-ul sa nu inceapa la fiecare NoteOn Corectat doua erori la ...[nvoice].AmpEnvelope si ...[nvoice].FreqEnvelope Scrisa interfata pentru ADnoteParameters.VoicePars (fara FM+OSCIL...) 04 Aug 2002 - Scrisa interfata cu FM (fara Oscil) @@ -680,8 +680,8 @@ - Corectata eroare care facea ca sa nu mearga MIDI - LANSAT PE INTERNET - VERSIUNEA (2.0.0pre2 VST) -------------------------------------------------------------------------------------------------- -13 Aug 2004 - Inceput sa scriu modurile continous si discrete la PADnote -14 Aug 2004 - Terminat modul continous la PADnote +13 Aug 2004 - Inceput sa scriu modurile continuous si discrete la PADnote +14 Aug 2004 - Terminat modul continuous la PADnote - Corectata o mica eroare la OscilGen care facea daca adaptive harmonics e activ si phase randomness>0 sa rezulte si aleatorism in amplitudinile armonicelor - Inceput sa scriu Presets/Clipboard (Clipboardul, in stadiu actual va putea copia doar parametrii folositi si nu cei dezactivati) - Merge partial partea de Copy in clipboard diff --git a/plugins/zynaddsubfx/RemoteZynAddSubFx.cpp b/plugins/zynaddsubfx/RemoteZynAddSubFx.cpp index a70c637bf..5e4b2c34b 100644 --- a/plugins/zynaddsubfx/RemoteZynAddSubFx.cpp +++ b/plugins/zynaddsubfx/RemoteZynAddSubFx.cpp @@ -1,7 +1,7 @@ /* * RemoteZynAddSubFx.cpp - ZynAddSubFx-embedding plugin * - * Copyright (c) 2008-2009 Tobias Doerffel + * Copyright (c) 2008-2010 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -23,6 +23,10 @@ */ #include +#ifdef LMMS_BUILD_WIN32 +#include +#endif + #include #define BUILD_REMOTE_PLUGIN_CLIENT @@ -130,10 +134,20 @@ public: LocalZynAddSubFx::processAudio( _out ); } - static void * guiThread( void * _arg ); + static void * guiThread( void * _arg ) + { + RemoteZynAddSubFx * _this = + static_cast( _arg ); + + _this->guiThread(); + + return NULL; + } private: + void guiThread(); + const int m_guiSleepTime; pthread_t m_guiThreadHandle; @@ -145,33 +159,38 @@ private: -void * RemoteZynAddSubFx::guiThread( void * _arg ) + +void RemoteZynAddSubFx::guiThread() { - int e; + int exitProgram; MasterUI * ui = NULL; - RemoteZynAddSubFx * _this = static_cast( _arg ); - Master * master = _this->m_master; - - while( !_this->m_guiExit ) + while( !m_guiExit ) { if( ui ) { - Fl::wait( _this->m_guiSleepTime / 1000.0 ); + Fl::wait( m_guiSleepTime / 1000.0 ); } else { #ifdef LMMS_BUILD_WIN32 - Sleep( _this->m_guiSleepTime ); + Sleep( m_guiSleepTime ); #else - usleep( _this->m_guiSleepTime*1000 ); + usleep( m_guiSleepTime*1000 ); #endif } - pthread_mutex_lock( &_this->m_guiMutex ); - while( _this->m_guiMessages.size() ) + if( exitProgram == 1 ) { - RemotePluginClient::message m = _this->m_guiMessages.front(); - _this->m_guiMessages.pop(); + pthread_mutex_lock( &m_master->mutex ); + sendMessage( IdHideUI ); + exitProgram = 0; + pthread_mutex_unlock( &m_master->mutex ); + } + pthread_mutex_lock( &m_guiMutex ); + while( m_guiMessages.size() ) + { + RemotePluginClient::message m = m_guiMessages.front(); + m_guiMessages.pop(); switch( m.id ) { case IdShowUI: @@ -179,44 +198,28 @@ void * RemoteZynAddSubFx::guiThread( void * _arg ) if( !ui ) { Fl::scheme( "plastic" ); - ui = new MasterUI( master, &e ); + ui = new MasterUI( m_master, &exitProgram ); } ui->showUI(); ui->refresh_master_ui(); break; - case IdHideUI: - if( !ui ) break; - switch( config.cfg.UserInterfaceMode ) - { - case 0: - ui->selectuiwindow->hide(); - break; - case 1: - ui->masterwindow->hide(); - break; - case 2: - ui->simplemasterwindow->hide(); - break; - } - break; - case IdLoadSettingsFromFile: { - _this->LocalZynAddSubFx::loadXML( m.getString() ); + LocalZynAddSubFx::loadXML( m.getString() ); if( ui ) { ui->refresh_master_ui(); } - pthread_mutex_lock( &master->mutex ); - _this->sendMessage( IdLoadSettingsFromFile ); - pthread_mutex_unlock( &master->mutex ); + pthread_mutex_lock( &m_master->mutex ); + sendMessage( IdLoadSettingsFromFile ); + pthread_mutex_unlock( &m_master->mutex ); break; } case IdLoadPresetFromFile: { - _this->LocalZynAddSubFx::loadPreset( m.getString(), ui ? + LocalZynAddSubFx::loadPreset( m.getString(), ui ? ui->npartcounter->value()-1 : 0 ); if( ui ) { @@ -224,9 +227,9 @@ void * RemoteZynAddSubFx::guiThread( void * _arg ) ui->updatepanel(); ui->refresh_master_ui(); } - pthread_mutex_lock( &master->mutex ); - _this->sendMessage( IdLoadPresetFromFile ); - pthread_mutex_unlock( &master->mutex ); + pthread_mutex_lock( &m_master->mutex ); + sendMessage( IdLoadPresetFromFile ); + pthread_mutex_unlock( &m_master->mutex ); break; } @@ -234,13 +237,11 @@ void * RemoteZynAddSubFx::guiThread( void * _arg ) break; } } - pthread_mutex_unlock( &_this->m_guiMutex ); + pthread_mutex_unlock( &m_guiMutex ); } Fl::flush(); delete ui; - - return NULL; } diff --git a/plugins/zynaddsubfx/ZynAddSubFx.cpp b/plugins/zynaddsubfx/ZynAddSubFx.cpp index 37c4dfb11..0f022e210 100644 --- a/plugins/zynaddsubfx/ZynAddSubFx.cpp +++ b/plugins/zynaddsubfx/ZynAddSubFx.cpp @@ -69,6 +69,39 @@ Plugin::Descriptor PLUGIN_EXPORT zynaddsubfx_plugin_descriptor = +ZynAddSubFxRemotePlugin::ZynAddSubFxRemotePlugin() : + QObject(), + RemotePlugin( "RemoteZynAddSubFx", false ) +{ +} + + + + +ZynAddSubFxRemotePlugin::~ZynAddSubFxRemotePlugin() +{ +} + + + +bool ZynAddSubFxRemotePlugin::processMessage( const message & _m ) +{ + switch( _m.id ) + { + case IdHideUI: + emit clickedCloseButton(); + return true; + default: + break; + } + + return RemotePlugin::processMessage( _m ); +} + + + + + ZynAddSubFxInstrument::ZynAddSubFxInstrument( InstrumentTrack * _instrumentTrack ) : Instrument( _instrumentTrack, &zynaddsubfx_plugin_descriptor ), @@ -277,7 +310,7 @@ void ZynAddSubFxInstrument::initPlugin() if( m_hasGUI ) { - m_remotePlugin = new RemotePlugin( "RemoteZynAddSubFx", false ); + m_remotePlugin = new ZynAddSubFxRemotePlugin(); m_remotePlugin->lock(); m_remotePlugin->waitForInitDone( false ); @@ -358,6 +391,12 @@ void ZynAddSubFxView::toggleUI() ZynAddSubFxInstrument * model = castModel(); model->m_hasGUI = m_toggleUIButton->isChecked(); model->reloadPlugin(); + + if( model->m_remotePlugin ) + { + connect( model->m_remotePlugin, SIGNAL( clickedCloseButton() ), + m_toggleUIButton, SLOT( toggle() ) ); + } } @@ -367,7 +406,7 @@ void ZynAddSubFxView::toggleUI() extern "C" { -// neccessary for getting instance out of shared lib +// necessary for getting instance out of shared lib Plugin * PLUGIN_EXPORT lmms_plugin_main( Model *, void * _data ) { diff --git a/plugins/zynaddsubfx/ZynAddSubFx.h b/plugins/zynaddsubfx/ZynAddSubFx.h index 3f2d91549..2792f30d7 100644 --- a/plugins/zynaddsubfx/ZynAddSubFx.h +++ b/plugins/zynaddsubfx/ZynAddSubFx.h @@ -39,6 +39,24 @@ class ZynAddSubFxView; class notePlayHandle; + +class ZynAddSubFxRemotePlugin : public QObject, public RemotePlugin +{ + Q_OBJECT +public: + ZynAddSubFxRemotePlugin(); + virtual ~ZynAddSubFxRemotePlugin(); + + virtual bool processMessage( const message & _m ); + + +signals: + void clickedCloseButton(); + +} ; + + + class ZynAddSubFxInstrument : public Instrument { Q_OBJECT @@ -77,7 +95,7 @@ private: bool m_hasGUI; QMutex m_pluginMutex; LocalZynAddSubFx * m_plugin; - RemotePlugin * m_remotePlugin; + ZynAddSubFxRemotePlugin * m_remotePlugin; friend class ZynAddSubFxView; diff --git a/plugins/zynaddsubfx/artwork.png b/plugins/zynaddsubfx/artwork.png index d661fc62f..7d158bdaa 100644 Binary files a/plugins/zynaddsubfx/artwork.png and b/plugins/zynaddsubfx/artwork.png differ diff --git a/plugins/zynaddsubfx/fltk/CMakeLists.txt b/plugins/zynaddsubfx/fltk/CMakeLists.txt index d877e6c18..5010016f3 100644 --- a/plugins/zynaddsubfx/fltk/CMakeLists.txt +++ b/plugins/zynaddsubfx/fltk/CMakeLists.txt @@ -25,7 +25,7 @@ SET(LIBRARY_OUTPUT_PATH "${FLTK_BINARY_DIR}/bin" CACHE INTERNAL OPTION(BUILD_SHARED_LIBS "Build FLTK as a shared library" OFF) # Search for modules in the FLTK source dir first -SET(CMAKE_MODULE_PATH "${FLTK_SOURCE_DIR}/CMake") +SET(CMAKE_MODULE_PATH ${FLTK_SOURCE_DIR}/CMake ${CMAKE_MODULE_PATH}) #----------------------------------------------------------------------------- # Test for some required system information. diff --git a/plugins/zynaddsubfx/fltk/FL/win32.H b/plugins/zynaddsubfx/fltk/FL/win32.H index a9f482979..ddd7230f1 100644 --- a/plugins/zynaddsubfx/fltk/FL/win32.H +++ b/plugins/zynaddsubfx/fltk/FL/win32.H @@ -34,6 +34,7 @@ # error "Never use directly; include instead." #endif // !Fl_X_H +#include #include // In some of the distributions, the gcc header files are missing some stuff: #ifndef LPMINMAXINFO diff --git a/plugins/zynaddsubfx/fltk/src/Fl_lock.cxx b/plugins/zynaddsubfx/fltk/src/Fl_lock.cxx index 1d2b617d1..58ae297e6 100644 --- a/plugins/zynaddsubfx/fltk/src/Fl_lock.cxx +++ b/plugins/zynaddsubfx/fltk/src/Fl_lock.cxx @@ -187,6 +187,7 @@ int Fl::awake(Fl_Awake_Handler func, void *data) { See also: \ref advanced_multithreading */ #ifdef WIN32 +# include # include # include # include diff --git a/plugins/zynaddsubfx/fltk/src/xutf8/utf8Wrap.c b/plugins/zynaddsubfx/fltk/src/xutf8/utf8Wrap.c index 4961ac0f4..8e513e767 100644 --- a/plugins/zynaddsubfx/fltk/src/xutf8/utf8Wrap.c +++ b/plugins/zynaddsubfx/fltk/src/xutf8/utf8Wrap.c @@ -284,7 +284,7 @@ load_fonts(Display *dpy, } /*********************************************************************/ -/** Creates an array of XFontStruct acording to the comma separated **/ +/** Creates an array of XFontStruct according to the comma separated **/ /** list of fonts. XLoad all fonts. **/ /*********************************************************************/ XUtf8FontStruct * diff --git a/plugins/zynaddsubfx/src/Params/LFOParams.cpp b/plugins/zynaddsubfx/src/Params/LFOParams.cpp index 3cfc37fc8..fe993ed93 100644 --- a/plugins/zynaddsubfx/src/Params/LFOParams.cpp +++ b/plugins/zynaddsubfx/src/Params/LFOParams.cpp @@ -33,7 +33,7 @@ LFOParams::LFOParams(char Pfreq_, char PLFOtype_, char Prandomness_, char Pdelay_, - char Pcontinous_, + char Pcontinuous_, char fel_):Presets() { switch(fel_) { @@ -53,7 +53,7 @@ LFOParams::LFOParams(char Pfreq_, DLFOtype = PLFOtype_; Drandomness = Prandomness_; Ddelay = Pdelay_; - Dcontinous = Pcontinous_; + Dcontinuous = Pcontinuous_; fel = fel_; time = 0; @@ -71,7 +71,7 @@ void LFOParams::defaults() PLFOtype = DLFOtype; Prandomness = Drandomness; Pdelay = Ddelay; - Pcontinous = Dcontinous; + Pcontinuous = Dcontinuous; Pfreqrand = 0; Pstretch = 64; } @@ -87,7 +87,7 @@ void LFOParams::add2XML(XMLwrapper *xml) xml->addpar("randomness_frequency", Pfreqrand); xml->addpar("delay", Pdelay); xml->addpar("stretch", Pstretch); - xml->addparbool("continous", Pcontinous); + xml->addparbool("continuous", Pcontinuous); } void LFOParams::getfromXML(XMLwrapper *xml) @@ -100,6 +100,6 @@ void LFOParams::getfromXML(XMLwrapper *xml) Pfreqrand = xml->getpar127("randomness_frequency", Pfreqrand); Pdelay = xml->getpar127("delay", Pdelay); Pstretch = xml->getpar127("stretch", Pstretch); - Pcontinous = xml->getparbool("continous", Pcontinous); + Pcontinuous = xml->getparbool("continuous", Pcontinuous); } diff --git a/plugins/zynaddsubfx/src/Params/LFOParams.h b/plugins/zynaddsubfx/src/Params/LFOParams.h index 6a7dcd915..b1b99eecd 100644 --- a/plugins/zynaddsubfx/src/Params/LFOParams.h +++ b/plugins/zynaddsubfx/src/Params/LFOParams.h @@ -35,7 +35,7 @@ class LFOParams:public Presets char PLFOtype_, char Prandomness_, char Pdelay_, - char Pcontinous, + char Pcontinuous, char fel_); ~LFOParams(); @@ -52,11 +52,11 @@ class LFOParams:public Presets unsigned char Prandomness; /**me = NULL; diff --git a/plugins/zynaddsubfx/src/Synth/LFO.cpp b/plugins/zynaddsubfx/src/Synth/LFO.cpp index a7d00232b..7b665852f 100644 --- a/plugins/zynaddsubfx/src/Synth/LFO.cpp +++ b/plugins/zynaddsubfx/src/Synth/LFO.cpp @@ -38,7 +38,7 @@ LFO::LFO(LFOParams *lfopars, REALTYPE basefreq) (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->Pcontinuous == 0) { if(lfopars->Pstartphase == 0) x = RND; else diff --git a/plugins/zynaddsubfx/src/UI/ADnoteUI.cc b/plugins/zynaddsubfx/src/UI/ADnoteUI.cc index 9d3ca6caf..854a88f1b 100644 --- a/plugins/zynaddsubfx/src/UI/ADnoteUI.cc +++ b/plugins/zynaddsubfx/src/UI/ADnoteUI.cc @@ -1050,7 +1050,7 @@ Fl_Group* ADvoiceUI::make_window() { o->value(pars->VoicePar[nvoice].Pfixedfreq); } // Fl_Check_Button* o { WidgetPDial* o = fixedfreqetdial = new WidgetPDial(405, 255, 15, 15, "Eq.T."); - fixedfreqetdial->tooltip("How the frequency varies acording to the keyboard (leftmost for fixed frequen\ + fixedfreqetdial->tooltip("How the frequency varies according to the keyboard (leftmost for fixed frequen\ cy)"); fixedfreqetdial->box(FL_ROUND_UP_BOX); fixedfreqetdial->color(FL_BACKGROUND_COLOR); diff --git a/plugins/zynaddsubfx/src/UI/ADnoteUI.fl b/plugins/zynaddsubfx/src/UI/ADnoteUI.fl index 748156c74..dc5e6adc6 100644 --- a/plugins/zynaddsubfx/src/UI/ADnoteUI.fl +++ b/plugins/zynaddsubfx/src/UI/ADnoteUI.fl @@ -481,7 +481,7 @@ if (x==0) fixedfreqetdial->deactivate(); Fl_Dial fixedfreqetdial { label {Eq.T.} callback {pars->VoicePar[nvoice].PfixedfreqET=(int) o->value();} - tooltip {How the frequency varies acording to the keyboard (leftmost for fixed frequency)} xywh {405 255 15 15} box ROUND_UP_BOX labelsize 10 align 8 maximum 127 step 1 + tooltip {How the frequency varies according to the keyboard (leftmost for fixed frequency)} xywh {405 255 15 15} box ROUND_UP_BOX labelsize 10 align 8 maximum 127 step 1 code0 {o->value(pars->VoicePar[nvoice].PfixedfreqET);} code1 {if (pars->VoicePar[nvoice].Pfixedfreq==0) o->deactivate();} class WidgetPDial diff --git a/plugins/zynaddsubfx/src/UI/LFOUI.cc b/plugins/zynaddsubfx/src/UI/LFOUI.cc index af6c1f189..57cdc956a 100644 --- a/plugins/zynaddsubfx/src/UI/LFOUI.cc +++ b/plugins/zynaddsubfx/src/UI/LFOUI.cc @@ -57,11 +57,11 @@ Fl_Menu_Item LFOUI::menu_LFOtype[] = { {0,0,0,0,0,0,0,0,0} }; -void LFOUI::cb_continous_i(Fl_Check_Button* o, void*) { - pars->Pcontinous=(int)o->value(); +void LFOUI::cb_continuous_i(Fl_Check_Button* o, void*) { + pars->Pcontinuous=(int)o->value(); } -void LFOUI::cb_continous(Fl_Check_Button* o, void* v) { - ((LFOUI*)(o->parent()->parent()->user_data()))->cb_continous_i(o,v); +void LFOUI::cb_continuous(Fl_Check_Button* o, void* v) { + ((LFOUI*)(o->parent()->parent()->user_data()))->cb_continuous_i(o,v); } void LFOUI::cb_freqrand_i(WidgetPDial* o, void*) { @@ -203,13 +203,13 @@ Fl_Group* LFOUI::make_window() { LFOtype->align(Fl_Align(FL_ALIGN_BOTTOM)); LFOtype->menu(menu_LFOtype); } // Fl_Choice* LFOtype - { continous = new Fl_Check_Button(165, 35, 15, 15, "C."); - continous->tooltip("Continous LFO"); - continous->down_box(FL_DOWN_BOX); - continous->labelsize(10); - continous->callback((Fl_Callback*)cb_continous); - continous->align(Fl_Align(FL_ALIGN_BOTTOM)); - } // Fl_Check_Button* continous + { continuous = new Fl_Check_Button(165, 35, 15, 15, "C."); + continuous->tooltip("Continuous LFO"); + continuous->down_box(FL_DOWN_BOX); + continuous->labelsize(10); + continuous->callback((Fl_Callback*)cb_continuous); + continuous->align(Fl_Align(FL_ALIGN_BOTTOM)); + } // Fl_Check_Button* continuous { freqrand = new WidgetPDial(205, 7, 20, 20, "F.R."); freqrand->tooltip("LFO Frequency Randomness"); freqrand->box(FL_ROUND_UP_BOX); @@ -268,7 +268,7 @@ void LFOUI::refresh() { intensity->value(pars->Pintensity); startphase->value(pars->Pstartphase); delay->value(pars->Pdelay); -continous->value(pars->Pcontinous); +continuous->value(pars->Pcontinuous); stretch->value(pars->Pstretch); randomness->value(pars->Prandomness); freqrand->value(pars->Pfreqrand); diff --git a/plugins/zynaddsubfx/src/UI/LFOUI.fl b/plugins/zynaddsubfx/src/UI/LFOUI.fl index ca0433a2d..d5fcc2eba 100644 --- a/plugins/zynaddsubfx/src/UI/LFOUI.fl +++ b/plugins/zynaddsubfx/src/UI/LFOUI.fl @@ -119,10 +119,10 @@ hide(); xywh {70 70 100 20} labelfont 1 labelsize 10 } } - Fl_Check_Button continous { + Fl_Check_Button continuous { label {C.} - callback {pars->Pcontinous=(int)o->value();} - tooltip {Continous LFO} xywh {165 35 15 15} down_box DOWN_BOX labelsize 10 align 2 + callback {pars->Pcontinuous=(int)o->value();} + tooltip {Continuous LFO} xywh {165 35 15 15} down_box DOWN_BOX labelsize 10 align 2 } Fl_Dial freqrand { label {F.R.} @@ -154,7 +154,7 @@ hide(); intensity->value(pars->Pintensity); startphase->value(pars->Pstartphase); delay->value(pars->Pdelay); -continous->value(pars->Pcontinous); +continuous->value(pars->Pcontinuous); stretch->value(pars->Pstretch); randomness->value(pars->Prandomness); freqrand->value(pars->Pfreqrand); diff --git a/plugins/zynaddsubfx/src/UI/LFOUI.h b/plugins/zynaddsubfx/src/UI/LFOUI.h index 6959fe3f3..f05c0bde2 100644 --- a/plugins/zynaddsubfx/src/UI/LFOUI.h +++ b/plugins/zynaddsubfx/src/UI/LFOUI.h @@ -56,10 +56,10 @@ private: static void cb_LFOtype(Fl_Choice*, void*); static Fl_Menu_Item menu_LFOtype[]; public: - Fl_Check_Button *continous; + Fl_Check_Button *continuous; private: - void cb_continous_i(Fl_Check_Button*, void*); - static void cb_continous(Fl_Check_Button*, void*); + void cb_continuous_i(Fl_Check_Button*, void*); + static void cb_continuous(Fl_Check_Button*, void*); public: WidgetPDial *freqrand; private: diff --git a/plugins/zynaddsubfx/src/UI/MasterUI.cc b/plugins/zynaddsubfx/src/UI/MasterUI.cc index bd8545239..bc1b836a9 100644 --- a/plugins/zynaddsubfx/src/UI/MasterUI.cc +++ b/plugins/zynaddsubfx/src/UI/MasterUI.cc @@ -433,10 +433,10 @@ void MasterUI::cb_masterwindow_i(Fl_Double_Window*, void*) { #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."); #else -if (fl_choice("Exit and leave the unsaved data?","No","Yes",NULL)) { +//if (fl_choice("Exit and leave the unsaved data?","No","Yes",NULL)) { config.save(); *exitprogram=1; -}; +//}; #endif } void MasterUI::cb_masterwindow(Fl_Double_Window* o, void* v) { @@ -996,10 +996,10 @@ void MasterUI::cb_simplemasterwindow_i(Fl_Double_Window*, void*) { #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."); #else -if (fl_choice("Exit and leave the unsaved data?","No","Yes",NULL)) { +//if (fl_choice("Exit and leave the unsaved data?","No","Yes",NULL)) { config.save(); *exitprogram=1; -}; +//}; #endif } void MasterUI::cb_simplemasterwindow(Fl_Double_Window* o, void* v) { @@ -2331,6 +2331,9 @@ configui=new ConfigUI(); sequi=new SeqUI(master); make_window(); +#ifdef OS_WINDOWS +masterwindow->icon((char *)LoadIcon(GetModuleHandle(NULL), "zynaddsubfx_icon")); +#endif presetsui=new PresetsUI(); setfilelabel(NULL); swapefftype=0; diff --git a/plugins/zynaddsubfx/src/UI/MasterUI.fl b/plugins/zynaddsubfx/src/UI/MasterUI.fl index a844def6c..451c9f422 100644 --- a/plugins/zynaddsubfx/src/UI/MasterUI.fl +++ b/plugins/zynaddsubfx/src/UI/MasterUI.fl @@ -421,10 +421,10 @@ class MasterUI {} { 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."); \#else -if (fl_choice("Exit and leave the unsaved data?","No","Yes",NULL)) { +//if (fl_choice("Exit and leave the unsaved data?","No","Yes",NULL)) { config.save(); *exitprogram=1; -}; +//}; \#endif} xywh {31 206 390 465} type Double hide xclass zynaddsubfx } { @@ -1076,10 +1076,10 @@ updatepanel();} 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."); \#else -if (fl_choice("Exit and leave the unsaved data?","No","Yes",NULL)) { +//if (fl_choice("Exit and leave the unsaved data?","No","Yes",NULL)) { config.save(); *exitprogram=1; -}; +//}; \#endif} xywh {400 405 600 335} type Double hide } { @@ -1636,6 +1636,9 @@ configui=new ConfigUI(); sequi=new SeqUI(master); make_window(); +\#ifdef OS_WINDOWS +masterwindow->icon((char *)LoadIcon(GetModuleHandle(NULL), "zynaddsubfx_icon")); +\#endif presetsui=new PresetsUI(); setfilelabel(NULL); swapefftype=0; diff --git a/plugins/zynaddsubfx/src/UI/PADnoteUI.cc b/plugins/zynaddsubfx/src/UI/PADnoteUI.cc index 0478e4cb1..86ab5fa78 100644 --- a/plugins/zynaddsubfx/src/UI/PADnoteUI.cc +++ b/plugins/zynaddsubfx/src/UI/PADnoteUI.cc @@ -516,7 +516,7 @@ void PADnoteUI::cb_spectrummode(Fl_Choice* o, void* v) { Fl_Menu_Item PADnoteUI::menu_spectrummode[] = { {"Bandwidth", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, {"Discrete", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"Continous", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, + {"Continuous", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, {0,0,0,0,0,0,0,0,0} }; @@ -1149,7 +1149,7 @@ Fl_Double_Window* PADnoteUI::make_window() { o->value(pars->Pfixedfreq); } // Fl_Check_Button* hz440 { WidgetPDial* o = fixedfreqetdial = new WidgetPDial(420, 295, 15, 15, "Eq.T."); - fixedfreqetdial->tooltip("How the frequency varies acording to the keyboard (leftmost for fixed frequen\ + fixedfreqetdial->tooltip("How the frequency varies according to the keyboard (leftmost for fixed frequen\ cy)"); fixedfreqetdial->box(FL_ROUND_UP_BOX); fixedfreqetdial->color(FL_BACKGROUND_COLOR); diff --git a/plugins/zynaddsubfx/src/UI/PADnoteUI.fl b/plugins/zynaddsubfx/src/UI/PADnoteUI.fl index 74441c199..3f03dc0ea 100644 --- a/plugins/zynaddsubfx/src/UI/PADnoteUI.fl +++ b/plugins/zynaddsubfx/src/UI/PADnoteUI.fl @@ -762,7 +762,7 @@ cbwidget->do_callback();} xywh {125 125 100 20} labelfont 1 labelsize 11 } MenuItem {} { - label Continous + label Continuous xywh {115 115 100 20} labelfont 1 labelsize 11 } } @@ -842,7 +842,7 @@ if (x==0) fixedfreqetdial->deactivate(); Fl_Dial fixedfreqetdial { label {Eq.T.} callback {pars->PfixedfreqET=(int) o->value();} - tooltip {How the frequency varies acording to the keyboard (leftmost for fixed frequency)} xywh {420 295 15 15} box ROUND_UP_BOX labelsize 10 align 8 maximum 127 step 1 + tooltip {How the frequency varies according to the keyboard (leftmost for fixed frequency)} xywh {420 295 15 15} box ROUND_UP_BOX labelsize 10 align 8 maximum 127 step 1 code0 {o->value(pars->PfixedfreqET);} code1 {if (pars->Pfixedfreq==0) o->deactivate();} class WidgetPDial diff --git a/plugins/zynaddsubfx/src/UI/SUBnoteUI.cc b/plugins/zynaddsubfx/src/UI/SUBnoteUI.cc index c00c374c4..a28f8d9a1 100644 --- a/plugins/zynaddsubfx/src/UI/SUBnoteUI.cc +++ b/plugins/zynaddsubfx/src/UI/SUBnoteUI.cc @@ -513,7 +513,7 @@ Fl_Double_Window* SUBnoteUI::make_window() { o->value(pars->Pfixedfreq); } // Fl_Check_Button* hz440 { WidgetPDial* o = fixedfreqetdial = new WidgetPDial(610, 45, 15, 15, "Eq.T."); - fixedfreqetdial->tooltip("How the frequency varies acording to the keyboard (leftmost for fixed frequen\ + fixedfreqetdial->tooltip("How the frequency varies according to the keyboard (leftmost for fixed frequen\ cy)"); fixedfreqetdial->box(FL_ROUND_UP_BOX); fixedfreqetdial->color(FL_BACKGROUND_COLOR); diff --git a/plugins/zynaddsubfx/src/UI/SUBnoteUI.fl b/plugins/zynaddsubfx/src/UI/SUBnoteUI.fl index ef50a0bb9..d7406d475 100644 --- a/plugins/zynaddsubfx/src/UI/SUBnoteUI.fl +++ b/plugins/zynaddsubfx/src/UI/SUBnoteUI.fl @@ -276,7 +276,7 @@ if (x==0) fixedfreqetdial->deactivate(); Fl_Dial fixedfreqetdial { label {Eq.T.} callback {pars->PfixedfreqET=(int) o->value();} - tooltip {How the frequency varies acording to the keyboard (leftmost for fixed frequency)} xywh {610 45 15 15} box ROUND_UP_BOX labelsize 10 align 8 maximum 127 step 1 + tooltip {How the frequency varies according to the keyboard (leftmost for fixed frequency)} xywh {610 45 15 15} box ROUND_UP_BOX labelsize 10 align 8 maximum 127 step 1 code0 {o->value(pars->PfixedfreqET);} code1 {if (pars->Pfixedfreq==0) o->deactivate();} class WidgetPDial diff --git a/plugins/zynaddsubfx/zynaddsubfx.rc.in b/plugins/zynaddsubfx/zynaddsubfx.rc.in new file mode 100644 index 000000000..ebc0c32ad --- /dev/null +++ b/plugins/zynaddsubfx/zynaddsubfx.rc.in @@ -0,0 +1,26 @@ +zynaddsubfx_icon ICON zynaddsubfx_icon.ico +#include + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 0,2,3,0 + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE VFT2_UNKNOWN +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + //language ID = U.S. English, charset = Windows, Multilingual + BEGIN + VALUE "Comments", "ZynAddSubFX Plugin - Linux MultiMedia Studio (http://lmms.sf.net)\0" + VALUE "CompanyName", "LMMS Developers\0" + VALUE "FileDescription", "ZynAddSubFX LMMS Plugin\0" + VALUE "FileVersion", "2.3.0/@VERSION@\0" + VALUE "LegalCopyright", "Copyright (c) Nasca Octavian Paul, Mark McCurry, Harald Hvaal, Tobias Doerffel\0" + VALUE "OriginalFilename", "RemoteZynAddSubFx.exe\0" + VALUE "ProductName", "ZynAddSubFX/LMMS\0" + VALUE "ProductVersion", "2.3.0/@VERSION@\0" + END + END +END diff --git a/plugins/zynaddsubfx/zynaddsubfx_icon.ico b/plugins/zynaddsubfx/zynaddsubfx_icon.ico new file mode 100644 index 000000000..80f0519d3 Binary files /dev/null and b/plugins/zynaddsubfx/zynaddsubfx_icon.ico differ diff --git a/src/3rdparty/samplerate/float_cast.h b/src/3rdparty/samplerate/float_cast.h index af3f237ed..ee981c5e4 100644 --- a/src/3rdparty/samplerate/float_cast.h +++ b/src/3rdparty/samplerate/float_cast.h @@ -45,7 +45,7 @@ ** long int lrint (double x) ; */ -#include "config.h" +#include "src_config.h" /* ** The presence of the required functions are detected during the configure diff --git a/src/3rdparty/samplerate/samplerate.c b/src/3rdparty/samplerate/samplerate.c index 67062e257..b41555f16 100644 --- a/src/3rdparty/samplerate/samplerate.c +++ b/src/3rdparty/samplerate/samplerate.c @@ -26,7 +26,7 @@ #include #include -#include "config.h" +#include "src_config.h" #include "samplerate.h" #include "float_cast.h" diff --git a/src/3rdparty/samplerate/config.h b/src/3rdparty/samplerate/src_config.h similarity index 82% rename from src/3rdparty/samplerate/config.h rename to src/3rdparty/samplerate/src_config.h index 9d6531864..77ba02454 100644 --- a/src/3rdparty/samplerate/config.h +++ b/src/3rdparty/samplerate/src_config.h @@ -5,4 +5,4 @@ #endif #define PACKAGE "libsamplerate" -#define VERSION "0.1.4" +#define VERSION "0.1.7" diff --git a/src/3rdparty/samplerate/src_linear.c b/src/3rdparty/samplerate/src_linear.c index f97ba45db..cfd585a3e 100644 --- a/src/3rdparty/samplerate/src_linear.c +++ b/src/3rdparty/samplerate/src_linear.c @@ -26,7 +26,7 @@ #include #include -#include "config.h" +#include "src_config.h" #include "float_cast.h" #include "common.h" diff --git a/src/3rdparty/samplerate/src_sinc.c b/src/3rdparty/samplerate/src_sinc.c index b9b00fed9..846e30a57 100644 --- a/src/3rdparty/samplerate/src_sinc.c +++ b/src/3rdparty/samplerate/src_sinc.c @@ -26,7 +26,7 @@ #include #include -#include "config.h" +#include "src_config.h" #include "float_cast.h" #include "common.h" diff --git a/src/3rdparty/samplerate/src_zoh.c b/src/3rdparty/samplerate/src_zoh.c index 5f36d28f6..87545f555 100644 --- a/src/3rdparty/samplerate/src_zoh.c +++ b/src/3rdparty/samplerate/src_zoh.c @@ -26,7 +26,7 @@ #include #include -#include "config.h" +#include "src_config.h" #include "float_cast.h" #include "common.h" diff --git a/src/core/AutomatableModel.cpp b/src/core/AutomatableModel.cpp index 7762edcb8..26d2e91bd 100644 --- a/src/core/AutomatableModel.cpp +++ b/src/core/AutomatableModel.cpp @@ -44,11 +44,11 @@ AutomatableModel::AutomatableModel( DataType _type, const QString & _display_name, bool _default_constructed ) : Model( _parent, _display_name, _default_constructed ), - m_minValue( _min ), - m_maxValue( _max ), m_dataType( _type ), m_value( _val ), m_initValue( _val ), + m_minValue( _min ), + m_maxValue( _max ), m_step( _step ), m_range( _max - _min ), m_journalEntryReady( false ), @@ -145,7 +145,7 @@ void AutomatableModel::loadSettings( const QDomElement & _this, p->loadSettings( node.toElement() ); setValue( p->valueAt( 0 ) ); // in older projects we sometimes have odd automations - // with just one value in - eliminate if neccessary + // with just one value in - eliminate if necessary if( !p->hasAutomation() ) { delete p; diff --git a/src/core/EnvelopeAndLfoParameters.cpp b/src/core/EnvelopeAndLfoParameters.cpp index 28209cb06..521c51452 100644 --- a/src/core/EnvelopeAndLfoParameters.cpp +++ b/src/core/EnvelopeAndLfoParameters.cpp @@ -1,8 +1,8 @@ /* * EnvelopeAndLfoParameters.cpp - class EnvelopeAndLfoParameters * - * Copyright (c) 2004-2008 Tobias Doerffel - * + * Copyright (c) 2004-2010 Tobias Doerffel + * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * * This program is free software; you can redistribute it and/or @@ -38,7 +38,53 @@ extern const float SECS_PER_ENV_SEGMENT = 5.0f; extern const float SECS_PER_LFO_OSCILLATION = 20.0f; -QVector EnvelopeAndLfoParameters::s_EaLParametersInstances; +EnvelopeAndLfoParameters::LfoInstances * EnvelopeAndLfoParameters::s_lfoInstances = NULL; + + +void EnvelopeAndLfoParameters::LfoInstances::trigger() +{ + QMutexLocker m( &m_lfoListMutex ); + for( LfoList::Iterator it = m_lfos.begin(); + it != m_lfos.end(); ++it ) + { + ( *it )->m_lfoFrame += + engine::getMixer()->framesPerPeriod(); + ( *it )->m_bad_lfoShapeData = true; + } +} + + + + +void EnvelopeAndLfoParameters::LfoInstances::reset() +{ + QMutexLocker m( &m_lfoListMutex ); + for( LfoList::Iterator it = m_lfos.begin(); + it != m_lfos.end(); ++it ) + { + ( *it )->m_lfoFrame = 0; + ( *it )->m_bad_lfoShapeData = true; + } +} + + + +void EnvelopeAndLfoParameters::LfoInstances::add( EnvelopeAndLfoParameters * lfo ) +{ + QMutexLocker m( &m_lfoListMutex ); + m_lfos.append( lfo ); +} + + + + +void EnvelopeAndLfoParameters::LfoInstances::remove( EnvelopeAndLfoParameters * lfo ) +{ + QMutexLocker m( &m_lfoListMutex ); + m_lfos.removeAll( lfo ); +} + + @@ -70,7 +116,12 @@ EnvelopeAndLfoParameters::EnvelopeAndLfoParameters( m_lfoAmountIsZero( false ), m_lfoShapeData( NULL ) { - s_EaLParametersInstances.push_back( this ); + if( s_lfoInstances == NULL ) + { + s_lfoInstances = new LfoInstances(); + } + + instances()->add( this ); connect( &m_predelayModel, SIGNAL( dataChanged() ), this, SLOT( updateSampleVars() ) ); @@ -133,10 +184,12 @@ EnvelopeAndLfoParameters::~EnvelopeAndLfoParameters() delete[] m_rEnv; delete[] m_lfoShapeData; - QVector & v = s_EaLParametersInstances; - if( qFind( v.begin(), v.end(), this ) != v.end() ) + instances()->remove( this ); + + if( instances()->isEmpty() ) { - v.erase( qFind( v.begin(), v.end(), this ) ); + delete instances(); + s_lfoInstances = NULL; } } @@ -187,35 +240,6 @@ void EnvelopeAndLfoParameters::updateLfoShapeData() -void EnvelopeAndLfoParameters::triggerLfo() -{ - QVector & v = s_EaLParametersInstances; - for( QVector::iterator it = v.begin(); - it != v.end(); ++it ) - { - ( *it )->m_lfoFrame += - engine::getMixer()->framesPerPeriod(); - ( *it )->m_bad_lfoShapeData = true; - } -} - - - - -void EnvelopeAndLfoParameters::resetLfo() -{ - QVector & v = s_EaLParametersInstances; - for( QVector::iterator it = v.begin(); - it != v.end(); ++it ) - { - ( *it )->m_lfoFrame = 0; - ( *it )->m_bad_lfoShapeData = true; - } -} - - - - inline void EnvelopeAndLfoParameters::fillLfoLevel( float * _buf, f_cnt_t _frame, const fpp_t _frames ) diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index 09d365050..8a331d1d1 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -1,7 +1,7 @@ /* * Mixer.cpp - Mixer for audio processing and rendering * - * Copyright (c) 2004-2009 Tobias Doerffel + * Copyright (c) 2004-2010 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -379,7 +379,7 @@ sampleFrameA * Mixer::renderNextBuffer() emit nextAudioBuffer(); // and trigger LFOs - EnvelopeAndLfoParameters::triggerLfo(); + EnvelopeAndLfoParameters::instances()->trigger(); Controller::triggerFrameCounter(); const float new_cpu_load = timer.elapsed() / 10000.0f * @@ -393,7 +393,7 @@ sampleFrameA * Mixer::renderNextBuffer() -// removes all play-handles. this is neccessary, when the song is stopped -> +// removes all play-handles. this is necessary, when the song is stopped -> // all remaining notes etc. would be played until their end void Mixer::clear() { diff --git a/src/core/engine.cpp b/src/core/engine.cpp index 0bb323b5e..0019b1372 100644 --- a/src/core/engine.cpp +++ b/src/core/engine.cpp @@ -1,7 +1,7 @@ /* * engine.cpp - implementation of LMMS' engine-system * - * Copyright (c) 2006-2009 Tobias Doerffel + * Copyright (c) 2006-2010 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -153,45 +153,32 @@ void engine::destroy() s_mixer->stopProcessing(); - delete s_projectNotes; - s_projectNotes = NULL; - delete s_songEditor; - s_songEditor = NULL; - delete s_bbEditor; - s_bbEditor = NULL; - delete s_pianoRoll; - s_pianoRoll = NULL; - delete s_automationEditor; - s_automationEditor = NULL; - - delete s_fxMixerView; - s_fxMixerView = NULL; + deleteHelper( &s_projectNotes ); + deleteHelper( &s_songEditor ); + deleteHelper( &s_bbEditor ); + deleteHelper( &s_pianoRoll ); + deleteHelper( &s_automationEditor ); + deleteHelper( &s_fxMixerView ); InstrumentTrackView::cleanupWindowPool(); s_song->clearProject(); - delete s_bbTrackContainer; - s_bbTrackContainer = NULL; - delete s_dummyTC; - s_dummyTC = NULL; - delete s_mixer; - s_mixer = NULL; - delete s_fxMixer; - s_fxMixer = NULL; + deleteHelper( &s_bbTrackContainer ); + deleteHelper( &s_dummyTC ); - delete s_ladspaManager; + deleteHelper( &s_mixer ); + deleteHelper( &s_fxMixer ); + + deleteHelper( &s_ladspaManager ); //delete configManager::inst(); - delete s_projectJournal; - s_projectJournal = NULL; + deleteHelper( &s_projectJournal ); + s_mainWindow = NULL; - delete s_song; - s_song = NULL; - - delete s_automationRecorder; - s_automationRecorder = NULL; + deleteHelper( &s_song ); + deleteHelper( &s_automationRecorder ); delete s_mergedResourceDB->provider(); s_mergedResourceDB = NULL; diff --git a/src/core/midi/MidiClient.cpp b/src/core/midi/MidiClient.cpp index 0863be226..2572d78da 100644 --- a/src/core/midi/MidiClient.cpp +++ b/src/core/midi/MidiClient.cpp @@ -265,7 +265,7 @@ void MidiClientRaw::processOutEvent( const midiEvent & _me, const midiTime & , const MidiPort * _port ) { - // TODO: also evaluate _time and queue event if neccessary + // TODO: also evaluate _time and queue event if necessary switch( _me.m_type ) { case MidiNoteOn: diff --git a/src/core/note_play_handle.cpp b/src/core/note_play_handle.cpp index f2f437000..ecda32aa2 100644 --- a/src/core/note_play_handle.cpp +++ b/src/core/note_play_handle.cpp @@ -467,8 +467,11 @@ bool notePlayHandle::operator==( const notePlayHandle & _nph ) const void notePlayHandle::updateFrequency() { const float pitch = - ( key() - m_instrumentTrack->baseNoteModel()->value() + - engine::getSong()->masterPitch() ) / 12.0f; + ( key() - + m_instrumentTrack->baseNoteModel()->value() + + engine::getSong()->masterPitch() + + m_baseDetuning->value() ) + / 12.0f; m_frequency = BaseFreq * powf( 2.0f, pitch + m_instrumentTrack->pitchModel()->value() / ( 100 * 12.0f ) ); m_unpitchedFrequency = BaseFreq * powf( 2.0f, pitch ); diff --git a/src/core/song.cpp b/src/core/song.cpp index 9b421a052..a893e4f7b 100644 --- a/src/core/song.cpp +++ b/src/core/song.cpp @@ -1,7 +1,7 @@ /* - * song.cpp - root of the model-tree + * song.cpp - root of the model tree * - * Copyright (c) 2004-2009 Tobias Doerffel + * Copyright (c) 2004-2010 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -301,7 +301,7 @@ void song::processNextBuffer() // at song-start we have to reset the LFOs if( m_playPos[Mode_PlaySong] == 0 ) { - EnvelopeAndLfoParameters::resetLfo(); + EnvelopeAndLfoParameters::instances()->reset(); } break; @@ -339,7 +339,7 @@ void song::processNextBuffer() return; } - // check for looping-mode and act if neccessary + // check for looping-mode and act if necessary timeLine * tl = m_playPos[m_playMode].m_timeLine; bool check_loop = tl != NULL && m_exporting == false && tl->loopPointsEnabled() && diff --git a/src/core/track.cpp b/src/core/track.cpp index 6fd741662..09a87ef68 100644 --- a/src/core/track.cpp +++ b/src/core/track.cpp @@ -1,9 +1,9 @@ /* - * track.cpp - implementation of classes concerning tracks -> neccessary for + * track.cpp - implementation of classes concerning tracks -> necessary for * all track-like objects (beat/bassline, sample-track...) * - * Copyright (c) 2004-2009 Tobias Doerffel - * + * Copyright (c) 2004-2010 Tobias Doerffel + * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * * This program is free software; you can redistribute it and/or @@ -249,7 +249,9 @@ void trackContentObject::paste() { if( Clipboard::getContent( nodeName() ) != NULL ) { + const midiTime pos = startPosition(); restoreState( *( Clipboard::getContent( nodeName() ) ) ); + movePosition( pos ); } } @@ -1764,8 +1766,11 @@ void track::removeTCO( trackContentObject * _tco ) { m_trackContentObjects.erase( it ); emit trackContentObjectRemoved( _tco ); - engine::getSong()->updateLength(); - engine::getSong()->setModified(); + if( engine::getSong() ) + { + engine::getSong()->updateLength(); + engine::getSong()->setModified(); + } } } diff --git a/src/gui/Forms/AboutDialog.ui b/src/gui/Forms/AboutDialog.ui index 3baacaa88..6c6cf7e6e 100644 --- a/src/gui/Forms/AboutDialog.ui +++ b/src/gui/Forms/AboutDialog.ui @@ -125,7 +125,7 @@ - Copyright (c) 2004-2009, LMMS developers + Copyright (c) 2004-2010, LMMS developers true diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index adfb00918..e0bc09661 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -823,6 +823,8 @@ void MainWindow::resetWindowTitle() bool MainWindow::mayChangeProject() { + engine::getSong()->stop(); + if( !engine::getSong()->isModified() ) { return true; @@ -833,17 +835,17 @@ bool MainWindow::mayChangeProject() "last saving. Do you want to save it " "now?" ), QMessageBox::Question, - QMessageBox::Yes, - QMessageBox::No, + QMessageBox::Save, + QMessageBox::Discard, QMessageBox::Cancel, this ); int answer = mb.exec(); - if( answer == QMessageBox::Yes ) + if( answer == QMessageBox::Save ) { return saveProject(); } - else if( answer == QMessageBox::No ) + else if( answer == QMessageBox::Discard ) { return true; } diff --git a/src/gui/automation_editor.cpp b/src/gui/automation_editor.cpp index 87f0111af..9ac296da1 100644 --- a/src/gui/automation_editor.cpp +++ b/src/gui/automation_editor.cpp @@ -24,10 +24,8 @@ * */ - #include "automation_editor.h" - #include #include #include @@ -77,6 +75,7 @@ automationEditor::automationEditor() : m_zoomingXModel(), m_zoomingYModel(), m_quantizeModel(), + m_patternMutex( QMutex::Recursive ), m_pattern( NULL ), m_minLevel( 0 ), m_maxLevel( 0 ), @@ -94,6 +93,10 @@ automationEditor::automationEditor() : m_editMode( ModeDraw ), m_scrollBack( false ) { + connect( this, SIGNAL( currentPatternChanged() ), + this, SLOT( updateAfterPatternChange() ), + Qt::QueuedConnection ); + // init pixmaps if( s_toolDraw == NULL ) { @@ -223,7 +226,7 @@ automationEditor::automationEditor() : "'Shift+E' on your keyboard to activate this mode." ) ); m_selectButton->setWhatsThis( tr( "Click here and select-mode will be activated. In this " - "mode you can select values. This is neccessary " + "mode you can select values. This is necessary " "if you want to cut, copy, paste, delete, or move " "values. You can also press 'Shift+S' on your keyboard " "to activate this mode." ) ); @@ -373,6 +376,8 @@ automationEditor::automationEditor() : automationEditor::~automationEditor() { + m_zoomingXModel.disconnect(); + m_zoomingYModel.disconnect(); } @@ -380,10 +385,39 @@ automationEditor::~automationEditor() void automationEditor::setCurrentPattern( automationPattern * _new_pattern ) { + m_patternMutex.lock(); m_pattern = _new_pattern; + m_patternMutex.unlock(); + + emit currentPatternChanged(); +} + + + + +void automationEditor::saveSettings( QDomDocument & _doc, QDomElement & _this ) +{ + MainWindow::saveWidgetState( this, _this ); +} + + + + +void automationEditor::loadSettings( const QDomElement & _this ) +{ + MainWindow::restoreWidgetState( this, _this ); +} + + + + +void automationEditor::updateAfterPatternChange() +{ + QMutexLocker m( &m_patternMutex ); + m_currentPosition = 0; - if( validPattern() == false ) + if( !validPattern() ) { setWindowTitle( tr( "Automation Editor - no pattern" ) ); m_minLevel = m_maxLevel = m_scrollLevel = 0; @@ -401,8 +435,7 @@ void automationEditor::setCurrentPattern( automationPattern * _new_pattern ) // of levels and so on...) resizeEvent( NULL ); - setWindowTitle( tr( "Automation Editor - %1" ).arg( - m_pattern->name() ) ); + setWindowTitle( tr( "Automation Editor - %1" ).arg( m_pattern->name() ) ); update(); } @@ -410,17 +443,16 @@ void automationEditor::setCurrentPattern( automationPattern * _new_pattern ) -void automationEditor::saveSettings( QDomDocument & _doc, QDomElement & _this ) +void automationEditor::update() { - MainWindow::saveWidgetState( this, _this ); -} + QWidget::update(); - - - -void automationEditor::loadSettings( const QDomElement & _this ) -{ - MainWindow::restoreWidgetState( this, _this ); + QMutexLocker m( &m_patternMutex ); + // Note detuning? + if( m_pattern && !m_pattern->getTrack() ) + { + engine::getPianoRoll()->update(); + } } @@ -684,7 +716,8 @@ void automationEditor::drawLine( int _x0, float _y0, int _x1, float _y1 ) void automationEditor::mousePressEvent( QMouseEvent * _me ) { - if( validPattern() == false ) + QMutexLocker m( &m_patternMutex ); + if( !validPattern() ) { return; } @@ -847,7 +880,8 @@ void automationEditor::mouseReleaseEvent( QMouseEvent * _me ) void automationEditor::mouseMoveEvent( QMouseEvent * _me ) { - if( validPattern() == false ) + QMutexLocker m( &m_patternMutex ); + if( !validPattern() ) { update(); return; @@ -1221,6 +1255,8 @@ inline void automationEditor::drawCross( QPainter & _p ) void automationEditor::paintEvent( QPaintEvent * _pe ) { + QMutexLocker m( &m_patternMutex ); + QStyleOption opt; opt.initFrom( this ); QPainter p( this ); @@ -1242,7 +1278,7 @@ void automationEditor::paintEvent( QPaintEvent * _pe ) Qt::Alignment text_flags = (Qt::Alignment)( Qt::AlignRight | Qt::AlignVCenter ); - if( m_pattern ) + if( validPattern() ) { if( m_y_auto ) { @@ -1391,7 +1427,7 @@ void automationEditor::paintEvent( QPaintEvent * _pe ) qSwap( selLevel_start, selLevel_end ); } - if( validPattern() == true ) + if( validPattern() ) { timeMap & time_map = m_pattern->getTimeMap(); timeMap::iterator it = time_map.begin(); @@ -1528,7 +1564,7 @@ void automationEditor::paintEvent( QPaintEvent * _pe ) p.drawRect( x + ValuesWidth, y, w, h ); // TODO: Get this out of paint event - int l = ( validPattern() == true )? (int) m_pattern->length() : 0; + int l = validPattern() ? (int) m_pattern->length() : 0; // reset scroll-range if( m_leftRightScroll->maximum() != l ) @@ -1537,7 +1573,7 @@ void automationEditor::paintEvent( QPaintEvent * _pe ) m_leftRightScroll->setPageStep( l ); } - if( validPattern() == true ) + if( validPattern() ) { drawCross( p ); } @@ -1666,7 +1702,9 @@ float automationEditor::getLevel( int _y ) inline bool automationEditor::inBBEditor() { - return( m_pattern->getTrack()->getTrackContainer() + QMutexLocker m( &m_patternMutex ); + return( validPattern() && + m_pattern->getTrack()->getTrackContainer() == engine::getBBTrackContainer() ); } @@ -1675,7 +1713,9 @@ inline bool automationEditor::inBBEditor() void automationEditor::play() { - if( validPattern() == false ) + QMutexLocker m( &m_patternMutex ); + + if( !validPattern() ) { return; } @@ -1749,6 +1789,8 @@ void automationEditor::play() void automationEditor::stop() { + QMutexLocker m( &m_patternMutex ); + if( !validPattern() ) { return; @@ -1832,7 +1874,8 @@ void automationEditor::moveButtonToggled() void automationEditor::selectAll() { - if( validPattern() == false ) + QMutexLocker m( &m_patternMutex ); + if( !validPattern() ) { return; } @@ -1870,7 +1913,8 @@ void automationEditor::selectAll() // returns vector with pointers to all selected values void automationEditor::getSelectedValues( timeMap & _selected_values ) { - if( validPattern() == false ) + QMutexLocker m( &m_patternMutex ); + if( !validPattern() ) { return; } @@ -1938,7 +1982,8 @@ void automationEditor::copySelectedValues() void automationEditor::cutSelectedValues() { - if( validPattern() == false ) + QMutexLocker m( &m_patternMutex ); + if( !validPattern() ) { return; } @@ -1969,12 +2014,8 @@ void automationEditor::cutSelectedValues() void automationEditor::pasteValues() { - if( validPattern() == false ) - { - return; - } - - if( !m_valuesToCopy.isEmpty() ) + QMutexLocker m( &m_patternMutex ); + if( validPattern() && !m_valuesToCopy.isEmpty() ) { for( timeMap::iterator it = m_valuesToCopy.begin(); it != m_valuesToCopy.end(); ++it ) @@ -1996,7 +2037,8 @@ void automationEditor::pasteValues() void automationEditor::deleteSelectedValues() { - if( validPattern() == false ) + QMutexLocker m( &m_patternMutex ); + if( !validPattern() ) { return; } @@ -2140,19 +2182,6 @@ void automationEditor::updateTopBottomLevels() -void automationEditor::update() -{ - QWidget::update(); - // Note detuning? - if( m_pattern && !m_pattern->getTrack() ) - { - engine::getPianoRoll()->update(); - } -} - - - - #include "moc_automation_editor.cxx" diff --git a/src/gui/widgets/EffectView.cpp b/src/gui/widgets/EffectView.cpp index 39ff50eff..764bcf6c5 100644 --- a/src/gui/widgets/EffectView.cpp +++ b/src/gui/widgets/EffectView.cpp @@ -2,7 +2,7 @@ * effect_view.cpp - view-component for an effect * * Copyright (c) 2006-2007 Danny McRae - * Copyright (c) 2007-2009 Tobias Doerffel + * Copyright (c) 2007-2010 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -47,8 +47,7 @@ EffectView::EffectView( Effect * _model, QWidget * _parent ) : PluginView( _model, _parent ), m_bg( embed::getIconPixmap( "effect_plugin" ) ), m_subWindow( NULL ), - m_controlView( NULL ), - m_show( true ) + m_controlView( NULL ) { setFixedSize( 210, 60 ); @@ -162,16 +161,16 @@ void EffectView::editControls() { if( m_subWindow ) { - if( m_show ) + if( !effect()->controls()->isViewVisible() ) { m_subWindow->show(); m_subWindow->raise(); - m_show = false; + effect()->controls()->setViewVisible( true ); } else { m_subWindow->hide(); - m_show = true; + effect()->controls()->setViewVisible( false ); } } } @@ -217,7 +216,7 @@ void EffectView::closeEffects() { m_subWindow->hide(); } - m_show = true; + effect()->controls()->setViewVisible( false ); } diff --git a/src/gui/widgets/InstrumentSoundShapingView.cpp b/src/gui/widgets/InstrumentSoundShapingView.cpp index 298094249..bb8c14b1e 100644 --- a/src/gui/widgets/InstrumentSoundShapingView.cpp +++ b/src/gui/widgets/InstrumentSoundShapingView.cpp @@ -58,7 +58,7 @@ InstrumentSoundShapingView::InstrumentSoundShapingView( QWidget * _parent ) : m_targetsTabWidget->setWhatsThis( tr( "These tabs contain envelopes. They're very important for " "modifying a sound, in that they are almost " - "always neccessary for substractive synthesis. For " + "always necessary for substractive synthesis. For " "example if you have a volume envelope, you can set " "when the sound should have a specific volume. " "If you want to create some soft strings then your " diff --git a/src/tracks/bb_track.cpp b/src/tracks/bb_track.cpp index 96e920efa..00a29c3a7 100644 --- a/src/tracks/bb_track.cpp +++ b/src/tracks/bb_track.cpp @@ -456,12 +456,16 @@ void bbTrack::loadTrackSpecificSettings( const QDomElement & _this ) engine::getBBTrackContainer()->createTCOsForBB( dst ); trackContainer::trackList tl = engine::getBBTrackContainer()->tracks(); + // copy TCOs of all tracks from source BB (at bar "src") to destination + // TCOs (which are created if they do not exist yet) for( trackContainer::trackList::iterator it = tl.begin(); it != tl.end(); ++it ) { ( *it )->getTCO( src )->copy(); ( *it )->getTCO( dst )->paste(); } + setName( tr( "Clone of %1" ).arg( + _this.parentNode().toElement().attribute( "name" ) ) ); } else {