├── .github └── workflows │ ├── build.yaml │ └── release.yaml ├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── CMakePresets.json ├── LICENSE ├── README.md ├── ci ├── build.sh └── config_cmake.sh └── plugin ├── Source ├── Drawbar.cpp ├── Drawbar.h ├── Organ.cpp ├── Organ.h ├── PluginEditor.cpp ├── PluginEditor.h ├── PluginProcessor.cpp ├── PluginProcessor.h └── ui.json └── setBfree ├── AUTHORS ├── COPYING ├── README.md ├── b_overdrive ├── README ├── filterTools.c ├── filterTools.h ├── overdrive.c ├── overdrive.h ├── overmakerdefs.h └── ovt_biased.h ├── b_reverb ├── reverb.c └── reverb.h ├── b_whirl ├── eqcomp.c ├── eqcomp.h ├── whirl.c └── whirl.h ├── doc ├── Doxyfile ├── b_synth.png ├── b_whirl.png ├── clang-format ├── jboverdrive.1 ├── setBfree.1 ├── setBfree.png ├── setBfreeUI.1 ├── signal_flow.png ├── x42-whirl.1 └── x42-whirl.png └── src ├── README ├── cfgParser.c ├── cfgParser.h ├── defaultpgm.h ├── global_inst.h ├── main.h ├── midi.c ├── midi.h ├── midi_aseq.c ├── midi_aseq.h ├── midi_types.h ├── midnam.c ├── pgmParser.c ├── pgmParser.h ├── program.c ├── program.h ├── state.c ├── state.h ├── tonegen.c ├── tonegen.h ├── vibrato.c └── vibrato.h /.github/workflows/build.yaml: -------------------------------------------------------------------------------- 1 | name: Build 2 | on: 3 | push: 4 | branches: 5 | - '**' 6 | 7 | concurrency: 8 | group: build-${{ github.ref || github.run_id }} 9 | 10 | jobs: 11 | build: 12 | name: Build 13 | runs-on: ${{ matrix.os }} 14 | strategy: 15 | matrix: 16 | os: [ubuntu-latest, windows-latest, macos-latest] 17 | steps: 18 | - uses: actions/checkout@v3 19 | with: 20 | submodules: recursive 21 | - uses: maxim-lobanov/setup-xcode@v1 22 | with: 23 | xcode-version: latest-stable 24 | if: matrix.os == 'macos-latest' 25 | - name: "Run script" 26 | run: | 27 | ./ci/build.sh 28 | shell: bash 29 | env: 30 | APPLICATION: ${{ secrets.APPLICATION }} 31 | INSTALLER: ${{ secrets.INSTALLER }} 32 | APPLE_PASS: ${{ secrets.APPLE_PASS }} 33 | APPLE_USER: ${{ secrets.APPLE_USER }} 34 | APIKEY: ${{ secrets.APIKEY }} 35 | - name: Upload Artifact 36 | uses: actions/upload-artifact@v3 37 | with: 38 | name: Binaries 39 | path: ci/bin/*.zip 40 | retention-days: 30 -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: Release 2 | on: 3 | push: 4 | tags: 5 | - '**' 6 | 7 | jobs: 8 | build: 9 | name: Build 10 | runs-on: ${{ matrix.os }} 11 | strategy: 12 | matrix: 13 | os: [ubuntu-latest, windows-latest, macos-latest] 14 | steps: 15 | - uses: actions/checkout@v3 16 | with: 17 | submodules: recursive 18 | - name: "Run script" 19 | run: | 20 | ./ci/build.sh 21 | shell: bash 22 | env: 23 | APPLICATION: ${{ secrets.APPLICATION }} 24 | INSTALLER: ${{ secrets.INSTALLER }} 25 | APPLE_PASS: ${{ secrets.APPLE_PASS }} 26 | APPLE_USER: ${{ secrets.APPLE_USER }} 27 | APIKEY: ${{ secrets.APIKEY }} 28 | - name: Upload Artifact 29 | uses: actions/upload-artifact@v3 30 | with: 31 | name: Binaries 32 | path: ci/bin/*.zip 33 | retention-days: 30 34 | 35 | release: 36 | name: Release 37 | needs: build 38 | runs-on: ubuntu-latest 39 | 40 | steps: 41 | - uses: actions/checkout@v3 42 | - name: Download Artifacts 43 | uses: actions/download-artifact@v3 44 | - name: Create Release 45 | run: ./release.sh 46 | shell: bash 47 | env: 48 | GH_TOKEN: ${{ secrets.ACCESS_TOKEN }} 49 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | JuceLibraryCode 35 | Builds 36 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "modules/juce"] 2 | path = modules/juce 3 | url = git@github.com:juce-framework/JUCE.git 4 | [submodule "modules/gin"] 5 | path = modules/gin 6 | url = git@github.com:FigBug/Gin.git 7 | [submodule "modules/plugin_sdk"] 8 | path = modules/plugin_sdk 9 | url = git@github.com:TurnipHat/plugin_sdk.git 10 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.24.0 FATAL_ERROR) 2 | 3 | # 4 | # Set for each plugin 5 | # 6 | set (PLUGIN_NAME Organ) 7 | set (BUNDLE_ID com.socalabs.organ) 8 | set (AU_ID OrganAU) 9 | set (LV2_URI https://socalabs.com/organ/) 10 | set (PLUGIN_CODE SLor) 11 | 12 | set (CMAKE_POLICY_DEFAULT_CMP0077 NEW) 13 | set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") 14 | set (CMAKE_SUPPRESS_REGENERATION true) 15 | set (CMAKE_SKIP_INSTALL_RULES YES) 16 | set_property (GLOBAL PROPERTY DEBUG_CONFIGURATIONS "Debug") 17 | 18 | set (CMAKE_C_FLAGS_DEVELOPMENT ${CMAKE_C_FLAGS_RELEASE}) 19 | set (CMAKE_CXX_FLAGS_DEVELOPMENT ${CMAKE_CXX_FLAGS_RELEASE}) 20 | 21 | project (${PLUGIN_NAME} VERSION 1.0.1 LANGUAGES CXX C HOMEPAGE_URL "https://socalabs.com/") 22 | 23 | include (CMakeDependentOption) 24 | 25 | set_property (DIRECTORY APPEND PROPERTY LABELS ${PLUGIN_NAME}) 26 | 27 | set_property (DIRECTORY APPEND PROPERTY LABELS SocaLabs) 28 | set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PLUGIN_NAME}_Standalone) 29 | 30 | set (CMAKE_OSX_DEPLOYMENT_TARGET 10.11) 31 | 32 | set (CMAKE_EXPORT_COMPILE_COMMANDS ON) 33 | set (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION ON) 34 | set (CMAKE_CXX_STANDARD 20) 35 | set (CMAKE_CXX_STANDARD_REQUIRED ON) 36 | set (CMAKE_CXX_EXTENSIONS OFF) 37 | set (CMAKE_OBJCXX_STANDARD 20) 38 | set (CMAKE_OBJCXX_STANDARD_REQUIRED ON) 39 | set (CMAKE_CXX_VISIBILITY_PRESET hidden) 40 | set (CMAKE_VISIBILITY_INLINES_HIDDEN ON) 41 | set (CMAKE_MINSIZEREL_POSTFIX -rm) 42 | set (CMAKE_RELWITHDEBINFO_POSTFIX -rd) 43 | set (CMAKE_OPTIMIZE_DEPENDENCIES OFF) 44 | 45 | set (BUILD_SHARED_LIBS OFF) 46 | 47 | if(APPLE) 48 | set (CMAKE_OSX_ARCHITECTURES arm64 x86_64) 49 | endif() 50 | 51 | if (WIN32) 52 | set (FORMATS Standalone VST VST3 LV2) 53 | else() 54 | set (FORMATS Standalone VST VST3 AU LV2) 55 | endif() 56 | 57 | set_property (GLOBAL PROPERTY USE_FOLDERS YES) 58 | set_property (GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER utility) 59 | set_property (GLOBAL PROPERTY REPORT_UNDEFINED_PROPERTIES "${CMAKE_BINARY_DIR}/undefined_properties.log") 60 | set_property (GLOBAL PROPERTY JUCE_COPY_PLUGIN_AFTER_BUILD YES) 61 | 62 | set_property (DIRECTORY APPEND PROPERTY LABELS External) 63 | 64 | # JUCE 65 | 66 | set (JUCE_MODULES_ONLY OFF) 67 | set (JUCE_ENABLE_MODULE_SOURCE_GROUPS ON) 68 | set (JUCE_BUILD_EXTRAS OFF) 69 | set (JUCE_BUILD_EXAMPLES OFF) 70 | 71 | add_subdirectory (modules/juce) 72 | 73 | set_property (DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/modules/juce" APPEND PROPERTY LABELS JUCE) 74 | 75 | # 76 | 77 | # Gin modules 78 | 79 | foreach(module_name IN ITEMS gin gin_dsp gin_simd gin_graphics gin_gui gin_metadata gin_network gin_plugin gin_webp) 80 | juce_add_module ( 81 | "${CMAKE_CURRENT_LIST_DIR}/modules/gin/modules/${module_name}" 82 | ) 83 | 84 | set_property (TARGET "${module_name}" APPEND PROPERTY LABELS Gin) 85 | endforeach() 86 | 87 | # Binary Data 88 | 89 | set_property (DIRECTORY APPEND PROPERTY LABELS Assets) 90 | 91 | juce_add_binary_data (${PLUGIN_NAME}_Assets SOURCES 92 | "plugin/Source/ui.json" 93 | ) 94 | 95 | set_target_properties(${PLUGIN_NAME}_Assets PROPERTIES UNITY_BUILD ON UNITY_BUILD_MODE BATCH UNITY_BUILD_BATCH_SIZE 50) 96 | 97 | set_property(GLOBAL PROPERTY USE_FOLDERS ON) 98 | 99 | juce_set_vst2_sdk_path (${CMAKE_SOURCE_DIR}/modules/plugin_sdk/vstsdk2.4) 100 | 101 | juce_add_plugin (${PLUGIN_NAME} 102 | PRODUCT_NAME ${PLUGIN_NAME} 103 | VERSION "${Organ_VERSION}" 104 | COMPANY_NAME SocaLabs 105 | COMPANY_WEBSITE "https://socalabs.com/" 106 | BUNDLE_ID ${BUNDLE_ID} 107 | FORMATS ${FORMATS} 108 | PLUGIN_MANUFACTURER_CODE Soca 109 | PLUGIN_CODE ${PLUGIN_CODE} 110 | IS_SYNTH ON 111 | NEEDS_MIDI_INPUT ON 112 | EDITOR_WANTS_KEYBOARD_FOCUS ON 113 | VST2_CATEGORY kPlugCategSynth 114 | VST3_CATEGORIES Instrument 115 | AU_MAIN_TYPE kAudioUnitType_MusicDevice 116 | AU_EXPORT_PREFIX ${AU_ID} 117 | AU_SANDBOX_SAFE FALSE 118 | LV2URI ${LV2_URI}) 119 | 120 | file (GLOB_RECURSE source_files CONFIGURE_DEPENDS 121 | ${CMAKE_CURRENT_SOURCE_DIR}/plugin/*.cpp 122 | ${CMAKE_CURRENT_SOURCE_DIR}/plugin/*.c 123 | ${CMAKE_CURRENT_SOURCE_DIR}/plugin/*.h) 124 | 125 | target_sources (${PLUGIN_NAME} PRIVATE ${source_files}) 126 | source_group (TREE ${CMAKE_CURRENT_SOURCE_DIR}/plugin PREFIX Source FILES ${source_files}) 127 | 128 | file (GLOB_RECURSE asset_files CONFIGURE_DEPENDS 129 | ${CMAKE_CURRENT_SOURCE_DIR}/Assets/*) 130 | 131 | target_sources (${PLUGIN_NAME} PRIVATE ${asset_files}) 132 | source_group (TREE ${CMAKE_CURRENT_SOURCE_DIR}/Assets PREFIX Assets FILES ${asset_files}) 133 | 134 | target_link_libraries (${PLUGIN_NAME} PRIVATE 135 | ${PLUGIN_NAME}_Assets 136 | 137 | gin 138 | gin_dsp 139 | gin_simd 140 | gin_graphics 141 | gin_gui 142 | gin_plugin 143 | 144 | juce::juce_audio_basics 145 | juce::juce_audio_devices 146 | juce::juce_audio_formats 147 | juce::juce_audio_plugin_client 148 | juce::juce_audio_processors 149 | juce::juce_audio_utils 150 | juce::juce_core 151 | juce::juce_cryptography 152 | juce::juce_data_structures 153 | juce::juce_events 154 | juce::juce_graphics 155 | juce::juce_gui_basics 156 | juce::juce_gui_extra 157 | 158 | juce::juce_recommended_config_flags 159 | ) 160 | 161 | target_include_directories (${PLUGIN_NAME} PRIVATE modules/fmt/include) 162 | target_include_directories (${PLUGIN_NAME} PRIVATE modules/ASIO/common) 163 | target_include_directories (${PLUGIN_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/Source/Definitions) 164 | 165 | juce_generate_juce_header (${PLUGIN_NAME}) 166 | 167 | target_compile_definitions (${PLUGIN_NAME} PRIVATE 168 | JUCE_DISPLAY_SPLASH_SCREEN=0 169 | JUCE_COREGRAPHICS_DRAW_ASYNC=1 170 | JUCE_MODAL_LOOPS_PERMITTED=1 171 | JUCE_WEB_BROWSER=0 172 | JUCE_USE_FLAC=0 173 | JUCE_USE_CURL=1 174 | JUCE_USE_MP3AUDIOFORMAT=0 175 | JUCE_USE_LAME_AUDIO_FORMAT=0 176 | JUCE_USE_WINDOWS_MEDIA_FORMAT=0 177 | JucePlugin_PreferredChannelConfigurations={0,2} 178 | _CRT_SECURE_NO_WARNINGS 179 | ) 180 | 181 | if (APPLE) 182 | set_target_properties("juce_vst3_helper" PROPERTIES XCODE_ATTRIBUTE_CLANG_LINK_OBJC_RUNTIME NO) 183 | 184 | foreach(t ${FORMATS} "Assets" "All" "") 185 | set(tgt ${CMAKE_PROJECT_NAME}) 186 | if (NOT t STREQUAL "") 187 | set(tgt ${tgt}_${t}) 188 | endif() 189 | if (TARGET ${tgt}) 190 | set_target_properties(${tgt} PROPERTIES 191 | XCODE_ATTRIBUTE_CLANG_LINK_OBJC_RUNTIME NO 192 | #XCODE_ATTRIBUTE_DEPLOYMENT_POSTPROCESSING[variant=Release] YES 193 | XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH[variant=Debug] "YES" 194 | ) 195 | if (NOT t STREQUAL "All") 196 | target_compile_options(${tgt} PRIVATE 197 | -Wall -Wstrict-aliasing -Wunused-parameter -Wconditional-uninitialized -Woverloaded-virtual -Wreorder -Wconstant-conversion -Wbool-conversion -Wextra-semi 198 | -Wunreachable-code -Winconsistent-missing-destructor-override -Wshift-sign-overflow -Wnullable-to-nonnull-conversion -Wuninitialized -Wno-missing-field-initializers 199 | -Wno-ignored-qualifiers -Wno-missing-braces -Wno-char-subscripts -Wno-unused-private-field -fno-aligned-allocation -Wunused-private-field -Wunreachable-code 200 | -Wenum-compare -Wshadow -Wfloat-conversion -Wshadow-uncaptured-local -Wshadow-field -Wsign-compare -Wdeprecated-this-capture -Wimplicit-float-conversion 201 | -ffast-math -fno-finite-math-only) 202 | endif() 203 | endif() 204 | endforeach() 205 | endif() 206 | 207 | if (WIN32) 208 | foreach(t ${FORMATS} "Assets" "All" "") 209 | set(tgt ${CMAKE_PROJECT_NAME}) 210 | if (NOT t STREQUAL "") 211 | set(tgt ${tgt}_${t}) 212 | endif() 213 | if (TARGET ${tgt}) 214 | set_property(TARGET ${tgt} APPEND_STRING PROPERTY LINK_FLAGS_DEBUG " /INCREMENTAL:NO") 215 | set_target_properties(${tgt} PROPERTIES LINK_FLAGS "/ignore:4099") 216 | endif() 217 | endforeach() 218 | endif() 219 | 220 | if(UNIX AND NOT APPLE) 221 | target_link_libraries (${PLUGIN_NAME} PRIVATE curl) 222 | endif() 223 | 224 | 225 | if(WIN32) 226 | set (dest "Program Files") 227 | else() 228 | set (dest "Applications") 229 | endif() 230 | 231 | install (TARGETS ${PLUGIN_NAME} DESTINATION "${dest}") 232 | -------------------------------------------------------------------------------- /CMakePresets.json: -------------------------------------------------------------------------------- 1 | { 2 | "cmakeMinimumRequired": { 3 | "major": 3, 4 | "minor": 24, 5 | "patch": 0 6 | }, 7 | "version": 5, 8 | "include": [ 9 | "modules/gin/ci/toolchains/xcode.json", 10 | "modules/gin/ci/toolchains/vs.json", 11 | "modules/gin/ci/toolchains/gcc.json" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Organ 2 | 3 | VST3 / AU / LV2 Organ based on setBfree 4 | https://github.com/pantherb/setBfree 5 | -------------------------------------------------------------------------------- /ci/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | PLUGIN="Organ" 4 | 5 | # linux specific stiff 6 | if [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then 7 | sudo apt-get update 8 | sudo apt-get install clang git ninja-build ladspa-sdk freeglut3-dev g++ libasound2-dev libcurl4-openssl-dev libfreetype6-dev libjack-jackd2-dev libx11-dev libxcomposite-dev libxcursor-dev libxinerama-dev libxrandr-dev mesa-common-dev webkit2gtk-4.0 juce-tools xvfb 9 | fi 10 | 11 | # mac specific stuff 12 | if [ "$(uname)" == "Darwin" ]; then 13 | # Create a temp keychain 14 | if [ -n "$GITHUB_ACTIONS" ]; then 15 | echo "Create a keychain" 16 | security create-keychain -p nr4aGPyz Keys.keychain 17 | 18 | echo $APPLICATION | base64 -D -o /tmp/Application.p12 19 | echo $INSTALLER | base64 -D -o /tmp/Installer.p12 20 | 21 | security import /tmp/Application.p12 -t agg -k Keys.keychain -P aym9PKWB -A -T /usr/bin/codesign 22 | security import /tmp/Installer.p12 -t agg -k Keys.keychain -P aym9PKWB -A -T /usr/bin/codesign 23 | 24 | security list-keychains -s Keys.keychain 25 | security default-keychain -s Keys.keychain 26 | security unlock-keychain -p nr4aGPyz Keys.keychain 27 | security set-keychain-settings -l -u -t 13600 Keys.keychain 28 | security set-key-partition-list -S apple-tool:,apple: -s -k nr4aGPyz Keys.keychain 29 | fi 30 | DEV_APP_ID="Developer ID Application: Roland Rabien (3FS7DJDG38)" 31 | DEV_INST_ID="Developer ID Installer: Roland Rabien (3FS7DJDG38)" 32 | fi 33 | 34 | ROOT=$(cd "$(dirname "$0")/.."; pwd) 35 | cd "$ROOT" 36 | echo "$ROOT" 37 | 38 | BRANCH=${GITHUB_REF##*/} 39 | echo "$BRANCH" 40 | 41 | cd "$ROOT/ci" 42 | rm -Rf bin 43 | mkdir bin 44 | 45 | # Build mac version 46 | if [ "$(uname)" == "Darwin" ]; then 47 | cd "$ROOT" 48 | cmake --preset xcode 49 | cmake --build --preset xcode --config Release 50 | 51 | cp -R "$ROOT/Builds/xcode/${PLUGIN}_artefacts/Release/AU/$PLUGIN.component" "$ROOT/ci/bin" 52 | cp -R "$ROOT/Builds/xcode/${PLUGIN}_artefacts/Release/VST/$PLUGIN.vst" "$ROOT/ci/bin" 53 | cp -R "$ROOT/Builds/xcode/${PLUGIN}_artefacts/Release/VST3/$PLUGIN.vst3" "$ROOT/ci/bin" 54 | 55 | cd "$ROOT/ci/bin" 56 | codesign -s "$DEV_APP_ID" -v $PLUGIN.vst --options=runtime --timestamp --force 57 | codesign -s "$DEV_APP_ID" -v $PLUGIN.vst3 --options=runtime --timestamp --force 58 | codesign -s "$DEV_APP_ID" -v $PLUGIN.component --options=runtime --timestamp --force 59 | 60 | # Notarize 61 | cd "$ROOT/ci/bin" 62 | zip -r ${PLUGIN}_Mac.zip $PLUGIN.vst $PLUGIN.vst3 $PLUGIN.component 63 | 64 | if [[ -n "$APPLE_USER" ]]; then 65 | xcrun notarytool submit --verbose --apple-id "$APPLE_USER" --password "$APPLE_PASS" --team-id "3FS7DJDG38" --wait --timeout 30m ${PLUGIN}_Mac.zip 66 | fi 67 | 68 | rm ${PLUGIN}_Mac.zip 69 | xcrun stapler staple $PLUGIN.vst 70 | xcrun stapler staple $PLUGIN.vst3 71 | xcrun stapler staple $PLUGIN.component 72 | zip -r ${PLUGIN}_Mac.zip $PLUGIN.vst $PLUGIN.vst3 $PLUGIN.component 73 | 74 | if [ "$BRANCH" = "release" ]; then 75 | curl -F "files=@${PLUGIN}_Mac.zip" "https://socalabs.com/files/set.php?key=$APIKEY" 76 | fi 77 | fi 78 | 79 | # Build linux version 80 | if [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then 81 | cd "$ROOT" 82 | 83 | cmake --preset ninja-gcc 84 | cmake --build --preset ninja-gcc --config Release 85 | 86 | cp -R "$ROOT/Builds/ninja-gcc/${PLUGIN}_artefacts/Release/LV2/$PLUGIN.lv2" "$ROOT/ci/bin" 87 | cp -R "$ROOT/Builds/ninja-gcc/${PLUGIN}_artefacts/Release/VST/lib$PLUGIN.so" "$ROOT/ci/bin/$PLUGIN.so" 88 | cp -R "$ROOT/Builds/ninja-gcc/${PLUGIN}_artefacts/Release/VST3/$PLUGIN.vst3" "$ROOT/ci/bin" 89 | 90 | cd "$ROOT/ci/bin" 91 | 92 | # Upload 93 | cd "$ROOT/ci/bin" 94 | zip -r ${PLUGIN}_Linux.zip $PLUGIN.so $PLUGIN.vst3 $PLUGIN.lv2 95 | 96 | if [ "$BRANCH" = "release" ]; then 97 | curl -F "files=@${PLUGIN}_Linux.zip" "https://socalabs.com/files/set.php?key=$APIKEY" 98 | fi 99 | fi 100 | 101 | # Build Win version 102 | if [ "$(expr substr $(uname -s) 1 10)" == "MINGW64_NT" ]; then 103 | cd "$ROOT" 104 | 105 | cmake --preset vs 106 | cmake --build --preset vs --config Release 107 | 108 | cd "$ROOT/ci/bin" 109 | 110 | cp -R "$ROOT/Builds/vs/${PLUGIN}_artefacts/Release/VST/$PLUGIN.dll" "$ROOT/ci/bin" 111 | cp -R "$ROOT/Builds/vs/${PLUGIN}_artefacts/Release/VST3/$PLUGIN.vst3" "$ROOT/ci/bin" 112 | 113 | 7z a ${PLUGIN}_Win.zip $PLUGIN.dll $PLUGIN.vst3 114 | 115 | if [ "$BRANCH" = "release" ]; then 116 | curl -F "files=@${PLUGIN}_Win.zip" "https://socalabs.com/files/set.php?key=$APIKEY" 117 | fi 118 | fi 119 | -------------------------------------------------------------------------------- /ci/config_cmake.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | ROOT=$(cd "$(dirname "$0")/.."; pwd) 4 | cd "$ROOT" 5 | 6 | export PATH=$PATH:"/c/Program Files/CMake/bin" 7 | 8 | if [ "$(uname)" == "Darwin" ]; then 9 | TOOLCHAIN="xcode" 10 | elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then 11 | TOOLCHAIN="ninja-gcc" 12 | elif [ "$(expr substr $(uname -s) 1 10)" == "MINGW64_NT" ]; then 13 | TOOLCHAIN="vs" 14 | fi 15 | 16 | cmake --preset $TOOLCHAIN -D BUILD_EXTRAS=OFF -D JUCE_COPY_PLUGIN_AFTER_BUILD=ON 17 | -------------------------------------------------------------------------------- /plugin/Source/Drawbar.cpp: -------------------------------------------------------------------------------- 1 | #include "Drawbar.h" 2 | 3 | //============================================================================== 4 | Drawbar::Drawbar (gin::Parameter* p) 5 | : ParamComponent (p), 6 | knob (parameter, juce::Slider::LinearVertical, juce::Slider::NoTextBox) 7 | { 8 | addAndMakeVisible (knob); 9 | 10 | knob.setTitle (parameter->getName (100)); 11 | knob.setDoubleClickReturnValue (true, parameter->getUserDefaultValue()); 12 | knob.setSkewFactor (parameter->getSkew(), parameter->isSkewSymmetric()); 13 | 14 | knob.setName (parameter->getShortName()); 15 | 16 | #if JUCE_IOS 17 | knob.setMouseDragSensitivity (500); 18 | #endif 19 | 20 | addMouseListener (this, true); 21 | } 22 | 23 | Drawbar::~Drawbar() 24 | { 25 | } 26 | 27 | void Drawbar::resized() 28 | { 29 | knob.setBounds (getLocalBounds()); 30 | } 31 | 32 | void Drawbar::parentHierarchyChanged() 33 | { 34 | auto a = wantsAccessibleKeyboard (*this); 35 | knob.setWantsKeyboardFocus (a); 36 | } 37 | -------------------------------------------------------------------------------- /plugin/Source/Drawbar.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | 6 | 7 | //============================================================================== 8 | class Drawbar : public gin::ParamComponent 9 | { 10 | public: 11 | Drawbar (gin::Parameter* parameter); 12 | ~Drawbar() override; 13 | 14 | private: 15 | void resized() override; 16 | void parentHierarchyChanged() override; 17 | 18 | class DrawBarSlider : public gin::PluginSlider 19 | { 20 | public: 21 | DrawBarSlider (gin::Parameter* p, SliderStyle s, TextEntryBoxPosition t) 22 | : PluginSlider (p, s, t) 23 | { 24 | } 25 | 26 | void paint (juce::Graphics& g) override 27 | { 28 | juce::Rectangle rc (0, 0, getWidth(), getHeight()); 29 | rc.removeFromBottom (getWidth()); 30 | 31 | auto numberHeight = rc.getHeight() / 8.0f; 32 | 33 | // Frame 34 | { 35 | rc = rc.withHeight (int (rc.getHeight() * (1.0f - valueToProportionOfLength (getValue())))); 36 | 37 | g.setColour (findColour (gin::PluginLookAndFeel::accentColourId).withAlpha (0.5f)); 38 | g.drawRect (rc); 39 | } 40 | 41 | // Numbers 42 | { 43 | auto nt = rc.toFloat(); 44 | nt.setTop (-1000.0); 45 | 46 | g.setFont (8.0f); 47 | g.setColour (findColour (gin::PluginLookAndFeel::accentColourId).withAlpha (0.8f)); 48 | 49 | for (int i = 1; i <= 8; i++) 50 | g.drawText (juce::String (i), nt.removeFromBottom (numberHeight), juce::Justification::centred); 51 | } 52 | 53 | // Knob 54 | { 55 | juce::Graphics::ScopedSaveState sss (g); 56 | g.setColour (getColour (getName().getTrailingIntValue() - 1)); 57 | g.reduceClipRegion (0, rc.getBottom(), rc.getWidth(), rc.getWidth()); 58 | g.fillEllipse (0, rc.getBottom() - rc.getWidth() / 2, rc.getWidth(), rc.getWidth()); 59 | } 60 | } 61 | 62 | juce::Colour getColour (int idx) 63 | { 64 | switch (idx) 65 | { 66 | case 0: 67 | case 1: 68 | return findColour (gin::PluginLookAndFeel::accentColourId).withAlpha (0.9f); 69 | case 2: 70 | case 3: 71 | case 5: 72 | case 8: 73 | return findColour (gin::PluginLookAndFeel::whiteColourId).withAlpha (0.9f); 74 | default: 75 | return findColour (gin::PluginLookAndFeel::blackColourId).withAlpha (0.9f); 76 | } 77 | } 78 | }; 79 | 80 | DrawBarSlider knob; 81 | 82 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Drawbar) 83 | }; 84 | -------------------------------------------------------------------------------- /plugin/Source/Organ.cpp: -------------------------------------------------------------------------------- 1 | #include "Organ.h" 2 | 3 | extern "C" 4 | { 5 | #include "../setBfree/src/state.h" 6 | #include "../setBfree/src/tonegen.h" 7 | #include "../setBfree/src/vibrato.h" 8 | #include "../setBfree/src/midi.h" 9 | } 10 | 11 | Organ::Organ (double sr, int bs) 12 | : sampleRate (sr) 13 | { 14 | fifo.setSize (2, std::max (1024, bs * 2)); 15 | allocAll(); 16 | initAll(); 17 | 18 | setDrawBars (&inst, 0, upper); 19 | setDrawBars (&inst, 1, lower); 20 | setDrawBars (&inst, 2, pedal); 21 | } 22 | 23 | Organ::~Organ() 24 | { 25 | freeAll(); 26 | } 27 | 28 | void Organ::allocAll() 29 | { 30 | inst.state = allocRunningConfig(); 31 | inst.progs = allocProgs(); 32 | inst.reverb = allocReverb(); 33 | inst.whirl = allocWhirl(); 34 | inst.synth = allocTonegen(); 35 | inst.midicfg = allocMidiCfg (inst.state); 36 | inst.preamp = allocPreamp(); 37 | } 38 | 39 | void Organ::freeAll() 40 | { 41 | freeReverb (inst.reverb); 42 | freeWhirl (inst.whirl); 43 | 44 | freeToneGenerator (inst.synth); 45 | freeMidiCfg (inst.midicfg); 46 | freePreamp (inst.preamp); 47 | freeProgs (inst.progs); 48 | freeRunningConfig (inst.state); 49 | } 50 | 51 | void Organ::initAll() 52 | { 53 | initToneGenerator (inst.synth, inst.midicfg, sampleRate); 54 | initVibrato (inst.synth, inst.midicfg, sampleRate); 55 | initPreamp (inst.preamp, inst.midicfg); 56 | initReverb (inst.reverb, inst.midicfg, sampleRate); 57 | initWhirl (inst.whirl, inst.midicfg, sampleRate); 58 | initRunningConfig (inst.state, inst.midicfg); 59 | 60 | initMidiTables (inst.midicfg); 61 | } 62 | 63 | void Organ::setUpperDrawBar (int idx, int val) 64 | { 65 | if (upper[idx] == (unsigned int)val) 66 | return; 67 | 68 | upper[idx] = (unsigned int)val; 69 | upperDirty = true; 70 | } 71 | 72 | void Organ::setLowerDrawBar (int idx, int val) 73 | { 74 | if (lower[idx] == (unsigned int)val) 75 | return; 76 | 77 | lower[idx] = (unsigned int)val; 78 | lowerDirty = true; 79 | } 80 | 81 | void Organ::setPedalDrawBar (int idx, int val) 82 | { 83 | if (pedal[idx] == (unsigned int)val) 84 | return; 85 | 86 | pedal[idx] = (unsigned int)val; 87 | pedalDirty = true; 88 | } 89 | 90 | void Organ::setVibratoUpper (bool v) 91 | { 92 | ::setVibratoUpper (inst.synth, v); 93 | } 94 | 95 | void Organ::setVibratoLower (bool v) 96 | { 97 | ::setVibratoLower (inst.synth, v); 98 | } 99 | 100 | void Organ::setVibratoChorus (int v) 101 | { 102 | switch (v) 103 | { 104 | case 0: 105 | setVibrato (&inst.synth->inst_vibrato, VIB1); 106 | break; 107 | case 1: 108 | setVibrato (&inst.synth->inst_vibrato, CHO1); 109 | break; 110 | case 2: 111 | setVibrato (&inst.synth->inst_vibrato, VIB2); 112 | break; 113 | case 3: 114 | setVibrato (&inst.synth->inst_vibrato, CHO2); 115 | break; 116 | case 4: 117 | setVibrato (&inst.synth->inst_vibrato, VIB3); 118 | break; 119 | case 5: 120 | setVibrato (&inst.synth->inst_vibrato, CHO3); 121 | break; 122 | } 123 | } 124 | 125 | void Organ::setLeslie (int v) 126 | { 127 | if (leslie != v) 128 | { 129 | leslie = v; 130 | switch (v) 131 | { 132 | case 0: useRevOption (inst.whirl, 0, 2); break; 133 | case 1: useRevOption (inst.whirl, 4, 2); break; 134 | case 2: useRevOption (inst.whirl, 8, 2); break; 135 | } 136 | } 137 | } 138 | 139 | void Organ::setPrec (bool v) 140 | { 141 | if (v != bool(inst.synth->percEnabled)) 142 | setPercussionEnabled (inst.synth, v); 143 | } 144 | 145 | void Organ::setPrecVol (bool v) 146 | { 147 | if (v != bool(inst.synth->percIsSoft)) 148 | setPercussionVolume (inst.synth, v); 149 | } 150 | 151 | void Organ::setPrecDecay (bool v) 152 | { 153 | if (v != bool(inst.synth->percIsSoft)) 154 | setPercussionFast (inst.synth, v); 155 | } 156 | 157 | void Organ::setPrecHarmSel (bool v) 158 | { 159 | setPercussionFirst (inst.synth, v); 160 | } 161 | 162 | void Organ::setReverb (float v) 163 | { 164 | setReverbMix (inst.reverb, v); 165 | } 166 | 167 | void Organ::setVolume (float v) 168 | { 169 | inst.synth->swellPedalGain = inst.synth->outputLevelTrim * v; 170 | } 171 | 172 | void Organ::setCharacter (float f) 173 | { 174 | fctl_biased_fat (inst.preamp, f); 175 | } 176 | 177 | void Organ::setOverdrive (bool v) 178 | { 179 | setClean (inst.preamp, ! v); 180 | } 181 | 182 | void Organ::setSplit (bool s) 183 | { 184 | split = s; 185 | } 186 | 187 | void Organ::processMidi (juce::MidiBuffer& midi, int pos, int len) 188 | { 189 | for (const juce::MidiMessageMetadata metadata : midi) 190 | { 191 | if (metadata.samplePosition < pos) 192 | continue; 193 | if (metadata.samplePosition >= pos + len) 194 | break; 195 | if (! metadata.getMessage().isNoteOnOrOff()) 196 | continue; 197 | 198 | auto data = metadata.data; 199 | auto size = metadata.numBytes; 200 | 201 | parse_raw_midi_data (&inst, data, size_t (size)); 202 | } 203 | } 204 | 205 | void Organ::processBlock (juce::AudioBuffer& buffer, juce::MidiBuffer& midi) 206 | { 207 | const int stepSize = BUFFER_SIZE_SAMPLES; 208 | int pos = 0; 209 | 210 | if (upperDirty) setDrawBars (&inst, 0, upper); 211 | if (lowerDirty) setDrawBars (&inst, 1, lower); 212 | if (pedalDirty) setDrawBars (&inst, 2, pedal); 213 | 214 | while (fifo.getNumReady() < buffer.getNumSamples()) 215 | { 216 | processMidi (midi, pos, stepSize); 217 | 218 | gin::ScratchBuffer temp {5, stepSize}; 219 | gin::ScratchBuffer out {2, stepSize}; 220 | auto a = temp.getWritePointer (0); 221 | auto b = temp.getWritePointer (1); 222 | auto c = temp.getWritePointer (2); 223 | auto t = temp.getWritePointer (3); 224 | auto u = temp.getWritePointer (4); 225 | 226 | auto l = out.getWritePointer (0); 227 | auto r = out.getWritePointer (1); 228 | 229 | oscGenerateFragment (inst.synth, a, stepSize); 230 | preamp (inst.preamp, a, b, stepSize); 231 | reverb (inst.reverb, b, c, stepSize); 232 | 233 | whirlProc3 (inst.whirl, c, l, r, t, u, stepSize); 234 | 235 | fifo.write (out); 236 | pos += stepSize; 237 | } 238 | 239 | if (pos < buffer.getNumSamples()) 240 | processMidi (midi, pos, buffer.getNumSamples() - pos); 241 | 242 | fifo.read (buffer); 243 | 244 | upperDirty = false; 245 | lowerDirty = false; 246 | pedalDirty = false; 247 | } 248 | 249 | void Organ::preprocessMidi (juce::MidiBuffer& src, juce::MidiBuffer& dst) 250 | { 251 | dst.clear(); 252 | if (! split) 253 | { 254 | dst.addEvents (src, 0, -1, 0); 255 | return; 256 | } 257 | 258 | for (auto event : src) 259 | { 260 | auto m = event.getMessage(); 261 | 262 | if (m.isNoteOnOrOff()) 263 | { 264 | auto n = m.getNoteNumber(); 265 | auto c = 0; 266 | 267 | if (n >= 84) 268 | { 269 | n = n - 84 + 36; 270 | c = 1; 271 | } 272 | else if (n >= 24) 273 | { 274 | n = n - 24 + 36; 275 | c = 2; 276 | } 277 | else 278 | { 279 | n = n + 24; 280 | c = 3; 281 | } 282 | 283 | m.setNoteNumber (n); 284 | m.setChannel (c); 285 | } 286 | 287 | dst.addEvent(m, event.samplePosition); 288 | } 289 | } 290 | -------------------------------------------------------------------------------- /plugin/Source/Organ.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | extern "C" 6 | { 7 | #include "../setBfree/src/global_inst.h" 8 | } 9 | 10 | class Organ 11 | { 12 | public: 13 | Organ (double sr, int bs); 14 | ~Organ(); 15 | 16 | void processBlock (juce::AudioBuffer&, juce::MidiBuffer&); 17 | 18 | void setUpperDrawBar (int idx, int val); 19 | void setLowerDrawBar (int idx, int val); 20 | void setPedalDrawBar (int idx, int val); 21 | 22 | void preprocessMidi (juce::MidiBuffer& src, juce::MidiBuffer& dst); 23 | void setVibratoUpper (bool v); 24 | void setVibratoLower (bool v); 25 | void setVibratoChorus (int v); 26 | void setLeslie (int v); 27 | void setPrec (bool v); 28 | void setPrecVol (bool v); 29 | void setPrecDecay (bool v); 30 | void setPrecHarmSel (bool v); 31 | void setReverb (float v); 32 | void setVolume (float v); 33 | void setOverdrive (bool v); 34 | void setCharacter (float f); 35 | void setSplit (bool s); 36 | 37 | private: 38 | void processMidi (juce::MidiBuffer& midi, int pos, int len); 39 | 40 | void allocAll(); 41 | void initAll(); 42 | void freeAll(); 43 | 44 | double sampleRate = 44100.0; 45 | b_instance inst; 46 | 47 | gin::AudioFifo fifo { 2, 1024 }; 48 | 49 | bool upperDirty = false; 50 | bool lowerDirty = false; 51 | bool pedalDirty = false; 52 | 53 | unsigned int upper[9] = { 0 }; 54 | unsigned int lower[9] = { 0 }; 55 | unsigned int pedal[9] = { 0 }; 56 | 57 | int leslie = -1; 58 | bool split = false; 59 | }; 60 | -------------------------------------------------------------------------------- /plugin/Source/PluginEditor.cpp: -------------------------------------------------------------------------------- 1 | #include "PluginProcessor.h" 2 | #include "PluginEditor.h" 3 | #include "Drawbar.h" 4 | 5 | //============================================================================== 6 | OrganAudioProcessorEditor::OrganAudioProcessorEditor (OrganAudioProcessor& p_) 7 | : ProcessorEditor (p_), proc (p_) 8 | { 9 | setName ("main"); 10 | 11 | upperKeyboard.setName ("upperKeys"); 12 | upperKeyboard.setOpaque (false); 13 | upperKeyboard.setMidiChannel (1); 14 | upperKeyboard.setMidiChannelsToDisplay (1 << 0); 15 | upperKeyboard.setKeyWidth (20); 16 | upperKeyboard.setAvailableRange (36, 96); 17 | upperKeyboard.setScrollButtonsVisible (false); 18 | addAndMakeVisible (upperKeyboard); 19 | 20 | lowerKeyboard.setName ("lowerKeys"); 21 | lowerKeyboard.setOpaque (false); 22 | lowerKeyboard.setMidiChannel (2); 23 | lowerKeyboard.setMidiChannelsToDisplay (1 << 1); 24 | lowerKeyboard.setKeyWidth (20); 25 | lowerKeyboard.setAvailableRange (36, 96); 26 | lowerKeyboard.setScrollButtonsVisible (false); 27 | addAndMakeVisible (lowerKeyboard); 28 | 29 | pedalKeyboard.setName ("pedalKeys"); 30 | pedalKeyboard.setOpaque (false); 31 | pedalKeyboard.setMidiChannel (3); 32 | pedalKeyboard.setMidiChannelsToDisplay (1 << 2); 33 | pedalKeyboard.setKeyWidth (20); 34 | pedalKeyboard.setAvailableRange (24, 49); 35 | pedalKeyboard.setScrollButtonsVisible (false); 36 | addAndMakeVisible (pedalKeyboard); 37 | 38 | for (auto p : proc.upperDrawBars) addAndMakeVisible (controls.add (new Drawbar (p))); 39 | for (auto p : proc.lowerDrawBars) addAndMakeVisible (controls.add (new Drawbar (p))); 40 | for (auto p : proc.pedalDrawBars) addAndMakeVisible (controls.add (new Drawbar (p))); 41 | 42 | addAndMakeVisible (controls.add (new gin::Switch (proc.vibratoUpper))); 43 | addAndMakeVisible (controls.add (new gin::Switch (proc.vibratoLower))); 44 | addAndMakeVisible (controls.add (new gin::Select (proc.vibratoChorus))); 45 | addAndMakeVisible (controls.add (new gin::Select (proc.leslie))); 46 | addAndMakeVisible (controls.add (new gin::Switch (proc.prec))); 47 | addAndMakeVisible (controls.add (new gin::Switch (proc.precVol))); 48 | addAndMakeVisible (controls.add (new gin::Switch (proc.precDecay))); 49 | addAndMakeVisible (controls.add (new gin::Switch (proc.precHarmSel))); 50 | addAndMakeVisible (controls.add (new gin::Knob (proc.reverb))); 51 | addAndMakeVisible (controls.add (new gin::Knob (proc.volume))); 52 | addAndMakeVisible (controls.add (new gin::Switch (proc.overdrive))); 53 | addAndMakeVisible (controls.add (new gin::Knob (proc.character))); 54 | addAndMakeVisible (controls.add (new gin::Switch (proc.split))); 55 | 56 | setGridSize (15, 5); 57 | 58 | layout.setLayout ("ui.json", juce::File (__FILE__).getSiblingFile ("ui.json")); 59 | } 60 | 61 | OrganAudioProcessorEditor::~OrganAudioProcessorEditor() 62 | { 63 | } 64 | 65 | //============================================================================== 66 | void OrganAudioProcessorEditor::paint (juce::Graphics& g) 67 | { 68 | ProcessorEditor::paint (g); 69 | } 70 | 71 | void OrganAudioProcessorEditor::resized() 72 | { 73 | ProcessorEditor::resized (); 74 | } 75 | -------------------------------------------------------------------------------- /plugin/Source/PluginEditor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "PluginProcessor.h" 5 | 6 | //============================================================================== 7 | class OrganAudioProcessorEditor : public gin::ProcessorEditor 8 | { 9 | public: 10 | OrganAudioProcessorEditor (OrganAudioProcessor&); 11 | ~OrganAudioProcessorEditor() override; 12 | 13 | //============================================================================== 14 | void paint (juce::Graphics&) override; 15 | void resized() override; 16 | 17 | private: 18 | gin::Layout layout {*this}; 19 | 20 | OrganAudioProcessor& proc; 21 | 22 | juce::MidiKeyboardComponent upperKeyboard { proc.upperState, juce::MidiKeyboardComponent::horizontalKeyboard }; 23 | juce::MidiKeyboardComponent lowerKeyboard { proc.lowerState, juce::MidiKeyboardComponent::horizontalKeyboard }; 24 | juce::MidiKeyboardComponent pedalKeyboard { proc.pedalState, juce::MidiKeyboardComponent::horizontalKeyboard }; 25 | 26 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OrganAudioProcessorEditor) 27 | }; 28 | -------------------------------------------------------------------------------- /plugin/Source/PluginProcessor.cpp: -------------------------------------------------------------------------------- 1 | #include "PluginProcessor.h" 2 | #include "PluginEditor.h" 3 | 4 | float defaultPreset[9] = { -8, -8, -6, 0, 0, 0, 0, 0, 0 }; 5 | 6 | static juce::String onOffTextFunction (const gin::Parameter&, float v) { return v > 0.5f ? "On" : "Off"; } 7 | static juce::String pVolTextFunction (const gin::Parameter&, float v) { return v > 0.5f ? "Soft" : "Norm"; } 8 | static juce::String pDecayTextFunction (const gin::Parameter&, float v) { return v > 0.5f ? "Fast" : "Slow"; } 9 | static juce::String pHarmTextFunction (const gin::Parameter&, float v) { return v > 0.5f ? "2nd" : "3rd"; } 10 | static juce::String percentTextFunction (const gin::Parameter&, float v) { return juce::String (juce::roundToInt(v * 100)) + "%"; } 11 | 12 | static juce::String vcTextFunction (const gin::Parameter&, float v) 13 | { 14 | switch (juce::roundToInt (v)) 15 | { 16 | case 0: return "V1"; 17 | case 1: return "C1"; 18 | case 2: return "V2"; 19 | case 3: return "C2"; 20 | case 4: return "V3"; 21 | case 5: return "C3"; 22 | default: return ""; 23 | } 24 | } 25 | 26 | static juce::String lesTextFunction (const gin::Parameter&, float v) 27 | { 28 | switch (juce::roundToInt (v)) 29 | { 30 | case 0: return "Stop"; 31 | case 1: return "Slow"; 32 | case 2: return "Fast"; 33 | default: return ""; 34 | } 35 | } 36 | 37 | //============================================================================== 38 | OrganAudioProcessor::OrganAudioProcessor() 39 | : gin::Processor (false, gin::ProcessorOptions().withAdditionalCredits ({"Fredrik Kilander, Robin Gareus, Will Panther"})) 40 | { 41 | for (int i = 0; i < 9; i++) 42 | { 43 | auto num = juce::String (i + 1); 44 | upperDrawBars[i] = addExtParam ("upper" + num, "Upper Draw Bar " + num, "Upper " + num, "", { -8.0f, 0.0f, 1.0f, 1.0f}, defaultPreset[i], 0.0f); 45 | } 46 | for (int i = 0; i < 9; i++) 47 | { 48 | auto num = juce::String (i + 1); 49 | lowerDrawBars[i] = addExtParam ("lower" + num, "Lower Draw Bar " + num, "Lower " + num, "", { -8.0f, 0.0f, 1.0f, 1.0f}, defaultPreset[i], 0.0f); 50 | } 51 | for (int i = 0; i < 2; i++) 52 | { 53 | auto num = juce::String (i + 1); 54 | pedalDrawBars[i] = addExtParam ("pedal" + num, "Pedal Draw Bar " + num, "Pedal " + num, "", { -8.0f, 0.0f, 1.0f, 1.0f}, defaultPreset[i], 0.0f); 55 | } 56 | 57 | vibratoUpper = addExtParam ("vibratoUpper", "Vibrato Upper", "", "", { 0.0f, 1.0f, 1.0f, 1.0f}, 0.0f, 0.0f, onOffTextFunction); 58 | vibratoLower = addExtParam ("vibratoLower", "Vibrato Lower", "", "", { 0.0f, 1.0f, 1.0f, 1.0f}, 0.0f, 0.0f, onOffTextFunction); 59 | vibratoChorus = addExtParam ("vibratoChorus", "Vib & Chrs", "", "", { 0.0f, 5.0f, 1.0f, 1.0f}, 0.0f, 0.0f, vcTextFunction); 60 | leslie = addExtParam ("leslie", "Leslie", "", "", { 0.0f, 2.0f, 1.0f, 1.0f}, 0.0f, 0.0f, lesTextFunction); 61 | prec = addExtParam ("prec", "Perc", "", "", { 0.0f, 2.0f, 1.0f, 1.0f}, 1.0f, 0.0f, onOffTextFunction); 62 | precVol = addExtParam ("precVol", "Perc Volume", "", "", { 0.0f, 2.0f, 1.0f, 1.0f}, 0.0f, 0.0f, pVolTextFunction); 63 | precDecay = addExtParam ("precDecay", "Perc Decay", "", "", { 0.0f, 2.0f, 1.0f, 1.0f}, 0.0f, 0.0f, pDecayTextFunction); 64 | precHarmSel = addExtParam ("precHarmSel", "Perc Harm Sel", "", "", { 0.0f, 2.0f, 1.0f, 1.0f}, 0.0f, 0.0f, pHarmTextFunction); 65 | reverb = addExtParam ("reverb", "Reverb", "", "", { 0.0f, 1.0f, 0.0f, 1.0f}, 0.2f, 0.0f, percentTextFunction); 66 | volume = addExtParam ("volume", "Volume", "", "", { 0.0f, 1.0f, 0.0f, 1.0f}, 1.0f, 0.0f, percentTextFunction); 67 | overdrive = addExtParam ("overdrive", "Overdrive", "", "", { 0.0f, 1.0f, 0.0f, 1.0f}, 0.0f, 0.0f, onOffTextFunction); 68 | character = addExtParam ("character", "Character", "", "", { 0.0f, 1.0f, 0.0f, 1.0f}, 0.0f, 0.0f, percentTextFunction); 69 | split = addExtParam ("split", "Split Keys", "", "", { 0.0f, 1.0f, 0.0f, 1.0f}, 0.0f, 0.0f, onOffTextFunction); 70 | 71 | midiOut.ensureSize (1024); 72 | init(); 73 | } 74 | 75 | OrganAudioProcessor::~OrganAudioProcessor() 76 | { 77 | } 78 | 79 | //============================================================================== 80 | void OrganAudioProcessor::stateUpdated() 81 | { 82 | } 83 | 84 | void OrganAudioProcessor::updateState() 85 | { 86 | } 87 | 88 | //============================================================================== 89 | void OrganAudioProcessor::reset() 90 | { 91 | Processor::reset(); 92 | } 93 | 94 | void OrganAudioProcessor::prepareToPlay (double newSampleRate, int newSamplesPerBlock) 95 | { 96 | Processor::prepareToPlay (newSampleRate, newSamplesPerBlock); 97 | 98 | organ = std::make_unique (newSampleRate, newSamplesPerBlock); 99 | } 100 | 101 | void OrganAudioProcessor::releaseResources() 102 | { 103 | } 104 | 105 | void OrganAudioProcessor::processBlock (juce::AudioBuffer& buffer, juce::MidiBuffer& midi) 106 | { 107 | juce::ScopedNoDenormals noDenormals; 108 | 109 | buffer.clear (); 110 | auto numSamples = buffer.getNumSamples(); 111 | 112 | if (organ != nullptr) 113 | { 114 | organ->preprocessMidi (midi, midiOut); 115 | 116 | upperState.processNextMidiBuffer (midiOut, 0, numSamples, true); 117 | lowerState.processNextMidiBuffer (midiOut, 0, numSamples, true); 118 | pedalState.processNextMidiBuffer (midiOut, 0, numSamples, true); 119 | 120 | for (int i = 0; i < 9; i++) organ->setUpperDrawBar (i, std::abs (upperDrawBars[i]->getUserValueInt())); 121 | for (int i = 0; i < 9; i++) organ->setLowerDrawBar (i, std::abs (lowerDrawBars[i]->getUserValueInt())); 122 | for (int i = 0; i < 2; i++) organ->setPedalDrawBar (i, std::abs (pedalDrawBars[i]->getUserValueInt())); 123 | 124 | organ->setSplit (split->getBoolValue()); 125 | organ->setVibratoUpper (vibratoUpper->getUserValueBool()); 126 | organ->setVibratoLower (vibratoLower->getUserValueBool()); 127 | organ->setVibratoChorus (vibratoChorus->getUserValueInt()); 128 | organ->setLeslie (leslie->getUserValueInt()); 129 | organ->setPrec (prec->getUserValueBool()); 130 | organ->setPrecVol (precVol->getUserValueBool()); 131 | organ->setPrecDecay (precDecay->getUserValueBool()); 132 | organ->setPrecHarmSel (precHarmSel->getUserValueBool()); 133 | organ->setReverb (reverb->getUserValue()); 134 | organ->setVolume (volume->getUserValue()); 135 | organ->setOverdrive (overdrive->getUserValueBool()); 136 | organ->setCharacter (character->getUserValueBool()); 137 | 138 | organ->processBlock (buffer, midiOut); 139 | } 140 | } 141 | 142 | //============================================================================== 143 | bool OrganAudioProcessor::hasEditor() const 144 | { 145 | return true; 146 | } 147 | 148 | juce::AudioProcessorEditor* OrganAudioProcessor::createEditor() 149 | { 150 | return new gin::ScaledPluginEditor (new OrganAudioProcessorEditor (*this), state); 151 | } 152 | 153 | //============================================================================== 154 | // This creates new instances of the plugin.. 155 | juce::AudioProcessor* JUCE_CALLTYPE createPluginFilter() 156 | { 157 | return new OrganAudioProcessor(); 158 | } 159 | -------------------------------------------------------------------------------- /plugin/Source/PluginProcessor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "Organ.h" 5 | 6 | //============================================================================== 7 | class OrganAudioProcessor : public gin::Processor 8 | { 9 | public: 10 | //============================================================================== 11 | OrganAudioProcessor(); 12 | ~OrganAudioProcessor() override; 13 | 14 | void stateUpdated() override; 15 | void updateState() override; 16 | 17 | //============================================================================== 18 | void reset() override; 19 | void prepareToPlay (double sampleRate, int samplesPerBlock) override; 20 | void releaseResources() override; 21 | 22 | void processBlock (juce::AudioBuffer&, juce::MidiBuffer&) override; 23 | 24 | //============================================================================== 25 | juce::AudioProcessorEditor* createEditor() override; 26 | bool hasEditor() const override; 27 | 28 | std::unique_ptr organ; 29 | 30 | gin::Parameter::Ptr upperDrawBars[9]; 31 | gin::Parameter::Ptr lowerDrawBars[9]; 32 | gin::Parameter::Ptr pedalDrawBars[2]; 33 | gin::Parameter::Ptr vibratoUpper, vibratoLower, vibratoChorus, leslie, prec, precVol, 34 | precDecay, precHarmSel, reverb, volume, overdrive, character, split; 35 | 36 | juce::MidiKeyboardState upperState; 37 | juce::MidiKeyboardState lowerState; 38 | juce::MidiKeyboardState pedalState; 39 | 40 | juce::MidiBuffer midiOut; 41 | 42 | //============================================================================== 43 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OrganAudioProcessor) 44 | }; 45 | -------------------------------------------------------------------------------- /plugin/Source/ui.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "main", "w": 736, "h": 360, 3 | "children": [ 4 | { "id": "Vibrato Upper", "x": "8", "y": 48, "w": 56, "h": 70 }, 5 | { "id": "Vibrato Lower", "x": "prevR() + 8", "y": 48, "w": 56, "h": 70 }, 6 | { "id": "Vib & Chrs", "x": "prevR() + 8", "y": 48, "w": 56, "h": 70 }, 7 | 8 | { "id": "Upper [1..9]", "x": "prevR() + 20,prevR() + 2", "y": 48, "w": 9, "h": 70 }, 9 | { "id": "Pedal [1..2]", "x": "prevR() + 20,prevR() + 2", "y": 48, "w": 9, "h": 70 }, 10 | { "id": "Lower [1..9]", "x": "prevR() + 20,prevR() + 2", "y": 48, "w": 9, "h": 70 }, 11 | 12 | { "id": "Perc", "x": "prevR() + 8", "y": 48, "w": 56, "h": 70 }, 13 | { "id": "Perc Volume", "x": "prevR() + 8", "y": 48, "w": 56, "h": 70 }, 14 | { "id": "Perc Decay", "x": "prevR() + 8", "y": 48, "w": 56, "h": 70 }, 15 | { "id": "Perc Harm Sel", "x": "prevR() + 8", "y": 48, "w": 56, "h": 70 }, 16 | 17 | { "id": "upperKeys", "x": 8, "y": "prevB() + 8", "w": 720, "h": 70 }, 18 | { "id": "lowerKeys", "x": 8, "y": "prevB() + 8", "w": 720, "h": 70 }, 19 | 20 | { "id": "Overdrive", "x": 8, "y": "prevB() + 8", "w": 56, "h": 70 }, 21 | { "id": "Character", "x": "prevR() + 8", "y": "prevY()", "w": 56, "h": 70 }, 22 | { "id": "Leslie", "x": "prevR() + 8", "y": "prevY()", "w": 56, "h": 70 }, 23 | 24 | { "id": "pedalKeys", "x": "prevR() + 10", "y": "prevY()", "w": 305, "h": 70 }, 25 | 26 | { "id": "Reverb", "x": "prevR() + 8", "y": "prevY()", "w": 56, "h": 70 }, 27 | { "id": "Volume", "x": "prevR() + 8", "y": "prevY()", "w": 56, "h": 70 }, 28 | { "id": "Split Keys", "x": "getX('/main/Perc Harm Sel')", "y": "prevY()", "w": 56, "h": 70 } 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /plugin/setBfree/AUTHORS: -------------------------------------------------------------------------------- 1 | Fredrik Kilander 2 | Will Panther 3 | Robin Gareus 4 | Ken Restivo 5 | -------------------------------------------------------------------------------- /plugin/setBfree/COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | -------------------------------------------------------------------------------- /plugin/setBfree/README.md: -------------------------------------------------------------------------------- 1 | setBfree 2 | ======== 3 | 4 | A DSP Tonewheel Organ emulator. 5 | 6 | setBfree is a MIDI-controlled, software synthesizer designed to imitate the 7 | sound and properties of the electromechanical organs and sound modification 8 | devices that brought world-wide fame to the names and products of Laurens 9 | Hammond and Don Leslie. 10 | 11 | * http://setbfree.org 12 | * https://github.com/pantherb/setBfree 13 | 14 | Download 15 | -------- 16 | 17 | Binaries for Intel platform, GNU/Linux, OSX and Windows are available from 18 | 19 | * https://github.com/pantherb/setBfree/releases/latest 20 | 21 | setBfree is also available on most Linux distributions. 22 | 23 | Quick-start 24 | ----------- 25 | 26 | - start jackd (see http://jackaudio.org, more below) 27 | - run `setBfreeUI` for the GUI version 28 | - run `setBfree` for the headless commandline application 29 | - or load the LV2 plugin "setBfree DSP Tonewheel Organ" in your favorite DAW 30 | 31 | Screenshots 32 | ----------- 33 | 34 | ![screenshot](https://raw.githubusercontent.com/pantherb/setBfree/master/doc/b_synth.png "setBfree GUI") 35 | 36 | 37 | [Demo Video](https://vimeo.com/130633814) 38 | 39 | 40 | Usage 41 | ----- 42 | 43 | setBfree is available as 3 different variants: 44 | 45 | * standalone JACK application with graphical user interface 46 | * LV2 plugin (with optional GUI) 47 | * commandline application 48 | 49 | Run `setBfree -h` for a quick overview. `setBfree --help` will output a 50 | lengthy list of available options and properties than can be modified. 51 | 52 | `setBfree` is the synthesizer engine. It responds to MIDI messages (JACK-MIDI 53 | or ALSA-sequencer) and outputs audio to JACK. The engine does not have any 54 | graphical user interface (GUI). It is usually started from the commandline. 55 | 56 | The GUI `setBfreeUI` is a standalone application that wraps the synth engine. 57 | It provides both visual feedback about the current synth state as well as allows 58 | to reconfigure and control numerous aspects of the organ. 59 | 60 | The complete organ (incl. GUI), as well as individual parts (leslie, reverb, 61 | overdrive) are also available as LV2 plugins. 62 | 63 | Examples: 64 | 65 | setBfree jack.out.left="system:playback_7" jack.out.right="system:playback_8" 66 | setBfreeUI 67 | jalv.gtk http://gareus.org/oss/lv2/b_synth # LV2 in jalv-host 68 | 69 | 70 | Getting started - standalone app 71 | -------------------------------- 72 | 73 | You'll want reliable, low-latency, real-time audio. Therefore you want 74 | [JACK](http://jackaudio.org/). On GNU/Linux we recommend `qjackctl` to start the 75 | jack-audio-server, on OSX jack comes with a GUI called JACK-pilot. On Windows use the 76 | Jack Control GUI. 77 | 78 | An excellent tutorial to get started with JACK can be found on the 79 | [libremusicproduction](http://libremusicproduction.com/articles/demystifying-jack-%E2%80%93-beginners-guide-getting-started-jack) 80 | website. 81 | 82 | Detailed documentation 83 | ---------------------- 84 | 85 | For a detailed documentation, run: 86 | 87 | setBfree -H 88 | 89 | Internal Signal Flow 90 | -------------------- 91 | 92 | +--------+ /-----------\ /--------\ 93 | | | | | | | 94 | MIDI | Synth- | | Preamp/ | | | 95 | --=->| +--->| +--->| Reverb +--\ 96 | | Engine | | Overdrive | | | | 97 | | | | | | | | 98 | +--------+ \-----------/ \--------/ | 99 | | 100 | /---------------------------------------------/ 101 | | 102 | | /--------\ Horn L/R /-----------\ 103 | | | +---------->| Cabinet +-----*--> Audio-Out Left 104 | | | +---------->| Emulation +--\ | 105 | \->| Leslie | \-----------/ | | 106 | | +--------------------------|--/ 107 | | +--------------------------*-----> Audio-Out Right 108 | \--------/ Drum L/R 109 | 110 | Render diagram with http://ditaa.org/ 111 | A pre-rendered image is available in the doc/ folder. 112 | 113 | Each of the stages - except the synth-engine itself - can be bypassed. The 114 | effects are available as standalone LV2 plugins which provides for creating 115 | custom effect chains and use 3rd party effects. 116 | 117 | The preamp/overdrive is disabled by default, reverb is set to 30% (unless 118 | overridden with `reverb.mix`, `reverb.dry` or `reverb.wet`). Note that a 119 | stopped leslie will still modify the sound (horn-speaker characteristics, 120 | angle-dependent reflections). Bypassing the leslie (`whirl.bypass=1`) will mute 121 | the drum-output signals and simply copy the incoming audio-signal to the horn 122 | L/R outputs. The cabinet-emulation is an experimental convolution engine and 123 | bypassed by default. 124 | 125 | The LV2-synth includes the first three effects until and including the Leslie. 126 | The effects can be triggered via MIDI just as with the standalone JACK 127 | application. The cabinet-emulation is not included in the LV2-synth because it 128 | depends on impulse-response files which are not shipped with the plugin. 129 | 130 | The Vibrato and Chorus effects are built into the synth-engine itself, as are 131 | key-click and percussion modes. These features are linked to the tone 132 | generation itself and can not be broken-out to standalone effects. 133 | 134 | Summary of Changes since Beatrix 135 | -------------------------------- 136 | 137 | * native JACK application (JACK Audio, JACK MIDI) 138 | * synth engine: variable sample-rate, floating point (beatrix is 22050 Hz, 16bit only) 139 | * broken-out effects as LV2 plugins; LV2 wrapper around synth-engine 140 | * built-in documentation 141 | * Graphical User Interface, with MIDI-feedback and dynamically bound MIDI-CC 142 | * fixed leslie aliasing noise 143 | * state save/restore 144 | * numerous bug fixes 145 | 146 | see the ChangeLog and git log for details. 147 | 148 | 149 | Compile 150 | ------- 151 | 152 | Install the dependencies and simply call `make` followed by `sudo make install`. 153 | 154 | * libjack-dev - **required** - [JACK](http://jackaudio.org/) is used for audio and MIDI I/O 155 | * libftgl-dev, libglu1-mesa-dev, ttf-bitstream-vera - optional, **recommended** - openGL GUI 156 | * lv2-dev - optional, **recommended** - [LV2](http://lv2plug.in/) plugins and GUI 157 | * libcairo and libpango - optional, **recommended** - GUI for standalone Leslie/Whirl-speaker LV2 158 | * libasound2-dev - optional - ALSA MIDI support 159 | * help2man - optional - re-create the man pages 160 | * doxygen - optional - create source-code annotations 161 | * liblo-dev - optional - [OSC](http://opensoundcontrol.org/) used only in standalone preamp/overdrive app, mainly useful for testing. 162 | * libzita-convolver-dev - optional, deprecated - [libzita-convolver](http://kokkinizita.linuxaudio.org/linuxaudio/downloads/index.html) is used for cabinet-emulation 163 | * libsndfile1-dev - optional, deprecated - [libsndfile](http://www.mega-nerd.com/libsndfile/) is needed to load IR samples for zita-convolver 164 | 165 | 166 | Since version 0.8, alsa-sequencer support is deprecated and no longer enabled by 167 | default (even if libasound is found), It is still available via `ENABLE_ALSA=yes`. 168 | 169 | The Makefile understands PREFIX and DESTDIR variables: e.g. 170 | 171 | make clean 172 | make PREFIX=/usr ENABLE_ALSA=yes 173 | make install ENABLE_ALSA=yes PREFIX=/usr DESTDIR=mypackage/setbfree/ 174 | 175 | **Packagers**: see debian/rules in the git-repository. LDFLAGS can be passed as is, 176 | CFLAGS should be specified by overriding the OPTIMIZATIONS variable. 177 | The packaging also includes a desktop-file to launch setBfree from the 178 | application-menu which is not included in the release. 179 | 180 | Thanks 181 | ------ 182 | 183 | Many thanks to all who contributed ideas, bug-reports, patches and feedback. In 184 | Particular (in alphabetical order): Dominique Michel, Fons Adriaensen, Jean-Luc 185 | Nest, Jeremy Jongepier, Julien Claasen and Ken Restivo. 186 | -------------------------------------------------------------------------------- /plugin/setBfree/b_overdrive/README: -------------------------------------------------------------------------------- 1 | Overdrive.txt 2 | 27-sep-2003/FK 3 | 4 | Conceptually, the overdrive FX consists of: 5 | 6 | Interpolation section 7 | - upsampler (zero injector) 8 | - a pre-emphasis filter 9 | - interpolation filter (anti-aliasing filter) 10 | 11 | Transfer section 12 | - transfer function 13 | 14 | Decimation section 15 | - decimation filter (anti-aliasing filter) 16 | - de-emphasis filter 17 | - downsampler 18 | 19 | The interpolation and decimation sections can be integrated. 20 | 21 | 22 | S-rate samples: ... x-9 x-8 x-7 x-6 x-5 x-4 x-3 x-2 x-1 x0 23 | 24 | After zero-injection 25 | 0 0 0 x-3 0 0 0 x-2 0 0 0 x-1 0 0 0 x0 26 | 27 | Assume a FIR of 13 weights (which is much to small) for interpolation 28 | 29 | 0 0 0 x-3 0 0 0 x-2 0 0 0 x-1 0 0 0 x0 30 | y0= w12 w8 w4 w0 31 | y1= w11 w7 w3 32 | y2= w10 w6 w2 33 | y3= w9 w5 w1 34 | 35 | or 36 | 37 | y0 = (w12 * x[-3]) + (w8 * x[-2]) + (w4 *x[-1]) + (w0 * x[0]) 38 | y1 = (w11 * x[-3]) + (w7 * x[-2]) + (w3 *x[-1]) 39 | y2 = (w10 * x[-3]) + (w6 * x[-2]) + (w2 *x[-1]) 40 | y3 = ( w9 * x[-3]) + (w5 * x[-2]) + (w1 *x[-1]) 41 | 42 | y4 = (w12 * x[-4]) + (w8 * x[-3]) + (w4 *x[-2]) + (w0 * x[-1]) 43 | y5 = (w11 * x[-4]) + (w7 * x[-3]) + (w3 *x[-2]) 44 | y6 = (w10 * x[-4]) + (w6 * x[-3]) + (w2 *x[-2]) 45 | y7 = ( w9 * x[-4]) + (w5 * x[-3]) + (w1 *x[-2]) 46 | 47 | Generalise this to interpolation rate R=4. 48 | 49 | For each input sample x[i], generate R output samples: 50 | y[i+0], y[i+1], ..., y[i+r] 51 | where r = R-1. 52 | 53 | y[i+0] = (w[0R-0] * x[i]) + (w[1R-0] * x[i-1]) + (w[2R-0] * x[i-2]) ... 54 | y[i+1] = (w[0R-1] * x[i]) + (w[1R-1] * x[i-1]) + (w[2R-1] * x[i-2]) ... 55 | y[i+2] = (w[0R-2] * x[i]) + (w[1R-2] * x[i-1]) + (w[2R-2] * x[i-2]) ... 56 | ... 57 | y[i+r] = (w[0R-r] * x[i]) + (w[1R-r] * x[i-1]) + (w[2R-r] * x[i-2]) ... 58 | 59 | where w[] indices that are undefined are zero and therefore can be eliminated 60 | from the expression. 61 | 62 | These outputs are passed through the transfer section yielding: 63 | 64 | z0 = t(y0) 65 | z1 = t(y1) 66 | ... 67 | z7 = t(y7) 68 | 69 | Decimation then 70 | 71 | ... z7 z6 z5 z4 z3 z2 z1 z0 72 | v0 = w0*z0 + w1*z1 + w2*z2 + w3*z3 + w4*z4 + ... + wn*zn 73 | v1 = w0*z4 + w1*z5 + w2*z6 + w3*z7 + w4*z8 + ... + wn*z(n+4) 74 | 75 | Generalizes to system output 76 | 77 | v[i+0] = w[0] * z[i-0-0R] + w[1] * z[i-1-0R] + ... + w[n] * z[i-n-0R] 78 | v[i+1] = w[0] * z[i-0-1R] + w[1] * z[i-1-1R] + ... + w[n] * z[i-n-1R] 79 | 80 | Simply skip R samples before convolving the next output sample. 81 | 82 | ------------------------ 83 | Why can we not insert the zeros after the transfer function? 84 | Because the harmonics will be present as aliases. 85 | -------------------------------------------------------------------------------- /plugin/setBfree/b_overdrive/filterTools.c: -------------------------------------------------------------------------------- 1 | /* setBfree - DSP tonewheel organ 2 | * 3 | * Copyright (C) 2003-2004 Fredrik Kilander 4 | * Copyright (C) 2008-2018 Robin Gareus 5 | * Copyright (C) 2012 Will Panther 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2, or (at your option) 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | /* filterTools.c */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "filterTools.h" 29 | 30 | /* ************************************************************************ 31 | * Windowing functions. These functions return a scale factor between 0-1. 32 | * It is applied to an array of signals so that they may be scaled 33 | * according to their position in the array. 34 | * 35 | * @param i Value w's position in array (m/2 is middle element) 36 | * @param m Total number of elements. 37 | * 38 | * For example, if the kernel has three elements, w[0], w[1] and w[2], then 39 | * the calls to the Hamming window function would be: 40 | * 41 | * w[0] = wdw_Hamming (w[0], 0, 3); 42 | * 43 | * The middle element is typically not called because the sinc function 44 | * commonly used for the left and right halfs collapse there into a 45 | * division by zero. 46 | * 47 | * w[2] = wdw_Hamming (w[2], 2, 3); 48 | * 49 | * The argument to cos() will typically go from 0-2pi, ie a full circle. 50 | * So as i (element index) is incremented from 0 to m-1, the Hanning window 51 | * expression 0.5 - (0.5 * cos(f(i))) will take the values 52 | * 53 | * [0, ..., 0.5, ..., 1.0, ..., 0.5, ..., 0] 54 | * 0pi 0.5pi 1pi 1.5pi 2pi 55 | * 56 | * which is the positive half of a sinusoid. The shape of the resulting 57 | * curve is modified by altering the coefficients slightly (Hamming) or 58 | * by introducing a touch of the second harmonic (Blackman). 59 | */ 60 | 61 | #ifndef M_PI 62 | #define M_PI 3.141592653589793238462643 63 | #endif 64 | 65 | double 66 | wdw_Hamming (int i, int m) 67 | { 68 | assert (i < m); 69 | return (0.54 - (0.46 * cos ((2.0 * M_PI * (double)i) / (double)(m - 1)))); 70 | } 71 | 72 | double 73 | wdw_Blackman (int i, int m) 74 | { 75 | assert (i < m); 76 | return (0.42 - (0.50 * cos (2.0 * M_PI * ((double)i / (double)(m - 1)))) + (0.08 * cos (4.0 * M_PI * ((double)i / (double)(m - 1))))); 77 | } 78 | 79 | double 80 | wdw_Hanning (int i, int m) 81 | { 82 | assert (i < m); 83 | return (0.5 - (0.5 * cos ((2.0 * M_PI * (double)i) / (double)(m - 1)))); 84 | } 85 | 86 | /* ************************************************************************ 87 | * 88 | * Creates a low-pass filter and applies the requested window function. 89 | * 90 | * @param fc Cutoff frequency 91 | * @param wdw Requested window function 92 | * @param a Kernel weights. 93 | * @param m Length of filter kernel (should be odd). 94 | */ 95 | 96 | void 97 | sincApply (double fc, int wdw, double a[], int m) 98 | { 99 | int i; 100 | int Mp = m - 1; 101 | double sum; 102 | 103 | for (i = 0; i < m; i++) { 104 | if ((i - (Mp / 2)) == 0) { 105 | a[i] = 2.0 * M_PI * fc; 106 | } else { 107 | double k = (double)(i - (Mp / 2)); 108 | a[i] = sin (2.0 * M_PI * fc * k) / k; 109 | /* Select window here */ 110 | switch (wdw) { 111 | case WDW_HAMMING: 112 | a[i] *= wdw_Hamming (i, m); 113 | break; 114 | case WDW_BLACKMAN: 115 | a[i] *= wdw_Blackman (i, m); 116 | break; 117 | case WDW_HANNING: 118 | a[i] *= wdw_Hanning (i, m); 119 | break; 120 | default: 121 | assert (0); 122 | } 123 | } 124 | } 125 | 126 | /* Sum all weights */ 127 | 128 | for (i = 0, sum = 0.0; i < m; i++) { 129 | sum += a[i]; 130 | } 131 | 132 | /* Normalize to unit gain */ 133 | 134 | for (i = 0; i < m; i++) { 135 | a[i] /= sum; 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /plugin/setBfree/b_overdrive/filterTools.h: -------------------------------------------------------------------------------- 1 | /* setBfree - DSP tonewheel organ 2 | * 3 | * Copyright (C) 2003-2004 Fredrik Kilander 4 | * Copyright (C) 2008-2018 Robin Gareus 5 | * Copyright (C) 2012 Will Panther 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2, or (at your option) 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef FILTERTOOLS_H 22 | #define FILTERTOOLS_H 23 | 24 | #define WDW_HAMMING 0 25 | #define WDW_BLACKMAN 1 26 | #define WDW_HANNING 2 27 | 28 | extern void sincApply (double fc, int wdw, double a[], int m); 29 | 30 | #endif /* FILTERTOOLS_H */ 31 | -------------------------------------------------------------------------------- /plugin/setBfree/b_overdrive/overdrive.h: -------------------------------------------------------------------------------- 1 | /* setBfree - DSP tonewheel organ 2 | * 3 | * Copyright (C) 2003-2004 Fredrik Kilander 4 | * Copyright (C) 2008-2018 Robin Gareus 5 | * Copyright (C) 2012 Will Panther 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2, or (at your option) 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef _OVERDRIVE_H_ 22 | #define _OVERDRIVE_H_ 23 | 24 | #include "../src/cfgParser.h" 25 | #include "../src/midi.h" // useMIDIControlFunction 26 | extern int ampConfig (void* pa, ConfigContext* cfg); 27 | extern const ConfigDoc* ampDoc (void); 28 | 29 | extern void initPreamp (void* pa, void* m); 30 | extern void setClean (void* pa, int useClean); 31 | 32 | extern void* allocPreamp (void); 33 | extern void freePreamp (void* pa); 34 | 35 | extern float* preamp (void* pa, float* inBuf, float* outBuf, size_t bufLengthSamples); 36 | extern float* overdrive (void* pa, const float* inBuf, float* outBuf, size_t buflen); 37 | 38 | /* the following depend on compile time configutaion 39 | * and should be created by overmaker 40 | */ 41 | 42 | /** Computes the constants for transfer curve */ 43 | void fctl_biased (void* d, float u); 44 | /** ovt_biased:Sets the positive feedback */ 45 | void fctl_biased_fb (void* d, float u); 46 | /** ovt_biased: Sets sag impact */ 47 | void fctl_sagtoBias (void* d, float u); 48 | /** ovt_biased: Postdiff feedback control */ 49 | void fctl_biased_fb2 (void* d, float u); 50 | /** ovt_biased: Global feedback control */ 51 | void fctl_biased_gfb (void* d, float u); 52 | /** ovt_biased: Fat control */ 53 | void fctl_biased_fat (void* d, float u); 54 | 55 | void fsetInputGain (void* d, float u); 56 | void fsetOutputGain (void* d, float u); 57 | 58 | #endif /* _OVERDRIVE_H_ */ 59 | -------------------------------------------------------------------------------- /plugin/setBfree/b_overdrive/overmakerdefs.h: -------------------------------------------------------------------------------- 1 | /* setBfree - DSP tonewheel organ 2 | * 3 | * Copyright (C) 2003-2004 Fredrik Kilander 4 | * Copyright (C) 2008-2018 Robin Gareus 5 | * Copyright (C) 2012 Will Panther 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2, or (at your option) 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | /* clang-format off */ 22 | 23 | /* 24 | * List of strings for system include-files in the output souce code. 25 | */ 26 | 27 | #define SYSTEM_INCLUDES {NULL} 28 | 29 | /* 30 | * List of strings for local include-files in the output source code. 31 | */ 32 | 33 | #define LOCAL_INCLUDES {"overdrive.h", NULL} 34 | 35 | /* The nof points in the interpolation filter. */ 36 | 37 | #define IPOL_LEN 33 38 | 39 | #define IPOL_FIR00 { \ 40 | 0.000000000000000000000000000000000069107852418382210791849936, /* [0] */ \ 41 | -0.000029195141905802302062511444091796875000000000000000000000, /* [1] */ \ 42 | -0.000240361885516904294490814208984375000000000000000000000000, /* [2] */ \ 43 | -0.000806394324172288179397583007812500000000000000000000000000, /* [3] */ \ 44 | -0.001801325590349733829498291015625000000000000000000000000000, /* [4] */ \ 45 | -0.003049216698855161666870117187500000000000000000000000000000, /* [5] */ \ 46 | -0.003958590794354677200317382812500000000000000000000000000000, /* [6] */ \ 47 | -0.003437968436628580093383789062500000000000000000000000000000, /* [7] */ \ 48 | 0.000000000000000001693113499430822435897489933176451870622259, /* [8] */ \ 49 | 0.007889833301305770874023437500000000000000000000000000000000, /* [9] */ \ 50 | 0.021269135177135467529296875000000000000000000000000000000000, /* [10] */ \ 51 | 0.040103543549776077270507812500000000000000000000000000000000, /* [11] */ \ 52 | 0.062911629676818847656250000000000000000000000000000000000000, /* [12] */ \ 53 | 0.086793623864650726318359375000000000000000000000000000000000, /* [13] */ \ 54 | 0.107942819595336914062500000000000000000000000000000000000000, /* [14] */ \ 55 | 0.122537523508071899414062500000000000000000000000000000000000, /* [15] */ \ 56 | 0.127749890089035034179687500000000000000000000000000000000000, /* [16] */ \ 57 | 0.122537523508071899414062500000000000000000000000000000000000, /* [17] */ \ 58 | 0.107942819595336914062500000000000000000000000000000000000000, /* [18] */ \ 59 | 0.086793623864650726318359375000000000000000000000000000000000, /* [19] */ \ 60 | 0.062911629676818847656250000000000000000000000000000000000000, /* [20] */ \ 61 | 0.040103543549776077270507812500000000000000000000000000000000, /* [21] */ \ 62 | 0.021269135177135467529296875000000000000000000000000000000000, /* [22] */ \ 63 | 0.007889833301305770874023437500000000000000000000000000000000, /* [23] */ \ 64 | 0.000000000000000001693113499430822435897489933176451870622259, /* [24] */ \ 65 | -0.003437968436628580093383789062500000000000000000000000000000, /* [25] */ \ 66 | -0.003958590794354677200317382812500000000000000000000000000000, /* [26] */ \ 67 | -0.003049216698855161666870117187500000000000000000000000000000, /* [27] */ \ 68 | -0.001801325590349733829498291015625000000000000000000000000000, /* [28] */ \ 69 | -0.000806394324172288179397583007812500000000000000000000000000, /* [29] */ \ 70 | -0.000240361885516904294490814208984375000000000000000000000000, /* [30] */ \ 71 | -0.000029195141905802302062511444091796875000000000000000000000, /* [31] */ \ 72 | 0.000000000000000000000000000000000069107852418382210791849936 /* [32] */ \ 73 | } 74 | 75 | /* fdes -o 4 -kn 33 */ 76 | 77 | #define IPOL_FIR01 { \ 78 | -0.000000000000000000388245104566976935245921787737133357154562, /* [0] */ \ 79 | -0.000718555646017193794250488281250000000000000000000000000000, /* [1] */ \ 80 | -0.001841715304180979728698730468750000000000000000000000000000, /* [2] */ \ 81 | -0.003549180924892425537109375000000000000000000000000000000000, /* [3] */ \ 82 | -0.005673130042850971221923828125000000000000000000000000000000, /* [4] */ \ 83 | -0.007573895156383514404296875000000000000000000000000000000000, /* [5] */ \ 84 | -0.008159336633980274200439453125000000000000000000000000000000, /* [6] */ \ 85 | -0.006069717928767204284667968750000000000000000000000000000000, /* [7] */ \ 86 | 0.000000000000000002620654384741260421634156257963965686030861, /* [8] */ \ 87 | 0.010914741083979606628417968750000000000000000000000000000000, /* [9] */ \ 88 | 0.026753284037113189697265625000000000000000000000000000000000, /* [10] */ \ 89 | 0.046604625880718231201171875000000000000000000000000000000000, /* [11] */ \ 90 | 0.068580508232116699218750000000000000000000000000000000000000, /* [12] */ \ 91 | 0.090065538883209228515625000000000000000000000000000000000000, /* [13] */ \ 92 | 0.108164526522159576416015625000000000000000000000000000000000, /* [14] */ \ 93 | 0.120252311229705810546875000000000000000000000000000000000000, /* [15] */ \ 94 | 0.124499998986721038818359375000000000000000000000000000000000, /* [16] */ \ 95 | 0.120252311229705810546875000000000000000000000000000000000000, /* [17] */ \ 96 | 0.108164526522159576416015625000000000000000000000000000000000, /* [18] */ \ 97 | 0.090065538883209228515625000000000000000000000000000000000000, /* [19] */ \ 98 | 0.068580508232116699218750000000000000000000000000000000000000, /* [20] */ \ 99 | 0.046604625880718231201171875000000000000000000000000000000000, /* [21] */ \ 100 | 0.026753284037113189697265625000000000000000000000000000000000, /* [22] */ \ 101 | 0.010914741083979606628417968750000000000000000000000000000000, /* [23] */ \ 102 | 0.000000000000000002620654384741260421634156257963965686030861, /* [24] */ \ 103 | -0.006069717928767204284667968750000000000000000000000000000000, /* [25] */ \ 104 | -0.008159336633980274200439453125000000000000000000000000000000, /* [26] */ \ 105 | -0.007573895156383514404296875000000000000000000000000000000000, /* [27] */ \ 106 | -0.005673130042850971221923828125000000000000000000000000000000, /* [28] */ \ 107 | -0.003549180924892425537109375000000000000000000000000000000000, /* [29] */ \ 108 | -0.001841715304180979728698730468750000000000000000000000000000, /* [30] */ \ 109 | -0.000718555646017193794250488281250000000000000000000000000000, /* [31] */ \ 110 | -0.000000000000000000388245104566976935245921787737133357154562 /* [32] */ \ 111 | } 112 | 113 | /* fdes -c 0.1 -kn 33 */ 114 | 115 | #define IPOL_FIR02 { \ 116 | -0.000935046351514756679534912109375000000000000000000000000000, /* [0] */ \ 117 | 0.000000000000000000692266834260169446329125780836832859677088, /* [1] */ \ 118 | 0.001536353491246700286865234375000000000000000000000000000000, /* [2] */ \ 119 | 0.003666520351544022560119628906250000000000000000000000000000, /* [3] */ \ 120 | 0.005414571147412061691284179687500000000000000000000000000000, /* [4] */ \ 121 | 0.004835680592805147171020507812500000000000000000000000000000, /* [5] */ \ 122 | -0.000000000000000002836163885632763486906778721552413458084629, /* [6] */ \ 123 | -0.009355833753943443298339843750000000000000000000000000000000, /* [7] */ \ 124 | -0.020424647256731986999511718750000000000000000000000000000000, /* [8] */ \ 125 | -0.027221690863370895385742187500000000000000000000000000000000, /* [9] */ \ 126 | -0.022317511960864067077636718750000000000000000000000000000000, /* [10] */ \ 127 | 0.000000000000000006199335706461330371347742684839943194674561, /* [11] */ \ 128 | 0.040453337132930755615234375000000000000000000000000000000000, /* [12] */ \ 129 | 0.093043193221092224121093750000000000000000000000000000000000, /* [13] */ \ 130 | 0.145996063947677612304687500000000000000000000000000000000000, /* [14] */ \ 131 | 0.185356348752975463867187500000000000000000000000000000000000, /* [15] */ \ 132 | 0.199905306100845336914062500000000000000000000000000000000000, /* [16] */ \ 133 | 0.185356348752975463867187500000000000000000000000000000000000, /* [17] */ \ 134 | 0.145996063947677612304687500000000000000000000000000000000000, /* [18] */ \ 135 | 0.093043193221092224121093750000000000000000000000000000000000, /* [19] */ \ 136 | 0.040453337132930755615234375000000000000000000000000000000000, /* [20] */ \ 137 | 0.000000000000000006199335706461330371347742684839943194674561, /* [21] */ \ 138 | -0.022317511960864067077636718750000000000000000000000000000000, /* [22] */ \ 139 | -0.027221690863370895385742187500000000000000000000000000000000, /* [23] */ \ 140 | -0.020424647256731986999511718750000000000000000000000000000000, /* [24] */ \ 141 | -0.009355833753943443298339843750000000000000000000000000000000, /* [25] */ \ 142 | -0.000000000000000002836163885632763486906778721552413458084629, /* [26] */ \ 143 | 0.004835680592805147171020507812500000000000000000000000000000, /* [27] */ \ 144 | 0.005414571147412061691284179687500000000000000000000000000000, /* [28] */ \ 145 | 0.003666520351544022560119628906250000000000000000000000000000, /* [29] */ \ 146 | 0.001536353491246700286865234375000000000000000000000000000000, /* [30] */ \ 147 | 0.000000000000000000692266834260169446329125780836832859677088, /* [31] */ \ 148 | -0.000935046351514756679534912109375000000000000000000000000000 /* [32] */ \ 149 | } 150 | 151 | /* fdes -c 0.15 -kn 33 */ 152 | 153 | #define IPOL_FIR03 { \ 154 | 0.000932948023546487092971801757812500000000000000000000000000, /* [0] */ \ 155 | 0.001880096038803458213806152343750000000000000000000000000000, /* [1] */ \ 156 | 0.001532905735075473785400390625000000000000000000000000000000, /* [2] */ \ 157 | -0.001188651192933320999145507812500000000000000000000000000000, /* [3] */ \ 158 | -0.005402419716119766235351562500000000000000000000000000000000, /* [4] */ \ 159 | -0.006640806794166564941406250000000000000000000000000000000000, /* [5] */ \ 160 | 0.000000000000000004244698820011787892322180359983008202107158, /* [6] */ \ 161 | 0.012848302721977233886718750000000000000000000000000000000000, /* [7] */ \ 162 | 0.020378811284899711608886718750000000000000000000000000000000, /* [8] */ \ 163 | 0.008825014345347881317138671875000000000000000000000000000000, /* [9] */ \ 164 | -0.022267427295446395874023437500000000000000000000000000000000, /* [10] */ \ 165 | -0.050509486347436904907226562500000000000000000000000000000000, /* [11] */ \ 166 | -0.040362555533647537231445312500000000000000000000000000000000, /* [12] */ \ 167 | 0.030163722112774848937988281250000000000000000000000000000000, /* [13] */ \ 168 | 0.145668432116508483886718750000000000000000000000000000000000, /* [14] */ \ 169 | 0.254548579454421997070312500000000000000000000000000000000000, /* [15] */ \ 170 | 0.299185037612915039062500000000000000000000000000000000000000, /* [16] */ \ 171 | 0.254548579454421997070312500000000000000000000000000000000000, /* [17] */ \ 172 | 0.145668432116508483886718750000000000000000000000000000000000, /* [18] */ \ 173 | 0.030163722112774848937988281250000000000000000000000000000000, /* [19] */ \ 174 | -0.040362555533647537231445312500000000000000000000000000000000, /* [20] */ \ 175 | -0.050509486347436904907226562500000000000000000000000000000000, /* [21] */ \ 176 | -0.022267427295446395874023437500000000000000000000000000000000, /* [22] */ \ 177 | 0.008825014345347881317138671875000000000000000000000000000000, /* [23] */ \ 178 | 0.020378811284899711608886718750000000000000000000000000000000, /* [24] */ \ 179 | 0.012848302721977233886718750000000000000000000000000000000000, /* [25] */ \ 180 | 0.000000000000000004244698820011787892322180359983008202107158, /* [26] */ \ 181 | -0.006640806794166564941406250000000000000000000000000000000000, /* [27] */ \ 182 | -0.005402419716119766235351562500000000000000000000000000000000, /* [28] */ \ 183 | -0.001188651192933320999145507812500000000000000000000000000000, /* [29] */ \ 184 | 0.001532905735075473785400390625000000000000000000000000000000, /* [30] */ \ 185 | 0.001880096038803458213806152343750000000000000000000000000000, /* [31] */ \ 186 | 0.000932948023546487092971801757812500000000000000000000000000 /* [32] */ \ 187 | } 188 | 189 | /* Static initializer for the interpolation filter, picked from above. */ 190 | 191 | #define IPOL_FIR IPOL_FIR00 192 | 193 | /* 194 | * When the symbol IPOC_FC is defined, it holds the digital cutoff frequency 195 | * of the interpolation filter. The filter coefficients will be computed by 196 | * the overmaker program. 197 | * 198 | * The symbol IPOL_WDW refers to the window function used to smooth the 199 | * ends of the impulse response. See filterTools.h for the available options. 200 | */ 201 | 202 | #define IPOL_FC 0.25 203 | 204 | #ifdef IPOL_FC 205 | #define IPOL_WDW 0 206 | #endif /* IPOL_FC */ 207 | 208 | /* XOVER_RATE: Oversampling rate */ 209 | 210 | #define XOVER_RATE 4 211 | 212 | /* XZB_SIZE: Input history buffer (interpolation filter) */ 213 | 214 | #define XZB_SIZE 64 215 | 216 | /* YZB_SIZE: Output history buffer (decimation filter) */ 217 | 218 | #define YZB_SIZE 128 219 | 220 | /* AAL_LEN: The nof points in the decimation filter */ 221 | 222 | #define AAL_LEN 33 223 | 224 | /* Static initialization of decimation filter, selected from above. 225 | * This is not used when AAL_FC is defined. 226 | */ 227 | 228 | #define AAL_FIR IPOL_FIR03 229 | 230 | /* 231 | * When the symbol AAL_FC is defined, it holds the digital cutoff frequency 232 | * of the decimation filter. The filter coefficients will then be computed 233 | * by the overmaker program. 234 | * 235 | * The symbol AAL_WDW refers to the window function used to smooth the 236 | * ends of the impulse response. See filterTools.h for the available options. 237 | */ 238 | 239 | #define AAL_FC IPOL_FC 240 | 241 | #ifdef AAL_FC 242 | #define AAL_WDW 0 243 | #endif /* AAL_FC */ 244 | 245 | /* Mix clean sound with overdriven */ 246 | /* #define CLEAN_MIX */ 247 | 248 | #define TR_BIASED 249 | 250 | #ifdef TR_BIASED 251 | #define SAG_EMULATION 252 | 253 | #define BIAS 0.5347 254 | #define BIAS_LO 0.0 255 | #define BIAS_HI 0.7 256 | 257 | #define ADWS_PRE_DIFF 258 | #ifdef ADWS_PRE_DIFF 259 | #define ADWS_FB 0.5821 260 | #define ADWS_FB_MAX 0.999 261 | #endif /* ADWS_PRE_DIFF */ 262 | 263 | #ifdef SAG_EMULATION 264 | 265 | #define SAG_FB 0.991 266 | 267 | #define SAG_ZGB 0.0094 268 | #define SAG_ZGB_LO 0.0 269 | #define SAG_ZGB_HI 0.05 270 | #endif /* SAG_EMULATION */ 271 | 272 | #define ADWS_NO_LINEAR /* Use curve with no linear segment */ 273 | #ifdef ADWS_NO_LINEAR 274 | #define ADWS_V_LO 0.0 275 | #define ADWS_V_HI 1.0 276 | #endif /* ADWS_NO_LINEAR */ 277 | 278 | #define ADWS_POST_DIFF 279 | #ifdef ADWS_POST_DIFF 280 | #define ADWS_FB2 0.999 281 | #define ADWS_FB2_MAX 0.999 282 | #endif /* ADWS_POST_DIFF */ 283 | 284 | #define ADWS_GFB /* Global feedback */ 285 | #ifdef ADWS_GFB 286 | #define ADWS_GFB_MAX -0.999 287 | #endif /* ADWS_GFB */ 288 | 289 | #define ADWS_FAT_CTRL 290 | 291 | #ifndef HAS_CALLBACKS 292 | #define HAS_CALLBACKS 293 | #endif /* HAS_CALLBACKS */ 294 | 295 | #endif /* TR_BIASED */ 296 | 297 | /* ================================================================ */ 298 | 299 | /* Prefilter type (undefine for no filter) */ 300 | /* #define PRE_FILTER_TYPE EQC_PEQ */ 301 | #define PRE_FILTER_HERTZ 800.0 /* Initial cutoff */ 302 | #define PRE_FILTER_HERTZ_LO 32.0 /* Minimum cutoff */ 303 | #define PRE_FILTER_HERTZ_HI 8000.0 /* Maximum cutoff */ 304 | #define PRE_FILTER_Q 1.0 305 | #define PRE_FILTER_Q_LO 0.01 306 | #define PRE_FILTER_Q_HI 6.0 307 | #define PRE_FILTER_G 0.0 308 | #define PRE_FILTER_G_LO -12.0 309 | #define PRE_FILTER_G_HI 12.0 310 | 311 | /* Postfilter type (undefine for no filter) */ 312 | /* #define POST_FILTER_TYPE EQC_PEQ */ 313 | /* #define POST_FILTER_TYPE EQC_BPF1 */ 314 | #define POST_FILTER_HERTZ 800.0 315 | #define POST_FILTER_HERTZ_LO 32.0 316 | #define POST_FILTER_HERTZ_HI 10000.0 317 | #define POST_FILTER_Q 1.0 318 | #define POST_FILTER_Q_LO 0.01 319 | #define POST_FILTER_Q_HI 6.0 320 | #define POST_FILTER_G 0.0 321 | #define POST_FILTER_G_LO -12.0 322 | #define POST_FILTER_G_HI 12.0 323 | 324 | /* If defined, gain is applied to the input signal */ 325 | #define INPUT_GAIN 3.5675 326 | #define INPUT_GAIN_LO 0.001 327 | #define INPUT_GAIN_HI 10.0 328 | 329 | /* If defined, gain is applied to output signal */ 330 | #define OUTPUT_GAIN 0.8795 331 | #define OUTPUT_GAIN_LO 0.1 332 | #define OUTPUT_GAIN_HI 10.0 333 | 334 | /* #define PRE_DC_OFFSET */ 335 | /* #define BASS_SIDECHAIN */ 336 | /* #define INPUT_COMPRESS */ 337 | #ifdef INPUT_COMPRESS 338 | 339 | #define IPC_THRESHOLD 1.0 340 | #define IPC_THR_LO 0.001 /* Must not be zero */ 341 | #define IPC_THR_HI 2.0 342 | 343 | #define IPC_GAIN_REDUCE 0.98 344 | #define IPC_ATK_LO 0.97 345 | #define IPC_ATK_HI 1.00 346 | 347 | #define IPC_GAIN_RECOVER 1.002 348 | #define IPC_RLS_LO 1.00 349 | #define IPC_RLS_HI 1.1 350 | 351 | #define IPC_GAIN_IDLE 1.0 352 | #endif /* INPUT_COMPRESS */ 353 | -------------------------------------------------------------------------------- /plugin/setBfree/b_overdrive/ovt_biased.h: -------------------------------------------------------------------------------- 1 | /* setBfree - DSP tonewheel organ 2 | * 3 | * Copyright (C) 2003-2004 Fredrik Kilander 4 | * Copyright (C) 2008-2018 Robin Gareus 5 | * Copyright (C) 2012 Will Panther 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2, or (at your option) 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | /* ovt_biased.h */ 22 | #ifndef OVT_BIASED_H 23 | #define OVT_BIASED_H 24 | 25 | #define HAS_CALLBACKS 26 | 27 | extern void hdr_biased (); 28 | extern void cfg_biased (); 29 | extern void ctl_biased (); 30 | extern void ini_biased (); 31 | extern void rst_biased (); 32 | 33 | extern void xfr_biased (); 34 | 35 | extern void bindCallbacks (); 36 | 37 | #endif /* OVT_BIASED_H */ 38 | -------------------------------------------------------------------------------- /plugin/setBfree/b_reverb/reverb.c: -------------------------------------------------------------------------------- 1 | /* setBfree - DSP tonewheel organ 2 | * 3 | * Copyright (C) 2003-2004 Fredrik Kilander 4 | * Copyright (C) 2008-2018 Robin Gareus 5 | * Copyright (C) 2012 Will Panther 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2, or (at your option) 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | /* 22 | * effect initialization is done in 3 steps: 23 | * - allocReverb() -- prepare instance, initialize default config 24 | * - reverbConfig() -- set configuration variables (optional) 25 | * - initReverb() -- derive static variables from cfg, allocate buffers 26 | * Note: SampleRate is unknown until step (3) initReverb() 27 | * 28 | * 29 | * The reverb algorithm was pieced together from two sources: 30 | * 31 | * 1. Philip Edelbrock, 'Room Acoustics Modeling', 32 | * http://pefarina.eng.unipr.it/Aurora/SAW/RoomSim.html 33 | * 34 | * All-pass filter implementation; placing the all-pass filters after 35 | * the delay lines. 36 | * 37 | * 2. Julius O. Smith III, 'Digital Waveguide Modeling of Musical Instruments', 38 | * 'A Schroeder Reverberator called JCRev', 39 | * https://ccrma.stanford.edu/~jos/waveguide/Schroeder_Reverberators.html 40 | * 41 | * All-pass filter delay lengths. 42 | * 43 | * The end result has a schematic like this: 44 | * 45 | * +-----[ D0 ]-------+ 46 | * | | 47 | * +-----[ D1 ]-------+ 48 | * | (+)---[AP4]---[AP5]---[AP6]-----+ 49 | * +-----[ D2 ]-------+ | 50 | * | | | 51 | * +-----[ D3 ]-------+ | 52 | * | | 53 | * (+)-------------------------------------------(+) 62 | * | | 63 | * /\ --- 64 | * inputNormalization outputScaling 65 | * -- \/ 66 | * | | 67 | * x y 68 | * 69 | * The delays (D0, D1, D2, D3) are structured thus: 70 | * 71 | * x---(+)--[ Dn ]--+---y 72 | * | | 73 | * +---------------+ 80 | * | | 81 | * x--+--(+)--[Gn>--[ Dn ]--+--(+)--y 82 | * | | 83 | * +-----<+1]--------+ 84 | * 85 | * Index numbers 4, 5 and 6 refers to the all-pass filters. 86 | */ 87 | #ifndef CONFIGDOCONLY 88 | 89 | #include 90 | #include 91 | #include 92 | #include 93 | #include 94 | 95 | #include "../src/midi.h" // useMIDIControlFunction 96 | #include "reverb.h" 97 | 98 | #if _WIN32 99 | #pragma warning(disable:4305) 100 | #pragma warning(disable:4244) 101 | #endif 102 | 103 | struct b_reverb* 104 | allocReverb () 105 | { 106 | struct b_reverb* r = (struct b_reverb*)calloc (1, sizeof (struct b_reverb)); 107 | 108 | if (!r) { 109 | return NULL; 110 | } 111 | 112 | r->inputGain = 0.1; /* Input gain value */ 113 | r->fbk = -0.015; /* Feedback gain */ 114 | r->wet = 0.1; /* Output dry gain */ 115 | r->dry = 0.9; /* Output wet gain */ 116 | 117 | /* These are all 1/sqrt(2) = 0.7071067811865475 */ 118 | r->gain[0] = sqrtf (0.5); /* FBCF (feedback combfilter) */ 119 | r->gain[1] = sqrtf (0.5); /* FBCF */ 120 | r->gain[2] = sqrtf (0.5); /* FBCF */ 121 | r->gain[3] = sqrtf (0.5); /* FBCF */ 122 | 123 | r->gain[4] = sqrtf (0.5); /* AP (all-pass filter) */ 124 | r->gain[5] = sqrtf (0.5); /* AP */ 125 | r->gain[6] = sqrtf (0.5); /* AP */ 126 | 127 | /* delay lines */ 128 | r->end[0] = 2999; 129 | r->end[1] = 2331; 130 | r->end[2] = 1893; 131 | r->end[3] = 1097; 132 | 133 | /* all pass filters */ 134 | r->end[4] = 1051; 135 | r->end[5] = 337; 136 | r->end[6] = 113; 137 | 138 | int i; 139 | for (i = 0; i < RV_NZ; ++i) { 140 | r->delays[i] = NULL; 141 | } 142 | 143 | r->yy1 = 0.0; 144 | r->y_1 = 0.0; 145 | 146 | return r; 147 | } 148 | 149 | void 150 | freeReverb (struct b_reverb* r) 151 | { 152 | int i; 153 | for (i = 0; i < RV_NZ; ++i) { 154 | free (r->delays[i]); 155 | } 156 | free (r); 157 | } 158 | 159 | /* used during initialization, set array end pointers */ 160 | static void 161 | setReverbPointers (struct b_reverb* r, int i) 162 | { 163 | if ((0 <= i) && (i < RV_NZ)) { 164 | int e = (r->end[i] * r->SampleRateD / 22050.0); 165 | e = e | 1; 166 | r->delays[i] = (float*)realloc ((void*)r->delays[i], (e + 2) * sizeof (float)); 167 | if (!r->delays[i]) { 168 | fprintf (stderr, "FATAL: memory allocation failed for reverb.\n"); 169 | exit (1); 170 | } else { 171 | memset (r->delays[i], 0, (e + 2) * sizeof (float)); 172 | } 173 | r->endp[i] = r->delays[i] + e + 1; 174 | r->idx0[i] = r->idxp[i] = &(r->delays[i][0]); 175 | } 176 | } 177 | 178 | void 179 | setReverbInputGain (struct b_reverb* r, float g) 180 | { 181 | r->inputGain = g; 182 | } 183 | 184 | void 185 | setReverbOutputGain (struct b_reverb* r, float g) 186 | { 187 | float u = r->wet + r->dry; 188 | r->wet = g * (r->wet / u); 189 | r->dry = g * (r->dry / u); 190 | } 191 | 192 | /* 193 | * @param g 0.0 Dry ... 1.0 wet 194 | */ 195 | void 196 | setReverbMix (struct b_reverb* r, float g) 197 | { 198 | float u = r->wet + r->dry; 199 | r->wet = g * u; 200 | r->dry = u - (g * u); 201 | } 202 | 203 | void 204 | setReverbMixFromMIDI (void* rev, unsigned char v) 205 | { 206 | struct b_reverb* r = (struct b_reverb*)rev; 207 | setReverbMix (r, (float)v / 127.0f); 208 | } 209 | 210 | int 211 | reverbConfig (struct b_reverb* r, ConfigContext* cfg) 212 | { 213 | int ack = 1; 214 | double d; 215 | if (getConfigParameter_d ("reverb.wet", cfg, &d) == 1) { 216 | r->wet = d; 217 | } else if (getConfigParameter_d ("reverb.dry", cfg, &d) == 1) { 218 | r->dry = d; 219 | } else if (getConfigParameter_d ("reverb.inputgain", cfg, &d) == 1) { 220 | setReverbInputGain (r, (float)d); 221 | } else if (getConfigParameter_d ("reverb.outputgain", cfg, &d) == 1) { 222 | setReverbOutputGain (r, (float)d); 223 | } else if (getConfigParameter_dr ("reverb.mix", cfg, &d, 0, 1.0) == 1) { 224 | setReverbMix (r, (float)d); 225 | } else { 226 | ack = 0; 227 | } 228 | return ack; 229 | } 230 | 231 | void 232 | initReverb (struct b_reverb* r, void* m, double rate) 233 | { 234 | int i; 235 | r->SampleRateD = rate; 236 | for (i = 0; i < RV_NZ; i++) { 237 | setReverbPointers (r, i); 238 | } 239 | setReverbInputGain (r, r->inputGain); 240 | useMIDIControlFunction (m, "reverb.mix", setReverbMixFromMIDI, r); 241 | } 242 | 243 | float* 244 | reverb (struct b_reverb* r, 245 | const float* inbuf, 246 | float* outbuf, 247 | size_t bufferLengthSamples) 248 | { 249 | float** const idxp = r->idxp; 250 | float* const* const endp = r->endp; 251 | float* const* const idx0 = r->idx0; 252 | const float* const gain = r->gain; 253 | const float inputGain = r->inputGain; 254 | const float fbk = r->fbk; 255 | const float wet = r->wet; 256 | const float dry = r->dry; 257 | 258 | unsigned int i; 259 | const float* xp = inbuf; 260 | float* yp = outbuf; 261 | 262 | float y_1 = r->y_1; 263 | float yy1 = r->yy1; 264 | 265 | for (i = 0; i < bufferLengthSamples; i++) { 266 | int j; 267 | float y; 268 | const float xo = (*xp++); 269 | const float x = y_1 + (inputGain * xo); 270 | float xa = 0.0; 271 | 272 | /* First we do four feedback comb filters (ie parallel delay lines, 273 | * each with a single tap at the end that feeds back at the start) */ 274 | 275 | for (j = 0; j < 4; j++) { 276 | y = (*idxp[j]); 277 | *idxp[j] = x + (gain[j] * y); 278 | if (endp[j] <= ++(idxp[j])) 279 | idxp[j] = idx0[j]; 280 | xa += y; 281 | } 282 | 283 | for (; j < 7; j++) { 284 | y = (*idxp[j]); 285 | *idxp[j] = gain[j] * (xa + y); 286 | if (endp[j] <= ++(idxp[j])) 287 | idxp[j] = idx0[j]; 288 | xa = y - xa; 289 | } 290 | 291 | y = 0.5 * (xa + yy1); 292 | yy1 = y; 293 | y_1 = fbk * xa; 294 | 295 | *yp++ = ((wet * y) + (dry * xo)); 296 | } 297 | 298 | r->y_1 = y_1 + DENORMAL_HACK; 299 | r->yy1 = yy1 + DENORMAL_HACK; 300 | return outbuf; 301 | } 302 | 303 | #else 304 | #include "cfgParser.h" 305 | #endif // CONFIGDOCONLY 306 | 307 | static const ConfigDoc doc[] = { 308 | { "reverb.wet", CFG_DOUBLE, "0.1", "Reverb Wet signal level; range [0..1]", INCOMPLETE_DOC }, 309 | { "reverb.dry", CFG_DOUBLE, "0.9", "Reverb Dry signal level; range [0..1]", INCOMPLETE_DOC }, 310 | { "reverb.inputgain", CFG_DOUBLE, "0.1", "Reverb Input Gain", "dB", 0.01, 0.5, 2.0 }, 311 | { "reverb.outputgain", CFG_DOUBLE, "1.0", "Reverb Output Gain (modifies dry/wet)", INCOMPLETE_DOC }, 312 | { "reverb.mix", CFG_DOUBLE, "0.1", "Reverb Mix (modifies dry/wet).", INCOMPLETE_DOC }, 313 | DOC_SENTINEL 314 | }; 315 | 316 | const ConfigDoc* 317 | reverbDoc () 318 | { 319 | return doc; 320 | } 321 | -------------------------------------------------------------------------------- /plugin/setBfree/b_reverb/reverb.h: -------------------------------------------------------------------------------- 1 | /* setBfree - DSP tonewheel organ 2 | * 3 | * Copyright (C) 2003-2004 Fredrik Kilander 4 | * Copyright (C) 2008-2018 Robin Gareus 5 | * Copyright (C) 2012 Will Panther 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2, or (at your option) 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef REVERB_H 22 | #define REVERB_H 23 | 24 | #define RV_NZ 7 25 | struct b_reverb { 26 | /* static buffers, pointers */ 27 | float* delays[RV_NZ]; /**< delay line buffer */ 28 | 29 | float* idx0[RV_NZ]; /**< Reset pointer ref delays[]*/ 30 | float* idxp[RV_NZ]; /**< Index pointer ref delays[]*/ 31 | float* endp[RV_NZ]; /**< End pointer ref delays[]*/ 32 | 33 | float gain[RV_NZ]; /**< feedback gains */ 34 | float yy1; /**< Previous output sample */ 35 | float y_1; /**< Feedback sample */ 36 | 37 | /* static config */ 38 | int end[RV_NZ]; 39 | double SampleRateD; 40 | 41 | /* dynamic config */ 42 | float inputGain; /**< Input gain value */ 43 | float fbk; /**< Feedback gain */ 44 | float wet; /**< Output dry gain */ 45 | float dry; /**< Output wet gain */ 46 | }; 47 | 48 | #include "../src/cfgParser.h" 49 | extern struct b_reverb* allocReverb (void); 50 | void freeReverb (struct b_reverb* r); 51 | 52 | extern int reverbConfig (struct b_reverb* r, ConfigContext* cfg); 53 | 54 | extern const ConfigDoc* reverbDoc (void); 55 | 56 | extern void setReverbInputGain (struct b_reverb* r, float g); 57 | 58 | extern void setReverbOutputGain (struct b_reverb* r, float g); 59 | 60 | extern void setReverbMix (struct b_reverb* r, float g); 61 | 62 | extern void setReverbDry (struct b_reverb* r, float g); 63 | 64 | extern void setReverbWet (struct b_reverb* r, float g); 65 | 66 | extern void initReverb (struct b_reverb* r, void* m, double rate); 67 | 68 | extern float* reverb (struct b_reverb* r, const float* inbuf, float* outbuf, size_t bufferLengthSamples); 69 | 70 | #endif /* REVERB_H */ 71 | -------------------------------------------------------------------------------- /plugin/setBfree/b_whirl/eqcomp.c: -------------------------------------------------------------------------------- 1 | /* setBfree - DSP tonewheel organ 2 | * 3 | * Copyright (C) 2003-2004 Fredrik Kilander 4 | * Copyright (C) 2008-2018 Robin Gareus 5 | * Copyright (C) 2010 Ken Restivo 6 | * Copyright (C) 2012 Will Panther 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2, or (at your option) 11 | * any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | */ 21 | 22 | #define _XOPEN_SOURCE 700 23 | /* clang-format off */ 24 | 25 | #include "eqcomp.h" 26 | #include 27 | #include 28 | #include 29 | 30 | #ifndef M_PI 31 | # define M_PI 3.14159265358979323846 32 | #endif 33 | 34 | /* Computes biquad EQ filter settings. 35 | * Based on 'Cookbook formulae for audio EQ biquad filter coefficents' 36 | * by Robert Bristow-Johnson 37 | * 38 | * 39 | * The functions below compute the coefficients for a single IIR stage. 40 | * Consider cascading two or more stages if you need a more powerful filter. 41 | * A single stage can easily become unstable if the parameters request too 42 | * much - the roundoff errors due to finite word lengths accumulate in the 43 | * feedback loop and result in, well, feedback. 44 | * Here a Direct Form I usage: 45 | * y[n] = b0*x[n] + b1*x[n-1] + b2*x[n-2] - a1*y[n-1] - a2*y[n-2] 46 | * If that means nothing to you, here is a short explanation: 47 | * y[n] : The current output sample 48 | * y[n-1] : The previous output sample 49 | * y[n-2] : The output sample before the previous output sample 50 | * x[n] : The current input sample 51 | * x[n-1] : The previous input sample 52 | * x[n-2] : The input sample before the previous input sample 53 | * a1, a2, b0, b1, b2 : Filter coefficients. 54 | * Coefficient a0 is not present because it has already been used to 55 | * normalize the other coefficients. 56 | * 57 | * However, I usually use a Direct Form II implementation: 58 | * static float Z0, Z1, Z2; 59 | * ... 60 | * Z0 = x - (a1 * Z1) - (a2 * Z2); 61 | * y = (Z0 * b0) + (Z1 * b1) + (Z2 * b2); 62 | * Z2 = Z1; 63 | * Z1 = Z0; 64 | * 65 | * The functions take as their last argument an array of double or float. 66 | * In the eqcom.h file are constants that give the indexes for the six 67 | * coefficients. See each function for further information. 68 | */ 69 | 70 | const char* filterTypeNames[10] = { 71 | "LPF low-pass", 72 | "HPF high-pass", 73 | "BF0 band-pass 0", 74 | "BF1 band-pass 1", 75 | "NOT notch", 76 | "APF all-pass", 77 | "PEQ peaking eq", 78 | "LSH low shelf", 79 | "HSH high shelf", 80 | "???" 81 | }; 82 | 83 | const char* 84 | eqGetTypeString (int t) 85 | { 86 | return filterTypeNames[((0 <= t) && (t < 9)) ? t : 9]; 87 | } 88 | 89 | /* 90 | * eqCompute 91 | * Computes the filter coefficients for the given filter type. 92 | * @param type The filter type (see eqcomp.h) 93 | * @param fqHz Cutoff or resonant frequency in Hertz. 94 | * @param Q The bandwidth of the filter (0.2 - 3) 95 | * @param dbG Gain in dB (for certain types only, see below) 96 | * @param C Array[6] of coefficients. 97 | */ 98 | void 99 | eqCompute (int type, 100 | double fqHz, 101 | double Q, 102 | double dbG, 103 | double* C, 104 | double SampleRateD) 105 | { 106 | double A = pow (10.0, (dbG / 40.0)); 107 | double omega = (2.0 * M_PI * fqHz) / SampleRateD; 108 | double sin_ = sin (omega); 109 | double cos_ = cos (omega); 110 | double alpha = sin_ / (2.0 * Q); 111 | double beta = sqrt (A) / Q; 112 | 113 | switch (type) { 114 | 115 | case EQC_LPF: /* Low Pass */ 116 | C[EQC_B0] = (1.0 - cos_) / 2.0; 117 | C[EQC_B1] = 1.0 - cos_; 118 | C[EQC_B2] = (1.0 - cos_) / 2.0; 119 | C[EQC_A0] = 1.0 + alpha; 120 | C[EQC_A1] = -2.0 * cos_; 121 | C[EQC_A2] = 1.0 - alpha; 122 | break; 123 | 124 | case EQC_HPF: /* High Pass */ 125 | C[EQC_B0] = (1.0 + cos_) / 2.0; 126 | C[EQC_B1] = -(1.0 + cos_); 127 | C[EQC_B2] = (1.0 + cos_) / 2.0; 128 | C[EQC_A0] = 1.0 + alpha; 129 | C[EQC_A1] = -2.0 * cos_; 130 | C[EQC_A2] = 1.0 - alpha; 131 | break; 132 | 133 | case EQC_BPF0: /* Constant skirt gain, peak gain = Q */ 134 | C[EQC_B0] = sin_ / 2.0; 135 | C[EQC_B1] = 0.0; 136 | C[EQC_B2] = -sin_ / 2.0; 137 | C[EQC_A0] = 1.0 + alpha; 138 | C[EQC_A1] = -2.0 * cos_; 139 | C[EQC_A2] = 1.0 - alpha; 140 | break; 141 | 142 | case EQC_BPF1: /* Constant 0 dB peak gain */ 143 | C[EQC_B0] = alpha; 144 | C[EQC_B1] = 0.0; 145 | C[EQC_B2] = -alpha; 146 | C[EQC_A0] = 1.0 + alpha; 147 | C[EQC_A1] = -2.0 * cos_; 148 | C[EQC_A2] = 1.0 - alpha; 149 | break; 150 | 151 | case EQC_NOTCH: /* Notch filter */ 152 | C[EQC_B0] = 1.0; 153 | C[EQC_B1] = -2.0 * cos_; 154 | C[EQC_B2] = 1.0; 155 | C[EQC_A0] = 1.0 + alpha; 156 | C[EQC_A1] = -2.0 * cos_; 157 | C[EQC_A2] = 1.0 - alpha; 158 | break; 159 | 160 | case EQC_APF: /* Allpass filter */ 161 | C[EQC_B0] = 1.0 - alpha; 162 | C[EQC_B1] = -2.0 * cos_; 163 | C[EQC_B2] = 1.0 + alpha; 164 | C[EQC_A0] = 1.0 + alpha; 165 | C[EQC_A1] = -2.0 * cos_; 166 | C[EQC_A2] = 1.0 - alpha; 167 | break; 168 | 169 | case EQC_PEQ: /* Peaking EQ */ 170 | C[EQC_B0] = 1.0 + (alpha * A); 171 | C[EQC_B1] = -2.0 * cos_; 172 | C[EQC_B2] = 1.0 - (alpha * A); 173 | C[EQC_A0] = 1.0 + (alpha / A); 174 | C[EQC_A1] = -2.0 * cos_; 175 | C[EQC_A2] = 1.0 - (alpha / A); 176 | break; 177 | 178 | case EQC_LOW: /* Low shelf */ 179 | C[EQC_B0] = A * ((A + 1) - ((A - 1) * cos_) + (beta * sin_)); 180 | C[EQC_B1] = (2.0 * A) * ((A - 1) - ((A + 1) * cos_)); 181 | C[EQC_B2] = A * ((A + 1) - ((A - 1) * cos_) - (beta * sin_)); 182 | C[EQC_A0] = (A + 1) + ((A - 1) * cos_) + (beta * sin_); 183 | C[EQC_A1] = -2.0 * ((A - 1) + ((A + 1) * cos_)); 184 | C[EQC_A2] = (A + 1) + ((A - 1) * cos_) - (beta * sin_); 185 | break; 186 | 187 | case EQC_HIGH: /* High shelf */ 188 | C[EQC_B0] = A * ((A + 1) + ((A - 1) * cos_) + (beta * sin_)); 189 | C[EQC_B1] = -(2.0 * A) * ((A - 1) + ((A + 1) * cos_)); 190 | C[EQC_B2] = A * ((A + 1) + ((A - 1) * cos_) - (beta * sin_)); 191 | C[EQC_A0] = (A + 1) - ((A - 1) * cos_) + (beta * sin_); 192 | C[EQC_A1] = 2.0 * ((A - 1) - ((A + 1) * cos_)); 193 | C[EQC_A2] = (A + 1) - ((A - 1) * cos_) - (beta * sin_); 194 | break; 195 | } 196 | 197 | C[EQC_B0] /= C[EQC_A0]; 198 | C[EQC_B1] /= C[EQC_A0]; 199 | C[EQC_B2] /= C[EQC_A0]; 200 | C[EQC_A1] /= C[EQC_A0]; 201 | C[EQC_A2] /= C[EQC_A0]; 202 | 203 | } 204 | -------------------------------------------------------------------------------- /plugin/setBfree/b_whirl/eqcomp.h: -------------------------------------------------------------------------------- 1 | /* setBfree - DSP tonewheel organ 2 | * 3 | * Copyright (C) 2003-2004 Fredrik Kilander 4 | * Copyright (C) 2008-2018 Robin Gareus 5 | * Copyright (C) 2010 Ken Restivo 6 | * Copyright (C) 2012 Will Panther 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2, or (at your option) 11 | * any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | */ 21 | 22 | #ifndef EQCOMP_H 23 | #define EQCOMP_H 24 | 25 | /* clang-format off */ 26 | 27 | /* Filter type selection values */ 28 | #define EQC_LPF 0 /* lowpass filter */ 29 | #define EQC_HPF 1 /* highpass filter */ 30 | #define EQC_BPF0 2 /* Bandpass filter with constant skirt gain */ 31 | #define EQC_BPF1 3 /* Bandpass filter with 0 db peak gain */ 32 | #define EQC_NOTCH 4 /* Notch filter */ 33 | #define EQC_APF 5 /* Allpass filter */ 34 | #define EQC_PEQ 6 /* Peaking eq filter */ 35 | #define EQC_LOW 7 /* Low shelf filter */ 36 | #define EQC_HIGH 8 /* High shelf filter */ 37 | 38 | /* Coefficient access symbols */ 39 | #define EQC_B0 0 40 | #define EQC_B1 1 41 | #define EQC_B2 2 42 | #define EQC_A0 3 43 | #define EQC_A1 4 44 | #define EQC_A2 5 45 | 46 | /* clang-format on */ 47 | 48 | /* Function prototypes */ 49 | extern const char* eqGetTypeString (int t); 50 | 51 | extern void eqCompute (int type, 52 | double fqHz, 53 | double Q, 54 | double dbG, 55 | double* C, 56 | double SampleRateD); 57 | 58 | #endif /* EQCOMP_H */ 59 | -------------------------------------------------------------------------------- /plugin/setBfree/b_whirl/whirl.h: -------------------------------------------------------------------------------- 1 | /* setBfree - DSP tonewheel organ 2 | * 3 | * Copyright (C) 2003-2004 Fredrik Kilander 4 | * Copyright (C) 2008-2018 Robin Gareus 5 | * Copyright (C) 2010 Ken Restivo 6 | * Copyright (C) 2012 Will Panther 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2, or (at your option) 11 | * any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | */ 21 | 22 | /* whirl.h */ 23 | #ifndef WHIRL_H 24 | #define WHIRL_H 25 | 26 | #include "../src/cfgParser.h" // ConfigContext 27 | #include "../src/midi.h" // useMIDIControlFunction 28 | 29 | #define WHIRL_DISPLC_SIZE ((unsigned int)(1 << 14)) 30 | #define WHIRL_DISPLC_MASK ((WHIRL_DISPLC_SIZE)-1) 31 | 32 | #define WHIRL_BUF_SIZE_SAMPLES ((unsigned int)(1 << 11)) 33 | #define WHIRL_BUF_MASK_SAMPLES (WHIRL_BUF_SIZE_SAMPLES - 1) 34 | 35 | #define AGBUF 8 36 | #define AGMASK (AGBUF - 1) 37 | 38 | typedef float iir_t; 39 | 40 | typedef enum { 41 | a0, 42 | a1, 43 | a2, 44 | b0, 45 | b1, 46 | b2, 47 | z0, 48 | z1 49 | } filterCoeff; 50 | 51 | typedef struct _revcontrol { 52 | double hornTarget; 53 | double drumTarget; 54 | } RevControl; 55 | 56 | struct _bw { 57 | float b[5]; 58 | }; 59 | 60 | struct b_whirl { 61 | double SampleRateD; 62 | int bypass; ///< if set to 1 completely bypass this effect 63 | double hnBrakePos; ///< where to stop horn - 0: free, 1.0: front-center, ]0..1] clockwise circle */ 64 | double drBrakePos; ///< where to stop drum 65 | 66 | /* 67 | * Forward (clockwise) displacement table for writing positions. 68 | */ 69 | float hnFwdDispl[WHIRL_DISPLC_SIZE]; /* Horn */ 70 | float drFwdDispl[WHIRL_DISPLC_SIZE]; /* Drum */ 71 | 72 | /* 73 | * Backward (counter-clockwise) displacement table. 74 | */ 75 | float hnBwdDispl[WHIRL_DISPLC_SIZE]; /* Horn */ 76 | float drBwdDispl[WHIRL_DISPLC_SIZE]; /* Drum */ 77 | 78 | struct _bw bfw[WHIRL_DISPLC_SIZE]; 79 | struct _bw bbw[WHIRL_DISPLC_SIZE]; 80 | 81 | float adx0[AGBUF]; 82 | float adx1[AGBUF]; 83 | float adx2[AGBUF]; 84 | int adi0; 85 | int adi1; 86 | int adi2; 87 | 88 | /* 89 | * Writing positions (actually, indexes into hnFwdDispl[]): 90 | * Left Right 91 | * Primary 0 1 92 | * First reflec. 2 3 93 | * Second refl. 4 5 94 | */ 95 | 96 | int hornPhase[6]; 97 | 98 | int drumPhase[6]; 99 | 100 | /* The current angle of rotating elements */ 101 | 102 | double hornAngleGRD; /* 0..1 */ 103 | double drumAngleGRD; 104 | 105 | double micAngle; 106 | 107 | /* target speed - rotational frequency */ 108 | float hornRPMslow; 109 | float hornRPMfast; 110 | float drumRPMslow; 111 | float drumRPMfast; 112 | 113 | /* time constants [s] -- first order differential */ 114 | float hornAcc; 115 | float hornDec; 116 | float drumAcc; 117 | float drumDec; 118 | 119 | #define revSelectEnd (3) 120 | RevControl revoptions[9]; 121 | int revselects[revSelectEnd]; 122 | int revSelect; 123 | 124 | int hornAcDc; 125 | int drumAcDc; 126 | 127 | double hornIncr; ///< current angular speed - unit: radians / sample / (2*M_PI) 128 | double drumIncr; ///< current angular speed - unit: radians / sample / (2*M_PI) 129 | 130 | double hornTarget; ///< target angular speed - unit: radians / sample / (2*M_PI) 131 | double drumTarget; ///< target angular speed - unit: radians / sample / (2*M_PI) 132 | 133 | /* 134 | * Spacing between reflections in samples. The first can't be zero, since 135 | * we must allow for the swing of the extent to wander close to the reader. 136 | */ 137 | 138 | float hornSpacing[6]; 139 | float hornRadiusCm; /* 17.0; 25-nov-04 */ 140 | float drumRadiusCm; 141 | 142 | float airSpeed; /* Meters per second */ 143 | float micDistCm; /* From mic to origin */ 144 | float hornXOffsetCm; /* offset of horn, towards left mic */ 145 | float hornZOffsetCm; /* offset of horn, perpendicular to mic to front */ 146 | float drumSpacing[6]; 147 | 148 | /* Delay buffers */ 149 | 150 | float HLbuf[WHIRL_BUF_SIZE_SAMPLES]; /* Horn left buffer */ 151 | float HRbuf[WHIRL_BUF_SIZE_SAMPLES]; /* Horn right buffer */ 152 | float DLbuf[WHIRL_BUF_SIZE_SAMPLES]; /* Drum left buffer */ 153 | float DRbuf[WHIRL_BUF_SIZE_SAMPLES]; /* Drum right buffer */ 154 | 155 | /* Single read position, incremented by one, always. */ 156 | 157 | unsigned int outpos; 158 | float z[4]; 159 | 160 | iir_t drfL[8]; /* Drum filter */ 161 | iir_t drfR[8]; /* Drum filter */ 162 | int lpT; /* high shelf */ 163 | double lpF; /* Frequency */ 164 | double lpQ; /* Q, bandwidth */ 165 | double lpG; /* Gain */ 166 | 167 | iir_t hafw[8]; /* Horn filter a */ 168 | float haT; /* low pass */ 169 | float haF; /* 3900.0; 25-nov-04 */ 170 | float haQ; /* 1.4; 25-nov-04 */ 171 | float haG; /* 0.0; 25-nov-04 */ 172 | 173 | iir_t hbfw[8]; 174 | float hbT; /* low shelf */ 175 | float hbF; 176 | float hbQ; /* 2.0; 25-nov-04 */ 177 | float hbG; /* -60.0; 25-nov-04 */ /* negative gain */ 178 | 179 | #ifdef HORN_COMB_FILTER 180 | #define COMB_SIZE ((unsigned int)(1 << 10)) 181 | #define COMB_MASK (COMB_SIZE - 1) 182 | 183 | float comb0[COMB_SIZE]; 184 | float cb0fb; 185 | int cb0dl; 186 | float* cb0wp; /* Write pointer */ 187 | float* cb0rp; /* Read pointer */ 188 | float* cb0bp; /* Begin pointer */ 189 | float* cb0es; /* End sentinel */ 190 | 191 | float comb1[COMB_SIZE]; 192 | float cb1fb; 193 | int cb1dl; 194 | float* cb1wp; 195 | float* cb1rp; 196 | float* cb1bp; 197 | float* cb1es; 198 | #else /* allow to parse config files which include these values */ 199 | float cb0fb; 200 | int cb0dl; 201 | float cb1fb; 202 | int cb1dl; 203 | #endif 204 | 205 | float hornLevel; 206 | float leakLevel; 207 | float leakage; 208 | 209 | float drumMicWidth, hornMicWidth; 210 | float drumMic_dll, hornMic_hll; 211 | float drumMic_dlr, hornMic_hlr; 212 | float drumMic_drl, hornMic_hrl; 213 | float drumMic_drr, hornMic_hrr; 214 | 215 | void* midi_cfg_ptr; 216 | }; 217 | 218 | extern struct b_whirl* allocWhirl (void); 219 | extern void freeWhirl (struct b_whirl* w); 220 | extern int whirlConfig (struct b_whirl* w, ConfigContext* cfg); 221 | extern const ConfigDoc* whirlDoc (void); 222 | 223 | extern void initWhirl (struct b_whirl* w, void* m, double rate); 224 | 225 | extern void whirlProc (struct b_whirl* w, 226 | const float* inbuffer, 227 | float* outbL, 228 | float* outbR, 229 | size_t bufferLengthSamples); 230 | 231 | extern void whirlProc2 (struct b_whirl* w, 232 | const float* inbuffer, 233 | float* outL, float* outR, 234 | float* outHL, float* outHR, 235 | float* outDL, float* outDR, 236 | size_t bufferLengthSamples); 237 | 238 | extern void whirlProc3 (struct b_whirl* w, 239 | const float* inbuffer, 240 | float* outL, float* outR, 241 | float* tmpL, float* tmpR, 242 | size_t bufferLengthSamples); 243 | 244 | /* match revselects[] */ 245 | #define WHIRL_FAST 2 246 | #define WHIRL_SLOW 0 247 | #define WHIRL_STOP 1 248 | 249 | extern void setRevSelect (struct b_whirl* w, int n); 250 | extern void useRevOption (struct b_whirl* w, int n, int signals); 251 | extern void isetHornFilterAType (struct b_whirl* w, int v); 252 | extern void fsetHornFilterAFrequency (struct b_whirl* w, float v); 253 | extern void fsetHornFilterAQ (struct b_whirl* w, float v); 254 | extern void fsetHornFilterAGain (struct b_whirl* w, float v); 255 | extern void isetHornFilterBType (struct b_whirl* w, int v); 256 | extern void fsetHornFilterBFrequency (struct b_whirl* w, float v); 257 | extern void fsetHornFilterBQ (struct b_whirl* w, float v); 258 | extern void fsetHornFilterBGain (struct b_whirl* w, float v); 259 | extern void isetDrumFilterType (struct b_whirl* w, int v); 260 | extern void fsetDrumFilterFrequency (struct b_whirl* w, float v); 261 | extern void fsetDrumFilterQ (struct b_whirl* w, float v); 262 | extern void fsetDrumFilterGain (struct b_whirl* w, float v); 263 | extern void computeRotationSpeeds (struct b_whirl* w); 264 | extern void computeOffsets (struct b_whirl* w); 265 | extern void fsetDrumMicWidth (void* d, const float dw); 266 | 267 | #endif /* WHIRL_H */ 268 | -------------------------------------------------------------------------------- /plugin/setBfree/doc/b_synth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FigBug/Organ/17f884126bb76d2d3c95e12224aab8f38ef8c96d/plugin/setBfree/doc/b_synth.png -------------------------------------------------------------------------------- /plugin/setBfree/doc/b_whirl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FigBug/Organ/17f884126bb76d2d3c95e12224aab8f38ef8c96d/plugin/setBfree/doc/b_whirl.png -------------------------------------------------------------------------------- /plugin/setBfree/doc/clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | BasedOnStyle: LLVM 4 | AlignAfterOpenBracket: Align 5 | AlignConsecutiveAssignments: true 6 | AlignConsecutiveDeclarations: true 7 | AlignEscapedNewlinesLeft: false 8 | AllowShortFunctionsOnASingleLine: Empty 9 | AllowShortBlocksOnASingleLine: false 10 | AllowShortCaseLabelsOnASingleLine : false 11 | AllowShortIfStatementsOnASingleLine: false 12 | AllowShortLoopsOnASingleLine: false 13 | AlwaysBreakAfterReturnType: AllDefinitions 14 | BreakBeforeBraces: Linux 15 | ColumnLimit: 0 16 | IndentCaseLabels: true 17 | KeepEmptyLinesAtTheStartOfBlocks: false 18 | MaxEmptyLinesToKeep: 1 19 | ReflowComments: true 20 | PointerAlignment: Left 21 | SortIncludes: true 22 | SpaceAfterCStyleCast: false 23 | SpaceBeforeAssignmentOperators: true 24 | SpaceBeforeParens: Always 25 | SpaceInEmptyParentheses: false 26 | SpacesBeforeTrailingComments: 1 27 | SpacesInContainerLiterals: true 28 | SpacesInCStyleCastParentheses: false 29 | SpacesInParentheses: false 30 | SpacesInSquareBrackets: false 31 | Cpp11BracedListStyle: false 32 | IndentWidth: 8 33 | TabWidth: 8 34 | UseTab: ForIndentation 35 | -------------------------------------------------------------------------------- /plugin/setBfree/doc/jboverdrive.1: -------------------------------------------------------------------------------- 1 | .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.40.4. 2 | .TH JBOVERDRIVE "1" "April 2014" "jboverdrive 0.7.5" "User Commands" 3 | .SH NAME 4 | jboverdrive \- The B Preamp/Overdrive Emulator 5 | .SH SYNOPSIS 6 | .B jboverdrive 7 | [ \fIOPTIONS \fR] 8 | .SH DESCRIPTION 9 | jboverdrive \- the B Preamp/Overdrive Emulator 10 | .PP 11 | Utility to write audio peak data to stdout of file as plain text of JSON data. 12 | .SH OPTIONS 13 | .TP 14 | \fB\-h\fR, \fB\-\-help\fR 15 | Print help text 16 | .TP 17 | \fB\-i\fR, \fB\-\-input\fR 18 | Connect to JACK input port 19 | .TP 20 | \fB\-o\fR, \fB\-\-output\fR 21 | Connect output to given JACK port 22 | .TP 23 | \fB\-p\fR, \fB\-\-parameter\fR 24 | Specify initial effect parameter 25 | .TP 26 | \fB\-V\fR, \fB\-\-version\fR 27 | Print version information 28 | .PP 29 | Effect parameters are all float values 0..1. 30 | Available keys and their default values are as follows: 31 | .TP 32 | gainin: 33 | Input Gain = 0.3567 34 | .TP 35 | bias: 36 | Bias = 0.87399 37 | .TP 38 | feedback: 39 | Feedback = 0.5821 40 | .TP 41 | sagtobias: 42 | Sag to Bias = 0.1880 43 | .TP 44 | postfeed: 45 | Postdiff Feedback = 1.0 46 | .TP 47 | globfeed: 48 | Global Feedback = 0.5826 49 | .TP 50 | gainout: 51 | Output Gain = 0.07873 52 | .SH EXAMPLES 53 | jboverdrive \fB\-i\fR system:capture_1 \fB\-o\fR system:playback_1 \fB\-p\fR bias=.5 \fB\-p\fR feedback=0.9 54 | .PP 55 | jboverdrive \fB\-i\fR system:capture_1 \fB\-o\fR system:playback_1 \fB\-O\fR 1234 56 | .PP 57 | oscsend localhost 1234 /boverdrive/bias f 0.9 58 | .PP 59 | oscsend localhost 1234 /boverdrive/gainout f 0.3 60 | .PP 61 | oscsend localhost 1234 /boverdrive/quit 62 | .SH "REPORTING BUGS" 63 | Report bugs to . 64 | .br 65 | Website and manual: 66 | .SH COPYRIGHT 67 | Copyright \(co 2003\-2004 Fredrik Kilander 68 | .br 69 | Copyright \(co 2012 Robin Gareus 70 | .PP 71 | .br 72 | This is free software; see the source for copying conditions. There is NO 73 | warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 74 | -------------------------------------------------------------------------------- /plugin/setBfree/doc/setBfree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FigBug/Organ/17f884126bb76d2d3c95e12224aab8f38ef8c96d/plugin/setBfree/doc/setBfree.png -------------------------------------------------------------------------------- /plugin/setBfree/doc/setBfreeUI.1: -------------------------------------------------------------------------------- 1 | .TH SETBFREEUI "1" "Feb 2015" "setBfreeUI 0.8" "User Commands" 2 | .SH NAME 3 | setBfree \- DSP tonewheel organ Graphical User Interface 4 | .SH SYNOPSIS 5 | .B setBfreeUI 6 | .SH DESCRIPTION 7 | setBfree \- DSP tonewheel organ Graphical User Interface 8 | .PP 9 | setBfree is a MIDI\-controlled, software synthesizer designed to imitate 10 | the sound and properties of the electromechanical organs and sound 11 | modification devices that brought world\-wide fame to the names and 12 | products of Laurens Hammond and Don Leslie. 13 | .PP 14 | Thes GUI takes no commandline arguments. see setBfree(1) for the 15 | commandline option and complete documentation. 16 | .SH "CONFIGURATOIN FILES" 17 | setBfreeUI reads $XDG_CONFIG_HOME/setBfree/default.cfg and 18 | $XDG_CONFIG_HOME/setBfree/default.pgm on startup. see setBfree(1) 19 | for details. 20 | .SH "REPORTING BUGS" 21 | Report bugs at . 22 | .br 23 | Website and manual: 24 | .SH COPYRIGHT 25 | Copyright \(co 2003\-2004 Fredrik Kilander 26 | .br 27 | Copyright \(co 2008\-2015 Robin Gareus 28 | .br 29 | Copyright \(co 2010 Ken Restivo 30 | .br 31 | Copyright \(co 2012 Will Panther 32 | .PP 33 | .br 34 | This is free software; see the source for copying conditions. There is NO 35 | warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 36 | -------------------------------------------------------------------------------- /plugin/setBfree/doc/signal_flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FigBug/Organ/17f884126bb76d2d3c95e12224aab8f38ef8c96d/plugin/setBfree/doc/signal_flow.png -------------------------------------------------------------------------------- /plugin/setBfree/doc/x42-whirl.1: -------------------------------------------------------------------------------- 1 | .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.8. 2 | .TH X42-WHIRL "1" "December 2019" "x42-whirl version 0.8.11" "User Commands" 3 | .SH NAME 4 | x42-whirl \- The B Whirl Speaker 5 | .SH SYNOPSIS 6 | .B x42-whirl 7 | [ \fI\,OPTIONS \/\fR] 8 | .SH DESCRIPTION 9 | x42\-whirl \- JACK x42 Whirl \- Rotary Speaker 10 | .PP 11 | This is a standalone JACK application of the LV2 plugin: 12 | "x42 Whirl \- Rotary Speaker". 13 | .PP 14 | Usage: 15 | All control elements are operated in using the mouse: 16 | .TP 17 | Click+Drag 18 | left/down: decrease, right/up: increase value. Hold the Ctrl key to increase sensitivity. 19 | .TP 20 | Shift+Click 21 | reset to default value 22 | .TP 23 | Scroll\-wheel 24 | up/down by 1 step (smallest possible adjustment for given setting). Rapid continuous scrolling increases the step\-size. 25 | .PP 26 | The application can be closed by sending a SIGTERM (CTRL+C) on the command\-line of by closing the window. 27 | .SH OPTIONS 28 | .TP 29 | \fB\-h\fR, \fB\-\-help\fR 30 | Display this help and exit 31 | .TP 32 | \fB\-j\fR, \fB\-\-jack\-name\fR 33 | Set the JACK client name 34 | (defaults to plugin\-name) 35 | .TP 36 | \fB\-G\fR, \fB\-\-nogui\fR 37 | run headless, useful for OSC remote ctrl. 38 | .TP 39 | \fB\-O\fR , \fB\-\-osc\fR 40 | Listen for OSC messages on the given UDP port 41 | .TP 42 | \fB\-p\fR :, \fB\-\-port\fR : 43 | Set initial value for given control port 44 | .TP 45 | \fB\-P\fR, \fB\-\-portlist\fR 46 | Print control port list on startup 47 | .TP 48 | \fB\-\-osc\-doc\fR 49 | Print available OSC commands and exit 50 | .TP 51 | \fB\-V\fR, \fB\-\-version\fR 52 | Print version information and exit 53 | .PP 54 | See also: 55 | Website: 56 | .SH COPYRIGHT 57 | Copyright \(co GPL 2013\-2019 Robin Gareus 58 | .br 59 | This is free software; see the source for copying conditions. There is NO 60 | warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 61 | -------------------------------------------------------------------------------- /plugin/setBfree/doc/x42-whirl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FigBug/Organ/17f884126bb76d2d3c95e12224aab8f38ef8c96d/plugin/setBfree/doc/x42-whirl.png -------------------------------------------------------------------------------- /plugin/setBfree/src/README: -------------------------------------------------------------------------------- 1 | 14-jun-2012/RG 2 | This file needs updating for v0.5 3 | 4 | ############################################################################### 5 | ### README vor v0.4.1 ### 6 | 7 | 28-nov-2004/FK 8 | 10-sep-2004/FK 9 | 21-jul-2004/FK 10 | 11 | The information in this file may be useful to you if you have 12 | experience from an earlier version of Beatrix. 13 | 14 | 15 | Version 0.4.1 16 | 17 | This version presents the third rewrite of the tonegenerator, introducing: 18 | 19 | - extensive and open crosstalk modelling 20 | - lower manual 21 | - pedals 22 | - separate control of vibrato depth and upper/lower manual vibrato 23 | - equal-tempered, 60 Hz, or 50 Hz gear train tuning 24 | - user-configurable MIDI controller assignments 25 | - upper manual split in 2 or 3 regions 26 | 27 | Some earlier signal routing inaccuracies are also addressed: percussion 28 | no longer passes through the vibrato scanner. However, the tonegenerator 29 | rewrite introduced another inaccuracy: the pedal signals should probably 30 | be mixed with the lower manual signals before the vibrato routing decision 31 | for the lower manual. Instead, Beatrix never routes pedals through 32 | the vibrato (which is not a great loss if you ask me). 33 | 34 | MIDI controllers can be freely assigned via configuration (see the 35 | file default.cfg). 36 | 37 | The upper manual can be split in two or three parts, to enable 38 | multi-manual performances from a single keyboard. 39 | 40 | Seven transpose parameters (split pedals, lower and upper manuals, 41 | global transpose and non-split pedals, lower and upper manuals). 42 | 43 | 44 | Incompatibilities to earlier versions: 45 | 46 | The programme vocabulary has been changed and extended (see the file 47 | default.pgm for details): 48 | 49 | The noteshift configuration parameter has been replaced by several 50 | transposition parameters: trssplitpedals, trssplitlower, 51 | trssplitupper, transpose, transposeupper, transposelower and 52 | transposepedals. 53 | 54 | To control keyboard split, two new programme parameters are 55 | introduced, keysplitlower and keysplitupper. 56 | 57 | The syntax and semantics of the vibrato programme parameter has 58 | changed. As from version 0.4.1, the vibrato programme no longer 59 | accepts the value 'off', only the vibrato knob settings of 'v1', 60 | 'c1' etc. Instead, two new manual routing parameters are 61 | introduced, vibratoupper and vibratolower. They take the arguments 62 | 'on' or 'off' and routes the upper or lower manual through the 63 | vibrato effect. 64 | 65 | Drawbars can be set for upper and lower manuals and pedals by the 66 | parameters drawbarsupper, drawbarslower and drawbarspedals. The 67 | old parameter name drawbars is now a synonym for drawbarsupper. 68 | Pedal drawbars in this version are 'wired' with nine drawbars, 69 | with no foldback and no tapering (all signals are at their 70 | reference level). 71 | 72 | Several new configuration parameters are introduced to modify the 73 | behaviour of the default crosstalk model. See the file default.cfg 74 | for details. 75 | 76 | The instrument now responds to three MIDI channels. These are 77 | selected in the configuration. The previous configuration parameter 78 | midi.swell.channel has been replaced by three new parameters: 79 | midi.upper.channel, midi.lower.channel and midi.pedals.channel. 80 | 81 | 82 | Things that will be addressed in later versions: 83 | 84 | - A terminal-based user interface. 85 | - More amplifier and loudspeaker models 86 | - Noise, crackle, mains hum and 'angel choir' 87 | 88 | -fk 89 | 90 | 91 | ### OLD README ### 92 | 93 | 28-nov-2004/FK 94 | 10-oct-2004/FK 95 | 96 | [Additional information can be found in the files 97 | READMEv041.txt 98 | default.cfg 99 | default.pgm] 100 | 101 | 102 | 103 | This is what you generally need to start playing on Beatrix: 104 | 105 | Computer: 106 | 107 | - A PIII personal computer running Linux at 400 MHz or more. 108 | [This is just a rough guideline; you may get acceptable 109 | performance on lesser systems.] 110 | 111 | - A soundcard with 22050 Hz, 16-bit stereo outputs (most have). 112 | 113 | - MIDI in (via soundcard, USB, serial port, PCCARD or any other means 114 | of connection). 115 | 116 | - The OSS sound/MIDI libraries (usually included in Linux distributions) 117 | 118 | 119 | Connected to the computer: 120 | 121 | - A MIDI source, like a MIDI keyboard, synthesizer or sequencer. It 122 | should have a modulation wheel (for volume control) and be able to 123 | send program change messages. 61 keys is also good, since that 124 | matches the popular models of the original instruments. Turning off 125 | aftertouch might be a good idea. Note on/off velocity is not 126 | needed. A sustain pedal is convenient for toggling speeds in the 127 | rotary FX. 128 | 129 | - Some kind of stereo sound amplification. Headphones are ok, but the 130 | rotary effect sounds better through loudspeakers placed a few meters 131 | apart. 132 | 133 | 134 | Notes: 135 | 136 | - Since there is no other command source than MIDI, the ability to send 137 | MIDI program change messages is important. For real-time playing, the 138 | ability to send MIDI continuous controllers greatly helps. See the file 139 | default.cfg for the controller numbers (and how to change them to match 140 | your equipment). 141 | 142 | - If you are recording, try a mono-mix, a half-way L-R pan, and a full pan 143 | and listen to the results. They are different and may suit your needs 144 | differently. 145 | 146 | - I play Beatrix from my laptop, using the ordinary headphone socket 147 | connected to an old stereo amplifier. When I first connected it, there 148 | was a lot of stutter and hum from the switched power-supply. I discovered, 149 | that it was possible to completely eliminate this by inserting a 1:1 150 | stereo audio transformer between the headphone socket and the amplifier. 151 | The transformer is actually a car accessory, and conveniently enough 152 | comes mounted with RCA plugs and wires. The cost was approx. 20 Euros. 153 | 154 | 155 | Installation 156 | 157 | Extract the tar-file in a directory of your choice: 158 | 159 | zcat file.tar.gz | tar xf - 160 | 161 | Then make that your current directory while running beatrix ('cd' to it). 162 | 163 | 164 | Compiling 165 | 166 | There is a statically linked version in the distribution named 167 | sbeatrix. It may work as is on your system. If you want to compile a 168 | shared library version, you need gcc and make. Issue the command: 169 | 170 | make beatrix 171 | 172 | 173 | Setting up 174 | 175 | There are three things to set up, 176 | 177 | the MIDI input device, 178 | 179 | the MIDI input channels, and 180 | 181 | the audio output device. 182 | 183 | These values are set by configuration parameters which can be given on 184 | the command line, or written to a configuration file in which case the 185 | file default.cfg is the natural place. 186 | 187 | The file default.cfg should be edited with a text editor. The file is 188 | initally all comments. When you have updated a parameter, make sure 189 | that the line is uncommented by deleting any '#'-characters at the 190 | start of the line. 191 | 192 | You must restart beatrix in order for it to reread the configuration. 193 | 194 | 195 | - MIDI input device 196 | 197 | On my system, MIDI input is read from /dev/midi00. To change this, 198 | set the configuration parameter: 199 | 200 | midi.device=/dev/midi00 201 | 202 | 203 | - MIDI input channels 204 | 205 | In my setup MIDI input is read from channel 1 (the first 206 | channel). The configuration parameters are: 207 | 208 | midi.upper.channel=1 209 | midi.lower.channel=2 210 | midi.pedals.channel=3 211 | 212 | 213 | - Audio output device 214 | 215 | On my system, sampled audio is written to /dev/dsp. To change this, 216 | set the configuration parameters: 217 | 218 | main.audiodevice=/dev/dsp 219 | 220 | 221 | Hints 222 | 223 | I usually use the system utility aumix to increase the signal 224 | strength from the audio port, especially when running the signal 225 | through an external amplifier. 226 | 227 | 228 | MIDI input can be quickly tested by opening a shell and doing: 229 | 230 | cat -v /dev/midi00 231 | 232 | If your MIDI keyboard has a pitch bend or modulation wheel, rolling 233 | one of them around a bit generates plenty of MIDI data which should 234 | be seen as several lines of characters arriving in rapid succession. 235 | Key aftertouch also works for testing, but Beatrix has no use for it 236 | so unless you need it elsewhere, consider turning it off. 237 | 238 | 239 | Beatrix does not need to run as root. On my Debian installation the 240 | user must be a member of the audio group to be allowed write access 241 | to /dev/dsp. 242 | 243 | 244 | Running 245 | 246 | Open a text-based shell, cd to the beatrix directory and do: 247 | 248 | ./beatrix 249 | 250 | or for the statically linked version: 251 | 252 | ./sbeatrix 253 | 254 | Commandline options are few: 255 | 256 | beatrix [-p programmefile] [-c] [config-option ...] 257 | 258 | -p programmefile This option reads the given programme file after 259 | having read default.pgm. The option can be 260 | given several times. Programme slots defined 261 | in a file overwrite existing slots. 262 | 263 | -c This flag prevents the program from reading 264 | the default configuration file default.cfg. 265 | 266 | config-option A list of configuration options that normally 267 | would be in a configuration file. Mostly 268 | useful for testing and for reading alternative 269 | configuration files. 270 | 271 | For example, to run with the configurations in file osc-middy.cfg, use: 272 | 273 | ./beatrix -p popular.pgm config.read=osc-middy.cfg 274 | 275 | 276 | Concluding remarks: 277 | 278 | There are several ways to control the workings of Beatrix, and in 279 | several places there are multiple ways to affect a particular 280 | parameter. 281 | 282 | First, the configuration parameters determine what kind of 283 | instrument you have. By selecting a particular configuration you 284 | determine what its properties should be, and just as with real 285 | instruments, these properties remain unchanged while you play. 286 | There is no generic technical or dogmatic reason that says Beatrix 287 | MUST be this way, it is simply they way it was developed. 288 | 289 | Second, a number of parameters can be changed from the programme 290 | feature. This has two purposes; it is convenient to be able to set 291 | the instrument into a defined state with a single command, and it 292 | may be the only way to control it for many users (at least until a 293 | computer user interface exists). 294 | 295 | Finally, the use of MIDI control messages enables hands-on runtime 296 | control of the performance parameters. For me, this is the most 297 | convenient form of playing, because I can have the relevant controls 298 | in front of me, close to the playing keys. 299 | 300 | 301 | Some caveats to watch out for: 302 | 303 | - Although I have worked to prevent it, it is still possible in 304 | certain situations to get digital clipping within Beatrix. This 305 | may happen on full volume, full distortion and all drawbars 306 | out. Percussion on top of that will certainly add to the 307 | fun. It sounds ugly and is not nice to your loudspeakers. Lower 308 | the volume (mod wheel) a bit until it disappears. 309 | 310 | - The filters in the rotary horn and drum simulation are quite 311 | capable of stunning amplification and feedback if driven too 312 | far. The filter parameters can also be adjusted in realtime with 313 | the proper MIDI controllers. If you do not know the 314 | mappings of *your* MIDI controller; 315 | 316 | * Experiment on low listening levels 317 | 318 | * As you modify an uncertain controller, watch the bottom line 319 | of output on the terminal where Beatrix runs. Parameter 320 | updates to the filters are reflected there in 321 | real-time. Watch out for high Q and gain levels! 322 | -------------------------------------------------------------------------------- /plugin/setBfree/src/cfgParser.h: -------------------------------------------------------------------------------- 1 | /* setBfree - DSP tonewheel organ 2 | * 3 | * Copyright (C) 2003-2004 Fredrik Kilander 4 | * Copyright (C) 2008-2018 Robin Gareus 5 | * Copyright (C) 2012 Will Panther 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2, or (at your option) 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | /* 22 | * cfgParser.h 23 | */ 24 | #ifndef _CFGPARSER_H_ 25 | #define _CFGPARSER_H_ 26 | 27 | #include 28 | 29 | /* clang-format off */ 30 | #define INCOMPLETE_DOC "", 0, 0, 0 31 | #define DOC_SENTINEL {NULL, CFG_TEXT, "", "", "", 0, 0, 0} 32 | /* clang-format on */ 33 | 34 | /* some filters - in particular butterworth shelfing - 35 | * end up producing denormal-values when fed with zeros */ 36 | #define DENORMAL_HACK (1e-14) 37 | #define IS_DENORMAL(f) (((*(unsigned int*)&f) & 0x7f800000) == 0) 38 | 39 | typedef struct _configContext { 40 | const char* fname; 41 | int linenr; 42 | const char* name; 43 | const char* value; 44 | } ConfigContext; 45 | 46 | enum conftype { 47 | CFG_TEXT = 0, 48 | CFG_DOUBLE, 49 | CFG_DECIBEL, /**< double; only relevant for GUI-formatting and ui_step */ 50 | CFG_FLOAT, 51 | CFG_INT, 52 | CFG_LAST 53 | }; 54 | 55 | typedef struct _configDoc { 56 | const char* name; /**< parameter name */ 57 | enum conftype type; /**< parameter type */ 58 | char const* dflt; /**< default value as text */ 59 | char const* desc; /**< descition */ 60 | char const* unit; /**< unit */ 61 | const float min, max; /**< min/max range where applicable or 0,0 for unbound */ 62 | const float ui_step; /**< suggested step size for GUI */ 63 | } ConfigDoc; 64 | 65 | void parseConfigurationLine ( 66 | void* instance, 67 | const char* fname, 68 | int lineNumber, 69 | char* oneLine, 70 | double SampleRateD); 71 | 72 | int parseConfigurationFile (void* instance, const char* fname, double SampleRateD); 73 | void dumpConfigDoc (void); 74 | int evaluateConfigKeyValue (void* inst, const char* key, const char* value, double SampleRateD); 75 | void showConfigfileContext (ConfigContext* cfg, const char* msg); 76 | void configIntUnparsable (ConfigContext* cfg); 77 | void configIntOutOfRange (ConfigContext* cfg, int min, int max); 78 | void configDoubleUnparsable (ConfigContext* cfg); 79 | 80 | void setConfigRangeInt (int* vp, ConfigContext* cfg); 81 | void setConfigInt (int* vp, ConfigContext* cfg); 82 | void setConfigDouble (double* vp, ConfigContext* cfg); 83 | const char* getConfigValue (ConfigContext* cfg); 84 | int getConfigParameter_d (const char* par, 85 | ConfigContext* cfg, 86 | double* dp); 87 | int getConfigParameter_i (const char* par, 88 | ConfigContext* cfg, 89 | int* dp); 90 | int getConfigParameter_f (const char* par, 91 | ConfigContext* cfg, 92 | float* dp); 93 | 94 | int getConfigParameter_ir (const char* par, 95 | ConfigContext* cfg, 96 | int* ip, 97 | int lowInc, 98 | int highInc); 99 | 100 | int getConfigParameter_dr (const char* par, 101 | ConfigContext* cfg, 102 | double* dp, 103 | double lowInc, 104 | double highInc); 105 | 106 | int getConfigParameter_fr (const char* par, 107 | ConfigContext* cfg, 108 | float* fp, 109 | float lowInc, 110 | float highInc); 111 | #endif /* _CONFIG_H_ */ 112 | -------------------------------------------------------------------------------- /plugin/setBfree/src/global_inst.h: -------------------------------------------------------------------------------- 1 | /* setBfree - DSP tonewheel organ 2 | * 3 | * Copyright (C) 2013-2018 Robin Gareus 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2, or (at your option) 8 | * any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #ifndef GLOBAL_INST_H 20 | #define GLOBAL_INST_H 21 | 22 | #include "midi.h" 23 | #include "../b_overdrive/overdrive.h" 24 | #include "program.h" 25 | #include "../b_reverb/reverb.h" 26 | #include "tonegen.h" 27 | #include "vibrato.h" 28 | #include "../b_whirl/whirl.h" 29 | 30 | typedef struct b_instance { 31 | struct b_reverb* reverb; 32 | struct b_whirl* whirl; 33 | struct b_tonegen* synth; 34 | struct b_programme* progs; 35 | void* midicfg; 36 | void* preamp; 37 | void* state; 38 | } b_instance; 39 | 40 | /* clang-format off */ 41 | #define LOCALEGUARD_START \ 42 | char* oldlocale = strdup (setlocale (LC_NUMERIC, NULL)); \ 43 | if (strcmp (oldlocale, "C")) { \ 44 | setlocale (LC_NUMERIC, "C"); \ 45 | } else { \ 46 | free (oldlocale); \ 47 | oldlocale = NULL; \ 48 | } 49 | 50 | #define LOCALEGUARD_END \ 51 | if (oldlocale) { \ 52 | setlocale (LC_NUMERIC, oldlocale); \ 53 | free (oldlocale); \ 54 | } 55 | /* clang-format on */ 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /plugin/setBfree/src/main.h: -------------------------------------------------------------------------------- 1 | /* setBfree - DSP tonewheel organ 2 | * 3 | * Copyright (C) 2003-2004 Fredrik Kilander 4 | * Copyright (C) 2008-2018 Robin Gareus 5 | * Copyright (C) 2012 Will Panther 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2, or (at your option) 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef MAIN_H 22 | #define MAIN_H 23 | 24 | #include "cfgParser.h" 25 | 26 | /* TODO: split those into common.h 27 | *or better just replace TRUE/FALSE throughout the program 28 | */ 29 | #ifndef TRUE 30 | #define TRUE 1 31 | #endif 32 | 33 | #ifndef FALSE 34 | #define FALSE 0 35 | #endif 36 | 37 | #define B_size 9 38 | 39 | extern int mainConfig (ConfigContext* cfg); 40 | extern const ConfigDoc* mainDoc (void); 41 | 42 | extern void save_midname (void* instp, FILE* f, char* model); // defined in midnam.c 43 | 44 | #endif /* MAIN_H */ 45 | -------------------------------------------------------------------------------- /plugin/setBfree/src/midi.h: -------------------------------------------------------------------------------- 1 | /* setBfree - DSP tonewheel organ 2 | * 3 | * Copyright (C) 2003-2004 Fredrik Kilander 4 | * Copyright (C) 2008-2018 Robin Gareus 5 | * Copyright (C) 2012 Will Panther 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2, or (at your option) 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef MIDI_H 22 | #define MIDI_H 23 | 24 | #include 25 | #include 26 | 27 | #include "cfgParser.h" 28 | 29 | typedef uint8_t midiccflags_t; 30 | 31 | enum { // 1,2,4,8,.. - adjust ctrlflg once >8 to uint16_t 32 | MFLAG_INV = 1, 33 | }; 34 | 35 | unsigned int getCtrlFlag (void* mcfg, uint8_t channel, uint8_t param); 36 | 37 | void useMIDIControlFunction (void* m, const char* cfname, void (*f) (void*, unsigned char), void* d); 38 | void callMIDIControlFunction (void* m, const char* cfname, unsigned char val); 39 | void notifyControlChangeByName (void* mcfg, const char* cfname, unsigned char val); 40 | void notifyControlChangeById (void* mcfg, int id, unsigned char val); 41 | 42 | extern int getCCFunctionCount (void); 43 | extern const char* getCCFunctionName (int x); 44 | 45 | extern void setKeyboardSplitMulti (void* mcfg, 46 | int flags, 47 | int p_splitA_PL, 48 | int p_splitA_UL, 49 | int p_nshA_PL, 50 | int p_nshA_UL, 51 | int p_nshA_U); 52 | 53 | extern void setKeyboardTransposeA (void* mcfg, int t); 54 | extern void setKeyboardTransposeB (void* mcfg, int t); 55 | extern void setKeyboardTransposeC (void* mcfg, int t); 56 | extern void setKeyboardTranspose (void* mcfg, int t); 57 | 58 | extern void midiPrimeControllerMapping (void* mcfg); 59 | 60 | extern int midiConfig (void* mcfg, ConfigContext* cfg); 61 | extern const ConfigDoc* midiDoc (void); 62 | 63 | extern void setMIDINoteShift (void* mcfg, char offset); 64 | 65 | extern void initMidiTables (void* mcfg); 66 | extern void initControllerTable (void* mcfg); 67 | extern int getCCFunctionId (const char* name); 68 | extern void listCCAssignments (void* mctl, FILE* fp); 69 | 70 | extern void* allocMidiCfg (void* stateptr); 71 | extern void freeMidiCfg (void* mcfg); 72 | 73 | #ifdef HAVE_ASEQ 74 | extern void* aseq_run (void* arg); 75 | extern int aseq_open (char* port_name); 76 | extern void aseq_close (void); 77 | #endif 78 | 79 | extern void parse_raw_midi_data (void* inst, const uint8_t* buffer, size_t size); 80 | extern void midi_panic (void* inst); 81 | 82 | typedef struct _midicc { 83 | struct _midicc* next; 84 | uint8_t channel; /**< the MIDI channel number 0-15 for CC (NYI: PGM changes maybe >16 or < 0)*/ 85 | uint8_t param; 86 | } midiCCmap; 87 | 88 | void setControlFunctionCallback (void* mcfg, void (*fn) (int, const char*, unsigned char, midiCCmap*, void*), void* d); 89 | 90 | void midi_uiassign_cc (void* mcfg, const char* fname, midiccflags_t flags); 91 | void midi_loopCCAssignment (void* mcfg, int ulp, void (*cb) (const char*, const unsigned char, const unsigned char, const unsigned char, void*), void* arg); 92 | void midi_channels (void* mcfg, int* upper, int* lower, int* pedals); 93 | #endif /* MIDI_H */ 94 | -------------------------------------------------------------------------------- /plugin/setBfree/src/midi_aseq.c: -------------------------------------------------------------------------------- 1 | /* setBfree - DSP tonewheel organ 2 | * 3 | * Copyright (C) 2003-2004 Fredrik Kilander 4 | * Copyright (C) 2008-2018 Robin Gareus 5 | * Copyright (C) 2012 Will Panther 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2, or (at your option) 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifdef HAVE_ASEQ /* ALSA SEQUENCER MIDI INTERFACE */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include "midi.h" 30 | #include "midi_aseq.h" 31 | #include "midi_types.h" 32 | 33 | snd_seq_t* seq = NULL; 34 | extern int aseq_stop; 35 | 36 | void 37 | aseq_close (void) 38 | { 39 | if (!seq) 40 | return; 41 | snd_seq_close (seq); 42 | seq = NULL; 43 | } 44 | 45 | int 46 | aseq_open (char* port_name) 47 | { 48 | int err = 0; 49 | snd_seq_addr_t port; 50 | char seq_name[32]; 51 | snprintf (seq_name, 32, "setBfree"); 52 | 53 | if (seq) 54 | return (-1); 55 | 56 | if ((err = snd_seq_open (&seq, "default", SND_SEQ_OPEN_INPUT, 0)) < 0) { 57 | fprintf (stderr, "cannot open alsa sequencer: %s\n", snd_strerror (err)); 58 | seq = NULL; 59 | return (-1); 60 | } 61 | 62 | if ((err = snd_seq_set_client_name (seq, seq_name)) < 0) { 63 | fprintf (stderr, "cannot set client name: %s\n", snd_strerror (err)); 64 | aseq_close (); 65 | return (-1); 66 | } 67 | 68 | if ((err = snd_seq_create_simple_port (seq, "midi_in", 69 | SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE, 70 | SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION)) < 0) { 71 | fprintf (stderr, "cannot create port: %s\n", snd_strerror (err)); 72 | aseq_close (); 73 | return (-1); 74 | } 75 | 76 | if (port_name && strlen (port_name) > 0) { 77 | err = snd_seq_parse_address (seq, &port, port_name); 78 | if (err < 0) { 79 | fprintf (stderr, "ALSA: Cannot find port %s - %s\n", port_name, snd_strerror (err)); 80 | } else { 81 | err = snd_seq_connect_from (seq, 0, port.client, port.port); 82 | if (err < 0) { 83 | fprintf (stderr, "ALSA: Cannot connect from port %d:%d - %s\n", port.client, port.port, snd_strerror (err)); 84 | } 85 | } 86 | } 87 | 88 | snd_seq_nonblock (seq, 1); 89 | return (0); 90 | } 91 | 92 | /** convert ALSA-sequencer event into internal MIDI message 93 | * format and process the event 94 | */ 95 | static void 96 | process_seq_event (void* inst, const snd_seq_event_t* ev) 97 | { 98 | // see "snd_seq_event_type" file:///usr/share/doc/libasound2-doc/html/group___seq_events.html 99 | struct bmidi_event_t bev; 100 | memset (&bev, 0, sizeof (struct bmidi_event_t)); 101 | 102 | switch (ev->type) { 103 | case SND_SEQ_EVENT_NOTEON: 104 | bev.channel = ev->data.note.channel; 105 | bev.type = NOTE_ON; 106 | bev.d.tone.note = ev->data.note.note; 107 | bev.d.tone.velocity = ev->data.note.velocity; 108 | break; 109 | case SND_SEQ_EVENT_NOTEOFF: 110 | bev.channel = ev->data.note.channel; 111 | bev.type = NOTE_OFF; 112 | bev.d.tone.note = ev->data.note.note; 113 | bev.d.tone.velocity = 0; 114 | break; 115 | case SND_SEQ_EVENT_PGMCHANGE: 116 | bev.type = PROGRAM_CHANGE; 117 | bev.d.control.value = ev->data.control.value; 118 | break; 119 | case SND_SEQ_EVENT_CONTROLLER: 120 | bev.type = CONTROL_CHANGE; 121 | bev.channel = ev->data.note.channel; 122 | bev.d.control.param = ev->data.control.param; 123 | bev.d.control.value = ev->data.control.value; 124 | break; 125 | default: 126 | return; 127 | } 128 | process_midi_event (inst, &bev); 129 | } 130 | 131 | void* 132 | aseq_run (void* arg) 133 | { 134 | int err; 135 | int npfds = 0; 136 | struct pollfd* pfds; 137 | 138 | npfds = snd_seq_poll_descriptors_count (seq, POLLIN); 139 | pfds = (struct pollfd*)malloc (sizeof (*pfds) * npfds); 140 | while (1) { 141 | snd_seq_poll_descriptors (seq, pfds, npfds, POLLIN); 142 | if (poll (pfds, npfds, 1) < 0) 143 | break; 144 | do { 145 | snd_seq_event_t* event; 146 | err = snd_seq_event_input (seq, &event); 147 | if (err < 0) 148 | break; 149 | if (event) 150 | process_seq_event (arg, event); 151 | } while (err > 0); 152 | if (aseq_stop) 153 | break; 154 | } 155 | free (pfds); 156 | pthread_exit (NULL); 157 | return (NULL); 158 | } 159 | #endif 160 | -------------------------------------------------------------------------------- /plugin/setBfree/src/midi_aseq.h: -------------------------------------------------------------------------------- 1 | /* setBfree - DSP tonewheel organ 2 | * 3 | * Copyright (C) 2003-2004 Fredrik Kilander 4 | * Copyright (C) 2008-2018 Robin Gareus 5 | * Copyright (C) 2012 Will Panther 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2, or (at your option) 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef SETBFREE_ASEQ_H_ 22 | #define SETBFREE_ASEQ_H_ 23 | 24 | extern void* aseq_run (void* arg); 25 | extern int aseq_open (char* port_name); 26 | extern void aseq_close (void); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /plugin/setBfree/src/midi_types.h: -------------------------------------------------------------------------------- 1 | /* setBfree - DSP tonewheel organ 2 | * 3 | * Copyright (C) 2003-2004 Fredrik Kilander 4 | * Copyright (C) 2008-2018 Robin Gareus 5 | * Copyright (C) 2012 Will Panther 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2, or (at your option) 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef MIDI_TYPES_H 22 | #define MIDI_TYPES_H 23 | 24 | #include 25 | 26 | #define MIDI_UTIL_SWELL 0 27 | #define MIDI_UTIL_GREAT 1 28 | #define MIDI_UTIL_PEDAL 2 29 | 30 | /* clang-format on */ 31 | #define MIDI_NOTEOFF 0x80 32 | #define MIDI_NOTEON 0x90 33 | #define MIDI_KEY_PRESSURE 0xA0 34 | #define MIDI_CTL_CHANGE 0xB0 35 | #define MIDI_PGM_CHANGE 0xC0 36 | #define MIDI_CHN_PRESSURE 0xD0 37 | #define MIDI_PITCH_BEND 0xE0 38 | #define MIDI_SYSTEM_PREFIX 0xF0 39 | /* clang-format off */ 40 | 41 | enum BMIDI_EV_TYPE { 42 | INVALID=0, 43 | NOTE_ON, 44 | NOTE_OFF, 45 | PROGRAM_CHANGE, 46 | CONTROL_CHANGE, 47 | }; 48 | 49 | /** internal MIDI event abstraction */ 50 | struct bmidi_event_t { 51 | enum BMIDI_EV_TYPE type; 52 | uint8_t channel; /**< the MIDI channel number 0-15 */ 53 | union { 54 | struct { 55 | uint8_t note; 56 | uint8_t velocity; 57 | } tone; 58 | struct { 59 | uint8_t param; 60 | uint8_t value; 61 | } control; 62 | } d; 63 | }; 64 | 65 | void process_midi_event(void *inst, const struct bmidi_event_t *ev); 66 | 67 | #endif /* MIDI_TYPES_H */ 68 | -------------------------------------------------------------------------------- /plugin/setBfree/src/midnam.c: -------------------------------------------------------------------------------- 1 | #define _XOPEN_SOURCE 700 2 | 3 | #include "global_inst.h" 4 | #include 5 | #include 6 | #include 7 | 8 | #if _WIN32 9 | #pragma warning(disable:4305) 10 | #pragma warning(disable:4244) 11 | #pragma warning(disable:4100) 12 | #pragma warning(disable:4706) 13 | #define strdup _strdup 14 | #endif 15 | 16 | static void 17 | midnam_header (FILE* f, char* model) 18 | { 19 | fprintf (f, 20 | "\n" 21 | "\n" 22 | "\n" 23 | " setBfree -- Robin Gareus\n" 24 | " \n" 25 | " Pather B Music\n" 26 | " %s\n", 27 | model); 28 | } 29 | 30 | static void 31 | midnam_footer (FILE* f) 32 | { 33 | fprintf (f, 34 | " \n" 35 | ""); 36 | } 37 | 38 | static void 39 | midnam_print_cc_cb (const char* fnname, const unsigned char chn, const unsigned char cc, const unsigned char flags, void* arg) 40 | { 41 | FILE* fp = (FILE*)arg; 42 | fprintf (fp, " \n", cc, fnname); 43 | } 44 | 45 | static void 46 | midnam_print_pgm_cb (int num, int pc, const char* name, void* arg) 47 | { 48 | FILE* fp = (FILE*)arg; 49 | 50 | int ent = 0; 51 | char* escaped; 52 | const char* tmp = name; 53 | while ((tmp = strchr (tmp, '&'))) { 54 | tmp++; 55 | ent++; 56 | } 57 | 58 | if (ent == 0) { 59 | escaped = strdup (name); 60 | } else { 61 | const char *t1, *t2; 62 | escaped = (char*)malloc ((strlen (name) + ent * 4 + 1) * sizeof (char)); 63 | escaped[0] = '\0'; 64 | t1 = name; 65 | while ((t2 = strchr (t1, '&'))) { 66 | strncat (escaped, t1, t2 - t1); 67 | strcat (escaped, "&"); 68 | t1 = t2 + 1; 69 | } 70 | strncat (escaped, t1, strlen (name) - (t1 - name)); 71 | } 72 | 73 | fprintf (fp, " \n", 74 | num, escaped, pc); 75 | free (escaped); 76 | } 77 | 78 | static void 79 | midnam_avail_channel (FILE* f, int c) 80 | { 81 | int i; 82 | for (i = 1; i <= 16; i++) { 83 | fprintf (f, " \n", 84 | i, (i == c) ? "true" : "false"); 85 | } 86 | } 87 | 88 | static void 89 | midnam_channe_set (FILE* f, const char* name, const char* ctrl, int c) 90 | { 91 | fprintf (f, 92 | " \n" 93 | " \n", 94 | name); 95 | midnam_avail_channel (f, c + 1); 96 | fprintf (f, 97 | " \n" 98 | " \n" 99 | " \n" 100 | " \n" 101 | " \n" 102 | " \n", 103 | ctrl); 104 | } 105 | 106 | void 107 | save_midname (void* instp, FILE* f, char* model) 108 | { 109 | b_instance* inst = (b_instance*)instp; 110 | midnam_header (f, model); 111 | int u, l, p; 112 | midi_channels (inst->midicfg, &u, &l, &p); 113 | 114 | fprintf (f, 115 | " \n" 116 | " \n" 117 | " \n" 118 | " \n" 119 | " \n" 120 | " \n" 121 | " \n", 122 | u + 1, l + 1, p + 1); 123 | 124 | midnam_channe_set (f, "Upper Manual", "Controls Upper", u); 125 | midnam_channe_set (f, "Lower Manual", "Controls Lower", l); 126 | midnam_channe_set (f, "Pedals", "Controls Pedals", p); 127 | 128 | fprintf (f, " \n"); 129 | loopProgammes (inst->progs, 1, &midnam_print_pgm_cb, f); 130 | fprintf (f, " \n"); 131 | 132 | fprintf (f, " \n"); 133 | midi_loopCCAssignment (inst->midicfg, 1, midnam_print_cc_cb, f); 134 | fprintf (f, " \n"); 135 | 136 | fprintf (f, " \n"); 137 | midi_loopCCAssignment (inst->midicfg, 2, midnam_print_cc_cb, f); 138 | fprintf (f, " \n"); 139 | 140 | fprintf (f, " \n"); 141 | midi_loopCCAssignment (inst->midicfg, 4, midnam_print_cc_cb, f); 142 | fprintf (f, " \n"); 143 | 144 | midnam_footer (f); 145 | } 146 | -------------------------------------------------------------------------------- /plugin/setBfree/src/pgmParser.c: -------------------------------------------------------------------------------- 1 | /* setBfree - DSP tonewheel organ 2 | * 3 | * Copyright (C) 2003-2004 Fredrik Kilander 4 | * Copyright (C) 2008-2018 Robin Gareus 5 | * Copyright (C) 2012 Will Panther 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2, or (at your option) 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #define _XOPEN_SOURCE 700 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #ifdef _WIN32 28 | #include 29 | #endif 30 | 31 | #include "pgmParser.h" 32 | #include "program.h" 33 | 34 | #if _WIN32 35 | #pragma warning(disable:4305) 36 | #pragma warning(disable:4244) 37 | #pragma warning(disable:4100) 38 | #pragma warning(disable:4706) 39 | #endif 40 | 41 | #define TKN_ERROR -3 42 | #define TKN_VOID -2 43 | #define TKN_EOF -1 44 | #define TKN_REFERENCE ((int)'@') 45 | #define TKN_STRING 256 46 | 47 | /* Parser return codes */ 48 | 49 | #define P_OK 0 /* Accepted */ 50 | #define P_WARNING 1 /* Warning, parsing continues */ 51 | #define P_ERROR 2 /* Fatal, parsing stopped */ 52 | 53 | /* Buffer sizes */ 54 | 55 | #define STRINGBUFFERSZ 280 56 | #define SYMBOLSIZE 256 57 | #define VALUESIZE 256 58 | 59 | typedef int B3TokenType; 60 | typedef int ParseReturnCode; 61 | 62 | typedef struct _parserstate { 63 | void* p; 64 | const char* fileName; 65 | FILE* fp; 66 | int lineNumber; 67 | B3TokenType nextToken; 68 | char stringBuffer[STRINGBUFFERSZ]; 69 | } ParserState; 70 | 71 | /* 72 | * New syntax: 8-apr-03 73 | * S ::= [...] 74 | * ::= [] '{' [[,] ...] '}' 75 | * ::= 76 | * ::= '=' 77 | * ::= {||} 78 | * ::= '@' 79 | * 80 | */ 81 | 82 | /* 83 | * Scans the next token from the input. Tokens are: 84 | * '{' '}' '=' string EOF 85 | */ 86 | static int 87 | getToken (FILE* fp, int* linePtr, char* tokbuf, size_t tblen) 88 | { 89 | int c = 0; 90 | size_t tp = 0; 91 | int tokType = TKN_VOID; 92 | int state = 1; 93 | 94 | tokbuf[tp] = '\0'; 95 | tokbuf[tp + 1] = '\0'; 96 | 97 | /* Scan leading space */ 98 | while (0 < state) { 99 | c = fgetc (fp); 100 | if (c == EOF) 101 | return TKN_EOF; 102 | 103 | if (state == 1) { 104 | if (c == '\n') { 105 | *linePtr += 1; 106 | continue; 107 | } else if (isspace (c)) { 108 | continue; 109 | } else if (c == '#') { 110 | state = 2; 111 | } else { 112 | state = 0; 113 | } 114 | } else if (state == 2) { /* Comment to end of line */ 115 | if (c == '\n') { 116 | *linePtr += 1; 117 | state = 1; 118 | } 119 | } 120 | } 121 | 122 | /* Examine character */ 123 | if ((c == '{') || (c == '}') || (c == '=') || (c == ',')) { 124 | tokType = c; /* The character is its own token */ 125 | tokbuf[0] = (char)c; 126 | tokbuf[1] = '\0'; 127 | } else { 128 | tokType = TKN_STRING; 129 | 130 | if (c == '"') { 131 | state = 0; 132 | 133 | for (;;) { 134 | c = fgetc (fp); 135 | 136 | if (c == EOF) { 137 | tokType = TKN_ERROR; 138 | strncpy (tokbuf, "End of file in quoted string", tblen); 139 | tokbuf[tblen - 1] = '\0'; 140 | break; 141 | } 142 | 143 | if (state == 0) { 144 | if (c == '"') { 145 | break; /* End of quoted string */ 146 | } else if (c == '\\') { /* Next char is escape char */ 147 | state = 1; 148 | continue; 149 | } else if (tp < tblen) { /* Append char to token buffer */ 150 | tokbuf[tp++] = c; 151 | } 152 | } else if (state == 1) { /* Escaped char */ 153 | if (tp < tblen) { 154 | tokbuf[tp++] = c; 155 | } 156 | state = 0; 157 | } 158 | } 159 | } else { 160 | while (isalnum (c) || (c == '-') || (c == '.') || (c == '_') || (c == '+')) { 161 | if (tp < tblen) { 162 | tokbuf[tp++] = c; 163 | } 164 | c = fgetc (fp); 165 | } 166 | ungetc (c, fp); 167 | } 168 | } 169 | 170 | tokbuf[tp] = '\0'; 171 | return tokType; 172 | } 173 | 174 | /* 175 | * Retrieves the next token from the input file and puts it in the parser 176 | * state. 177 | */ 178 | static B3TokenType 179 | getNextToken (ParserState* ps) 180 | { 181 | return ps->nextToken = getToken (ps->fp, 182 | &(ps->lineNumber), 183 | ps->stringBuffer, 184 | STRINGBUFFERSZ); 185 | } 186 | 187 | /* 188 | * Idempotent predicate: does the next token match the parameter? 189 | */ 190 | static int 191 | nextTokenMatches (ParserState* ps, B3TokenType t) 192 | { 193 | return ps->nextToken == t; 194 | } 195 | 196 | /* 197 | * Parses an integer number by parsing a string and then parsing it as 198 | * a number. 199 | */ 200 | static ParseReturnCode 201 | parseInteger (ParserState* ps, int* value) 202 | { 203 | if (nextTokenMatches (ps, TKN_STRING)) { 204 | if (sscanf (ps->stringBuffer, "%d", value) == 1) { 205 | (void)getNextToken (ps); 206 | return P_OK; 207 | } 208 | } 209 | return P_ERROR; /* Not an integer */ 210 | } 211 | 212 | /* 213 | * Parses an identifier (actually, a string). 214 | */ 215 | static ParseReturnCode 216 | parseIdentifier (ParserState* ps, char* identifier) 217 | { 218 | if (!nextTokenMatches (ps, TKN_STRING)) { 219 | return P_ERROR; 220 | } else { 221 | /* Should be a setter function */ 222 | strncpy (identifier, ps->stringBuffer, SYMBOLSIZE - 1); 223 | identifier[SYMBOLSIZE - 1] = '\0'; 224 | } 225 | (void)getNextToken (ps); 226 | return P_OK; 227 | } 228 | 229 | /* 230 | * Parses a single token. 231 | */ 232 | static ParseReturnCode 233 | parseToken (ParserState* ps, int token) 234 | { 235 | if (nextTokenMatches (ps, token)) { 236 | (void)getNextToken (ps); 237 | return P_OK; 238 | } else { 239 | return P_ERROR; 240 | } 241 | } 242 | 243 | /* 244 | * This method is just a syntactic element since it equates an expression 245 | * with an identifier. 246 | */ 247 | static ParseReturnCode 248 | parseExpression (ParserState* ps, char* value) 249 | { 250 | return parseIdentifier (ps, value); 251 | } 252 | 253 | /* 254 | * Prints a message on standard output giving a message, the filename and 255 | * the linenumber. 256 | */ 257 | static ParseReturnCode 258 | stateMessage (ParserState* ps, 259 | ParseReturnCode code, 260 | const char* msg) 261 | { 262 | if (code == P_WARNING) { 263 | fprintf (stderr, "WARNING : "); 264 | } else if (code == P_ERROR) { 265 | fprintf (stderr, "ERROR : "); 266 | } 267 | fprintf (stderr, "%s : in file %s on line %d\n", msg, ps->fileName, ps->lineNumber); 268 | return code; 269 | } 270 | 271 | /* 272 | * Parses a list of programme property assignments and sends each to the 273 | * application via a call to bindToProgram(...); 274 | */ 275 | static ParseReturnCode 276 | parseAssignmentList (ParserState* ps, const int pgmNr) 277 | { 278 | ParseReturnCode R; 279 | char symbol[SYMBOLSIZE]; 280 | char value[VALUESIZE]; 281 | char msg[STRINGBUFFERSZ]; 282 | 283 | while (!nextTokenMatches (ps, '}')) { 284 | if ((R = parseIdentifier (ps, symbol)) == P_ERROR) { 285 | return stateMessage (ps, R, "identifier expected."); 286 | } 287 | 288 | if ((R = parseToken (ps, '=')) == P_ERROR) { 289 | snprintf (msg, sizeof(msg), "'=' expected after '%s'", symbol); 290 | return stateMessage (ps, R, msg); 291 | } 292 | 293 | if ((R = parseExpression (ps, value)) == P_ERROR) { 294 | snprintf (msg, sizeof(msg), "bad expression after '%s='", symbol); 295 | return stateMessage (ps, R, msg); 296 | } 297 | 298 | if (bindToProgram (ps->p, ps->fileName, ps->lineNumber, pgmNr, symbol, value)) { 299 | return P_ERROR; 300 | } 301 | 302 | if (nextTokenMatches (ps, ',')) { 303 | (void)getNextToken (ps); 304 | } 305 | } 306 | (void)getNextToken (ps); 307 | return P_OK; 308 | } 309 | 310 | /* 311 | * Parses one program definition by reading a programme number followed 312 | * by an assignment list. 313 | */ 314 | static ParseReturnCode 315 | parseProgramDefinition (ParserState* ps) 316 | { 317 | ParseReturnCode R; 318 | int programNumber; 319 | if ((R = parseInteger (ps, &programNumber)) == P_ERROR) { 320 | return stateMessage (ps, R, "program number expected"); 321 | } 322 | if ((R = parseToken (ps, '{')) == P_ERROR) { 323 | return stateMessage (ps, R, "assignment list expected"); 324 | } 325 | return parseAssignmentList (ps, programNumber); 326 | } 327 | 328 | /* 329 | * Parse all program definitions from the current parser state to the 330 | * end of the file. 331 | */ 332 | static ParseReturnCode 333 | parseProgramDefinitionList (ParserState* ps) 334 | { 335 | ParseReturnCode R; 336 | while (!nextTokenMatches (ps, TKN_EOF)) { 337 | if ((R = parseProgramDefinition (ps)) == P_ERROR) { 338 | return stateMessage (ps, R, "bad program definition"); 339 | } 340 | } 341 | return P_OK; 342 | } 343 | 344 | /* 345 | * Opens the named programme file and parses its contents. 346 | * fileName The path to the programme file. 347 | * return 0 if the file was successfully read, non-zero otherwise. 348 | */ 349 | int 350 | loadProgrammeFile (void* p, char* fileName) 351 | { 352 | ParserState ps; 353 | ps.p = p; 354 | if ((ps.fp = fopen (fileName, "r")) != NULL) { 355 | int rtn; 356 | ps.fileName = fileName; 357 | ps.lineNumber = 0; 358 | getNextToken (&ps); 359 | rtn = (int)parseProgramDefinitionList (&ps); 360 | fclose (ps.fp); 361 | return rtn; 362 | } else { 363 | perror (fileName); 364 | return (int)P_ERROR; 365 | } 366 | } 367 | -------------------------------------------------------------------------------- /plugin/setBfree/src/pgmParser.h: -------------------------------------------------------------------------------- 1 | /* setBfree - DSP tonewheel organ 2 | * 3 | * Copyright (C) 2003-2004 Fredrik Kilander 4 | * Copyright (C) 2008-2018 Robin Gareus 5 | * Copyright (C) 2012 Will Panther 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2, or (at your option) 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | /* pgmParser.h */ 22 | #ifndef PGMPARSER_H 23 | #define PGMPARSER_H 24 | 25 | //#include "memstream.h" 26 | 27 | extern int loadProgrammeFile (void* p, char* fileName); 28 | extern int loadProgrammeString (void* p, char* pdef); 29 | 30 | #endif /* PGMPARSER_H */ 31 | -------------------------------------------------------------------------------- /plugin/setBfree/src/program.h: -------------------------------------------------------------------------------- 1 | /* setBfree - DSP tonewheel organ 2 | * 3 | * Copyright (C) 2003-2004 Fredrik Kilander 4 | * Copyright (C) 2008-2018 Robin Gareus 5 | * Copyright (C) 2012 Will Panther 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2, or (at your option) 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef PROGRAM_H 22 | #define PROGRAM_H 23 | 24 | #include "cfgParser.h" 25 | 26 | #define MAXPROGS (129) 27 | 28 | #define NAMESZ 22 29 | #define NFLAGS 1 /* The nof flag fields in Programme struct */ 30 | typedef struct _programme { 31 | char name[NAMESZ]; 32 | unsigned int flags[NFLAGS]; 33 | unsigned int drawbars[9]; 34 | unsigned int lowerDrawbars[9]; 35 | unsigned int pedalDrawbars[9]; 36 | short keyAttackEnvelope; // unused 37 | float keyAttackClickLevel; // unused 38 | float keyAttackClickDuration; // unused 39 | short keyReleaseEnvelope; // unused 40 | float keyReleaseClickLevel; // unused 41 | float keyReleaseClickDuration; // unused 42 | short scanner; 43 | short percussionEnabled; 44 | short percussionVolume; 45 | short percussionSpeed; 46 | short percussionHarmonic; 47 | short overdriveSelect; 48 | short rotaryEnabled; // unused 49 | short rotarySpeedSelect; 50 | float reverbMix; 51 | short keyboardSplitLower; 52 | short keyboardSplitPedals; 53 | short transpose[7]; 54 | } Programme; 55 | 56 | /* Flag bits used in the first field */ 57 | 58 | #define FL_INUSE 0x0001 /* Record is in use */ 59 | 60 | #define FL_DRAWBR 0x0002 /* Set drawbars */ 61 | 62 | #define FL_ATKENV 0x0004 /* Attack envelope */ 63 | #define FL_ATKCKL 0x0008 /* Attack Click level */ 64 | #define FL_ATKCKD 0x0010 /* Attack click duration */ 65 | 66 | #define FL_RLSENV 0x0020 /* Release envelope */ 67 | #define FL_RLSCKL 0x0040 /* Release level */ 68 | #define FL_RLSCKD 0x0080 /* Release duration */ 69 | 70 | #define FL_SCANNR 0x0100 /* Vibrato scanner modulation depth */ 71 | 72 | #define FL_PRCENA 0x0200 /* Percussion on/off */ 73 | #define FL_PRCVOL 0x0400 /* Percussion soft/normal */ 74 | #define FL_PRCSPD 0x0800 /* Percussion slow/fast */ 75 | #define FL_PRCHRM 0x1000 /* Percussion 2nd/3rd */ 76 | 77 | #define FL_OVRSEL 0x2000 /* Overdrive on/off */ 78 | 79 | #define FL_ROTENA 0x4000 /* Rotary on/off */ 80 | #define FL_ROTSPS 0x8000 /* Rotary speed select */ 81 | 82 | #define FL_RVBMIX 0x00010000 /* Reverb on/off */ 83 | 84 | #define FL_DRWRND 0x00020000 /* Randomize drawbars */ 85 | #define FL_KSPLTL 0x00040000 /* Keyboard split point lower/upper */ 86 | 87 | #define FL_LOWDRW 0x00080000 /* Lower manual drawbars */ 88 | #define FL_PDLDRW 0x00100000 /* Pedal drawbars */ 89 | 90 | #define FL_KSPLTP 0x00200000 /* Keyboard split point pedal/lower */ 91 | 92 | #define FL_TRA_PD 0x00400000 /* Transpose for pedal split region */ 93 | #define FL_TRA_LM 0x00800000 /* Transpose for lower split region */ 94 | #define FL_TRA_UM 0x01000000 /* Transpose for upper split region */ 95 | #define FL_TRANSP 0x02000000 /* Global transpose */ 96 | #define FL_TRCH_A 0x04000000 /* Channel A (upper) transpose */ 97 | #define FL_TRCH_B 0x08000000 /* Channel B (lower) transpose */ 98 | #define FL_TRCH_C 0x10000000 /* Channel C (pedal) transpose */ 99 | 100 | #define FL_VCRUPR 0x20000000 /* Vib/cho upper manual routing */ 101 | #define FL_VCRLWR 0x40000000 /* Vib/cho lower manual routing */ 102 | 103 | struct b_programme { 104 | /** 105 | * This is to compensate for MIDI controllers that number the programs 106 | * from 1 to 128 on their interface. Internally we use 0-127, as does 107 | * MIDI. 108 | */ 109 | int MIDIControllerPgmOffset; 110 | int previousPgmNr; 111 | Programme programmes[MAXPROGS]; 112 | }; 113 | 114 | extern int pgmConfig (struct b_programme* p, ConfigContext* cfg); 115 | extern const ConfigDoc* pgmDoc (void); 116 | 117 | extern void installProgram (void* inst, unsigned char uc); 118 | 119 | extern void listProgrammes (struct b_programme* p, FILE* fp); 120 | extern int walkProgrammes (struct b_programme* p, int clear); 121 | extern void loopProgammes (struct b_programme* p, int all, void (*cb) (int, int, const char*, void*), void* arg); 122 | extern int formatProgram (Programme* p, char* out, int maxlen); 123 | extern int saveProgramm (void* inst, int pgm, char* name, int flagmask); 124 | extern void exportProgramms (struct b_programme* p, FILE* fp); 125 | extern void writeProgramm (int pgmNr, Programme* p, const char* sep, FILE* fp); 126 | 127 | extern struct b_programme* allocProgs (void); 128 | extern void freeProgs (struct b_programme* p); 129 | 130 | extern int bindToProgram (void* pp, 131 | const char* fileName, 132 | const int lineNumber, 133 | const int pgmnr, 134 | const char* sym, 135 | const char* val); 136 | 137 | #endif /* PROGRAM_H */ 138 | -------------------------------------------------------------------------------- /plugin/setBfree/src/state.c: -------------------------------------------------------------------------------- 1 | /* setBfree - DSP tonewheel organ 2 | * 3 | * Copyright (C) 2013-2018 Robin Gareus 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2, or (at your option) 8 | * any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* keep track of the current state/config. 20 | * This is done by using the initial-state + all runtime changes. 21 | * We only keep track of the latest (aka current) state -> no undo. 22 | * 23 | * 24 | * The current organ state: 25 | * * /hardcoded/ initialization 26 | * + configuration file 27 | * + MIDI-CCs 28 | * + [MIDI program-changes] 29 | * -> collection of MIDI-CCs (remembered via MIDI-CC above) 30 | * -> keytable changes; affect loadKeyTable[A-C] (transpose, etc) 31 | * 32 | * We hook into midi-CC function calls and remember the latest value 33 | */ 34 | 35 | #define _XOPEN_SOURCE 700 36 | 37 | #include 38 | #include 39 | #include 40 | 41 | #if _WIN32 42 | #pragma warning(disable:4305) 43 | #pragma warning(disable:4244) 44 | #pragma warning(disable:4100) 45 | #pragma warning(disable:4706) 46 | #define strdup _strdup 47 | #endif 48 | 49 | void rc_dump_state (void* t); 50 | /* simple key-value store */ 51 | 52 | struct b_kv { 53 | struct b_kv* next; 54 | char* key; 55 | char* value; 56 | }; 57 | 58 | static void* 59 | kvstore_alloc () 60 | { 61 | struct b_kv* kv = (struct b_kv*)calloc (1, sizeof (struct b_kv)); 62 | return kv; 63 | } 64 | 65 | static void 66 | kvstore_free (void* kvs) 67 | { 68 | struct b_kv* kv = (struct b_kv*)kvs; 69 | while (kv) { 70 | struct b_kv* me = kv; 71 | free (kv->key); 72 | free (kv->value); 73 | kv = kv->next; 74 | free (me); 75 | } 76 | } 77 | 78 | static void 79 | kvstore_store (void* kvs, const char* key, const char* value) 80 | { 81 | struct b_kv* kv = (struct b_kv*)kvs; 82 | struct b_kv* it = NULL; 83 | while (kv) { 84 | if (!kv->next) { 85 | /* "->next == NULL" : "terminal node" */ 86 | break; 87 | } 88 | if (!strcmp (kv->key, key)) { 89 | it = kv; 90 | break; 91 | } 92 | kv = kv->next; 93 | } 94 | if (!it) { 95 | /* allocate new terminal node */ 96 | it = (struct b_kv*)calloc (1, sizeof (struct b_kv)); 97 | kv->next = it; 98 | it = kv; 99 | it->key = strdup (key); 100 | } 101 | free (it->value); 102 | it->value = strdup (value); 103 | } 104 | 105 | /* setBfree resource/running config */ 106 | 107 | #include "midi.h" 108 | 109 | struct b_midirc { 110 | int mccc; // count of midi-CCs 111 | int* mcc; // midi-CC values for each midi-CC function 112 | }; 113 | 114 | struct b_rc { 115 | struct b_midirc mrc; 116 | struct b_kv* rrc; 117 | }; 118 | 119 | void 120 | freeRunningConfig (void* t) 121 | { 122 | struct b_rc* rc = (struct b_rc*)t; 123 | free (rc->mrc.mcc); 124 | kvstore_free (rc->rrc); 125 | free (rc); 126 | } 127 | 128 | void* 129 | allocRunningConfig (void) 130 | { 131 | int i, mccc; 132 | struct b_rc* rc = (struct b_rc*)malloc (sizeof (struct b_rc)); 133 | if (!rc) 134 | return NULL; 135 | 136 | mccc = rc->mrc.mccc = getCCFunctionCount (); 137 | rc->mrc.mcc = (int*)malloc (mccc * sizeof (int)); 138 | if (!rc->mrc.mcc) { 139 | free (rc); 140 | return NULL; 141 | } 142 | 143 | rc->rrc = (struct b_kv*)kvstore_alloc (); 144 | 145 | if (!rc->rrc) { 146 | free (rc->mrc.mcc); 147 | free (rc); 148 | return NULL; 149 | } 150 | 151 | for (i = 0; i < mccc; ++i) { 152 | rc->mrc.mcc[i] = -1; // mark as unset 153 | } 154 | 155 | return rc; 156 | } 157 | 158 | void 159 | rc_add_midicc (void* t, int id, unsigned char val) 160 | { 161 | struct b_rc* rc = (struct b_rc*)t; 162 | if (id < 0 || id >= rc->mrc.mccc) { 163 | #if 0 // devel&debug 164 | fprintf(stderr, "ignored state save: fn:%d -> %d\n", id, val); 165 | #endif 166 | return; 167 | } 168 | rc->mrc.mcc[id] = (int)val; 169 | } 170 | 171 | void 172 | rc_add_cfg (void* t, ConfigContext* cfg) 173 | { 174 | struct b_rc* rc = (struct b_rc*)t; 175 | #if 0 176 | if (getCCFunctionId(cfg->name) > 0) { 177 | /* if there is a MIDI-CC function corresponding to the cfg -> use it */ 178 | 179 | // mmh. what to do with 'cfg->value' ?! 180 | // - check doc for function parameter type. 181 | // CFG_DOUBLE, CFG_FLOAT -> * 127.0 -- won't work for all though :( 182 | // CFG_INT -> mmh, keep as is ?! 183 | // CFG_TEXT -> fall though to cfg_eval() 184 | // 185 | // major rework: have all useMIDIControlFunction() /users/ 186 | // specify a target range and/or conversion function. 187 | // -> that'll also remove lots of wrapper function bloat: 188 | // eg. setDrumBreakPosition(), revControl(), setPercEnableFromMIDI(),.. etc 189 | printf (" cfg_midi(\"%s\", \"%s\")\n", cfg->name, cfg->value); 190 | return; 191 | } else 192 | #endif 193 | kvstore_store (rc->rrc, cfg->name, cfg->value); 194 | } 195 | 196 | void 197 | rc_loop_state (void* t, void (*cb) (int, const char*, const char*, unsigned char, void*), void* arg) 198 | { 199 | struct b_rc* rc = (struct b_rc*)t; 200 | int i; 201 | for (i = 0; i < rc->mrc.mccc; ++i) { 202 | if (rc->mrc.mcc[i] < 0) 203 | continue; 204 | cb (i, getCCFunctionName (i), NULL, (unsigned char)rc->mrc.mcc[i], arg); 205 | } 206 | 207 | struct b_kv* kv = rc->rrc; 208 | while (kv && kv->next != NULL) { 209 | if (kv->key == NULL) 210 | continue; 211 | cb (-1, kv->key, kv->value, 0, arg); 212 | kv = kv->next; 213 | } 214 | } 215 | 216 | /* ------------- */ 217 | 218 | static void 219 | state_print_cb (int fnid, const char* key, const char* kv, unsigned char val, void* arg) 220 | { 221 | if (fnid < 0) { 222 | printf (" rc_cfg (\"%s\", \"%s\");\n", key, kv); 223 | } else { 224 | printf (" rc_ccf (\"%s\", %d); // id:%d\n", key, val, fnid); 225 | } 226 | } 227 | 228 | void 229 | rc_dump_state (void* t) 230 | { 231 | rc_loop_state (t, &state_print_cb, NULL); 232 | } 233 | 234 | /* ------------- */ 235 | 236 | /* this is a bit of a dirty hack 237 | * 238 | * In order for the LV2 plugin to query the complete state, 239 | * we save defaults as as midi-CC. 240 | * 241 | * All modules should /register/ their default values and settings! 242 | * 243 | * some stuff, e.g. midiPrimeControllerMapping() and 244 | * program-table are also dependent on commandline args.. Ugh. 245 | * 246 | */ 247 | void 248 | initRunningConfig (void* t, void* mcfg) 249 | { 250 | #if 0 // these are set by main() -> midi-CC hooks are called. 251 | notifyControlChangeByName(mcfg, "upper.drawbar16", 0); 252 | notifyControlChangeByName(mcfg, "upper.drawbar513", 0); 253 | notifyControlChangeByName(mcfg, "upper.drawbar8", 32); 254 | notifyControlChangeByName(mcfg, "upper.drawbar4", 127); 255 | notifyControlChangeByName(mcfg, "upper.drawbar223", 127); 256 | notifyControlChangeByName(mcfg, "upper.drawbar2", 127); 257 | notifyControlChangeByName(mcfg, "upper.drawbar135", 127); 258 | notifyControlChangeByName(mcfg, "upper.drawbar113", 127); 259 | notifyControlChangeByName(mcfg, "upper.drawbar1", 127); 260 | #endif 261 | notifyControlChangeByName (mcfg, "lower.drawbar16", 0); 262 | notifyControlChangeByName (mcfg, "lower.drawbar513", 80); 263 | notifyControlChangeByName (mcfg, "lower.drawbar8", 0); 264 | notifyControlChangeByName (mcfg, "lower.drawbar4", 127); 265 | notifyControlChangeByName (mcfg, "lower.drawbar223", 127); 266 | notifyControlChangeByName (mcfg, "lower.drawbar2", 127); 267 | notifyControlChangeByName (mcfg, "lower.drawbar135", 127); 268 | notifyControlChangeByName (mcfg, "lower.drawbar113", 127); 269 | notifyControlChangeByName (mcfg, "lower.drawbar1", 127); 270 | notifyControlChangeByName (mcfg, "pedal.drawbar16", 0); 271 | notifyControlChangeByName (mcfg, "pedal.drawbar8", 32); 272 | 273 | notifyControlChangeByName (mcfg, "vibrato.routing", 0); 274 | notifyControlChangeByName (mcfg, "vibrato.upper", 0); 275 | notifyControlChangeByName (mcfg, "vibrato.lower", 0); 276 | notifyControlChangeByName (mcfg, "vibrato.knob", 0); 277 | 278 | notifyControlChangeByName (mcfg, "percussion.enable", 0); 279 | notifyControlChangeByName (mcfg, "percussion.volume", 0); 280 | notifyControlChangeByName (mcfg, "percussion.decay", 0); 281 | notifyControlChangeByName (mcfg, "percussion.harmonic", 0); 282 | 283 | notifyControlChangeByName (mcfg, "overdrive.enable", 0); 284 | notifyControlChangeByName (mcfg, "overdrive.character", 0); 285 | 286 | notifyControlChangeByName (mcfg, "reverb.mix", 127 * .1); 287 | notifyControlChangeByName (mcfg, "swellpedal1", 127); 288 | notifyControlChangeByName (mcfg, "rotary.speed-select", 4 * 15); 289 | } 290 | -------------------------------------------------------------------------------- /plugin/setBfree/src/state.h: -------------------------------------------------------------------------------- 1 | /* setBfree - DSP tonewheel organ 2 | * 3 | * Copyright (C) 2013 Robin Gareus 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2, or (at your option) 8 | * any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #ifndef SETBFREE_STATE_H_ 20 | #define SETBFREE_STATE_H_ 21 | 22 | #include "cfgParser.h" 23 | 24 | void* allocRunningConfig (void); 25 | void initRunningConfig (void* t, void* mcfg); 26 | void freeRunningConfig (void* t); 27 | 28 | void rc_add_midicc (void* t, int id, unsigned char val); 29 | void rc_add_cfg (void* t, ConfigContext* cfg); 30 | 31 | void rc_loop_state (void* t, void (*cb) (int, const char*, const char*, unsigned char, void*), void* arg); 32 | 33 | void rc_dump_state (void* t); 34 | #endif 35 | -------------------------------------------------------------------------------- /plugin/setBfree/src/vibrato.c: -------------------------------------------------------------------------------- 1 | /* setBfree - DSP tonewheel organ 2 | * 3 | * Copyright (C) 2003-2004 Fredrik Kilander 4 | * Copyright (C) 2008-2018 Robin Gareus 5 | * Copyright (C) 2012 Will Panther 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2, or (at your option) 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef CONFIGDOCONLY 22 | 23 | #define _XOPEN_SOURCE 700 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "cfgParser.h" 31 | #include "main.h" 32 | #include "midi.h" 33 | #include "tonegen.h" 34 | #include "vibrato.h" 35 | 36 | #if _WIN32 37 | #pragma warning(disable:4305) 38 | #pragma warning(disable:4244) 39 | #pragma warning(disable:4100) 40 | #endif 41 | 42 | 43 | /* 44 | * The increment is encoded using a 16-bit fixed-point mantissa. 45 | * This means that an increment of 1.0 is represented by 2^16, or (1<<16). 46 | * This quantity is added to inPos using ordinary arithmetic. 47 | * 48 | * When writing at inPos, the position is divided into (h.l). 49 | * The integer part, h, is the first sample to write to. It receives 50 | * x(1.0 - l) + y(h) of the input sample. That is, we add the fraction to 51 | * the value already present. The next sample, receives x*l + y(h+1). 52 | * In order to prevent repeated echoes, the buffer is cleared by the 53 | * read operation. 54 | * 55 | * We need to translate these values into fixed-point integer aritmetic. 56 | * Since the fraction is 16-bit, they are represented by l/(2^16). 57 | * Thus we do (x * l) >> 16 to compute (x * l). 58 | * Having that, we simply do x - xl to arrive at the value to add to x(h). 59 | * 60 | * In order to avoid a buffer overrun at (h+1), we must use a temporary 61 | * variable for the address of (h+1) and wrap it back to 0 if it equals 62 | * the length of the buffer. 63 | * 64 | * Increments less than 1.0 will be perceived as a rise in pitch, because 65 | * they are the ones first seen by the reader, and the energy will be 66 | * compressed into fewer samples than in the source. Conversely, increments 67 | * above 1.0 will be perceived as a drop in pitch, because the information 68 | * tries to escape from the reader, and the energy is distributed across 69 | * more samples than in the source. 70 | * 71 | * Increments must be less than 2.0, or some samples will be skipped which 72 | * will cause nasty clicks or noise, depending on the output DACs. 73 | */ 74 | 75 | #define INCTBL_MASK 0x07ffffff /* Fixed point */ 76 | #define BUF_MASK_SAMPLES 0x000003FF 77 | #define BUF_MASK_POSN 0x03FFFFFF /* Fixed-point mask */ 78 | 79 | /* 80 | * Sets the scanner frequency. It operates at a fixed frequency beacuse 81 | * it is driven from the tonegenerator motor which runs at a steady 1200 82 | * or 1500 rpm (50 Hz models). The usual frequency is somewhere between 83 | * 7 or 8 Hz. 84 | */ 85 | static void 86 | setScannerFrequency (struct b_vibrato* v, double Hertz, double SampleRateD) 87 | { 88 | v->vibFqHertz = Hertz; 89 | v->statorIncrement = 90 | (unsigned int)(((v->vibFqHertz * INCTBL_SIZE) / SampleRateD) * 65536.0); 91 | } 92 | 93 | /* 94 | * Controls the amount of vibrato to apply by selecting the proper lookup 95 | * table for the processing routine. 96 | */ 97 | void 98 | setVibrato (struct b_vibrato* v, int select) 99 | { 100 | switch (select & 3) { 101 | case 0: /* disable */ 102 | v->effectEnabled = FALSE; 103 | break; 104 | 105 | case 1: 106 | v->effectEnabled = TRUE; 107 | v->offsetTable = v->offset1Table; 108 | break; 109 | 110 | case 2: 111 | v->effectEnabled = TRUE; 112 | v->offsetTable = v->offset2Table; 113 | break; 114 | 115 | case 3: 116 | v->effectEnabled = TRUE; 117 | v->offsetTable = v->offset3Table; 118 | break; 119 | } 120 | 121 | v->mixedBuffers = select & CHO_; 122 | } 123 | 124 | /* 125 | * Implements the vibrato knob response to a MIDI controller. 126 | */ 127 | static void 128 | setVibratoFromMIDI (void* t, unsigned char u) 129 | { 130 | struct b_vibrato* v = &(((struct b_tonegen*)t)->inst_vibrato); 131 | switch (u / 23) { 132 | case 0: 133 | setVibrato (v, VIB1); 134 | break; 135 | case 1: 136 | setVibrato (v, CHO1); 137 | break; 138 | case 2: 139 | setVibrato (v, VIB2); 140 | break; 141 | case 3: 142 | setVibrato (v, CHO2); 143 | break; 144 | case 4: 145 | setVibrato (v, VIB3); 146 | break; 147 | case 5: 148 | setVibrato (v, CHO3); 149 | break; 150 | } 151 | } 152 | 153 | /* 154 | * Vibrato routing. 155 | */ 156 | static void 157 | setVibratoRoutingFromMIDI (void* t, unsigned char uc) 158 | { 159 | struct b_tonegen* inst_synth = (struct b_tonegen*)t; 160 | switch (uc / 32) { 161 | case 0: 162 | setVibratoUpper (inst_synth, FALSE); 163 | setVibratoLower (inst_synth, FALSE); 164 | break; 165 | case 1: 166 | setVibratoUpper (inst_synth, FALSE); 167 | setVibratoLower (inst_synth, TRUE); 168 | break; 169 | case 2: 170 | setVibratoUpper (inst_synth, TRUE); 171 | setVibratoLower (inst_synth, FALSE); 172 | break; 173 | case 3: 174 | setVibratoUpper (inst_synth, TRUE); 175 | setVibratoLower (inst_synth, TRUE); 176 | break; 177 | } 178 | int vr = getVibratoRouting (inst_synth); 179 | notifyControlChangeByName (inst_synth->midi_cfg_ptr, "vibrato.upper", (vr & 2) ? 127 : 0); 180 | notifyControlChangeByName (inst_synth->midi_cfg_ptr, "vibrato.lower", (vr & 1) ? 127 : 0); 181 | } 182 | 183 | static void 184 | setVibratoUpperFromMIDI (void* t, unsigned char uc) 185 | { 186 | struct b_tonegen* inst_synth = (struct b_tonegen*)t; 187 | setVibratoUpper (inst_synth, uc < 64 ? FALSE : TRUE); 188 | notifyControlChangeByName (inst_synth->midi_cfg_ptr, "vibrato.routing", getVibratoRouting (inst_synth) << 5); 189 | } 190 | 191 | static void 192 | setVibratoLowerFromMIDI (void* t, unsigned char uc) 193 | { 194 | struct b_tonegen* inst_synth = (struct b_tonegen*)t; 195 | setVibratoLower (inst_synth, uc < 64 ? FALSE : TRUE); 196 | notifyControlChangeByName (inst_synth->midi_cfg_ptr, "vibrato.routing", getVibratoRouting (inst_synth) << 5); 197 | } 198 | 199 | /* 200 | * Initialises tables. 201 | */ 202 | static void 203 | initIncrementTables (struct b_vibrato* v) 204 | { 205 | int i; 206 | double S = 65536.0; 207 | double voff1; 208 | double voff2; 209 | double voff3; 210 | 211 | voff1 = v->vib1OffAmp; 212 | voff2 = v->vib2OffAmp; 213 | voff3 = v->vib3OffAmp; 214 | 215 | for (i = 0; i < BUF_SIZE_BYTES; i++) { 216 | v->vibBuffer[i] = 0; 217 | } 218 | 219 | /* 220 | * The offset tables contains fixed-point offsets from the writer's 221 | * standard positions. The offsets run ahead for half a cycle and lag 222 | * behind the writer for the other half. The amplitude applied determines 223 | * the distance ahead and behind (they are symmetric) and thus the 224 | * perceived Doppler effect. It is, after all, just a variable delay. 225 | */ 226 | 227 | for (i = 0; i < INCTBL_SIZE; i++) { 228 | double m = sin ((2.0 * M_PI * i) / INCTBL_SIZE); 229 | v->offset1Table[i] = (unsigned int)((1.0 + voff1 + (m * v->vib1OffAmp)) * S); 230 | v->offset2Table[i] = (unsigned int)((1.0 + voff2 + (m * v->vib2OffAmp)) * S); 231 | v->offset3Table[i] = (unsigned int)((1.0 + voff3 + (m * v->vib3OffAmp)) * S); 232 | } 233 | 234 | #ifdef DEBUG_DUMP_SCANNER 235 | { 236 | FILE* fp; 237 | char* debugfile = "scanner.log"; 238 | if ((fp = fopen (debugfile, "w")) != NULL) { 239 | fprintf (fp, 240 | "statorIncrement = 0x%08x %g\n", 241 | v->statorIncrement, 242 | ((double)v->statorIncrement) / S); 243 | 244 | fprintf (fp, "voff1 = %g, voff2 = %g, voff3 = %g\n", 245 | voff1, voff2, voff3); 246 | 247 | fprintf (fp, "offset1Table\n"); 248 | for (i = 0; i < INCTBL_SIZE; i++) { 249 | fprintf (fp, 250 | "%4d 0x%08x %g\n", 251 | i, 252 | v->offset1Table[i], 253 | ((double)v->offset1Table[i]) / S); 254 | } 255 | fclose (fp); 256 | } else { 257 | perror (debugfile); 258 | exit (1); 259 | } 260 | } 261 | #endif /* DEBUG */ 262 | } 263 | 264 | /* 265 | * Initialises this module. 266 | */ 267 | void 268 | reset_vibrato (struct b_vibrato* v) 269 | { 270 | v->offsetTable = v->offset3Table; 271 | v->stator = 0; 272 | v->statorIncrement = 0; 273 | 274 | v->outPos = BUF_MASK_SAMPLES / 2; 275 | 276 | v->vib1OffAmp = 3.0; 277 | v->vib2OffAmp = 6.0; 278 | v->vib3OffAmp = 9.0; 279 | 280 | v->vibFqHertz = 7.25; 281 | 282 | v->mixedBuffers = FALSE; 283 | v->effectEnabled = FALSE; 284 | } 285 | 286 | void 287 | resetVibrato (void* t) 288 | { 289 | struct b_vibrato* v = &(((struct b_tonegen*)t)->inst_vibrato); 290 | reset_vibrato (v); 291 | } 292 | 293 | void 294 | init_vibrato (struct b_vibrato* v, double SampleRateD) 295 | { 296 | setScannerFrequency (v, v->vibFqHertz, SampleRateD); 297 | initIncrementTables (v); 298 | setVibrato (v, 0); 299 | } 300 | 301 | void 302 | initVibrato (void* t, void* m, double SampleRateD) 303 | { 304 | struct b_vibrato* v = &(((struct b_tonegen*)t)->inst_vibrato); 305 | init_vibrato (v, SampleRateD); 306 | useMIDIControlFunction (m, "vibrato.knob", setVibratoFromMIDI, t); 307 | useMIDIControlFunction (m, "vibrato.routing", setVibratoRoutingFromMIDI, t); 308 | useMIDIControlFunction (m, "vibrato.upper", setVibratoUpperFromMIDI, t); 309 | useMIDIControlFunction (m, "vibrato.lower", setVibratoLowerFromMIDI, t); 310 | } 311 | 312 | /* 313 | * Configuration interface. 314 | */ 315 | int 316 | scannerConfig (void* t, ConfigContext* cfg, double SampleRateD) 317 | { 318 | struct b_vibrato* v = &(((struct b_tonegen*)t)->inst_vibrato); 319 | int ack = 0; 320 | double d; 321 | if ((ack = getConfigParameter_dr ("scanner.hz", 322 | cfg, 323 | &d, 324 | 4.0, 22.0)) == 1) { 325 | setScannerFrequency (v, d, SampleRateD); 326 | } else if ((ack = getConfigParameter_dr ("scanner.modulation.v1", 327 | cfg, 328 | &v->vib1OffAmp, 329 | 0.0, 12.0)) == 1) { 330 | } else if ((ack = getConfigParameter_dr ("scanner.modulation.v2", 331 | cfg, 332 | &v->vib2OffAmp, 333 | 0.0, 12.0)) == 1) { 334 | } else if ((ack = getConfigParameter_dr ("scanner.modulation.v3", 335 | cfg, 336 | &v->vib3OffAmp, 337 | 0.0, 12.0)) == 1) { 338 | } 339 | return ack; 340 | } /* scannerConfig */ 341 | 342 | /* 343 | * Floating-point version of vibrato scanner. 344 | * Since this is a variable delay, delayed samples take a rest in vibBuffer 345 | * between calls to this function. 346 | */ 347 | void 348 | vibratoProc (struct b_vibrato* v, float const* inbuffer, float* outbuffer, size_t bufferLengthSamples) 349 | { 350 | const float fnorm = 1.0 / 65536.0; 351 | const float mixnorm = 0.7071067811865475; /* 1/sqrt(2) */ 352 | unsigned int i; 353 | float const* xp = inbuffer; 354 | float* yp = outbuffer; 355 | 356 | for (i = 0; i < bufferLengthSamples; i++) { 357 | /* Fetch the next input sample */ 358 | const float x = *xp++; 359 | /* Determine the fixed point writing position. This is relative to */ 360 | /* the current output position (outpos). */ 361 | const unsigned int j = 362 | ((v->outPos << 16) + v->offsetTable[v->stator >> 16]) & BUF_MASK_POSN; 363 | /* Convert fixpoint writing position to integer sample */ 364 | const int h = j >> 16; 365 | /* And the following sample, possibly wrapping the delay buffer. */ 366 | const int k = (h + 1) & BUF_MASK_SAMPLES; 367 | /* Drop the integer part of the fixpoint position. */ 368 | const float f = fnorm * ((float)(j & 0xFFFF)); 369 | /* Amplify incoming sample and normalise */ 370 | const float g = f * x; 371 | 372 | /* Write to delay buffer */ 373 | v->vibBuffer[h] += x - g; 374 | v->vibBuffer[k] += g; 375 | 376 | if (v->mixedBuffers) { 377 | *yp++ = (x + v->vibBuffer[v->outPos]) * mixnorm; 378 | } else { 379 | *yp++ = v->vibBuffer[v->outPos]; 380 | } 381 | 382 | /* Zero delay buffer at the reading position. */ 383 | v->vibBuffer[v->outPos] = 0; 384 | /* Update the reading position, wrapping back to start if needed. */ 385 | v->outPos = (v->outPos + 1) & BUF_MASK_SAMPLES; 386 | /* Update the delay amount index. */ 387 | v->stator = (v->stator + v->statorIncrement) & INCTBL_MASK; 388 | } 389 | } 390 | 391 | #else 392 | #include "cfgParser.h" 393 | #endif // CONFIGDOCONLY 394 | 395 | static const ConfigDoc doc[] = { 396 | { "scanner.hz", CFG_DOUBLE, "7.25", "Frequency of the vibrato scanner", "Hz", 4, 22, .5 }, 397 | { "scanner.modulation.v1", CFG_DOUBLE, "3.0", "Amount of modulation for vibrato/chorus 1 setting", "Hz", 0, 12, .5 }, 398 | { "scanner.modulation.v2", CFG_DOUBLE, "6.0", "Amount of modulation for vibrato/chorus 2 setting", "Hz", 0, 12, .5 }, 399 | { "scanner.modulation.v3", CFG_DOUBLE, "9.0", "Amount of modulation for vibrato/chorus 3 setting", "Hz", 0, 12, .5 }, 400 | DOC_SENTINEL 401 | }; 402 | 403 | const ConfigDoc* 404 | scannerDoc () 405 | { 406 | return doc; 407 | } 408 | -------------------------------------------------------------------------------- /plugin/setBfree/src/vibrato.h: -------------------------------------------------------------------------------- 1 | /* setBfree - DSP tonewheel organ 2 | * 3 | * Copyright (C) 2003-2004 Fredrik Kilander 4 | * Copyright (C) 2008-2018 Robin Gareus 5 | * Copyright (C) 2012 Will Panther 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2, or (at your option) 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef SCANNER_H 22 | #define SCANNER_H 23 | 24 | #include "cfgParser.h" 25 | 26 | #define VIB1 0x01 27 | #define VIB2 0x02 28 | #define VIB3 0x03 29 | #define CHO_ 0x80 /* The bit that turns on chorus. */ 30 | #define CHO1 0x81 31 | #define CHO2 0x82 32 | #define CHO3 0x83 33 | 34 | #define INCTBL_SIZE 2048 35 | 36 | #define BUF_SIZE_BYTES 1024 37 | 38 | struct b_vibrato { 39 | unsigned int offset1Table[INCTBL_SIZE]; 40 | unsigned int offset2Table[INCTBL_SIZE]; 41 | unsigned int offset3Table[INCTBL_SIZE]; 42 | 43 | unsigned int* offsetTable; 44 | 45 | unsigned int stator; 46 | unsigned int statorIncrement; 47 | 48 | unsigned int outPos; 49 | 50 | float vibBuffer[BUF_SIZE_BYTES]; 51 | 52 | /* 53 | * Amplitudes of phase shift for the three vibrato settings. 54 | */ 55 | 56 | double vib1OffAmp; 57 | double vib2OffAmp; 58 | double vib3OffAmp; 59 | 60 | double vibFqHertz; 61 | 62 | int mixedBuffers; 63 | int effectEnabled; 64 | }; 65 | 66 | extern void vibratoProc (struct b_vibrato* v, float const* inbuffer, float* outbuffer, size_t bufferLengthSamples); 67 | 68 | /* for standalone use */ 69 | extern void reset_vibrato (struct b_vibrato* v); 70 | extern void init_vibrato (struct b_vibrato* v, double SampleRateD); 71 | 72 | /* tonegen integration */ 73 | extern void resetVibrato (void* tonegen); 74 | extern void initVibrato (void* tonegen, void* m, double SampleRateD); 75 | 76 | extern int scannerConfig (void* t, ConfigContext* cfg, double SampleRateD); 77 | extern const ConfigDoc* scannerDoc (void); 78 | 79 | extern void setVibrato (struct b_vibrato* v, int select); 80 | 81 | #endif /* SCANNER_H */ 82 | --------------------------------------------------------------------------------