├── .gitignore ├── CMakeLists.txt ├── ChangeLog ├── LICENSE ├── README ├── debian ├── changelog ├── compat ├── control ├── copyright ├── docs ├── rules ├── synthv1-jack.docs ├── synthv1-jack.install └── synthv1-lv2.install ├── rpm └── synthv1.spec └── src ├── CMakeLists.txt ├── appdata ├── org.rncbc.synthv1.desktop └── org.rncbc.synthv1.metainfo.xml ├── config.h.cmake ├── images ├── fileOpen.png ├── itemReset.png ├── ledOff.png ├── ledOn.png ├── presetBank.png ├── presetBankOpen.png ├── presetDelete.png ├── presetEdit.png ├── presetNew.png ├── presetOpen.png ├── presetSave.png ├── synthv1.png ├── synthv1.svg ├── synthv1_control.png └── synthv1_preset.png ├── lv2 ├── lv2_external_ui.h ├── lv2_port_change_request.h └── lv2_programs.h ├── man1 ├── synthv1.1 └── synthv1.fr.1 ├── mimetypes ├── org.rncbc.synthv1.application-x-synthv1-preset.png ├── org.rncbc.synthv1.application-x-synthv1-preset.svg └── org.rncbc.synthv1.xml ├── palette ├── KXStudio.conf └── Wonton Soup.conf ├── synthv1.cpp ├── synthv1.h ├── synthv1.lv2 ├── manifest-win32.ttl ├── manifest.ttl ├── synthv1.ttl ├── synthv1_ui-win32.ttl └── synthv1_ui.ttl ├── synthv1.qrc ├── synthv1_config.cpp ├── synthv1_config.h ├── synthv1_controls.cpp ├── synthv1_controls.h ├── synthv1_filter.h ├── synthv1_formant.cpp ├── synthv1_formant.h ├── synthv1_fx.h ├── synthv1_jack.cpp ├── synthv1_jack.h ├── synthv1_list.h ├── synthv1_lv2.cpp ├── synthv1_lv2.h ├── synthv1_lv2ui.cpp ├── synthv1_lv2ui.h ├── synthv1_nsm.cpp ├── synthv1_nsm.h ├── synthv1_param.cpp ├── synthv1_param.h ├── synthv1_programs.cpp ├── synthv1_programs.h ├── synthv1_ramp.h ├── synthv1_reverb.h ├── synthv1_sched.cpp ├── synthv1_sched.h ├── synthv1_tuning.cpp ├── synthv1_tuning.h ├── synthv1_ui.cpp ├── synthv1_ui.h ├── synthv1_wave.cpp ├── synthv1_wave.h ├── synthv1widget.cpp ├── synthv1widget.h ├── synthv1widget.ui ├── synthv1widget_config.cpp ├── synthv1widget_config.h ├── synthv1widget_config.ui ├── synthv1widget_control.cpp ├── synthv1widget_control.h ├── synthv1widget_control.ui ├── synthv1widget_controls.cpp ├── synthv1widget_controls.h ├── synthv1widget_env.cpp ├── synthv1widget_env.h ├── synthv1widget_filt.cpp ├── synthv1widget_filt.h ├── synthv1widget_jack.cpp ├── synthv1widget_jack.h ├── synthv1widget_keybd.cpp ├── synthv1widget_keybd.h ├── synthv1widget_lv2.cpp ├── synthv1widget_lv2.h ├── synthv1widget_palette.cpp ├── synthv1widget_palette.h ├── synthv1widget_palette.ui ├── synthv1widget_param.cpp ├── synthv1widget_param.h ├── synthv1widget_preset.cpp ├── synthv1widget_preset.h ├── synthv1widget_programs.cpp ├── synthv1widget_programs.h ├── synthv1widget_status.cpp ├── synthv1widget_status.h ├── synthv1widget_wave.cpp └── synthv1widget_wave.h /.gitignore: -------------------------------------------------------------------------------- 1 | build* 2 | *.txt.user 3 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | synthv1 - an old-school polyphonic synthesizer 2 | ---------------------------------------------- 3 | 4 | an old-school 4-oscillator subtractive polyphonic synthesizer 5 | with stereo fx. 6 | 7 | Features: 8 | 9 | - pure stand-alone JACK [1] client with JACK-session, NSM [3] and both 10 | JACK MIDI and ALSA MIDI [2] input support; 11 | 12 | - LV2 [4] instrument plugin. 13 | URI: http://synthv1.sourceforge.net/lv2 14 | 15 | License: 16 | 17 | synthv1 is free, Linux Audio [5] open-source software, distributed under 18 | the terms of the GNU General Public License (GPL) [6] version 2 or later. 19 | 20 | Website: 21 | 22 | https://synthv1.sourceforge.io 23 | http://synthv1.sourceforge.net 24 | 25 | Project page: 26 | 27 | https://sourceforge.net/projects/synthv1 28 | 29 | Git repos: 30 | 31 | https://git.code.sf.net/p/synthv1/code 32 | https://github.com/rncbc/synthv1.git 33 | https://gitlab.com/rncbc/synthv1.git 34 | https://codeberg.org/rncbc/synthv1.git 35 | 36 | Weblog: 37 | 38 | https://www.rncbc.org 39 | 40 | Requirements: 41 | 42 | mandatory, 43 | 44 | - Qt framework [7], C++ class library and tools for 45 | cross-platform application and UI development 46 | https://qt.io/ 47 | 48 | optional (opted-in at build time), 49 | 50 | - JACK [1] Audio Connection Kit 51 | https://jackaudio.org/ 52 | 53 | - ALSA [2], Advanced Linux Sound Architecture 54 | https://www.alsa-project.org/ 55 | 56 | - LV2 [4], Audio Plugin Standard, the extensible successor of LADSPA 57 | https://lv2plug.in/ 58 | 59 | - liblo [8], Lightweight OSC implementation 60 | (needed for NSM support [3]) 61 | http://liblo.sourceforge.net/ 62 | 63 | Installation: 64 | 65 | - unpack tarball as usual; in the extracted source directory: 66 | 67 | cmake [-DCMAKE_INSTALL_PREFIX=] -B build 68 | cmake --build build [--parallel ] 69 | 70 | - optionally, as root: 71 | 72 | [sudo] cmake --install build 73 | 74 | - note that the default installation path () is /usr/local . 75 | 76 | Acknowledgements: 77 | 78 | synthv1 logo/icon is an original fine work of Jarle Richard Akselsen. 79 | 80 | References: 81 | 82 | [1] JACK Audio Connection Kit 83 | https://jackaudio.org/ 84 | 85 | [2] ALSA, Advanced Linux Sound Architecture 86 | https://www.alsa-project.org/ 87 | 88 | [3] Non Session Management (NSM) (legacy) 89 | http://non.tuxfamily.org/nsm/ 90 | New Session Manager (NSM) 91 | https://new-session-manager.jackaudio.org/ 92 | 93 | [4] LV2, Audio Plugin Standard, the extensible successor of LADSPA 94 | http://lv2plug.in/ 95 | 96 | [5] Linux Audio consortium of libre software for audio-related work 97 | https://linuxaudio.org 98 | 99 | [6] GNU General Public License 100 | https://www.gnu.org/copyleft/gpl.html 101 | 102 | [7] Qt framework, C++ class library and tools for 103 | cross-platform application and UI development 104 | https://qt.io/ 105 | 106 | [8] liblo [8], Lightweight OSC implementation 107 | (needed for NSM support) 108 | http://liblo.sourceforge.net/ 109 | 110 | 111 | Cheers && Enjoy. 112 | -- 113 | rncbc aka. Rui Nuno Capela 114 | rncbc@rncbc.org 115 | https://www.rncbc.org 116 | -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | synthv1 (1.3.2-9.1) unstable; urgency=low 2 | 3 | * A Mid-Spring'25 Release. 4 | 5 | -- Rui Nuno Capela Tue, 20 May 2025 18:00:00 +0100 6 | 7 | synthv1 (1.3.1-8.1) unstable; urgency=low 8 | 9 | * An Early Spring'25 Release. 10 | 11 | -- Rui Nuno Capela Thu, 3 Apr 2025 18:00:00 +0100 12 | 13 | synthv1 (1.3.0-7.1) unstable; urgency=low 14 | 15 | * A New-Year'25 Release. 16 | 17 | -- Rui Nuno Capela Thu, 16 Jan 2025 18:00:00 +0000 18 | 19 | synthv1 (1.2.0-6.1) unstable; urgency=low 20 | 21 | * An End-of-Year'24 release. 22 | 23 | -- Rui Nuno Capela Sun, 15 Dec 2024 12:00:00 +0000 24 | 25 | synthv1 (1.1.3-5.1) unstable; urgency=low 26 | 27 | * A Halloween'24 release. 28 | 29 | -- Rui Nuno Capela Thu, 31 Oct 2024 20:00:00 +0000 30 | 31 | synthv1 (1.1.2-4.1) unstable; urgency=low 32 | 33 | * An Early-Fall'24 release. 34 | 35 | -- Rui Nuno Capela Wed, 2 oct 2024 18:00:00 +0100 36 | 37 | synthv1 (1.1.1-3.1) unstable; urgency=low 38 | 39 | * An End-of-Summer'24 release. 40 | 41 | -- Rui Nuno Capela Fri, 20 Sep 2024 18:00:00 +0100 42 | 43 | synthv1 (1.1.0-2.1) unstable; urgency=low 44 | 45 | * A Mid-Summer'24 release. 46 | 47 | -- Rui Nuno Capela Wed, 28 Aug 2024 18:00:00 +0100 48 | 49 | synthv1 (1.0.0-1.1) unstable; urgency=low 50 | 51 | * An Unthinkable release. 52 | 53 | -- Rui Nuno Capela Thu, 20 Jun 2024 18:00:00 +0100 54 | -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 11 2 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: synthv1 2 | Section: sound 3 | Priority: optional 4 | Maintainer: Rui Nuno Capela 5 | Build-Depends: debhelper (>= 11), cmake, pkg-config, 6 | qtbase6.9-static (>= 6.9), qttools6.9-static (>= 6.9), 7 | qtsvg6.9-static (>= 6.9), qttranslations6.9-static (>= 6.9), 8 | libjack-dev | libjack-jackd2-dev, libasound2-dev, 9 | lv2-dev, liblo-dev 10 | Standards-Version: 4.6.2 11 | Rules-Requires-Root: no 12 | 13 | Package: synthv1-jack 14 | Architecture: any 15 | Depends: ${shlibs:Depends}, ${misc:Depends}, libjack0 | libjack-jackd2-0 16 | Replaces: synthv1-common (<= ${source:Version}), synthv1 (<= ${source:Version}) 17 | Description: An old-school polyphonic subtractive synthesizer - JACK standalone 18 | An old-school all-digital 4-oscillator subtractive polyphonic synthesizer 19 | with stereo fx. 20 | . 21 | This package provides the standalone JACK client application (synthv1_jack) 22 | 23 | Package: synthv1-lv2 24 | Architecture: any 25 | Depends: ${shlibs:Depends}, ${misc:Depends} 26 | Replaces: synthv1-common (<= ${source:Version}) 27 | Description: An old-school polyphonic subtractive synthesizer - LV2 plugin 28 | An old-school all-digital 4-oscillator subtractive polyphonic synthesizer 29 | with stereo fx. 30 | . 31 | This package provides the LV2 plugin (http://synthv1.sourceforge.net/lv2) 32 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: synthv1 3 | Upstream-Contact: Rui Nuno Capela 4 | Source: https://synthv1.sourceforge.io 5 | 6 | Files: * 7 | Copyright: 2012-2025 Rui Nuno Capela 8 | License: GPL-2+ 9 | This package is free software; you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License as published by 11 | the Free Software Foundation; either version 2 of the License, or (at 12 | your option) any later version. 13 | . 14 | This package is distributed in the hope that it will be useful, but 15 | WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | General Public License for more details. 18 | . 19 | On Debian systems, the complete text of the GNU General Public 20 | License can be found in /usr/share/common-licenses/GPL-2. 21 | 22 | Files: src/appdata/* 23 | Copyright: 2012-2025 Rui Nuno Capela 24 | License: FSFAP 25 | Copying and distribution of this file, with or without modification, 26 | are permitted in any medium without royalty provided the copyright 27 | notice and this notice are preserved. This file is offered as-is, 28 | without any warranty. 29 | -------------------------------------------------------------------------------- /debian/docs: -------------------------------------------------------------------------------- 1 | README 2 | ChangeLog 3 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | # 3 | QTDIR ?= /opt/qt6.9-static 4 | 5 | %: 6 | dh $@ 7 | 8 | override_dh_auto_configure: 9 | # Add here commands to configure the package. 10 | cmake -DCMAKE_INSTALL_PREFIX=/usr \ 11 | -DCMAKE_INSTALL_LIBDIR=lib \ 12 | -DCMAKE_PREFIX_PATH=$(QTDIR) . 13 | # --- end custom part for configure 14 | -------------------------------------------------------------------------------- /debian/synthv1-jack.docs: -------------------------------------------------------------------------------- 1 | README 2 | LICENSE 3 | ChangeLog 4 | -------------------------------------------------------------------------------- /debian/synthv1-jack.install: -------------------------------------------------------------------------------- 1 | debian/tmp/usr/bin/synthv1_jack 2 | debian/tmp/usr/share/metainfo/org.rncbc.synthv1.metainfo.xml 3 | debian/tmp/usr/share/applications/org.rncbc.synthv1.desktop 4 | debian/tmp/usr/share/mime/packages/org.rncbc.synthv1.xml 5 | debian/tmp/usr/share/icons/hicolor/32x32/apps/org.rncbc.synthv1.png 6 | debian/tmp/usr/share/icons/hicolor/32x32/mimetypes/org.rncbc.synthv1.application-x-synthv1*.png 7 | debian/tmp/usr/share/icons/hicolor/scalable/apps/org.rncbc.synthv1.svg 8 | debian/tmp/usr/share/icons/hicolor/scalable/mimetypes/org.rncbc.synthv1.application-x-synthv1*.svg 9 | debian/tmp/usr/share/man/man1/synthv1*.* 10 | debian/tmp/usr/share/synthv1/palette/*.conf 11 | -------------------------------------------------------------------------------- /debian/synthv1-lv2.install: -------------------------------------------------------------------------------- 1 | debian/tmp/usr/lib*/lv2/synthv1.lv2/manifest.ttl 2 | debian/tmp/usr/lib*/lv2/synthv1.lv2/synthv1.ttl 3 | debian/tmp/usr/lib*/lv2/synthv1.lv2/synthv1.so 4 | debian/tmp/usr/lib*/lv2/synthv1.lv2/synthv1_ui.ttl 5 | -------------------------------------------------------------------------------- /rpm/synthv1.spec: -------------------------------------------------------------------------------- 1 | # 2 | # spec file for package synthv1 3 | # 4 | # Copyright (C) 2012-2025, rncbc aka Rui Nuno Capela. All rights reserved. 5 | # 6 | # All modifications and additions to the file contributed by third parties 7 | # remain the property of their copyright owners, unless otherwise agreed 8 | # upon. The license for this file, and modifications and additions to the 9 | # file, is the same license as for the pristine package itself (unless the 10 | # license for the pristine package is not an Open Source License, in which 11 | # case the license is the MIT License). An "Open Source License" is a 12 | # license that conforms to the Open Source Definition (Version 1.9) 13 | # published by the Open Source Initiative. 14 | 15 | # Please submit bugfixes or comments via http://bugs.opensuse.org/ 16 | # 17 | 18 | Summary: An old-school polyphonic subtractive synthesizer 19 | Name: synthv1 20 | Version: 1.3.2 21 | Release: 9.1 22 | License: GPL-2.0-or-later 23 | Group: Productivity/Multimedia/Sound/Midi 24 | Source: %{name}-%{version}.tar.gz 25 | URL: http://synthv1.sourceforge.net 26 | #Packager: rncbc.org 27 | 28 | %if 0%{?fedora_version} >= 34 || 0%{?suse_version} > 1500 || ( 0%{?sle_version} >= 150200 && 0%{?is_opensuse} ) 29 | %define qt_major_version 6 30 | %else 31 | %define qt_major_version 5 32 | %endif 33 | 34 | %if %{defined fedora} 35 | %global debug_package %{nil} 36 | %endif 37 | 38 | BuildRequires: coreutils 39 | BuildRequires: pkgconfig 40 | BuildRequires: glibc-devel 41 | BuildRequires: cmake >= 3.15 42 | %if 0%{?sle_version} >= 150200 && 0%{?is_opensuse} 43 | BuildRequires: gcc10 >= 10 44 | BuildRequires: gcc10-c++ >= 10 45 | %define _GCC /usr/bin/gcc-10 46 | %define _GXX /usr/bin/g++-10 47 | %else 48 | BuildRequires: gcc >= 10 49 | BuildRequires: gcc-c++ >= 10 50 | %define _GCC /usr/bin/gcc 51 | %define _GXX /usr/bin/g++ 52 | %endif 53 | %if 0%{qt_major_version} == 6 54 | BuildRequires: qtbase6.9-static >= 6.9 55 | BuildRequires: qttools6.9-static 56 | BuildRequires: qttranslations6.9-static 57 | BuildRequires: qtsvg6.9-static 58 | %else 59 | BuildRequires: pkgconfig(Qt5Core) 60 | BuildRequires: pkgconfig(Qt5Gui) 61 | BuildRequires: pkgconfig(Qt5Widgets) 62 | BuildRequires: pkgconfig(Qt5Svg) 63 | BuildRequires: pkgconfig(Qt5Xml) 64 | %endif 65 | %if %{defined fedora} 66 | BuildRequires: jack-audio-connection-kit-devel 67 | %else 68 | BuildRequires: pkgconfig(jack) 69 | %endif 70 | BuildRequires: pkgconfig(alsa) 71 | 72 | BuildRequires: pkgconfig(liblo) 73 | BuildRequires: pkgconfig(lv2) 74 | 75 | BuildRequires: pkgconfig(egl) 76 | 77 | %description 78 | An old-school all-digital 4-oscillator subtractive polyphonic synthesizer 79 | with stereo fx. 80 | 81 | 82 | %package -n %{name}-jack 83 | Summary: An old-school polyphonic subtractive synthesizer - JACK standalone 84 | Provides: %{name}_jack 85 | Obsoletes: %{name}-common <= %{version}, %{name} <= %{version} 86 | 87 | %description -n %{name}-jack 88 | An old-school all-digital 4-oscillator subtractive polyphonic synthesizer 89 | with stereo fx. 90 | 91 | This package provides the standalone JACK client application (synthv1_jack) 92 | 93 | 94 | %package -n %{name}-lv2 95 | Summary: An old-school polyphonic subtractive synthesizer - LV2 plugin 96 | Provides: %{name}_lv2, %{name}_lv2ui 97 | Obsoletes: %{name}-common <= %{version} 98 | 99 | %description -n %{name}-lv2 100 | An old-school all-digital 4-oscillator subtractive polyphonic synthesizer 101 | with stereo fx. 102 | 103 | This package provides the LV2 plugin (http://synthv1.sourceforge.net/lv2) 104 | 105 | 106 | %prep 107 | %setup -q 108 | 109 | %build 110 | %if 0%{qt_major_version} == 6 111 | source /opt/qt6.9-static/bin/qt6.9-static-env.sh 112 | %endif 113 | CXX=%{_GXX} CC=%{_GCC} \ 114 | cmake -DCMAKE_INSTALL_PREFIX=%{_prefix} -Wno-dev -B build 115 | cmake --build build %{?_smp_mflags} 116 | 117 | %install 118 | DESTDIR="%{buildroot}" \ 119 | cmake --install build 120 | 121 | 122 | %files -n %{name}-jack 123 | %license LICENSE 124 | %doc README ChangeLog 125 | #dir %{_datadir}/applications 126 | %dir %{_datadir}/metainfo 127 | #dir %{_datadir}/mime 128 | #dir %{_datadir}/mime/packages 129 | %dir %{_datadir}/icons/hicolor 130 | %dir %{_datadir}/icons/hicolor/32x32 131 | %dir %{_datadir}/icons/hicolor/32x32/apps 132 | %dir %{_datadir}/icons/hicolor/32x32/mimetypes 133 | %dir %{_datadir}/icons/hicolor/scalable 134 | %dir %{_datadir}/icons/hicolor/scalable/apps 135 | %dir %{_datadir}/icons/hicolor/scalable/mimetypes 136 | #dir %{_datadir}/man 137 | #dir %{_datadir}/man/man1 138 | #dir %{_datadir}/man/fr 139 | #dir %{_datadir}/man/fr/man1 140 | %dir %{_datadir}/%{name} 141 | %dir %{_datadir}/%{name}/palette 142 | %{_bindir}/%{name}_jack 143 | %{_datadir}/metainfo/org.rncbc.%{name}.metainfo.xml 144 | %{_datadir}/applications/org.rncbc.%{name}.desktop 145 | %{_datadir}/mime/packages/org.rncbc.%{name}.xml 146 | %{_datadir}/icons/hicolor/32x32/apps/org.rncbc.%{name}.png 147 | %{_datadir}/icons/hicolor/scalable/apps/org.rncbc.%{name}.svg 148 | %{_datadir}/icons/hicolor/32x32/mimetypes/org.rncbc.%{name}.application-x-%{name}*.png 149 | %{_datadir}/icons/hicolor/scalable/mimetypes/org.rncbc.%{name}.application-x-%{name}*.svg 150 | %{_datadir}/man/man1/%{name}.1.gz 151 | %{_datadir}/man/fr/man1/%{name}.1.gz 152 | %{_datadir}/%{name}/palette/*.conf 153 | 154 | %files -n %{name}-lv2 155 | %dir %{_libdir}/lv2 156 | %dir %{_libdir}/lv2/%{name}.lv2 157 | %{_libdir}/lv2/%{name}.lv2/manifest.ttl 158 | %{_libdir}/lv2/%{name}.lv2/%{name}.ttl 159 | %{_libdir}/lv2/%{name}.lv2/%{name}.so 160 | %{_libdir}/lv2/%{name}.lv2/%{name}_ui.ttl 161 | 162 | 163 | %changelog 164 | * Tue May 20 2025 Rui Nuno Capela 1.3.2 165 | - A Mid-Spring'25 Release. 166 | * Thu Apr 3 2025 Rui Nuno Capela 1.3.1 167 | - An Early Spring'25 Release. 168 | * Thu Jan 16 2025 Rui Nuno Capela 1.3.0 169 | - A New-Year'25 Release. 170 | * Sun Dec 15 2024 Rui Nuno Capela 1.2.0 171 | - An End-of-Year'24 Release. 172 | * Thu Oct 31 2024 Rui Nuno Capela 1.1.3 173 | - A Halloween'24 Release. 174 | * Wed Oct 2 2024 Rui Nuno Capela 1.1.2 175 | - An Early-Fall'24 Release. 176 | * Fri Sep 20 2024 Rui Nuno Capela 1.1.1 177 | - An End-of-Summer'24 Release. 178 | * Wed Aug 28 2024 Rui Nuno Capela 1.1.0 179 | - A Mid-Summer'24 Release. 180 | * Thu Jun 20 2024 Rui Nuno Capela 1.0.0 181 | - An Unthinkable Release. 182 | -------------------------------------------------------------------------------- /src/appdata/org.rncbc.synthv1.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=synthv1 3 | Version=1.0 4 | GenericName=MIDI 5 | Comment=synthv1 is an old school polyphonic synthesizer 6 | Comment[fr]=synthv1 est un synthétiseur polyphonique à l'ancienne 7 | Exec=synthv1_jack %f 8 | Icon=org.rncbc.synthv1 9 | Categories=Audio;AudioVideo;Midi;X-Alsa;X-Jack;Qt; 10 | MimeType=application/x-synthv1-preset; 11 | Keywords=Audio;MIDI;ALSA;JACK;Synthesizer;LV2;Qt; 12 | Terminal=false 13 | Type=Application 14 | StartupWMClass=synthv1_jack 15 | X-Window-Icon=synthv1 16 | X-SuSE-translate=true 17 | X-NSM-Capable=true 18 | X-NSM-Exec=synthv1_jack 19 | -------------------------------------------------------------------------------- /src/appdata/org.rncbc.synthv1.metainfo.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | org.rncbc.synthv1 5 | FSFAP 6 | GPL-2.0+ 7 | synthv1 8 | an old-school polyphonic synthesizer 9 | 10 |

synthv1 is an old-school 4-oscillator subtractive polyphonic synthesizer 11 | with stereo fx.

12 |

features:

    13 |
  • pure stand-alone JACK client with JACK-session, NSM and both JACK MIDI 14 | and ALSA MIDI input support;
  • 15 |
  • LV2 instrument plugin. 16 | URI: http\://synthv1.sourceforge.net/lv2
  • 17 |

18 |
19 | org.rncbc.synthv1.desktop 20 | 21 | synthv1_jack 22 | 23 | 24 | 25 | https://synthv1.sourceforge.io/image/synthv1-screenshot9.png 26 | The main window showing the application in action 27 | 28 | 29 | 30 | Audio 31 | MIDI 32 | ALSA 33 | JACK 34 | Synthesizer 35 | LV2 36 | Qt 37 | 38 | https://synthv1.sourceforge.io 39 | rncbc.org 40 | rncbc aka. Rui Nuno Capela 41 | rncbc@rncbc.org 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 |
52 | -------------------------------------------------------------------------------- /src/config.h.cmake: -------------------------------------------------------------------------------- 1 | #ifndef CONFIG_H 2 | #define CONFIG_H 3 | 4 | /* Define to the name of this package. */ 5 | #cmakedefine PROJECT_NAME "@PROJECT_NAME@" 6 | 7 | /* Define to the version of this package. */ 8 | #cmakedefine PROJECT_VERSION "@PROJECT_VERSION@" 9 | 10 | /* Define to the description of this package. */ 11 | #cmakedefine PROJECT_DESCRIPTION "@PROJECT_DESCRIPTION@" 12 | 13 | /* Define to the homepage of this package. */ 14 | #cmakedefine PROJECT_HOMEPAGE_URL "@PROJECT_HOMEPAGE_URL@" 15 | 16 | /* Define to the copyright of this package. */ 17 | #cmakedefine PROJECT_COPYRIGHT "@PROJECT_COPYRIGHT@" 18 | 19 | /* Define to the domain of this package. */ 20 | #cmakedefine PROJECT_DOMAIN "@PROJECT_DOMAIN@" 21 | 22 | 23 | /* Default installation prefix. */ 24 | #cmakedefine CONFIG_PREFIX "@CONFIG_PREFIX@" 25 | 26 | /* Define to target installation dirs. */ 27 | #cmakedefine CONFIG_BINDIR "@CONFIG_BINDIR@" 28 | #cmakedefine CONFIG_LIBDIR "@CONFIG_LIBDIR@" 29 | #cmakedefine CONFIG_DATADIR "@CONFIG_DATADIR@" 30 | #cmakedefine CONFIG_MANDIR "@CONFIG_MANDIR@" 31 | 32 | /* Define if debugging is enabled. */ 33 | #cmakedefine CONFIG_DEBUG @CONFIG_DEBUG@ 34 | 35 | /* Define to 1 if you have the header file. */ 36 | #cmakedefine HAVE_SIGNAL_H @HAVE_SIGNAL_H@ 37 | 38 | /* Define if JACK library is available. */ 39 | #cmakedefine CONFIG_JACK @CONFIG_JACK@ 40 | 41 | /* Define if ALSA MIDI support is enabled. */ 42 | #cmakedefine CONFIG_ALSA_MIDI @CONFIG_ALSA_MIDI@ 43 | 44 | /* Define if LIBLO library is available. */ 45 | #cmakedefine CONFIG_LIBLO @CONFIG_LIBLO@ 46 | 47 | /* Define if JACK session support is available. */ 48 | #cmakedefine CONFIG_JACK_SESSION @CONFIG_JACK_SESSION@ 49 | 50 | /* Define if JACK MIDI support is enabled. */ 51 | #cmakedefine CONFIG_JACK_MIDI @CONFIG_JACK_MIDI@ 52 | 53 | /* Define if LV2 plug-in build is enabled. */ 54 | #cmakedefine CONFIG_LV2 @CONFIG_LV2@ 55 | 56 | /* Define if LV2 old headers are enabled. */ 57 | #cmakedefine CONFIG_LV2_OLD_HEADERS @CONFIG_LV2_OLD_HEADERS@ 58 | 59 | /* Define if lv2_atom_forge_object is available. */ 60 | #cmakedefine CONFIG_LV2_ATOM_FORGE_OBJECT @CONFIG_LV2_ATOM_FORGE_OBJECT@ 61 | 62 | /* Define if lv2_atom_forge_key is available. */ 63 | #cmakedefine CONFIG_LV2_ATOM_FORGE_KEY @CONFIG_LV2_ATOM_FORGE_KEY@ 64 | 65 | /* Define if LV2 X11 UI support is available. */ 66 | #cmakedefine CONFIG_LV2_UI_X11 @CONFIG_LV2_UI_X11@ 67 | 68 | /* Define if LV2 Windows UI support is available. */ 69 | #cmakedefine CONFIG_LV2_UI_WINDOWS @CONFIG_LV2_UI_WINDOWS@ 70 | 71 | /* Define if LV2 External UI extension is available. */ 72 | #cmakedefine CONFIG_LV2_UI_EXTERNAL @CONFIG_LV2_UI_EXTERNAL@ 73 | 74 | /* Define if LV2 UI Idle interface support is available. */ 75 | #cmakedefine CONFIG_LV2_UI_IDLE @CONFIG_LV2_UI_IDLE@ 76 | 77 | /* Define if LV2 UI Show interface support is available. */ 78 | #cmakedefine CONFIG_LV2_UI_SHOW @CONFIG_LV2_UI_SHOW@ 79 | 80 | /* Define if LV2 UI Resize interface support is available. */ 81 | #cmakedefine CONFIG_LV2_UI_RESIZE @CONFIG_LV2_UI_RESIZE@ 82 | 83 | /* Define if LV2 Programs extension is available. */ 84 | #cmakedefine CONFIG_LV2_PROGRAMS @CONFIG_LV2_PROGRAMS@ 85 | 86 | /* Define if LV2 Patch is supported. */ 87 | #cmakedefine CONFIG_LV2_PATCH @CONFIG_LV2_PATCH@ 88 | 89 | /* Define if LV2 Port-event is supported. */ 90 | #cmakedefine CONFIG_LV2_PORT_EVENT @CONFIG_LV2_PORT_EVENT@ 91 | 92 | /* Define if LV2 Port-change request is supported. */ 93 | #cmakedefine CONFIG_LV2_PORT_CHANGE_REQUEST @CONFIG_LV2_PORT_CHANGE_REQUEST@ 94 | 95 | /* Define if NSM support is available. */ 96 | #cmakedefine CONFIG_NSM @CONFIG_NSM@ 97 | 98 | /* Define if Wayland is supported */ 99 | #cmakedefine CONFIG_WAYLAND @CONFIG_WAYLAND@ 100 | 101 | 102 | #endif /* CONFIG_H */ 103 | -------------------------------------------------------------------------------- /src/images/fileOpen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rncbc/synthv1/0545b01a1945bc24d50bc5c325567353ee6fed67/src/images/fileOpen.png -------------------------------------------------------------------------------- /src/images/itemReset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rncbc/synthv1/0545b01a1945bc24d50bc5c325567353ee6fed67/src/images/itemReset.png -------------------------------------------------------------------------------- /src/images/ledOff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rncbc/synthv1/0545b01a1945bc24d50bc5c325567353ee6fed67/src/images/ledOff.png -------------------------------------------------------------------------------- /src/images/ledOn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rncbc/synthv1/0545b01a1945bc24d50bc5c325567353ee6fed67/src/images/ledOn.png -------------------------------------------------------------------------------- /src/images/presetBank.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rncbc/synthv1/0545b01a1945bc24d50bc5c325567353ee6fed67/src/images/presetBank.png -------------------------------------------------------------------------------- /src/images/presetBankOpen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rncbc/synthv1/0545b01a1945bc24d50bc5c325567353ee6fed67/src/images/presetBankOpen.png -------------------------------------------------------------------------------- /src/images/presetDelete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rncbc/synthv1/0545b01a1945bc24d50bc5c325567353ee6fed67/src/images/presetDelete.png -------------------------------------------------------------------------------- /src/images/presetEdit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rncbc/synthv1/0545b01a1945bc24d50bc5c325567353ee6fed67/src/images/presetEdit.png -------------------------------------------------------------------------------- /src/images/presetNew.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rncbc/synthv1/0545b01a1945bc24d50bc5c325567353ee6fed67/src/images/presetNew.png -------------------------------------------------------------------------------- /src/images/presetOpen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rncbc/synthv1/0545b01a1945bc24d50bc5c325567353ee6fed67/src/images/presetOpen.png -------------------------------------------------------------------------------- /src/images/presetSave.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rncbc/synthv1/0545b01a1945bc24d50bc5c325567353ee6fed67/src/images/presetSave.png -------------------------------------------------------------------------------- /src/images/synthv1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rncbc/synthv1/0545b01a1945bc24d50bc5c325567353ee6fed67/src/images/synthv1.png -------------------------------------------------------------------------------- /src/images/synthv1_control.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rncbc/synthv1/0545b01a1945bc24d50bc5c325567353ee6fed67/src/images/synthv1_control.png -------------------------------------------------------------------------------- /src/images/synthv1_preset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rncbc/synthv1/0545b01a1945bc24d50bc5c325567353ee6fed67/src/images/synthv1_preset.png -------------------------------------------------------------------------------- /src/lv2/lv2_external_ui.h: -------------------------------------------------------------------------------- 1 | /* 2 | LV2 External UI extension 3 | This work is in public domain. 4 | 5 | This file is distributed in the hope that it will be useful, 6 | but WITHOUT ANY WARRANTY; without even the implied warranty of 7 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 8 | 9 | If you have questions, contact Filipe Coelho (aka falkTX) 10 | or ask in #lad channel, FreeNode IRC network. 11 | */ 12 | 13 | /** 14 | @file lv2_external_ui.h 15 | C header for the LV2 External UI extension . 16 | */ 17 | 18 | #ifndef LV2_EXTERNAL_UI_H 19 | #define LV2_EXTERNAL_UI_H 20 | 21 | #ifdef CONFIG_LV2_OLD_HEADERS 22 | #include "lv2/lv2plug.in/ns/extensions/ui/ui.h" 23 | #else 24 | #include "lv2/ui/ui.h" 25 | #endif 26 | 27 | #define LV2_EXTERNAL_UI_URI "http://kxstudio.sf.net/ns/lv2ext/external-ui" 28 | #define LV2_EXTERNAL_UI_PREFIX LV2_EXTERNAL_UI_URI "#" 29 | 30 | #define LV2_EXTERNAL_UI__Host LV2_EXTERNAL_UI_PREFIX "Host" 31 | #define LV2_EXTERNAL_UI__Widget LV2_EXTERNAL_UI_PREFIX "Widget" 32 | 33 | /** This extension used to be defined by a lv2plug.in URI */ 34 | #define LV2_EXTERNAL_UI_DEPRECATED_URI "http://lv2plug.in/ns/extensions/ui#external" 35 | 36 | #ifdef __cplusplus 37 | extern "C" { 38 | #endif 39 | 40 | /** 41 | * When LV2_EXTERNAL_UI__Widget UI is instantiated, the returned 42 | * LV2UI_Widget handle must be cast to pointer to LV2_External_UI_Widget. 43 | * UI is created in invisible state. 44 | */ 45 | typedef struct _LV2_External_UI_Widget { 46 | /** 47 | * Host calls this function regulary. UI library implementing the 48 | * callback may do IPC or redraw the UI. 49 | * 50 | * @param _this_ the UI context 51 | */ 52 | void (*run)(struct _LV2_External_UI_Widget * _this_); 53 | 54 | /** 55 | * Host calls this function to make the plugin UI visible. 56 | * 57 | * @param _this_ the UI context 58 | */ 59 | void (*show)(struct _LV2_External_UI_Widget * _this_); 60 | 61 | /** 62 | * Host calls this function to make the plugin UI invisible again. 63 | * 64 | * @param _this_ the UI context 65 | */ 66 | void (*hide)(struct _LV2_External_UI_Widget * _this_); 67 | 68 | } LV2_External_UI_Widget; 69 | 70 | #define LV2_EXTERNAL_UI_RUN(ptr) (ptr)->run(ptr) 71 | #define LV2_EXTERNAL_UI_SHOW(ptr) (ptr)->show(ptr) 72 | #define LV2_EXTERNAL_UI_HIDE(ptr) (ptr)->hide(ptr) 73 | 74 | /** 75 | * On UI instantiation, host must supply LV2_EXTERNAL_UI__Host feature. 76 | * LV2_Feature::data must be pointer to LV2_External_UI_Host. 77 | */ 78 | typedef struct _LV2_External_UI_Host { 79 | /** 80 | * Callback that plugin UI will call when UI (GUI window) is closed by user. 81 | * This callback will be called during execution of LV2_External_UI_Widget::run() 82 | * (i.e. not from background thread). 83 | * 84 | * After this callback is called, UI is defunct. Host must call LV2UI_Descriptor::cleanup(). 85 | * If host wants to make the UI visible again, the UI must be reinstantiated. 86 | * 87 | * @note When using the depreated URI LV2_EXTERNAL_UI_DEPRECATED_URI, 88 | * some hosts will not call LV2UI_Descriptor::cleanup() as they should, 89 | * and may call show() again without re-initialization. 90 | * 91 | * @param controller Host context associated with plugin UI, as 92 | * supplied to LV2UI_Descriptor::instantiate(). 93 | */ 94 | void (*ui_closed)(LV2UI_Controller controller); 95 | 96 | /** 97 | * Optional (may be NULL) "user friendly" identifier which the UI 98 | * may display to allow a user to easily associate this particular 99 | * UI instance with the correct plugin instance as it is represented 100 | * by the host (e.g. "track 1" or "channel 4"). 101 | * 102 | * If supplied by host, the string will be referenced only during 103 | * LV2UI_Descriptor::instantiate() 104 | */ 105 | const char * plugin_human_id; 106 | 107 | } LV2_External_UI_Host; 108 | 109 | #ifdef __cplusplus 110 | } /* extern "C" */ 111 | #endif 112 | 113 | #endif /* LV2_EXTERNAL_UI_H */ 114 | -------------------------------------------------------------------------------- /src/lv2/lv2_port_change_request.h: -------------------------------------------------------------------------------- 1 | /* 2 | LV2 ControlInputPort change request extension 3 | Copyright 2020 Filipe Coelho 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any 6 | purpose with or without fee is hereby granted, provided that the above 7 | copyright notice and this permission notice appear in all copies. 8 | 9 | THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | */ 17 | 18 | /** 19 | @file control-input-port-change-request.h 20 | C header for the LV2 ControlInputPort change request extension . 21 | */ 22 | 23 | #ifndef LV2_CONTROL_INPUT_PORT_CHANGE_REQUEST_H 24 | #define LV2_CONTROL_INPUT_PORT_CHANGE_REQUEST_H 25 | 26 | #if CONFIG_LV2_OLD_HEADERS 27 | #include "lv2.h" 28 | #else 29 | #include "lv2/core/lv2.h" 30 | #endif 31 | 32 | #define LV2_CONTROL_INPUT_PORT_CHANGE_REQUEST_URI "http://kx.studio/ns/lv2ext/control-input-port-change-request" 33 | #define LV2_CONTROL_INPUT_PORT_CHANGE_REQUEST_PREFIX LV2_CONTROL_INPUT_PORT_CHANGE_REQUEST_URI "#" 34 | 35 | #include 36 | 37 | #ifdef __cplusplus 38 | extern "C" { 39 | #else 40 | #include 41 | #endif 42 | 43 | /** A status code for LV2_CONTROL_INPUT_PORT_CHANGE_REQUEST_URI functions. */ 44 | typedef enum { 45 | LV2_CONTROL_INPUT_PORT_CHANGE_SUCCESS = 0, /**< Completed successfully. */ 46 | LV2_CONTROL_INPUT_PORT_CHANGE_ERR_UNKNOWN = 1, /**< Unknown error. */ 47 | LV2_CONTROL_INPUT_PORT_CHANGE_ERR_INVALID_INDEX = 2 /**< Failed due to invalid port index. */ 48 | } LV2_ControlInputPort_Change_Status; 49 | 50 | /** 51 | * Opaque handle for LV2_CONTROL_INPUT_PORT_CHANGE_REQUEST_URI feature. 52 | */ 53 | typedef void* LV2_ControlInputPort_Change_Request_Handle; 54 | 55 | /** 56 | * On instantiation, host must supply LV2_CONTROL_INPUT_PORT_CHANGE_REQUEST_URI feature. 57 | * LV2_Feature::data must be pointer to LV2_ControlInputPort_Change_Request. 58 | */ 59 | typedef struct _LV2_ControlInputPort_Change_Request { 60 | /** 61 | * Opaque host data. 62 | */ 63 | LV2_ControlInputPort_Change_Request_Handle handle; 64 | 65 | /** 66 | * request_change() 67 | * 68 | * Ask the host to change a plugin's control input port value. 69 | * Parameter handle MUST be the 'handle' member of this struct. 70 | * Parameter index is port index to change. 71 | * Parameter value is the requested value to change the control port input to. 72 | * 73 | * Returns status of the request. 74 | * The host may decline this request, if e.g. it is currently automating this port. 75 | * 76 | * The plugin MUST call this function during run(). 77 | */ 78 | LV2_ControlInputPort_Change_Status (*request_change)(LV2_ControlInputPort_Change_Request_Handle handle, 79 | uint32_t index, 80 | float value); 81 | 82 | } LV2_ControlInputPort_Change_Request; 83 | 84 | #ifdef __cplusplus 85 | } /* extern "C" */ 86 | #endif 87 | 88 | #endif /* LV2_CONTROL_INPUT_PORT_CHANGE_REQUEST_H */ 89 | -------------------------------------------------------------------------------- /src/lv2/lv2_programs.h: -------------------------------------------------------------------------------- 1 | /* 2 | LV2 Programs Extension 3 | Copyright 2012 Filipe Coelho 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any 6 | purpose with or without fee is hereby granted, provided that the above 7 | copyright notice and this permission notice appear in all copies. 8 | 9 | THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | */ 17 | 18 | /** 19 | @file lv2_programs.h 20 | C header for the LV2 programs extension . 21 | */ 22 | 23 | #ifndef LV2_PROGRAMS_H 24 | #define LV2_PROGRAMS_H 25 | 26 | #ifdef CONFIG_LV2_OLD_HEADERS 27 | #include "lv2.h" 28 | #include "lv2/lv2plug.in/ns/extensions/ui/ui.h" 29 | #else 30 | #include "lv2/core/lv2.h" 31 | #include "lv2//ui/ui.h" 32 | #endif 33 | 34 | #define LV2_PROGRAMS_URI "http://kxstudio.sf.net/ns/lv2ext/programs" 35 | #define LV2_PROGRAMS_PREFIX LV2_PROGRAMS_URI "#" 36 | 37 | #define LV2_PROGRAMS__Host LV2_PROGRAMS_PREFIX "Host" 38 | #define LV2_PROGRAMS__Interface LV2_PROGRAMS_PREFIX "Interface" 39 | #define LV2_PROGRAMS__UIInterface LV2_PROGRAMS_PREFIX "UIInterface" 40 | 41 | #ifdef __cplusplus 42 | extern "C" { 43 | #endif 44 | 45 | typedef void* LV2_Programs_Handle; 46 | 47 | typedef struct _LV2_Program_Descriptor { 48 | 49 | /** Bank number for this program. Note that this extension does not 50 | support MIDI-style separation of bank LSB and MSB values. There is 51 | no restriction on the set of available banks: the numbers do not 52 | need to be contiguous, there does not need to be a bank 0, etc. */ 53 | uint32_t bank; 54 | 55 | /** Program number (unique within its bank) for this program. There is 56 | no restriction on the set of available programs: the numbers do not 57 | need to be contiguous, there does not need to be a program 0, etc. */ 58 | uint32_t program; 59 | 60 | /** Name of the program. */ 61 | const char * name; 62 | 63 | } LV2_Program_Descriptor; 64 | 65 | /** 66 | Programs extension, plugin data. 67 | 68 | When the plugin's extension_data is called with argument LV2_PROGRAMS__Interface, 69 | the plugin MUST return an LV2_Programs_Instance structure, which remains valid 70 | for the lifetime of the plugin. 71 | */ 72 | typedef struct _LV2_Programs_Interface { 73 | /** 74 | * get_program() 75 | * 76 | * This member is a function pointer that provides a description 77 | * of a program (named preset sound) available on this plugin. 78 | * 79 | * The index argument is an index into the plugin's list of 80 | * programs, not a program number as represented by the Program 81 | * field of the LV2_Program_Descriptor. (This distinction is 82 | * needed to support plugins that use non-contiguous program or 83 | * bank numbers.) 84 | * 85 | * This function returns a LV2_Program_Descriptor pointer that is 86 | * guaranteed to be valid only until the next call to get_program 87 | * or deactivate, on the same plugin instance. This function must 88 | * return NULL if passed an index argument out of range, so that 89 | * the host can use it to query the number of programs as well as 90 | * their properties. 91 | */ 92 | const LV2_Program_Descriptor *(*get_program)(LV2_Handle handle, 93 | uint32_t index); 94 | 95 | /** 96 | * select_program() 97 | * 98 | * This member is a function pointer that selects a new program 99 | * for this plugin. The program change should take effect 100 | * immediately at the start of the next run() call. (This 101 | * means that a host providing the capability of changing programs 102 | * between any two notes on a track must vary the block size so as 103 | * to place the program change at the right place. A host that 104 | * wanted to avoid this would probably just instantiate a plugin 105 | * for each program.) 106 | * 107 | * Plugins should ignore a select_program() call with an invalid 108 | * bank or program. 109 | * 110 | * A plugin is not required to select any particular default 111 | * program on activate(): it's the host's duty to set a program 112 | * explicitly. 113 | * 114 | * A plugin is permitted to re-write the values of its input 115 | * control ports when select_program is called. The host should 116 | * re-read the input control port values and update its own 117 | * records appropriately. (This is the only circumstance in which 118 | * a LV2 plugin is allowed to modify its own control-input ports.) 119 | */ 120 | void (*select_program)(LV2_Handle handle, 121 | uint32_t bank, 122 | uint32_t program); 123 | 124 | } LV2_Programs_Interface; 125 | 126 | /** 127 | Programs extension, UI data. 128 | 129 | When the UI's extension_data is called with argument LV2_PROGRAMS__UIInterface, 130 | the UI MUST return an LV2_Programs_UI_Interface structure, which remains valid 131 | for the lifetime of the UI. 132 | */ 133 | typedef struct _LV2_Programs_UI_Interface { 134 | /** 135 | * select_program() 136 | * 137 | * This is exactly the same as select_program in LV2_Programs_Instance, 138 | * but this struct relates to the UI instead of the plugin. 139 | * 140 | * When called, UIs should update their state to match the selected program. 141 | */ 142 | void (*select_program)(LV2UI_Handle handle, 143 | uint32_t bank, 144 | uint32_t program); 145 | 146 | } LV2_Programs_UI_Interface; 147 | 148 | /** 149 | Feature data for LV2_PROGRAMS__Host. 150 | */ 151 | typedef struct _LV2_Programs_Host { 152 | /** 153 | * Opaque host data. 154 | */ 155 | LV2_Programs_Handle handle; 156 | 157 | /** 158 | * program_changed() 159 | * 160 | * Tell the host to reload a plugin's program. 161 | * Parameter handle MUST be the 'handle' member of this struct. 162 | * Parameter index is program index to change. 163 | * When index is -1, host should reload all the programs. 164 | * 165 | * The plugin MUST NEVER call this function on a RT context or during run(). 166 | * 167 | * NOTE: This call is to inform the host about a program's bank, program or name change. 168 | * It DOES NOT change the current selected program. 169 | */ 170 | void (*program_changed)(LV2_Programs_Handle handle, 171 | int32_t index); 172 | 173 | } LV2_Programs_Host; 174 | 175 | #ifdef __cplusplus 176 | } /* extern "C" */ 177 | #endif 178 | 179 | #endif /* LV2_PROGRAMS_H */ 180 | -------------------------------------------------------------------------------- /src/man1/synthv1.1: -------------------------------------------------------------------------------- 1 | .TH SYNTHV1 "1" "August 31, 2020" 2 | .SH NAME 3 | synthv1 \- an old-school polyphonic synthesizer 4 | .SH SYNOPSIS 5 | .B synthv1_jack 6 | [\fIoptions\fR] [\fIpreset-file\fR] 7 | .SH DESCRIPTION 8 | This manual page documents briefly the 9 | .B synthv1_jack 10 | command. 11 | .PP 12 | \fBsynthv1\fP is an old-school 4-oscillator subtractive 13 | polyphonic synthesizer with stereo fx. 14 | .PP 15 | features: 16 | .IP 17 | a pure stand-alone JACK client with JACK-session, 18 | NSM and both JACK MIDI and ALSA MIDI input support; 19 | .IP 20 | a LV2 instrument plugin. 21 | URI: http://synthv1.sourceforge.net/lv2 22 | .SH OPTIONS 23 | .HP 24 | \fB\-g\fR, \fB\-\-no\-gui\fR 25 | .IP 26 | Disable the graphical user interface (GUI) 27 | .HP 28 | \fB\-n\fR, \fB\-\-client\-name\fR=[\fIlabel\fR] 29 | .IP 30 | Set the JACK client name (default: synthv1) 31 | .HP 32 | \fB\-h\fR, \fB\-\-help\fR 33 | .IP 34 | Show help about command line options 35 | .HP 36 | \fB\-v\fR, \fB\-\-version\fR 37 | .IP 38 | Show version information 39 | .SH FILES 40 | Configuration settings are stored in ~/.config/rncbc.org/synthv1.conf 41 | .SH AUTHOR 42 | synthv1 was written by Rui Nuno Capela. 43 | -------------------------------------------------------------------------------- /src/man1/synthv1.fr.1: -------------------------------------------------------------------------------- 1 | .TH SYNTHV1 "1" "Juin 17, 2014" 2 | .SH NOM 3 | synthv1 \- un synthétiseur polyphonique à l'ancienne 4 | .SH SYNOPSIS 5 | .B synthv1_jack 6 | [\fIoptions\fR] [\fIfichier-de-pré-réglage\fR] 7 | .SH DESCRIPTION 8 | Cette page de manuel documente rapidement la commande 9 | .B synthv1_jack 10 | . 11 | .PP 12 | \fBsynthv1\fP est un synthétiseur polyphonique soustractif 4-oscillateurs à 13 | l'ancienne, avec des effets stéréo. 14 | .PP 15 | fonctionnalités : 16 | .IP 17 | un client JACK autonome pur avec JACK-session, NSM, et un support d'entrée 18 | JACK MIDI ainsi que ALSA MIDI; 19 | .IP 20 | un greffon d'instrument LV2. 21 | URI : http://synthv1.sourceforge.net/lv2 22 | .SH OPTIONS 23 | .HP 24 | \fB\-g\fR, \fB\-\-no\-gui\fR 25 | .IP 26 | Désactive l'interface graphique utilisateur 27 | .HP 28 | \fB\-h\fR, \fB\-\-help\fR 29 | .IP 30 | Affiche de l'aide à propos des options de ligne de commande 31 | .HP 32 | \fB\-v\fR, \fB\-\-version\fR 33 | .IP 34 | Affiche des informations de version 35 | .SH FICHIERS 36 | Les paramètres de configuration sont stockés dans ~/.config/rncbc.org/synthv1.conf 37 | .SH AUTEUR 38 | synthv1 a été écrit par Rui Nuno Capela. 39 | .PP 40 | La version française de cette page de manuel a été traduite par Olivier Humbert 41 | , pour le projet LibraZiK (mais peut être utilisée par 42 | d'autres). 43 | -------------------------------------------------------------------------------- /src/mimetypes/org.rncbc.synthv1.application-x-synthv1-preset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rncbc/synthv1/0545b01a1945bc24d50bc5c325567353ee6fed67/src/mimetypes/org.rncbc.synthv1.application-x-synthv1-preset.png -------------------------------------------------------------------------------- /src/mimetypes/org.rncbc.synthv1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | synthv1 preset 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/palette/KXStudio.conf: -------------------------------------------------------------------------------- 1 | [ColorThemes] 2 | KXStudio\AlternateBase=#0e0e0e, #0e0e0e, #0c0c0c 3 | KXStudio\Base=#070707, #070707, #060606 4 | KXStudio\BrightText=#ffffff, #ffffff, #ffffff 5 | KXStudio\Button=#1c1c1c, #1c1c1c, #181818 6 | KXStudio\ButtonText=#f0f0f0, #f0f0f0, #5a5a5a 7 | KXStudio\Dark=#818181, #818181, #818181 8 | KXStudio\Highlight=#3c3c3c, #222222, #0e0e0e 9 | KXStudio\HighlightedText=#ffffff, #f0f0f0, #535353 10 | KXStudio\Light=#bfbfbf, #bfbfbf, #bfbfbf 11 | KXStudio\Link=#6464e6, #6464e6, #22224a 12 | KXStudio\LinkVisited=#e664e6, #e664e6, #4a224a 13 | KXStudio\Mid=#5e5e5e, #5e5e5e, #5e5e5e 14 | KXStudio\Midlight=#9b9b9b, #9b9b9b, #9b9b9b 15 | KXStudio\NoRole=#000000, #000000, #000000 16 | KXStudio\PlaceholderText=#000000, #000000, #000000 17 | KXStudio\Shadow=#9b9b9b, #9b9b9b, #9b9b9b 18 | KXStudio\Text=#e6e6e6, #e6e6e6, #4a4a4a 19 | KXStudio\ToolTipBase=#040404, #040404, #040404 20 | KXStudio\ToolTipText=#e6e6e6, #e6e6e6, #e6e6e6 21 | KXStudio\Window=#111111, #111111, #0e0e0e 22 | KXStudio\WindowText=#f0f0f0, #f0f0f0, #535353 23 | -------------------------------------------------------------------------------- /src/palette/Wonton Soup.conf: -------------------------------------------------------------------------------- 1 | [ColorThemes] 2 | Wonton%20Soup\AlternateBase=#434750, #434750, #3b3e46 3 | Wonton%20Soup\Base=#3c4048, #3c4048, #34383f 4 | Wonton%20Soup\BrightText=#ffffff, #ffffff, #ffffff 5 | Wonton%20Soup\Button=#525863, #525863, #484d57 6 | Wonton%20Soup\ButtonText=#d2def0, #d2def0, #6f7682 7 | Wonton%20Soup\Dark=#282b31, #282b31, #23262b 8 | Wonton%20Soup\Highlight=#78889c, #515a67, #40444d 9 | Wonton%20Soup\HighlightedText=#d1e1f4, #b6c1d0, #616872 10 | Wonton%20Soup\Light=#5f6572, #5f6572, #565c68 11 | Wonton%20Soup\Link=#9cd4ff, #9cd4ff, #526677 12 | Wonton%20Soup\LinkVisited=#4080ff, #4080ff, #364c77 13 | Wonton%20Soup\Mid=#3f444c, #3f444c, #383b43 14 | Wonton%20Soup\Midlight=#545a65, #545a65, #4b515b 15 | Wonton%20Soup\NoRole=#000000, #000000, #000000 16 | Wonton%20Soup\PlaceholderText=#000000, #000000, #000000 17 | Wonton%20Soup\Shadow=#1d1f23, #1d1f23, #191b1e 18 | Wonton%20Soup\Text=#d2def0, #d2def0, #636973 19 | Wonton%20Soup\ToolTipBase=#b6c1d0, #b6c1d0, #b6c1d0 20 | Wonton%20Soup\ToolTipText=#2a2c30, #2a2c30, #2a2c30 21 | Wonton%20Soup\Window=#494e58, #494e58, #40444d 22 | Wonton%20Soup\WindowText=#b6c1d0, #b6c1d0, #616872 23 | -------------------------------------------------------------------------------- /src/synthv1.h: -------------------------------------------------------------------------------- 1 | // synthv1.h 2 | // 3 | /**************************************************************************** 4 | Copyright (C) 2012-2024, rncbc aka Rui Nuno Capela. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | *****************************************************************************/ 21 | 22 | #ifndef __synthv1_h 23 | #define __synthv1_h 24 | 25 | #include "config.h" 26 | 27 | #include 28 | 29 | 30 | // forward declarations 31 | class synthv1_impl; 32 | class synthv1_port; 33 | class synthv1_controls; 34 | class synthv1_programs; 35 | 36 | 37 | //------------------------------------------------------------------------- 38 | // synthv1 - decl. 39 | // 40 | 41 | class synthv1 42 | { 43 | public: 44 | 45 | synthv1(uint16_t nchannels = 2, float srate = 44100.0f, uint32_t nsize = 1024); 46 | 47 | virtual ~synthv1(); 48 | 49 | void setChannels(uint16_t nchannels); 50 | uint16_t channels() const; 51 | 52 | void setSampleRate(float srate); 53 | float sampleRate() const; 54 | 55 | void setBufferSize(uint32_t nsize); 56 | uint32_t bufferSize() const; 57 | 58 | void setTempo(float bpm); 59 | float tempo() const; 60 | 61 | enum ParamIndex { 62 | 63 | DCO1_SHAPE1 = 0, 64 | DCO1_WIDTH1, 65 | DCO1_BANDL1, 66 | DCO1_SYNC1, 67 | DCO1_SHAPE2, 68 | DCO1_WIDTH2, 69 | DCO1_BANDL2, 70 | DCO1_SYNC2, 71 | DCO1_BALANCE, 72 | DCO1_DETUNE, 73 | DCO1_PHASE, 74 | DCO1_RINGMOD, 75 | DCO1_OCTAVE, 76 | DCO1_TUNING, 77 | DCO1_GLIDE, 78 | DCO1_ENVTIME, 79 | DCF1_ENABLED, 80 | DCF1_CUTOFF, 81 | DCF1_RESO, 82 | DCF1_TYPE, 83 | DCF1_SLOPE, 84 | DCF1_ENVELOPE, 85 | DCF1_ATTACK, 86 | DCF1_DECAY, 87 | DCF1_SUSTAIN, 88 | DCF1_RELEASE, 89 | LFO1_ENABLED, 90 | LFO1_SHAPE, 91 | LFO1_WIDTH, 92 | LFO1_BPM, 93 | LFO1_RATE, 94 | LFO1_SYNC, 95 | LFO1_SWEEP, 96 | LFO1_PITCH, 97 | LFO1_BALANCE, 98 | LFO1_RINGMOD, 99 | LFO1_CUTOFF, 100 | LFO1_RESO, 101 | LFO1_PANNING, 102 | LFO1_VOLUME, 103 | LFO1_ATTACK, 104 | LFO1_DECAY, 105 | LFO1_SUSTAIN, 106 | LFO1_RELEASE, 107 | DCA1_VOLUME, 108 | DCA1_ATTACK, 109 | DCA1_DECAY, 110 | DCA1_SUSTAIN, 111 | DCA1_RELEASE, 112 | OUT1_WIDTH, 113 | OUT1_PANNING, 114 | OUT1_FXSEND, 115 | OUT1_VOLUME, 116 | 117 | DEF1_PITCHBEND, 118 | DEF1_MODWHEEL, 119 | DEF1_PRESSURE, 120 | DEF1_VELOCITY, 121 | DEF1_CHANNEL, 122 | DEF1_MONO, 123 | 124 | DCO2_SHAPE1, 125 | DCO2_WIDTH1, 126 | DCO2_BANDL1, 127 | DCO2_SYNC1, 128 | DCO2_SHAPE2, 129 | DCO2_WIDTH2, 130 | DCO2_BANDL2, 131 | DCO2_SYNC2, 132 | DCO2_BALANCE, 133 | DCO2_DETUNE, 134 | DCO2_PHASE, 135 | DCO2_RINGMOD, 136 | DCO2_OCTAVE, 137 | DCO2_TUNING, 138 | DCO2_GLIDE, 139 | DCO2_ENVTIME, 140 | DCF2_ENABLED, 141 | DCF2_CUTOFF, 142 | DCF2_RESO, 143 | DCF2_TYPE, 144 | DCF2_SLOPE, 145 | DCF2_ENVELOPE, 146 | DCF2_ATTACK, 147 | DCF2_DECAY, 148 | DCF2_SUSTAIN, 149 | DCF2_RELEASE, 150 | LFO2_ENABLED, 151 | LFO2_SHAPE, 152 | LFO2_WIDTH, 153 | LFO2_BPM, 154 | LFO2_RATE, 155 | LFO2_SYNC, 156 | LFO2_SWEEP, 157 | LFO2_PITCH, 158 | LFO2_BALANCE, 159 | LFO2_RINGMOD, 160 | LFO2_CUTOFF, 161 | LFO2_RESO, 162 | LFO2_PANNING, 163 | LFO2_VOLUME, 164 | LFO2_ATTACK, 165 | LFO2_DECAY, 166 | LFO2_SUSTAIN, 167 | LFO2_RELEASE, 168 | DCA2_VOLUME, 169 | DCA2_ATTACK, 170 | DCA2_DECAY, 171 | DCA2_SUSTAIN, 172 | DCA2_RELEASE, 173 | OUT2_WIDTH, 174 | OUT2_PANNING, 175 | OUT2_FXSEND, 176 | OUT2_VOLUME, 177 | 178 | DEF2_PITCHBEND, 179 | DEF2_MODWHEEL, 180 | DEF2_PRESSURE, 181 | DEF2_VELOCITY, 182 | DEF2_CHANNEL, 183 | DEF2_MONO, 184 | 185 | CHO1_WET, 186 | CHO1_DELAY, 187 | CHO1_FEEDB, 188 | CHO1_RATE, 189 | CHO1_MOD, 190 | FLA1_WET, 191 | FLA1_DELAY, 192 | FLA1_FEEDB, 193 | FLA1_DAFT, 194 | PHA1_WET, 195 | PHA1_RATE, 196 | PHA1_FEEDB, 197 | PHA1_DEPTH, 198 | PHA1_DAFT, 199 | DEL1_WET, 200 | DEL1_DELAY, 201 | DEL1_FEEDB, 202 | DEL1_BPM, 203 | REV1_WET, 204 | REV1_ROOM, 205 | REV1_DAMP, 206 | REV1_FEEDB, 207 | REV1_WIDTH, 208 | DYN1_COMPRESS, 209 | DYN1_LIMITER, 210 | 211 | KEY1_LOW, 212 | KEY1_HIGH, 213 | 214 | NUM_PARAMS 215 | }; 216 | 217 | void setParamPort(ParamIndex index, float *pfParam); 218 | synthv1_port *paramPort(ParamIndex index) const; 219 | 220 | synthv1_controls *controls() const; 221 | synthv1_programs *programs() const; 222 | 223 | void setParamValue(ParamIndex index, float fValue); 224 | float paramValue(ParamIndex index) const; 225 | 226 | bool running(bool on); 227 | 228 | void stabilize(); 229 | void reset(); 230 | 231 | void process_midi(uint8_t *data, uint32_t size); 232 | void process(float **ins, float **outs, uint32_t nframes); 233 | 234 | virtual void updatePreset(bool bDirty) = 0; 235 | virtual void updateParam(ParamIndex index) = 0; 236 | virtual void updateParams() = 0; 237 | 238 | void midiInEnabled(bool on); 239 | uint32_t midiInCount(); 240 | 241 | void directNoteOn(int note, int vel); 242 | 243 | void setTuningEnabled(bool enabled); 244 | bool isTuningEnabled() const; 245 | 246 | void setTuningRefPitch(float refPitch); 247 | float tuningRefPitch() const; 248 | 249 | void setTuningRefNote(int refNote); 250 | int tuningRefNote() const; 251 | 252 | void setTuningScaleFile(const char *pszScaleFile); 253 | const char *tuningScaleFile() const; 254 | 255 | void setTuningKeyMapFile(const char *pszKeyMapFile); 256 | const char *tuningKeyMapFile() const; 257 | 258 | void resetTuning(); 259 | 260 | virtual void updateTuning() = 0; 261 | 262 | private: 263 | 264 | synthv1_impl *m_pImpl; 265 | }; 266 | 267 | 268 | #endif// __synthv1_h 269 | 270 | // end of synthv1.h 271 | -------------------------------------------------------------------------------- /src/synthv1.lv2/manifest-win32.ttl: -------------------------------------------------------------------------------- 1 | @prefix lv2: . 2 | @prefix rdfs: . 3 | 4 | 5 | a lv2:Plugin, lv2:InstrumentPlugin ; 6 | lv2:binary ; 7 | rdfs:seeAlso , . 8 | -------------------------------------------------------------------------------- /src/synthv1.lv2/manifest.ttl: -------------------------------------------------------------------------------- 1 | @prefix lv2: . 2 | @prefix rdfs: . 3 | 4 | 5 | a lv2:Plugin, lv2:InstrumentPlugin ; 6 | lv2:binary ; 7 | rdfs:seeAlso , . 8 | -------------------------------------------------------------------------------- /src/synthv1.lv2/synthv1_ui-win32.ttl: -------------------------------------------------------------------------------- 1 | @prefix lv2: . 2 | @prefix lv2ui: . 3 | 4 | @prefix synthv1_lv2: . 5 | 6 | 7 | lv2ui:ui synthv1_lv2:ui_windows, synthv1_lv2:ui_external . 8 | 9 | 10 | a lv2ui:Qt6UI ; 11 | lv2:requiredFeature ; 12 | lv2ui:binary . 13 | 14 | 15 | a lv2ui:WindowsUI ; 16 | lv2:requiredFeature ; 17 | lv2:optionalFeature lv2ui:resize, lv2ui:idleInterface, lv2ui:showInterface ; 18 | lv2:extensionData lv2ui:resize, lv2ui:idleInterface, lv2ui:showInterface ; 19 | lv2ui:binary . 20 | 21 | 22 | a ; 23 | lv2:requiredFeature ; 24 | lv2ui:binary . 25 | -------------------------------------------------------------------------------- /src/synthv1.lv2/synthv1_ui.ttl: -------------------------------------------------------------------------------- 1 | @prefix lv2: . 2 | @prefix lv2ui: . 3 | 4 | @prefix synthv1_lv2: . 5 | 6 | 7 | lv2ui:ui synthv1_lv2:ui_x11, synthv1_lv2:ui_external . 8 | 9 | 10 | a lv2ui:Qt6UI ; 11 | lv2:requiredFeature ; 12 | lv2ui:binary . 13 | 14 | 15 | a lv2ui:X11UI ; 16 | lv2:requiredFeature ; 17 | lv2:optionalFeature lv2ui:resize, lv2ui:idleInterface, lv2ui:showInterface ; 18 | lv2:extensionData lv2ui:resize, lv2ui:idleInterface, lv2ui:showInterface ; 19 | lv2ui:binary . 20 | 21 | 22 | a ; 23 | lv2:requiredFeature ; 24 | lv2ui:binary . 25 | -------------------------------------------------------------------------------- /src/synthv1.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | images/synthv1.png 4 | images/synthv1.svg 5 | images/ledOn.png 6 | images/ledOff.png 7 | images/presetNew.png 8 | images/presetOpen.png 9 | images/presetSave.png 10 | images/presetDelete.png 11 | images/presetBank.png 12 | images/presetBankOpen.png 13 | images/presetEdit.png 14 | images/itemReset.png 15 | images/fileOpen.png 16 | images/synthv1_preset.png 17 | images/synthv1_control.png 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/synthv1_config.h: -------------------------------------------------------------------------------- 1 | // synthv1_config.h 2 | // 3 | /**************************************************************************** 4 | Copyright (C) 2012-2024, rncbc aka Rui Nuno Capela. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | *****************************************************************************/ 21 | 22 | #ifndef __synthv1_config_h 23 | #define __synthv1_config_h 24 | 25 | #include "config.h" 26 | 27 | 28 | //------------------------------------------------------------------------- 29 | // synthv1_config - Prototype settings class (singleton). 30 | // 31 | 32 | #include 33 | #include 34 | 35 | // forward decls. 36 | class synthv1_programs; 37 | class synthv1_controls; 38 | 39 | 40 | class synthv1_config : public QSettings 41 | { 42 | public: 43 | 44 | // Constructor. 45 | synthv1_config(); 46 | 47 | // Default destructor. 48 | ~synthv1_config(); 49 | 50 | // Default options... 51 | QString sPreset; 52 | QString sPresetDir; 53 | 54 | // Knob behavior modes. 55 | int iKnobDialMode; 56 | int iKnobEditMode; 57 | 58 | // Default randomize factor (percent). 59 | float fRandomizePercent; 60 | 61 | // Special persistent options. 62 | bool bControlsEnabled; 63 | bool bProgramsEnabled; 64 | bool bProgramsPreview; 65 | bool bUseNativeDialogs; 66 | // Run-time special non-persistent options. 67 | bool bDontUseNativeDialogs; 68 | 69 | // Custom color palette/widget style themes. 70 | QString sCustomColorTheme; 71 | QString sCustomStyleTheme; 72 | 73 | // Micro-tuning options. 74 | bool bTuningEnabled; 75 | float fTuningRefPitch; 76 | int iTuningRefNote; 77 | QString sTuningScaleDir; 78 | QString sTuningScaleFile; 79 | QString sTuningKeyMapDir; 80 | QString sTuningKeyMapFile; 81 | 82 | // Singleton instance accessor. 83 | static synthv1_config *getInstance(); 84 | 85 | // Preset utility methods. 86 | QString presetFile(const QString& sPreset); 87 | void setPresetFile(const QString& sPreset, const QString& sPresetFile); 88 | void removePreset(const QString& sPreset); 89 | const QStringList& presetList(); 90 | 91 | // Programs utility methods. 92 | void loadPrograms(synthv1_programs *pPrograms); 93 | void savePrograms(synthv1_programs *pPrograms); 94 | 95 | // Controllers utility methods. 96 | void loadControls(synthv1_controls *pControls); 97 | void saveControls(synthv1_controls *pControls); 98 | 99 | protected: 100 | 101 | // Preset group path. 102 | QString presetGroup() const; 103 | 104 | // Banks programs group path. 105 | QString programsGroup() const; 106 | QString bankPrefix() const; 107 | 108 | void clearPrograms(); 109 | 110 | // Controllers group path. 111 | QString controlsGroup() const; 112 | QString controlPrefix() const; 113 | 114 | void clearControls(); 115 | 116 | // Explicit I/O methods. 117 | void load(); 118 | void save(); 119 | 120 | private: 121 | 122 | // The presets list cache. 123 | QStringList m_presetList; 124 | 125 | // The singleton instance. 126 | static synthv1_config *g_pSettings; 127 | }; 128 | 129 | 130 | #endif // __synthv1_config_h 131 | 132 | // end of synthv1_config.h 133 | 134 | -------------------------------------------------------------------------------- /src/synthv1_controls.h: -------------------------------------------------------------------------------- 1 | // synthv1_controls.h 2 | // 3 | /**************************************************************************** 4 | Copyright (C) 2012-2024, rncbc aka Rui Nuno Capela. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | *****************************************************************************/ 21 | 22 | #ifndef __synthv1_controls_h 23 | #define __synthv1_controls_h 24 | 25 | #include "synthv1_param.h" 26 | #include "synthv1_sched.h" 27 | 28 | #include 29 | 30 | 31 | //------------------------------------------------------------------------- 32 | // synthv1_controls - Controller processs class. 33 | // 34 | 35 | class synthv1_controls 36 | { 37 | public: 38 | 39 | // ctor. 40 | synthv1_controls(synthv1 *pSynth); 41 | 42 | // dtor. 43 | ~synthv1_controls(); 44 | 45 | // operational mode flags. 46 | void enabled(bool on) 47 | { m_enabled = on; } 48 | bool enabled() const 49 | { return m_enabled; } 50 | 51 | // controller types, 52 | enum Type { None = 0, CC = 0x100, RPN = 0x200, NRPN = 0x300, CC14 = 0x400 }; 53 | 54 | // controller hash key. 55 | struct Key 56 | { 57 | Key () : status(0), param(0) {} 58 | Key (const Key& key) 59 | : status(key.status), param(key.param) {} 60 | 61 | Type type() const 62 | { return Type(status & 0xf00); } 63 | unsigned short channel() const 64 | { return (status & 0x1f); } 65 | 66 | // hash key comparator. 67 | bool operator< (const Key& key) const 68 | { 69 | if (status != key.status) 70 | return (status < key.status); 71 | else 72 | return (param < key.param); 73 | } 74 | 75 | // copy assignment operator. 76 | Key& operator= (const Key& key) 77 | { 78 | if (this != &key) { 79 | status = key.status; 80 | param = key.param; 81 | } 82 | return *this; 83 | } 84 | 85 | unsigned short status; 86 | unsigned short param; 87 | }; 88 | 89 | // controller flags, 90 | enum Flag { Logarithmic = 1, Invert = 2, Hook = 4 }; 91 | 92 | // controller data. 93 | struct Data 94 | { 95 | Data () : index(-1), flags(0), val(0.0f), sync(false) {} 96 | 97 | int index; 98 | int flags; 99 | float val; 100 | bool sync; 101 | }; 102 | 103 | typedef QMap Map; 104 | 105 | // controller events. 106 | struct Event 107 | { 108 | Key key; 109 | unsigned short value; 110 | }; 111 | 112 | // controller map methods. 113 | const Map& map() const { return m_map; } 114 | 115 | int find_control(const Key& key) const 116 | { return m_map.value(key).index; } 117 | void add_control(const Key& key, const Data& data) 118 | { m_map.insert(key, data); } 119 | void remove_control(const Key& key) 120 | { m_map.remove(key); } 121 | 122 | void clear() { m_map.clear(); } 123 | 124 | // reset all controllers. 125 | void reset(); 126 | 127 | // controller queue methods. 128 | void process_enqueue( 129 | unsigned short channel, 130 | unsigned short param, 131 | unsigned short value); 132 | 133 | void process_dequeue(); 134 | 135 | // process timer counter. 136 | void process(unsigned int nframes); 137 | 138 | // text utilities. 139 | static Type typeFromText(const QString& sText); 140 | static QString textFromType(Type ctype); 141 | 142 | // current/last controller accessor. 143 | const Key& current_key() const; 144 | 145 | protected: 146 | 147 | // controller action. 148 | void process_event(const Event& event); 149 | 150 | // input controller scheduled events (learn) 151 | class SchedIn : public synthv1_sched 152 | { 153 | public: 154 | 155 | // ctor. 156 | SchedIn (synthv1 *pSynth) 157 | : synthv1_sched(pSynth, Controller) {} 158 | 159 | void schedule_key(const Key& key) 160 | { m_key = key; schedule(); } 161 | 162 | // process (virtual stub). 163 | void process(int) {} 164 | 165 | // current controller accessor. 166 | const Key& current_key() const 167 | { return m_key; } 168 | 169 | private: 170 | 171 | // instance variables,. 172 | Key m_key; 173 | }; 174 | 175 | // output controller scheduled events (assignments) 176 | class SchedOut : public synthv1_sched 177 | { 178 | public: 179 | 180 | // ctor. 181 | SchedOut (synthv1 *pSynth) 182 | : synthv1_sched(pSynth, Controls), m_value(0.0f) {} 183 | 184 | void schedule_event(synthv1::ParamIndex index, float value) 185 | { 186 | if (qAbs(value - m_value) > 0.001f) { 187 | m_value = value; 188 | schedule(int(index)); 189 | } 190 | } 191 | 192 | // process (virtual stub). 193 | void process(int sid) 194 | { 195 | synthv1 *pSynth = instance(); 196 | synthv1::ParamIndex index = synthv1::ParamIndex(sid); 197 | pSynth->setParamValue(index, m_value); 198 | pSynth->updateParam(index); 199 | } 200 | 201 | private: 202 | 203 | // instance variables 204 | float m_value; 205 | }; 206 | 207 | private: 208 | 209 | // instance variables. 210 | class Impl; 211 | 212 | Impl *m_pImpl; 213 | 214 | // operational mode flags. 215 | bool m_enabled; 216 | 217 | // controller schedulers. 218 | SchedIn m_sched_in; 219 | SchedOut m_sched_out; 220 | 221 | // controllers map. 222 | Map m_map; 223 | 224 | // frame timers. 225 | unsigned int m_timeout; 226 | unsigned int m_timein; 227 | }; 228 | 229 | 230 | #endif // __synthv1_controls_h 231 | 232 | // end of synthv1_controls.h 233 | -------------------------------------------------------------------------------- /src/synthv1_filter.h: -------------------------------------------------------------------------------- 1 | // synthv1_filter.h 2 | // 3 | /**************************************************************************** 4 | Copyright (C) 2012-2021, rncbc aka Rui Nuno Capela. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | *****************************************************************************/ 21 | 22 | #ifndef __synthv1_filter_h 23 | #define __synthv1_filter_h 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | 30 | //------------------------------------------------------------------------- 31 | // synthv1_filter1 - Hal Chamberlin's State Variable (12dB/oct) filter 32 | // 33 | 34 | class synthv1_filter1 35 | { 36 | public: 37 | 38 | enum Type { Low = 0, Band, High, Notch }; 39 | 40 | synthv1_filter1(Type type = Low, uint16_t nover = 2) 41 | { reset(type, nover); } 42 | 43 | Type type() const 44 | { return m_type; } 45 | 46 | void reset(Type type = Low, uint16_t nover = 2) 47 | { 48 | m_type = type; 49 | m_nover = nover; 50 | 51 | m_low = 0.0f; 52 | m_band = 0.0f; 53 | m_high = 0.0f; 54 | m_notch = 0.0f; 55 | 56 | switch (m_type) { 57 | case Notch: 58 | m_out = &m_notch; 59 | break; 60 | case High: 61 | m_out = &m_high; 62 | break; 63 | case Band: 64 | m_out = &m_band; 65 | break; 66 | case Low: 67 | default: 68 | m_out = &m_low; 69 | break; 70 | } 71 | } 72 | 73 | float output(float in, float cutoff, float reso) 74 | { 75 | const float q = (1.0f - reso); 76 | 77 | for (uint16_t i = 0; i < m_nover; ++i) { 78 | m_low += cutoff * m_band; 79 | m_high = in - m_low - q * m_band; 80 | m_band += cutoff * m_high; 81 | m_notch = m_high + m_low; 82 | } 83 | 84 | return *m_out; 85 | } 86 | 87 | private: 88 | 89 | Type m_type; 90 | 91 | uint16_t m_nover; 92 | 93 | float m_low; 94 | float m_band; 95 | float m_high; 96 | float m_notch; 97 | 98 | float *m_out; 99 | }; 100 | 101 | 102 | //------------------------------------------------------------------------- 103 | // synthv1_filter2 - Stilson/Smith Moog (24dB/oct) filter 104 | // 105 | 106 | class synthv1_filter2 107 | { 108 | public: 109 | 110 | enum Type { Low = 0, Band, High, Notch }; 111 | 112 | synthv1_filter2(Type type = Low) { reset(type); } 113 | 114 | Type type() const 115 | { return m_type; } 116 | 117 | void reset(Type type = Low) 118 | { 119 | m_type = type; 120 | 121 | m_b0 = m_b1 = m_b2 = m_b3 = m_b4 = 0.0f; 122 | m_t1 = m_t2 = 0.0f; 123 | } 124 | 125 | float output(float in, float cutoff, float reso) 126 | { 127 | const float c = 1.0f - cutoff; 128 | const float p = cutoff + 0.8f * cutoff * c; 129 | const float f = p + p - 1.0f; 130 | const float q = reso * (1.0f + 0.5f * c * (1.0f - c + 5.6f * c * c)); 131 | 132 | in -= q * m_b4; // feedback 133 | 134 | m_t1 = m_b1; m_b1 = (in + m_b0) * p - m_b1 * f; 135 | m_t2 = m_b2; m_b2 = (m_b1 + m_t1) * p - m_b2 * f; 136 | m_t1 = m_b3; m_b3 = (m_b2 + m_t2) * p - m_b3 * f; 137 | 138 | m_b4 = (m_b3 + m_t1) * p - m_b4 * f; 139 | m_b4 = m_b4 - m_b4 * m_b4 * m_b4 * 0.166667f; // clipping 140 | 141 | m_b0 = in; 142 | 143 | switch (m_type) { 144 | case Notch: 145 | return 3.0f * (m_b3 - m_b4) - in; 146 | case High: 147 | return in - m_b4; 148 | case Band: 149 | return 3.0f * (m_b3 - m_b4); 150 | case Low: 151 | default: 152 | return m_b4; 153 | } 154 | } 155 | 156 | private: 157 | 158 | // filter type 159 | Type m_type; 160 | 161 | float m_b0, m_b1, m_b2, m_b3, m_b4; 162 | float m_t1, m_t2; 163 | }; 164 | 165 | 166 | //------------------------------------------------------------------------- 167 | // synthv1_filter3 - RBJ biquad filter implementation. 168 | // 169 | // http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt 170 | 171 | class synthv1_filter3 172 | { 173 | public: 174 | 175 | enum Type { Low = 0, Band, High, Notch }; 176 | 177 | synthv1_filter3(Type type = Low) 178 | : m_type(type), m_cutoff(0.5f), m_reso(0.0f) { reset(type); } 179 | 180 | Type type() const 181 | { return m_type; } 182 | 183 | void reset(Type type) 184 | { 185 | m_type = type; 186 | 187 | m_out1 = m_out2 = 0.0f; 188 | m_in1 = m_in2 = 0.0f; 189 | 190 | reset(); 191 | } 192 | 193 | float output(float in, float cutoff, float reso) 194 | { 195 | // parameter changes 196 | if (::fabsf(m_cutoff - cutoff) > 0.001f || 197 | ::fabsf(m_reso - reso) > 0.001f) { 198 | m_cutoff = cutoff; 199 | m_reso = reso; 200 | reset(); 201 | } 202 | 203 | // filter 204 | const float out = m_b0a0 * in 205 | + m_b1a0 * m_in1 + m_b2a0 * m_in2 206 | - m_a1a0 * m_out1 - m_a2a0 * m_out2; 207 | 208 | // push in/out buffers 209 | m_in2 = m_in1; 210 | m_in1 = in; 211 | m_out2 = m_out1; 212 | m_out1 = out; 213 | 214 | // return output 215 | return out; 216 | } 217 | 218 | protected: 219 | 220 | void reset() 221 | { 222 | const float q = 2.0f * m_reso * m_reso + 1.0f; 223 | 224 | const float omega = M_PI * m_cutoff; 225 | const float tsin = ::sinf(omega); 226 | const float tcos = ::cosf(omega); 227 | const float alpha = tsin / (2.0f * q); 228 | 229 | // temp vars 230 | const float a0 = 1.0f + alpha; 231 | const float a1 = -2.0f * tcos; 232 | const float a2 = 1.0f - alpha; 233 | 234 | float b0, b1, b2; 235 | 236 | switch (m_type) { 237 | case Notch: 238 | b0 = 1.0f; 239 | b1 = -2.0f * tcos; 240 | b2 = 1.0f; 241 | break; 242 | case High: 243 | b0 = (1.0f + tcos) / 2.0f; 244 | b1 = -1.0f - tcos; 245 | b2 = b0; 246 | break; 247 | case Band: 248 | b0 = tsin / 2.0f; 249 | b1 = 0.0f; 250 | b2 = -b0; 251 | break; 252 | case Low: 253 | default: 254 | b0 = (1.0f - tcos) / 2.0f; 255 | b1 = 1.0f - tcos; 256 | b2 = b0; 257 | break; 258 | } 259 | 260 | // set filter coeffs 261 | m_b0a0 = b0 / a0; 262 | m_b1a0 = b1 / a0; 263 | m_b2a0 = b2 / a0; 264 | m_a1a0 = a1 / a0; 265 | m_a2a0 = a2 / a0; 266 | } 267 | 268 | private: 269 | 270 | // filter type 271 | Type m_type; 272 | 273 | // filter params 274 | float m_cutoff; 275 | float m_reso; 276 | 277 | // filter coeffs 278 | float m_b0a0, m_b1a0, m_b2a0, m_a1a0, m_a2a0; 279 | 280 | // in/out history 281 | float m_out1, m_out2, m_in1, m_in2; 282 | }; 283 | 284 | 285 | #endif // __synthv1_filter_h 286 | 287 | 288 | // end of synthv1_filter.h 289 | -------------------------------------------------------------------------------- /src/synthv1_formant.h: -------------------------------------------------------------------------------- 1 | // synthv1_formant.h 2 | // 3 | /**************************************************************************** 4 | Copyright (C) 2012-2021, rncbc aka Rui Nuno Capela. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | *****************************************************************************/ 21 | 22 | #ifndef __synthv1_formant_h 23 | #define __synthv1_formant_h 24 | 25 | #include 26 | #include 27 | 28 | 29 | //--------------------------------------------------------------------- 30 | // synthv1_formant - formant parallel filter after Dennis H. Klatt's 31 | // Software for a cascade/parallel formant synthesizer 32 | // 1979 MIT; 1980 Acoustical Society of America. 33 | // 34 | 35 | class synthv1_formant 36 | { 37 | public: 38 | 39 | // constants 40 | static const uint32_t NUM_VTABS = 5; 41 | static const uint32_t NUM_VOWELS = 5; 42 | static const uint32_t NUM_FORMANTS = 5; 43 | static const uint32_t NUM_STEPS = 320; 44 | 45 | // 2-pole filter coeffs. 46 | struct Coeffs { float a0, b1, b2; }; 47 | 48 | // vocal/vowel table 49 | struct Vtab 50 | { 51 | float freq[NUM_FORMANTS]; // frequency [Hz] 52 | float gain[NUM_FORMANTS]; // peak gain [dB] 53 | float band[NUM_FORMANTS]; // bandwidth [Hz] 54 | }; 55 | 56 | // main impl. 57 | class Impl 58 | { 59 | public: 60 | 61 | // ctor. 62 | Impl(float srate = 44100.0f) 63 | : m_srate(srate) { reset_coeffs(); } 64 | 65 | // sample-rate accessors 66 | void setSampleRate(float srate) 67 | { m_srate = srate; reset_coeffs(); } 68 | float sampleRate() const 69 | { return m_srate; } 70 | 71 | // formant coeffs. accessor 72 | const Coeffs& coeffs(uint32_t i) const 73 | { return m_ctabs[i]; } 74 | 75 | // reset coeffs. method 76 | void reset_coeffs(float cutoff = 0.5f, float reso = 0.0f); 77 | 78 | protected: 79 | 80 | // compute coeffs. for given vocal formant table 81 | void vtab_coeffs(Coeffs& coeffs, const Vtab *vtab, uint32_t i, float p); 82 | 83 | private: 84 | 85 | // instance members 86 | float m_srate; 87 | 88 | // filter coeffs. 89 | Coeffs m_ctabs[NUM_FORMANTS]; 90 | }; 91 | 92 | // ctor. 93 | synthv1_formant(Impl *pImpl = 0) 94 | : m_pImpl(pImpl), m_cutoff(0.5f), m_reso(0.0f), m_nstep(0) 95 | { reset_coeffs(); } 96 | 97 | // reset impl. 98 | void reset(Impl *pImpl) 99 | { m_pImpl = pImpl; reset_coeffs(); } 100 | 101 | void reset_filters(float cutoff, float reso) 102 | { 103 | for (uint32_t i = 0; i < NUM_FORMANTS; ++i) 104 | m_filters[i].reset(); 105 | 106 | update(cutoff, reso); 107 | } 108 | 109 | // output tick 110 | float output(float in, float cutoff, float reso) 111 | { 112 | update(cutoff, reso); 113 | 114 | float out = 0.0f; 115 | for (uint32_t i = 0; i < NUM_FORMANTS; ++i) 116 | out += m_filters[i].output(in); 117 | return out; 118 | } 119 | 120 | // process block 121 | void process(float *in, uint32_t nframes, float wet, float cutoff, float reso) 122 | { 123 | for (uint32_t i = 0; i < nframes; ++i) { 124 | const float out = output(in[i], cutoff, reso); 125 | in[i] *= (1.0f - wet); 126 | in[i] += (wet * out); 127 | } 128 | } 129 | 130 | protected: 131 | 132 | // step-wise smoothed coeff. 133 | class Coeff 134 | { 135 | public: 136 | 137 | Coeff() { reset(); } 138 | 139 | void reset() 140 | { 141 | m_value = m_vstep = 0.0f; 142 | m_nstep = 0; 143 | } 144 | 145 | void set_value(float value) 146 | { 147 | m_nstep = NUM_STEPS; 148 | m_vstep = (value - m_value) / float(m_nstep); 149 | } 150 | 151 | float value() const 152 | { return m_value + m_vstep * float(m_nstep); } 153 | 154 | float tick() 155 | { 156 | if (m_nstep > 0) { 157 | m_value += m_vstep; 158 | --m_nstep; 159 | } 160 | return m_value; 161 | } 162 | 163 | private: 164 | 165 | float m_value; 166 | float m_vstep; 167 | uint32_t m_nstep; 168 | }; 169 | 170 | // 2-pole resonator filter 171 | class Filter 172 | { 173 | public: 174 | 175 | Filter() { reset(); } 176 | 177 | void reset() 178 | { 179 | m_a0.reset(); 180 | m_b1.reset(); 181 | m_b2.reset(); 182 | 183 | m_out1 = m_out2 = 0.0f; 184 | } 185 | 186 | void reset_coeffs(const Coeffs& coeffs) 187 | { 188 | m_a0.set_value(coeffs.a0); 189 | m_b1.set_value(coeffs.b1); 190 | m_b2.set_value(coeffs.b2); 191 | } 192 | 193 | float output(float in) 194 | { 195 | const float out 196 | = m_a0.tick() * in 197 | + m_b1.tick() * m_out1 198 | - m_b2.tick() * m_out2; 199 | 200 | m_out2 = m_out1; 201 | m_out1 = out; 202 | return out; 203 | } 204 | 205 | private: 206 | 207 | Coeff m_a0, m_b1, m_b2; 208 | float m_out1, m_out2; 209 | }; 210 | 211 | // update method 212 | void update(float cutoff, float reso) 213 | { 214 | if (m_nstep > 0) 215 | --m_nstep; 216 | else 217 | if (::fabsf(m_cutoff - cutoff) > 0.001f || 218 | ::fabsf(m_reso - reso) > 0.001f) { 219 | m_nstep = NUM_STEPS; 220 | m_cutoff = cutoff; 221 | m_reso = reso; 222 | reset_coeffs(); 223 | } 224 | } 225 | 226 | // reset coeffs. method 227 | void reset_coeffs(); 228 | 229 | private: 230 | 231 | // instance members 232 | Impl *m_pImpl; 233 | 234 | // parameters. 235 | float m_cutoff; 236 | float m_reso; 237 | 238 | // slew-rate control. 239 | uint32_t m_nstep; 240 | 241 | // formant filters 242 | Filter m_filters[NUM_FORMANTS]; 243 | 244 | // base vocal tables 245 | static Vtab g_bass_vtab[NUM_VOWELS]; 246 | static Vtab g_tenor_vtab[NUM_VOWELS]; 247 | static Vtab g_countertenor_vtab[NUM_VOWELS]; 248 | static Vtab g_soprano_vtab[NUM_VOWELS]; 249 | static Vtab g_alto_vtab[NUM_VOWELS]; 250 | 251 | static Vtab *g_vtabs[NUM_VTABS]; 252 | }; 253 | 254 | 255 | #endif // __synthv1_formant_h 256 | 257 | // end of synthv1_formant.h 258 | -------------------------------------------------------------------------------- /src/synthv1_jack.h: -------------------------------------------------------------------------------- 1 | // synthv1_jack.h 2 | // 3 | /**************************************************************************** 4 | Copyright (C) 2012-2025, rncbc aka Rui Nuno Capela. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | *****************************************************************************/ 21 | 22 | #ifndef __synthv1_jack_h 23 | #define __synthv1_jack_h 24 | 25 | #include "synthv1.h" 26 | 27 | #include 28 | 29 | 30 | #ifdef CONFIG_ALSA_MIDI 31 | #include 32 | #include 33 | // forward decls. 34 | class synthv1_alsa_thread; 35 | #endif 36 | 37 | 38 | //------------------------------------------------------------------------- 39 | // synthv1_jack - decl. 40 | // 41 | 42 | class synthv1_jack : public synthv1 43 | { 44 | public: 45 | 46 | synthv1_jack(const char *client_name); 47 | 48 | ~synthv1_jack(); 49 | 50 | jack_client_t *client() const; 51 | 52 | void open(const char *client_name); 53 | void close(); 54 | 55 | void activate(); 56 | void deactivate(); 57 | 58 | int process(jack_nframes_t nframes); 59 | 60 | #ifdef CONFIG_ALSA_MIDI 61 | snd_seq_t *alsa_seq() const; 62 | void alsa_capture(snd_seq_event_t *ev); 63 | #endif 64 | 65 | #ifdef CONFIG_JACK_SESSION 66 | // JACK session event handler. 67 | void sessionEvent(void *pvSessionArg); 68 | #endif 69 | 70 | void shutdown(); 71 | void shutdown_close(); 72 | 73 | protected: 74 | 75 | void updatePreset(bool bDirty); 76 | void updateParam(synthv1::ParamIndex index); 77 | void updateParams(); 78 | void updateTuning(); 79 | 80 | private: 81 | 82 | jack_client_t *m_client; 83 | 84 | volatile bool m_activated; 85 | 86 | jack_port_t **m_audio_ins; 87 | jack_port_t **m_audio_outs; 88 | 89 | float **m_ins; 90 | float **m_outs; 91 | 92 | float m_params[synthv1::NUM_PARAMS]; 93 | 94 | #ifdef CONFIG_JACK_MIDI 95 | jack_port_t *m_midi_in; 96 | #endif 97 | #ifdef CONFIG_ALSA_MIDI 98 | snd_seq_t *m_alsa_seq; 99 | // int m_alsa_client; 100 | int m_alsa_port; 101 | snd_midi_event_t *m_alsa_decoder; 102 | jack_ringbuffer_t *m_alsa_buffer; 103 | synthv1_alsa_thread *m_alsa_thread; 104 | #endif 105 | }; 106 | 107 | 108 | //------------------------------------------------------------------------- 109 | // synthv1_jack_application -- Singleton application instance. 110 | // 111 | 112 | #include 113 | #include 114 | 115 | 116 | // forward decls. 117 | class QCoreApplication; 118 | class synthv1widget_jack; 119 | 120 | #ifdef CONFIG_NSM 121 | class synthv1_nsm; 122 | #endif 123 | 124 | #ifdef HAVE_SIGNAL_H 125 | class QSocketNotifier; 126 | #endif 127 | 128 | class synthv1_jack_application : public QObject 129 | { 130 | Q_OBJECT 131 | 132 | public: 133 | 134 | // Constructor. 135 | synthv1_jack_application(int& argc, char **argv); 136 | 137 | // Destructor. 138 | ~synthv1_jack_application(); 139 | 140 | // Facade method. 141 | int exec(); 142 | 143 | // JACK shutdown handler. 144 | void shutdown(); 145 | 146 | // Pseudo-singleton accessor. 147 | static synthv1_jack_application *getInstance(); 148 | 149 | signals: 150 | 151 | void shutdown_signal(); 152 | 153 | protected slots: 154 | 155 | #ifdef CONFIG_NSM 156 | // NSM callback slots. 157 | void openSession(); 158 | void saveSession(); 159 | void hideSession(); 160 | void showSession(); 161 | #endif // CONFIG_NSM 162 | 163 | #ifdef HAVE_SIGNAL_H 164 | // SIGTERM signal handler. 165 | void handle_sigterm(); 166 | #endif 167 | 168 | void watchdog_slot(); 169 | void shutdown_slot(); 170 | 171 | protected: 172 | 173 | // Argument parser method. 174 | bool parse_args(); 175 | #if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0) 176 | void show_error(const QString& msg); 177 | #endif 178 | 179 | // Startup method. 180 | bool setup(); 181 | 182 | void watchdog_start(); 183 | 184 | private: 185 | 186 | // Instance variables. 187 | QCoreApplication *m_pApp; 188 | bool m_bGui; 189 | 190 | QString m_sClientName; 191 | QStringList m_presets; 192 | 193 | synthv1_jack *m_pSynth; 194 | synthv1widget_jack *m_pWidget; 195 | 196 | #ifdef CONFIG_NSM 197 | synthv1_nsm *m_pNsmClient; 198 | #endif 199 | 200 | #ifdef HAVE_SIGNAL_H 201 | QSocketNotifier *m_pSigtermNotifier; 202 | #endif 203 | 204 | static synthv1_jack_application *g_pInstance; 205 | }; 206 | 207 | 208 | #endif// __synthv1_jack_h 209 | 210 | // end of synthv1_jack.h 211 | 212 | -------------------------------------------------------------------------------- /src/synthv1_list.h: -------------------------------------------------------------------------------- 1 | // synthv1_list.h 2 | // 3 | /**************************************************************************** 4 | Copyright (C) 2012, rncbc aka Rui Nuno Capela. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | *****************************************************************************/ 21 | 22 | #ifndef __synthv1_list_h 23 | #define __synthv1_list_h 24 | 25 | 26 | //------------------------------------------------------------------------- 27 | // synthv1_list - generic double-linked list node. 28 | 29 | template 30 | class synthv1_list 31 | { 32 | public: 33 | 34 | synthv1_list() : m_prev(0), m_next(0) {} 35 | 36 | void append(T *p) 37 | { 38 | p->m_prev = m_prev; 39 | p->m_next = 0; 40 | 41 | if (m_prev) 42 | m_prev->m_next = p; 43 | else 44 | m_next = p; 45 | 46 | m_prev = p; 47 | } 48 | 49 | void remove(T *p) 50 | { 51 | if (p->m_prev) 52 | p->m_prev->m_next = p->m_next; 53 | else 54 | m_next = p->m_next; 55 | 56 | if (p->m_next) 57 | p->m_next->m_prev = p->m_prev; 58 | else 59 | m_prev = p->m_prev; 60 | } 61 | 62 | T *prev() const { return m_prev; } 63 | T *next() const { return m_next; } 64 | 65 | private: 66 | 67 | T *m_prev; 68 | T *m_next; 69 | }; 70 | 71 | 72 | #endif // __synthv1_list_h 73 | 74 | // end of synthv1_list.h 75 | -------------------------------------------------------------------------------- /src/synthv1_lv2.h: -------------------------------------------------------------------------------- 1 | // synthv1_lv2.h 2 | // 3 | /**************************************************************************** 4 | Copyright (C) 2012-2025, rncbc aka Rui Nuno Capela. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | *****************************************************************************/ 21 | 22 | #ifndef __synthv1_lv2_h 23 | #define __synthv1_lv2_h 24 | 25 | #include "synthv1.h" 26 | 27 | #ifdef CONFIG_LV2_OLD_HEADERS 28 | #include "lv2/lv2plug.in/ns/ext/urid/urid.h" 29 | #include "lv2/lv2plug.in/ns/ext/atom/atom.h" 30 | #include "lv2/lv2plug.in/ns/ext/atom/forge.h" 31 | #include "lv2/lv2plug.in/ns/ext/worker/worker.h" 32 | #else 33 | #include "lv2/urid/urid.h" 34 | #include "lv2/atom/atom.h" 35 | #include "lv2/atom/forge.h" 36 | #include "lv2/worker/worker.h" 37 | #endif 38 | 39 | 40 | #define SYNTHV1_LV2_URI "http://synthv1.sourceforge.net/lv2" 41 | #define SYNTHV1_LV2_PREFIX SYNTHV1_LV2_URI "#" 42 | 43 | 44 | #ifdef CONFIG_LV2_PROGRAMS 45 | #include "lv2_programs.h" 46 | #include 47 | #endif 48 | 49 | #ifdef CONFIG_LV2_PORT_CHANGE_REQUEST 50 | #include "lv2_port_change_request.h" 51 | #endif 52 | 53 | // Forward decls. 54 | class QApplication; 55 | 56 | 57 | //------------------------------------------------------------------------- 58 | // synthv1_lv2 - decl. 59 | // 60 | 61 | class synthv1_lv2 : public synthv1 62 | { 63 | public: 64 | 65 | synthv1_lv2(double sample_rate, const LV2_Feature *const *host_features); 66 | 67 | ~synthv1_lv2(); 68 | 69 | enum PortIndex { 70 | 71 | MidiIn = 0, 72 | Notify, 73 | AudioInL, 74 | AudioInR, 75 | AudioOutL, 76 | AudioOutR, 77 | ParamBase 78 | }; 79 | 80 | void connect_port(uint32_t port, void *data); 81 | 82 | void run(uint32_t nframes); 83 | 84 | void activate(); 85 | void deactivate(); 86 | 87 | uint32_t urid_map(const char *uri) const; 88 | 89 | #ifdef CONFIG_LV2_PROGRAMS 90 | const LV2_Program_Descriptor *get_program(uint32_t index); 91 | void select_program(uint32_t bank, uint32_t program); 92 | #endif 93 | 94 | bool worker_work(const void *data, uint32_t size); 95 | bool worker_response(const void *data, uint32_t size); 96 | 97 | static void qapp_instantiate(); 98 | static void qapp_cleanup(); 99 | 100 | static QApplication *qapp_instance(); 101 | 102 | protected: 103 | 104 | void updatePreset(bool bDirty); 105 | void updateParam(synthv1::ParamIndex index); 106 | void updateParams(); 107 | void updateTuning(); 108 | 109 | bool state_changed(); 110 | 111 | #ifdef CONFIG_LV2_PATCH 112 | bool patch_set(LV2_URID key); 113 | bool patch_get(LV2_URID key); 114 | #endif 115 | 116 | #ifdef CONFIG_LV2_PORT_EVENT 117 | bool port_event(synthv1::ParamIndex index); 118 | bool port_events(); 119 | #endif 120 | 121 | #ifdef CONFIG_LV2_PORT_CHANGE_REQUEST 122 | bool port_change_request(synthv1::ParamIndex index); 123 | bool port_change_requests(); 124 | #endif 125 | 126 | private: 127 | 128 | LV2_URID_Map *m_urid_map; 129 | 130 | struct lv2_urids 131 | { 132 | LV2_URID p201_tuning_enabled; 133 | LV2_URID p202_tuning_refPitch; 134 | LV2_URID p203_tuning_refNote; 135 | LV2_URID p204_tuning_scaleFile; 136 | LV2_URID p205_tuning_keyMapFile; 137 | LV2_URID tun1_update; 138 | LV2_URID atom_Blank; 139 | LV2_URID atom_Object; 140 | LV2_URID atom_Float; 141 | LV2_URID atom_Int; 142 | LV2_URID atom_Bool; 143 | LV2_URID atom_Path; 144 | #ifdef CONFIG_LV2_PORT_EVENT 145 | LV2_URID atom_PortEvent; 146 | LV2_URID atom_portTuple; 147 | #endif 148 | LV2_URID time_Position; 149 | LV2_URID time_beatsPerMinute; 150 | LV2_URID midi_MidiEvent; 151 | LV2_URID bufsz_minBlockLength; 152 | LV2_URID bufsz_maxBlockLength; 153 | LV2_URID bufsz_nominalBlockLength; 154 | LV2_URID state_StateChanged; 155 | #ifdef CONFIG_LV2_PATCH 156 | LV2_URID patch_Get; 157 | LV2_URID patch_Set; 158 | LV2_URID patch_property; 159 | LV2_URID patch_value; 160 | #endif 161 | } m_urids; 162 | 163 | LV2_Atom_Forge m_forge; 164 | LV2_Atom_Forge_Frame m_notify_frame; 165 | 166 | LV2_Worker_Schedule *m_schedule; 167 | 168 | uint32_t m_ndelta; 169 | 170 | LV2_Atom_Sequence *m_atom_in; 171 | LV2_Atom_Sequence *m_atom_out; 172 | 173 | float **m_ins; 174 | float **m_outs; 175 | 176 | #ifdef CONFIG_LV2_PROGRAMS 177 | LV2_Program_Descriptor m_program; 178 | QByteArray m_aProgramName; 179 | #endif 180 | 181 | #ifdef CONFIG_LV2_PORT_CHANGE_REQUEST 182 | LV2_ControlInputPort_Change_Request *m_port_change_request; 183 | #endif 184 | 185 | static QApplication *g_qapp_instance; 186 | static unsigned int g_qapp_refcount; 187 | }; 188 | 189 | 190 | #endif// __synthv1_lv2_h 191 | 192 | // end of synthv1_lv2.h 193 | 194 | -------------------------------------------------------------------------------- /src/synthv1_lv2ui.h: -------------------------------------------------------------------------------- 1 | // synthv1_lv2ui.h 2 | // 3 | /**************************************************************************** 4 | Copyright (C) 2012-2024, rncbc aka Rui Nuno Capela. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | *****************************************************************************/ 21 | 22 | #ifndef __synthv1_lv2ui_h 23 | #define __synthv1_lv2ui_h 24 | 25 | #include "synthv1_ui.h" 26 | 27 | #ifdef CONFIG_LV2_OLD_HEADERS 28 | #include "lv2/lv2plug.in/ns/extensions/ui/ui.h" 29 | #else 30 | #include "lv2/ui/ui.h" 31 | #endif 32 | 33 | #define SYNTHV1_LV2UI_URI SYNTHV1_LV2_PREFIX "ui" 34 | 35 | #if defined(CONFIG_LV2_UI_X11) || defined(CONFIG_LV2_UI_WINDOWS) 36 | #include 37 | #endif 38 | 39 | #ifdef CONFIG_LV2_UI_X11 40 | #define SYNTHV1_LV2UI_X11_URI SYNTHV1_LV2_PREFIX "ui_x11" 41 | #endif 42 | 43 | #ifdef CONFIG_LV2_UI_WINDOWS 44 | #include 45 | #define SYNTHV1_LV2UI_WINDOWS_URI SYNTHV1_LV2_PREFIX "ui_windows" 46 | 47 | // Polyfill for windows size (minimal suitable size) 48 | // Qt cannot determine the right window size on Windows. 49 | #define UI_WINDOWS_RECOMMENDED_WIDTH 1380 50 | #define UI_WINDOWS_RECOMMENDED_HEIGHT 650 51 | #endif 52 | 53 | #ifdef CONFIG_LV2_UI_EXTERNAL 54 | #include "lv2_external_ui.h" 55 | #define SYNTHV1_LV2UI_EXTERNAL_URI SYNTHV1_LV2_PREFIX "ui_external" 56 | #endif 57 | 58 | 59 | // Forward decls. 60 | class synthv1_lv2; 61 | 62 | 63 | //------------------------------------------------------------------------- 64 | // synthv1_lv2ui - decl. 65 | // 66 | 67 | class synthv1_lv2ui : public synthv1_ui 68 | { 69 | public: 70 | 71 | // Constructor. 72 | synthv1_lv2ui(synthv1_lv2 *pSynth, 73 | LV2UI_Controller controller, LV2UI_Write_Function write_function); 74 | 75 | // Accessors. 76 | const LV2UI_Controller& controller() const; 77 | void write_function(synthv1::ParamIndex index, float fValue) const; 78 | 79 | private: 80 | 81 | // Instance variables. 82 | LV2UI_Controller m_controller; 83 | LV2UI_Write_Function m_write_function; 84 | }; 85 | 86 | 87 | #endif // __synthv1_lv2ui_h 88 | 89 | // end of synthv1_lv2ui.h 90 | -------------------------------------------------------------------------------- /src/synthv1_nsm.h: -------------------------------------------------------------------------------- 1 | // synthv1_nsm.h 2 | // 3 | /**************************************************************************** 4 | Copyright (C) 2012-2023, rncbc aka Rui Nuno Capela. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | *****************************************************************************/ 21 | 22 | #ifndef __synthv1_nsm_h 23 | #define __synthv1_nsm_h 24 | 25 | #include "synthv1_config.h" 26 | 27 | #include 28 | 29 | #ifdef CONFIG_LIBLO 30 | #include 31 | #endif 32 | 33 | 34 | //--------------------------------------------------------------------------- 35 | // synthv1_nsm - NSM OSC client agent. 36 | 37 | class synthv1_nsm : public QObject 38 | { 39 | Q_OBJECT 40 | 41 | public: 42 | 43 | // Constructor. 44 | synthv1_nsm(const QString& nsm_url, QObject *pParent = 0); 45 | 46 | // Destructor. 47 | ~synthv1_nsm(); 48 | 49 | // Session activation accessor. 50 | bool is_active() const; 51 | 52 | // Session manager accessors. 53 | const QString& manager() const; 54 | const QString& capabilities() const; 55 | 56 | // Session client accessors. 57 | const QString& path_name() const; 58 | const QString& display_name() const; 59 | const QString& client_name() const; 60 | 61 | // Session client methods. 62 | void announce(const QString& app_name, const QString& capabilities); 63 | void dirty(bool is_dirty); 64 | void visible(bool is_visible); 65 | void progress(float percent); 66 | void message(int priority, const QString& mesg); 67 | 68 | // Status/error codes 69 | enum ReplyCode 70 | { 71 | ERR_OK = 0, 72 | ERR_GENERAL = -1, 73 | ERR_INCOMPATIBLE_API = -2, 74 | ERR_BLACKLISTED = -3, 75 | ERR_LAUNCH_FAILED = -4, 76 | ERR_NO_SUCH_FILE = -5, 77 | ERR_NO_SESSION_OPEN = -6, 78 | ERR_UNSAVED_CHANGES = -7, 79 | ERR_NOT_NOW = -8, 80 | ERR_BAD_PROJECT = -9, 81 | ERR_CREATE_FAILED = -10 82 | }; 83 | 84 | // Session client reply methods. 85 | void open_reply(ReplyCode reply_code = ERR_OK); 86 | void save_reply(ReplyCode reply_code = ERR_OK); 87 | 88 | // Server methods response methods. 89 | void nsm_announce_error( 90 | const char *mesg); 91 | 92 | void nsm_announce_reply( 93 | const char *mesg, 94 | const char *manager, 95 | const char *capabilities); 96 | 97 | void nsm_open( 98 | const char *path_name, 99 | const char *display_name, 100 | const char *client_name); 101 | 102 | void nsm_save(); 103 | void nsm_loaded(); 104 | void nsm_show(); 105 | void nsm_hide(); 106 | 107 | protected: 108 | 109 | void reply(const QString& path, ReplyCode reply_code); 110 | 111 | signals: 112 | 113 | // Session client callbacks. 114 | void active(bool is_active); 115 | void open(); 116 | void save(); 117 | void loaded(); 118 | void show(); 119 | void hide(); 120 | 121 | private: 122 | 123 | // Instance variables. 124 | #ifdef CONFIG_LIBLO 125 | lo_address m_address; 126 | lo_server_thread m_thread; 127 | lo_server m_server; 128 | #endif 129 | bool m_active; 130 | bool m_dirty; 131 | QString m_manager; 132 | QString m_capabilities; 133 | QString m_path_name; 134 | QString m_display_name; 135 | QString m_client_name; 136 | }; 137 | 138 | 139 | #endif // __synthv1_nsm_h 140 | 141 | // end of synthv1_nsm.h 142 | -------------------------------------------------------------------------------- /src/synthv1_param.h: -------------------------------------------------------------------------------- 1 | // synthv1_param.h 2 | // 3 | /**************************************************************************** 4 | Copyright (C) 2012-2024, rncbc aka Rui Nuno Capela. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | *****************************************************************************/ 21 | 22 | #ifndef __synthv1_param_h 23 | #define __synthv1_param_h 24 | 25 | #include "synthv1.h" 26 | 27 | #include 28 | 29 | // forward decl. 30 | class QDomElement; 31 | class QDomDocument; 32 | 33 | 34 | //------------------------------------------------------------------------- 35 | // synthv1_param - decl. 36 | // 37 | 38 | namespace synthv1_param 39 | { 40 | // Preset initialization method. 41 | bool newPreset(synthv1 *pSynth); 42 | 43 | // Preset serialization methods. 44 | bool loadPreset(synthv1 *pSynth, 45 | const QString& sFilename); 46 | bool savePreset(synthv1 *pSynth, 47 | const QString& sFilename, 48 | bool bSymLink = false); 49 | 50 | // Tuning serialization methods. 51 | void loadTuning(synthv1 *pSynth, 52 | const QDomElement& eTuning); 53 | void saveTuning(synthv1 *pSynth, 54 | QDomDocument& doc, QDomElement& eTuning, 55 | bool bSymLink = false); 56 | 57 | // Default parameter name/value helpers. 58 | const char *paramName(synthv1::ParamIndex index); 59 | float paramDefaultValue(synthv1::ParamIndex index); 60 | float paramSafeValue(synthv1::ParamIndex index, float fValue); 61 | float paramValue(synthv1::ParamIndex index, float fScale); 62 | float paramScale(synthv1::ParamIndex index, float fValue); 63 | bool paramFloat(synthv1::ParamIndex index); 64 | 65 | // Load/save and convert canonical/absolute filename helpers. 66 | QString loadFilename(const QString& sFilename); 67 | QString saveFilename(const QString& sFilename, bool bSymLink); 68 | }; 69 | 70 | 71 | #endif // __synthv1_param_h 72 | 73 | // end of synthv1_param.h 74 | -------------------------------------------------------------------------------- /src/synthv1_programs.cpp: -------------------------------------------------------------------------------- 1 | // synthv1_programs.cpp 2 | // 3 | /**************************************************************************** 4 | Copyright (C) 2012-2024 rncbc aka Rui Nuno Capela. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | *****************************************************************************/ 21 | 22 | #include "synthv1_programs.h" 23 | 24 | 25 | //------------------------------------------------------------------------- 26 | // synthv1_programs - Bank/programs database class (singleton). 27 | // 28 | 29 | // ctor. 30 | synthv1_programs::synthv1_programs ( synthv1 *pSynth ) 31 | : m_enabled(false), m_sched(pSynth), 32 | m_bank_msb(0), m_bank_lsb(0), 33 | m_bank(nullptr), m_prog(nullptr) 34 | { 35 | } 36 | 37 | 38 | // dtor. 39 | synthv1_programs::~synthv1_programs (void) 40 | { 41 | clear_banks(); 42 | } 43 | 44 | 45 | // prog. managers 46 | synthv1_programs::Prog *synthv1_programs::Bank::find_prog ( uint16_t prog_id ) const 47 | { 48 | return m_progs.value(prog_id, nullptr); 49 | } 50 | 51 | 52 | synthv1_programs::Prog *synthv1_programs::Bank::add_prog ( 53 | uint16_t prog_id, const QString& prog_name ) 54 | { 55 | Prog *prog = find_prog(prog_id); 56 | if (prog) { 57 | prog->set_name(prog_name); 58 | } else { 59 | prog = new Prog(prog_id, prog_name); 60 | m_progs.insert(prog_id, prog); 61 | } 62 | return prog; 63 | } 64 | 65 | 66 | void synthv1_programs::Bank::remove_prog ( uint16_t prog_id ) 67 | { 68 | Prog *prog = find_prog(prog_id); 69 | if (prog && m_progs.remove(prog_id)) 70 | delete prog; 71 | } 72 | 73 | 74 | void synthv1_programs::Bank::clear_progs (void) 75 | { 76 | qDeleteAll(m_progs); 77 | m_progs.clear(); 78 | } 79 | 80 | 81 | // bank managers 82 | synthv1_programs::Bank *synthv1_programs::find_bank ( uint16_t bank_id ) const 83 | { 84 | return m_banks.value(bank_id, nullptr); 85 | } 86 | 87 | 88 | synthv1_programs::Bank *synthv1_programs::add_bank ( 89 | uint16_t bank_id, const QString& bank_name ) 90 | { 91 | Bank *bank = find_bank(bank_id); 92 | if (bank) { 93 | bank->set_name(bank_name); 94 | } else { 95 | bank = new Bank(bank_id, bank_name); 96 | m_banks.insert(bank_id, bank); 97 | } 98 | return bank; 99 | } 100 | 101 | 102 | void synthv1_programs::remove_bank ( uint16_t bank_id ) 103 | { 104 | Bank *bank = find_bank(bank_id); 105 | if (bank && m_banks.remove(bank_id)) 106 | delete bank; 107 | } 108 | 109 | 110 | void synthv1_programs::clear_banks (void) 111 | { 112 | m_bank_msb = 0; 113 | m_bank_lsb = 0; 114 | 115 | m_bank = nullptr; 116 | m_prog = nullptr; 117 | 118 | qDeleteAll(m_banks); 119 | m_banks.clear(); 120 | } 121 | 122 | 123 | // current bank/prog. managers 124 | void synthv1_programs::bank_select_msb ( uint8_t bank_msb ) 125 | { 126 | m_bank_msb = 0x80 | (bank_msb & 0x7f); 127 | } 128 | 129 | 130 | void synthv1_programs::bank_select_lsb ( uint8_t bank_lsb ) 131 | { 132 | m_bank_lsb = 0x80 | (bank_lsb & 0x7f); 133 | } 134 | 135 | 136 | void synthv1_programs::bank_select ( uint16_t bank_id ) 137 | { 138 | bank_select_msb(bank_id >> 7); 139 | bank_select_lsb(bank_id); 140 | } 141 | 142 | 143 | uint16_t synthv1_programs::current_bank_id (void) const 144 | { 145 | uint16_t bank_id = 0; 146 | 147 | if (m_bank_msb & 0x80) 148 | bank_id = (m_bank_msb & 0x7f); 149 | if (m_bank_lsb & 0x80) { 150 | bank_id <<= 7; 151 | bank_id |= (m_bank_lsb & 0x7f); 152 | } 153 | 154 | return bank_id; 155 | } 156 | 157 | 158 | void synthv1_programs::prog_change ( uint16_t prog_id ) 159 | { 160 | select_program(current_bank_id(), prog_id); 161 | } 162 | 163 | 164 | void synthv1_programs::select_program ( uint16_t bank_id, uint16_t prog_id ) 165 | { 166 | if (!enabled()) 167 | return; 168 | 169 | if (m_bank && m_bank->id() == bank_id && 170 | m_prog && m_prog->id() == prog_id) 171 | return; 172 | 173 | m_sched.select_program(bank_id, prog_id); 174 | } 175 | 176 | 177 | void synthv1_programs::process_program ( 178 | synthv1 *pSynth, uint16_t bank_id, uint16_t prog_id ) 179 | { 180 | m_bank = find_bank(bank_id); 181 | m_prog = (m_bank ? m_bank->find_prog(prog_id) : nullptr); 182 | 183 | if (m_prog) { 184 | synthv1_param::loadPreset(pSynth, m_prog->name()); 185 | pSynth->updateParams(); 186 | } 187 | } 188 | 189 | 190 | // end of synthv1_programs.cpp 191 | -------------------------------------------------------------------------------- /src/synthv1_programs.h: -------------------------------------------------------------------------------- 1 | // synthv1_programs.h 2 | // 3 | /**************************************************************************** 4 | Copyright (C) 2012-2024, rncbc aka Rui Nuno Capela. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | *****************************************************************************/ 21 | 22 | #ifndef __synthv1_programs_h 23 | #define __synthv1_programs_h 24 | 25 | #include "synthv1_sched.h" 26 | #include "synthv1_param.h" 27 | 28 | #include 29 | 30 | 31 | //------------------------------------------------------------------------- 32 | // synthv1_programs - Bank/programs database class. 33 | // 34 | 35 | class synthv1_programs 36 | { 37 | public: 38 | 39 | // ctor. 40 | synthv1_programs(synthv1 *pSynth); 41 | 42 | // dtor. 43 | ~synthv1_programs(); 44 | 45 | // operational mode flags. 46 | void enabled(bool on) 47 | { m_enabled = on; } 48 | bool enabled() const 49 | { return m_enabled; } 50 | 51 | // prog. base node 52 | class Prog 53 | { 54 | public: 55 | 56 | Prog(uint16_t id, const QString& name) 57 | : m_id(id), m_name(name) {} 58 | 59 | uint16_t id() const { return m_id; } 60 | const QString& name() const { return m_name; } 61 | void set_name(const QString& name) { m_name = name; } 62 | 63 | private: 64 | 65 | uint16_t m_id; 66 | QString m_name; 67 | }; 68 | 69 | typedef QMap Progs; 70 | 71 | // bank node 72 | class Bank : public Prog 73 | { 74 | public: 75 | 76 | Bank(uint16_t id, const QString& name) 77 | : Prog(id, name) {} 78 | 79 | ~Bank() { clear_progs(); } 80 | 81 | const Progs& progs() const { return m_progs; } 82 | 83 | // prog. managers 84 | Prog *find_prog(uint16_t prog_id) const; 85 | Prog *add_prog(uint16_t prog_id, const QString& prog_name); 86 | void remove_prog(uint16_t prog_id); 87 | void clear_progs(); 88 | 89 | private: 90 | 91 | Progs m_progs; 92 | }; 93 | 94 | typedef QMap Banks; 95 | 96 | const Banks& banks() const { return m_banks; } 97 | 98 | // bank managers 99 | Bank *find_bank(uint16_t bank_id) const; 100 | Bank *add_bank(uint16_t bank_id, const QString& bank_name); 101 | void remove_bank(uint16_t bank_id); 102 | 103 | void clear_banks(); 104 | 105 | // current bank/prog. managers 106 | void bank_select_msb(uint8_t bank_msb); 107 | void bank_select_lsb(uint8_t bank_lsb); 108 | 109 | void bank_select(uint16_t bank_id); 110 | void prog_change(uint16_t prog_id); 111 | 112 | void select_program(uint16_t bank_id, uint16_t prog_id); 113 | 114 | void process_program(synthv1 *pSynth, uint16_t bank_id, uint16_t prog_id); 115 | 116 | Bank *current_bank() const { return m_bank; } 117 | Prog *current_prog() const { return m_prog; } 118 | 119 | protected: 120 | 121 | uint16_t current_bank_id() const; 122 | 123 | // current bank/prog. scheduled thread 124 | class Sched : public synthv1_sched 125 | { 126 | public: 127 | 128 | // ctor. 129 | Sched (synthv1 *pSynth) 130 | : synthv1_sched(pSynth, Programs), m_bank_id(0), m_prog_id(0) {} 131 | 132 | // schedule (override) 133 | void select_program(uint16_t bank_id, uint16_t prog_id) 134 | { 135 | if (m_bank_id != bank_id || 136 | m_prog_id != prog_id) { 137 | m_bank_id = bank_id; 138 | m_prog_id = prog_id; 139 | schedule(); 140 | } 141 | } 142 | 143 | // process (virtual). 144 | void process(int) 145 | { 146 | synthv1 *pSynth = instance(); 147 | synthv1_programs *pPrograms = pSynth->programs(); 148 | pPrograms->process_program(pSynth, m_bank_id, m_prog_id); 149 | } 150 | 151 | private: 152 | 153 | // instance variables. 154 | uint16_t m_bank_id; 155 | uint16_t m_prog_id; 156 | }; 157 | 158 | private: 159 | 160 | // instance variables. 161 | bool m_enabled; 162 | 163 | Sched m_sched; 164 | 165 | uint8_t m_bank_msb; 166 | uint8_t m_bank_lsb; 167 | 168 | Bank *m_bank; 169 | Prog *m_prog; 170 | 171 | Banks m_banks; 172 | }; 173 | 174 | 175 | #endif // __synthv1_programs_h 176 | 177 | // end of synthv1_programs.h 178 | -------------------------------------------------------------------------------- /src/synthv1_ramp.h: -------------------------------------------------------------------------------- 1 | // synthv1_ramp.h 2 | // 3 | /**************************************************************************** 4 | Copyright (C) 2012-2021, rncbc aka Rui Nuno Capela. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | *****************************************************************************/ 21 | 22 | #ifndef __synthv1_ramp_h 23 | #define __synthv1_ramp_h 24 | 25 | #include 26 | #include 27 | 28 | 29 | //------------------------------------------------------------------------- 30 | // synthv1_ramp - ramp/smooth parameter changes 31 | 32 | class synthv1_ramp 33 | { 34 | public: 35 | 36 | synthv1_ramp(uint16_t nvalues = 1) 37 | { 38 | m_nvalues = nvalues; 39 | m_value0 = new float [m_nvalues]; 40 | m_value1 = new float [m_nvalues]; 41 | m_delta = new float [m_nvalues]; 42 | 43 | for (uint16_t i = 0; i < m_nvalues; ++i) 44 | m_value0[i] = m_value1[i] = m_delta[i] = 0.0f; 45 | 46 | m_frames = 0; 47 | } 48 | 49 | virtual ~synthv1_ramp() 50 | { 51 | delete [] m_delta; 52 | delete [] m_value1; 53 | delete [] m_value0; 54 | } 55 | 56 | void reset() 57 | { 58 | for (uint16_t i = 0; i < m_nvalues; ++i) { 59 | m_value0[i] = m_value1[i]; 60 | m_value1[i] = evaluate(i); 61 | } 62 | 63 | m_frames = 0; 64 | } 65 | 66 | void process(uint32_t nframes) 67 | { 68 | if (m_frames > 0) { 69 | if (nframes > m_frames) 70 | nframes = m_frames; 71 | for (uint16_t i = 0; i < m_nvalues; ++i) 72 | m_value0[i] += float(nframes) * m_delta[i]; 73 | m_frames -= nframes; 74 | } 75 | else 76 | if (probe()) { 77 | reset(); 78 | m_frames = nframes; 79 | const uint32_t MIN_FRAMES = 32; 80 | if (m_frames < MIN_FRAMES) 81 | m_frames = MIN_FRAMES; 82 | for (uint16_t i = 0; i < m_nvalues; ++i) 83 | m_delta[i] = (m_value1[i] - m_value0[i]) / float(m_frames); 84 | } 85 | } 86 | 87 | float value(uint32_t n, uint16_t i = 0) const 88 | { 89 | return (n < m_frames ? (m_value0[i] + float(n) * m_delta[i]) : m_value1[i]); 90 | } 91 | 92 | protected: 93 | 94 | virtual bool probe() const = 0; 95 | virtual float evaluate(uint16_t i) = 0; 96 | 97 | private: 98 | 99 | uint16_t m_nvalues; 100 | 101 | float *m_value1; 102 | float *m_value0; 103 | float *m_delta; 104 | 105 | uint32_t m_frames; 106 | }; 107 | 108 | 109 | //------------------------------------------------------------------------- 110 | // synthv1_ramp1 (1 port tracking) 111 | 112 | class synthv1_ramp1 : public synthv1_ramp 113 | { 114 | public: 115 | 116 | synthv1_ramp1(uint16_t nvalues = 1) 117 | : synthv1_ramp(nvalues), m_param1(nullptr), m_param1_v(0.0f) {} 118 | 119 | void reset(float *param1) 120 | { 121 | m_param1 = param1; 122 | m_param1_v = 0.0f; 123 | 124 | synthv1_ramp::reset(); 125 | } 126 | 127 | protected: 128 | 129 | virtual bool probe() const 130 | { 131 | return m_param1 && ::fabsf(*m_param1 - m_param1_v) > 0.001f; 132 | } 133 | 134 | virtual float evaluate(uint16_t) 135 | { 136 | update(); 137 | 138 | return m_param1_v; 139 | } 140 | 141 | void update() 142 | { 143 | if (m_param1) 144 | m_param1_v = *m_param1; 145 | } 146 | 147 | float *m_param1; 148 | float m_param1_v; 149 | }; 150 | 151 | 152 | //------------------------------------------------------------------------- 153 | // synthv1_ramp2 (2 port tracking) 154 | 155 | class synthv1_ramp2 : public synthv1_ramp1 156 | { 157 | public: 158 | 159 | synthv1_ramp2(uint16_t nvalues = 1) 160 | : synthv1_ramp1(nvalues), m_param2(nullptr), m_param2_v(0.0f) {} 161 | 162 | void reset(float *param1, float *param2) 163 | { 164 | m_param2 = param2; 165 | m_param2_v = 0.0f; 166 | 167 | synthv1_ramp1::reset(param1); 168 | } 169 | 170 | protected: 171 | 172 | virtual bool probe() const 173 | { 174 | return synthv1_ramp1::probe() 175 | || (m_param2 && ::fabsf(*m_param2 - m_param2_v) > 0.001f); 176 | } 177 | 178 | virtual float evaluate(uint16_t i) 179 | { 180 | update(); 181 | 182 | return synthv1_ramp1::evaluate(i) * m_param2_v; 183 | } 184 | 185 | void update() 186 | { 187 | synthv1_ramp1::update(); 188 | 189 | if (m_param2) 190 | m_param2_v = *m_param2; 191 | } 192 | 193 | float *m_param2; 194 | float m_param2_v; 195 | }; 196 | 197 | 198 | //------------------------------------------------------------------------- 199 | // synthv1_ramp3 (3 port tracking) 200 | 201 | class synthv1_ramp3 : public synthv1_ramp2 202 | { 203 | public: 204 | 205 | synthv1_ramp3(uint16_t nvalues = 1) 206 | : synthv1_ramp2(nvalues), m_param3(nullptr), m_param3_v(0.0f) {} 207 | 208 | void reset(float *param1, float *param2, float *param3) 209 | { 210 | m_param3 = param3; 211 | m_param3_v = 0.0f; 212 | 213 | synthv1_ramp2::reset(param1, param2); 214 | } 215 | 216 | protected: 217 | 218 | virtual bool probe() const 219 | { 220 | return synthv1_ramp2::probe() 221 | || (m_param3 && ::fabsf(*m_param3 - m_param3_v) > 0.001f); 222 | } 223 | 224 | virtual float evaluate(uint16_t i) 225 | { 226 | update(); 227 | 228 | return synthv1_ramp2::evaluate(i) * m_param3_v; 229 | } 230 | 231 | void update() 232 | { 233 | synthv1_ramp2::update(); 234 | 235 | if (m_param3) 236 | m_param3_v = *m_param3; 237 | } 238 | 239 | float *m_param3; 240 | float m_param3_v; 241 | }; 242 | 243 | 244 | 245 | 246 | //------------------------------------------------------------------------- 247 | // synthv1_ramp4 (4 port tracking) 248 | 249 | class synthv1_ramp4 : public synthv1_ramp3 250 | { 251 | public: 252 | 253 | synthv1_ramp4(uint16_t nvalues = 1) 254 | : synthv1_ramp3(nvalues), m_param4(nullptr), m_param4_v(0.0f) {} 255 | 256 | void reset(float *param1, float *param2, float *param3, float *param4) 257 | { 258 | m_param4 = param4; 259 | m_param4_v = 0.0f; 260 | 261 | synthv1_ramp3::reset(param1, param2, param3); 262 | } 263 | 264 | protected: 265 | 266 | virtual bool probe() const 267 | { 268 | return synthv1_ramp3::probe() 269 | || (m_param4 && ::fabsf(*m_param4 - m_param4_v) > 0.001f); 270 | } 271 | 272 | virtual float evaluate(uint16_t i) 273 | { 274 | update(); 275 | 276 | return synthv1_ramp3::evaluate(i) * m_param4_v; 277 | } 278 | 279 | void update() 280 | { 281 | synthv1_ramp3::update(); 282 | 283 | if (m_param4) 284 | m_param4_v = *m_param4; 285 | } 286 | 287 | float *m_param4; 288 | float m_param4_v; 289 | }; 290 | 291 | 292 | #endif // __synthv1_ramp_h 293 | 294 | // end of synthv1_ramp.h 295 | -------------------------------------------------------------------------------- /src/synthv1_reverb.h: -------------------------------------------------------------------------------- 1 | // synthv1_reverb.h 2 | // 3 | /**************************************************************************** 4 | Copyright (C) 2012-2021, rncbc aka Rui Nuno Capela. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | *****************************************************************************/ 21 | 22 | #ifndef __synthv1_reverb_h 23 | #define __synthv1_reverb_h 24 | 25 | #include 26 | #include 27 | 28 | 29 | //------------------------------------------------------------------------- 30 | // synthv1_reverb 31 | // 32 | // -- borrowed, stirred and refactored from original FreeVerb -- 33 | // by Jezar at Dreampoint, June 2000 (public domain) 34 | // 35 | 36 | class synthv1_reverb 37 | { 38 | public: 39 | 40 | synthv1_reverb (float srate = 44100.0f) 41 | : m_srate(srate), m_room(0.5f), m_damp(0.5f), m_feedb(0.5f) 42 | { reset(); } 43 | 44 | void setSampleRate(float srate) 45 | { m_srate = srate; } 46 | float sampleRate() const 47 | { return m_srate; } 48 | 49 | void reset() 50 | { 51 | static const uint32_t s_comb[NUM_COMBS] 52 | = { 1116, 1188, 1277, 1356, 1422, 1491, 1557, 1617, 1685, 1748 }; 53 | static const uint32_t s_allpass[NUM_ALLPASSES] 54 | = { 556, 441, 341, 225, 180, 153 }; 55 | 56 | const float sr = m_srate / 44100.0f; 57 | 58 | uint32_t j; 59 | 60 | for (j = 0; j < NUM_ALLPASSES; ++j) { 61 | m_allpass0[j].resize(uint32_t(s_allpass[j] * sr)); 62 | m_allpass0[j].reset(); 63 | m_allpass1[j].resize(uint32_t((s_allpass[j] + STEREO_SPREAD) * sr)); 64 | m_allpass1[j].reset(); 65 | } 66 | 67 | for (j = 0; j < NUM_COMBS; ++j) { 68 | m_comb0[j].resize(uint32_t(s_comb[j] * sr)); 69 | m_comb0[j].reset(); 70 | m_comb1[j].resize(uint32_t((s_comb[j] + STEREO_SPREAD) * sr)); 71 | m_comb1[j].reset(); 72 | } 73 | 74 | reset_feedb(); 75 | reset_room(); 76 | reset_damp(); 77 | } 78 | 79 | void process(float *in0, float *in1, uint32_t nframes, 80 | float wet, float feedb, float room, float damp, float width) 81 | { 82 | if (wet < 1E-9f) 83 | return; 84 | 85 | if (m_feedb != feedb) { 86 | m_feedb = feedb; 87 | reset_feedb(); 88 | } 89 | 90 | if (m_room != room) { 91 | m_room = room; 92 | reset_room(); 93 | } 94 | 95 | if (m_damp != damp) { 96 | m_damp = damp; 97 | reset_damp(); 98 | } 99 | 100 | uint32_t i, j; 101 | 102 | for (i = 0; i < nframes; ++i) { 103 | 104 | float out0 = *in0 * 0.05f; // 0.015f; 105 | float out1 = *in1 * 0.05f; // 0.015f; 106 | 107 | float tmp0 = 0.0f; 108 | float tmp1 = 0.0f; 109 | 110 | for (j = 0; j < NUM_COMBS; ++j) { 111 | tmp0 += m_comb0[j].output(out0); 112 | tmp1 += m_comb1[j].output(out1); 113 | } 114 | 115 | for (j = 0; j < NUM_ALLPASSES; ++j) { 116 | tmp0 = m_allpass0[j].output(tmp0); 117 | tmp1 = m_allpass1[j].output(tmp1); 118 | } 119 | 120 | if (width < 0.0f) { 121 | out0 = tmp0 * (1.0f + width) - tmp1 * width; 122 | out1 = tmp1 * (1.0f + width) - tmp0 * width; 123 | } else { 124 | out0 = tmp0 * width + tmp1 * (1.0f - width); 125 | out1 = tmp1 * width + tmp0 * (1.0f - width); 126 | } 127 | 128 | *in0++ += wet * out0; 129 | *in1++ += wet * out1; 130 | } 131 | } 132 | 133 | protected: 134 | 135 | static const uint32_t NUM_COMBS = 10; 136 | static const uint32_t NUM_ALLPASSES = 6; 137 | static const uint32_t STEREO_SPREAD = 23; 138 | 139 | void reset_room() 140 | { 141 | for (uint32_t j = 0; j < NUM_COMBS; ++j) { 142 | m_comb0[j].set_feedb(m_room); 143 | m_comb1[j].set_feedb(m_room); 144 | } 145 | } 146 | 147 | void reset_damp() 148 | { 149 | const float damp2 = m_damp * m_damp; 150 | for (uint32_t j = 0; j < NUM_COMBS; ++j) { 151 | m_comb0[j].set_damp(damp2); 152 | m_comb1[j].set_damp(damp2); 153 | } 154 | } 155 | 156 | void reset_feedb() 157 | { 158 | const float feedb2 = 2.0f * m_feedb * (2.0f - m_feedb) / 3.0f; 159 | for (uint32_t j = 0; j < NUM_ALLPASSES; ++j) { 160 | m_allpass0[j].set_feedb(feedb2); 161 | m_allpass1[j].set_feedb(feedb2); 162 | } 163 | } 164 | 165 | class sample_buffer 166 | { 167 | public: 168 | 169 | sample_buffer (uint32_t size = 0) 170 | : m_buffer(0), m_size(0), m_index(0) 171 | { resize(size); } 172 | 173 | virtual ~sample_buffer() 174 | { delete [] m_buffer; } 175 | 176 | void reset() 177 | { ::memset(m_buffer, 0, m_size * sizeof(float)); m_index = 0; } 178 | 179 | void resize(uint32_t size) 180 | { 181 | if (size < 1) 182 | size = 1; 183 | if (m_size != size) { 184 | const uint32_t old_size = m_size; 185 | if (size > old_size) { 186 | float *old_buffer = m_buffer; 187 | m_buffer = new float [size]; 188 | m_size = size; 189 | if (old_buffer) { 190 | ::memcpy(m_buffer, old_buffer, 191 | old_size * sizeof(float)); 192 | delete [] old_buffer; 193 | } 194 | } 195 | } 196 | } 197 | 198 | float *tick() 199 | { 200 | float *buf = m_buffer + m_index; 201 | if (++m_index >= m_size) 202 | m_index = 0; 203 | return buf; 204 | } 205 | 206 | private: 207 | 208 | float *m_buffer; 209 | uint32_t m_size; 210 | uint32_t m_index; 211 | }; 212 | 213 | class comb_filter : public sample_buffer 214 | { 215 | public: 216 | 217 | comb_filter (uint32_t size = 0) 218 | : sample_buffer(size), m_feedb(0.5f), m_damp(0.5f), m_out(0.0f) {} 219 | 220 | void set_feedb(float feedb) 221 | { m_feedb = feedb; } 222 | float feedb() const 223 | { return m_feedb; } 224 | 225 | void set_damp(float damp) 226 | { m_damp = damp; } 227 | float damp() const 228 | { return m_damp; } 229 | 230 | void reset() 231 | { sample_buffer::reset(); m_out = 0.0f; } 232 | 233 | float output(float in) 234 | { 235 | float *buf = tick(); 236 | float out = *buf; 237 | m_out = denormal(out * (1.0f - m_damp) + m_out * m_damp); 238 | *buf = in + (m_out * m_feedb); 239 | return out; 240 | } 241 | 242 | private: 243 | 244 | float m_feedb; 245 | float m_damp; 246 | float m_out; 247 | }; 248 | 249 | class allpass_filter : public sample_buffer 250 | { 251 | public: 252 | 253 | allpass_filter(uint32_t size = 0) 254 | : sample_buffer(size), m_feedb(0.5f) {} 255 | 256 | void set_feedb(float feedb) 257 | { m_feedb = feedb; } 258 | float feedb () const 259 | { return m_feedb; } 260 | 261 | float output(float in) 262 | { 263 | float *buf = tick(); 264 | float out = *buf; 265 | *buf = denormal(in + out * m_feedb); 266 | return out - in; 267 | } 268 | 269 | private: 270 | 271 | float m_feedb; 272 | }; 273 | 274 | static float denormal(float v) 275 | { 276 | union { float f; uint32_t w; } u; 277 | u.f = v; 278 | return (u.w & 0x7f800000) ? v : 0.0f; 279 | } 280 | 281 | private: 282 | 283 | float m_srate; 284 | 285 | float m_room; 286 | float m_damp; 287 | float m_feedb; 288 | 289 | comb_filter m_comb0[NUM_COMBS]; 290 | comb_filter m_comb1[NUM_COMBS]; 291 | 292 | allpass_filter m_allpass0[NUM_ALLPASSES]; 293 | allpass_filter m_allpass1[NUM_ALLPASSES]; 294 | }; 295 | 296 | 297 | #endif // __synthv1_reverb_h 298 | -------------------------------------------------------------------------------- /src/synthv1_sched.cpp: -------------------------------------------------------------------------------- 1 | // synthv1_sched.cpp 2 | // 3 | /**************************************************************************** 4 | Copyright (C) 2012-2024, rncbc aka Rui Nuno Capela. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | *****************************************************************************/ 21 | 22 | #include "synthv1_sched.h" 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | 30 | 31 | //------------------------------------------------------------------------- 32 | // synthv1_sched_thread - worker/schedule thread decl. 33 | // 34 | 35 | class synthv1_sched_thread : public QThread 36 | { 37 | public: 38 | 39 | // ctor. 40 | synthv1_sched_thread(uint32_t nsize = 32); 41 | 42 | // dtor. 43 | ~synthv1_sched_thread(); 44 | 45 | // schedule processing and wake from wait condition. 46 | void schedule(synthv1_sched *sched); 47 | 48 | // process all pending runs immediately. 49 | void sync_pending(); 50 | 51 | // clear all pending runs immediately. 52 | void sync_reset(); 53 | 54 | protected: 55 | 56 | // main thread executive. 57 | void run(); 58 | void run_process(); 59 | 60 | // clear all. 61 | void clear(); 62 | 63 | private: 64 | 65 | // sync queue instance reference. 66 | uint32_t m_nsize; 67 | uint32_t m_nmask; 68 | 69 | synthv1_sched **m_items; 70 | 71 | volatile uint32_t m_iread; 72 | volatile uint32_t m_iwrite; 73 | 74 | // whether the thread is logically running. 75 | volatile bool m_running; 76 | 77 | // thread synchronization objects. 78 | QMutex m_mutex; 79 | QWaitCondition m_cond; 80 | }; 81 | 82 | 83 | static synthv1_sched_thread *g_sched_thread = nullptr; 84 | static uint32_t g_sched_refcount = 0; 85 | 86 | static QHash > g_sched_notifiers; 87 | 88 | 89 | //------------------------------------------------------------------------- 90 | // synthv1_sched_thread - worker/schedule thread impl. 91 | // 92 | 93 | // ctor. 94 | synthv1_sched_thread::synthv1_sched_thread ( uint32_t nsize ) : QThread() 95 | { 96 | m_nsize = (4 << 1); 97 | while (m_nsize < nsize) 98 | m_nsize <<= 1; 99 | m_nmask = (m_nsize - 1); 100 | m_items = new synthv1_sched * [m_nsize]; 101 | 102 | m_iread = 0; 103 | m_iwrite = 0; 104 | 105 | ::memset(m_items, 0, m_nsize * sizeof(synthv1_sched *)); 106 | 107 | m_running = false; 108 | } 109 | 110 | 111 | // dtor. 112 | synthv1_sched_thread::~synthv1_sched_thread (void) 113 | { 114 | // fake sync and wait 115 | if (m_running && isRunning()) do { 116 | if (m_mutex.tryLock()) { 117 | m_running = false; 118 | m_cond.wakeAll(); 119 | m_mutex.unlock(); 120 | } 121 | } while (!wait(100)); 122 | 123 | delete [] m_items; 124 | } 125 | 126 | 127 | // schedule processing and wake from wait condition. 128 | void synthv1_sched_thread::schedule ( synthv1_sched *sched ) 129 | { 130 | if (!sched->sync_wait()) { 131 | const uint32_t w = (m_iwrite + 1) & m_nmask; 132 | if (w != m_iread) { 133 | m_items[m_iwrite] = sched; 134 | m_iwrite = w; 135 | } 136 | } 137 | 138 | if (m_mutex.tryLock()) { 139 | m_cond.wakeAll(); 140 | m_mutex.unlock(); 141 | } 142 | } 143 | 144 | 145 | // process all pending runs, immediately. 146 | void synthv1_sched_thread::sync_pending (void) 147 | { 148 | QMutexLocker locker(&m_mutex); 149 | 150 | run_process(); 151 | } 152 | 153 | 154 | // clear all pending runs, immediately. 155 | void synthv1_sched_thread::sync_reset (void) 156 | { 157 | QMutexLocker locker(&m_mutex); 158 | 159 | clear(); 160 | } 161 | 162 | 163 | void synthv1_sched_thread::clear (void) 164 | { 165 | m_iread = 0; 166 | m_iwrite = 0; 167 | 168 | ::memset(m_items, 0, m_nsize * sizeof(synthv1_sched *)); 169 | } 170 | 171 | 172 | // main thread executive. 173 | void synthv1_sched_thread::run (void) 174 | { 175 | m_mutex.lock(); 176 | 177 | m_running = true; 178 | 179 | while (m_running) { 180 | // do whatever we must... 181 | run_process(); 182 | // wait for sync... 183 | m_cond.wait(&m_mutex); 184 | } 185 | 186 | m_mutex.unlock(); 187 | } 188 | 189 | 190 | void synthv1_sched_thread::run_process (void) 191 | { 192 | uint32_t r = m_iread; 193 | while (r != m_iwrite) { 194 | synthv1_sched *sched = m_items[r]; 195 | if (sched) { 196 | sched->sync_process(); 197 | m_items[r] = nullptr; 198 | } 199 | ++r &= m_nmask; 200 | } 201 | m_iread = r; 202 | } 203 | 204 | 205 | //------------------------------------------------------------------------- 206 | // synthv1_sched - worker/scheduled stuff (pure virtual). 207 | // 208 | 209 | // ctor. 210 | synthv1_sched::synthv1_sched ( synthv1 *pSynth, Type stype, uint32_t nsize ) 211 | : m_pSynth(pSynth), m_stype(stype), m_sync_wait(false) 212 | { 213 | m_nsize = (4 << 1); 214 | while (m_nsize < nsize) 215 | m_nsize <<= 1; 216 | m_nmask = (m_nsize - 1); 217 | m_items = new int [m_nsize]; 218 | 219 | m_iread = 0; 220 | m_iwrite = 0; 221 | 222 | ::memset(m_items, 0, m_nsize * sizeof(int)); 223 | 224 | if (++g_sched_refcount == 1 && g_sched_thread == nullptr) { 225 | g_sched_thread = new synthv1_sched_thread(); 226 | g_sched_thread->start(); 227 | } 228 | } 229 | 230 | 231 | // dtor (virtual). 232 | synthv1_sched::~synthv1_sched (void) 233 | { 234 | delete [] m_items; 235 | 236 | if (--g_sched_refcount == 0) { 237 | if (g_sched_thread) { 238 | delete g_sched_thread; 239 | g_sched_thread = nullptr; 240 | } 241 | } 242 | } 243 | 244 | 245 | // instance access. 246 | synthv1 *synthv1_sched::instance (void) const 247 | { 248 | return m_pSynth; 249 | } 250 | 251 | 252 | // schedule process. 253 | void synthv1_sched::schedule ( int sid ) 254 | { 255 | const uint32_t w = (m_iwrite + 1) & m_nmask; 256 | if (w != m_iread) { 257 | m_items[m_iwrite] = sid; 258 | m_iwrite = w; 259 | } 260 | 261 | if (g_sched_thread) 262 | g_sched_thread->schedule(this); 263 | } 264 | 265 | 266 | // test-and-set. 267 | bool synthv1_sched::sync_wait (void) 268 | { 269 | const bool sync_wait = m_sync_wait; 270 | 271 | if (!sync_wait) 272 | m_sync_wait = true; 273 | 274 | return sync_wait; 275 | } 276 | 277 | 278 | // scheduled processor. 279 | void synthv1_sched::sync_process (void) 280 | { 281 | // do whatever we must... 282 | uint32_t r = m_iread; 283 | while (r != m_iwrite) { 284 | const int sid = m_items[r]; 285 | process(sid); 286 | sync_notify(m_pSynth, m_stype, sid); 287 | m_items[r] = 0; 288 | ++r &= m_nmask; 289 | } 290 | m_iread = r; 291 | 292 | m_sync_wait = false; 293 | } 294 | 295 | 296 | // signal broadcast (static). 297 | void synthv1_sched::sync_notify ( synthv1 *pSynth, Type stype, int sid ) 298 | { 299 | if (g_sched_notifiers.contains(pSynth)) { 300 | const QList& list 301 | = g_sched_notifiers.value(pSynth); 302 | QListIterator iter(list); 303 | while (iter.hasNext()) 304 | iter.next()->notify(stype, sid); 305 | } 306 | } 307 | 308 | 309 | // process/clear pending schedules, immediately. (static) 310 | void synthv1_sched::sync_pending (void) 311 | { 312 | if (g_sched_thread) 313 | g_sched_thread->sync_pending(); 314 | } 315 | 316 | 317 | void synthv1_sched::sync_reset (void) 318 | { 319 | if (g_sched_thread) 320 | g_sched_thread->sync_reset(); 321 | } 322 | 323 | 324 | //------------------------------------------------------------------------- 325 | // synthv1_sched::Notifier - worker/schedule proxy decl. 326 | // 327 | 328 | // ctor. 329 | synthv1_sched::Notifier::Notifier ( synthv1 *pSynth ) 330 | : m_pSynth(pSynth) 331 | { 332 | g_sched_notifiers[pSynth].append(this); 333 | } 334 | 335 | 336 | // dtor. 337 | synthv1_sched::Notifier::~Notifier (void) 338 | { 339 | if (g_sched_notifiers.contains(m_pSynth)) { 340 | QList& list = g_sched_notifiers[m_pSynth]; 341 | list.removeAll(this); 342 | if (list.isEmpty()) 343 | g_sched_notifiers.remove(m_pSynth); 344 | } 345 | } 346 | 347 | 348 | // end of synthv1_sched.cpp 349 | -------------------------------------------------------------------------------- /src/synthv1_sched.h: -------------------------------------------------------------------------------- 1 | // synthv1_sched.h 2 | // 3 | /**************************************************************************** 4 | Copyright (C) 2012-2024, rncbc aka Rui Nuno Capela. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | *****************************************************************************/ 21 | 22 | #ifndef __synthv1_sched_h 23 | #define __synthv1_sched_h 24 | 25 | #include 26 | 27 | // forward decls. 28 | class synthv1; 29 | 30 | 31 | //------------------------------------------------------------------------- 32 | // synthv1_sched - worker/scheduled stuff (pure virtual). 33 | // 34 | 35 | class synthv1_sched 36 | { 37 | public: 38 | 39 | // plausible sched types. 40 | enum Type { Wave, Programs, Controls, Controller, MidiIn }; 41 | 42 | // ctor. 43 | synthv1_sched(synthv1 *pSynth, Type stype, uint32_t nsize = 8); 44 | 45 | // virtual dtor. 46 | virtual ~synthv1_sched(); 47 | 48 | // instance access. 49 | synthv1 *instance() const; 50 | 51 | // schedule process. 52 | void schedule(int sid = 0); 53 | 54 | // test-and-set wait. 55 | bool sync_wait(); 56 | 57 | // scheduled processor. 58 | void sync_process(); 59 | 60 | // (pure) virtual processor. 61 | virtual void process(int sid) = 0; 62 | 63 | // signal broadcast (static). 64 | static void sync_notify(synthv1 *pSynth, Type stype, int sid); 65 | 66 | // Notifier - Worker/schedule proxy decl. 67 | // 68 | class Notifier 69 | { 70 | public: 71 | 72 | // ctor. 73 | Notifier(synthv1 *pSynth); 74 | 75 | // dtor. 76 | virtual ~Notifier(); 77 | 78 | // signal notifier. 79 | virtual void notify(synthv1_sched::Type stype, int sid) const = 0; 80 | 81 | private: 82 | 83 | // instance variables. 84 | synthv1 *m_pSynth; 85 | }; 86 | 87 | // process/clear pending schedules, immediately. (static) 88 | static void sync_pending(); 89 | static void sync_reset(); 90 | 91 | private: 92 | 93 | // instance variables. 94 | synthv1 *m_pSynth; 95 | 96 | Type m_stype; 97 | 98 | // sched queue instance reference. 99 | uint32_t m_nsize; 100 | uint32_t m_nmask; 101 | 102 | int *m_items; 103 | 104 | volatile uint32_t m_iread; 105 | volatile uint32_t m_iwrite; 106 | 107 | volatile bool m_sync_wait; 108 | }; 109 | 110 | 111 | #endif // __synthv1_sched_h 112 | 113 | // end of synthv1_sched.h 114 | -------------------------------------------------------------------------------- /src/synthv1_tuning.h: -------------------------------------------------------------------------------- 1 | // synthv1_tuning.h 2 | // 3 | /**************************************************************************** 4 | Copyright (C) 2012-2021, rncbc aka Rui Nuno Capela. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | *****************************************************************************/ 21 | 22 | #ifndef __synthv1_tuning_h 23 | #define __synthv1_tuning_h 24 | 25 | #include 26 | #include 27 | 28 | //------------------------------------------------------------------------- 29 | // TuningMap 30 | // 31 | // -- borrowed, stirred and refactored from amsynth -- 32 | // https://github.com/amsynth/amsynth 33 | // Copyright (C) 2001-2012 Nick Dowell 34 | // 35 | 36 | /* 37 | * A TuningMap consists of two parts. 38 | * 39 | * The "key map" maps from MIDI note numbers to logical note numbers 40 | * for the scale. This is often the identity mapping, but if your 41 | * scale has, for example, 11 notes in it, you'll want to skip one 42 | * per octave so the scale lines up with the pattern of keys on a 43 | * standard keyboard. 44 | * 45 | * The "scale" maps from those logical note numbers to actual pitches. 46 | * In terms of member variables, "scale" and "scaleDesc" belong to the 47 | * scale, and everything else belongs to the mapping. 48 | * 49 | * For more information, refer to http://www.huygens-fokker.org/scala/ 50 | */ 51 | 52 | class synthv1_tuning 53 | { 54 | public: 55 | 56 | // Default reference note and pitch (A4 @440hz) 57 | synthv1_tuning(float refPitch = 440.0f, int refNote = 69); 58 | 59 | // Default 12-tone equal temperament, wstern standard mapping 60 | void reset(float refPitch, int refNote); 61 | 62 | // Reference note and pitch accessors. 63 | float refPitch() const { return m_refPitch; } 64 | int refNote() const { return m_refNote; } 65 | 66 | // Load custom Scala key map file (.kbm) 67 | bool loadKeyMapFile (const QString& filename); 68 | 69 | // Load custom Scala scale file (.scl) 70 | bool loadScaleFile (const QString& filename); 71 | 72 | const QString& keyMapFile() const { return m_keyMapFile; } 73 | 74 | const QString& scaleFile() const { return m_scaleFile; } 75 | const QString& scaleDesc() const { return m_scaleDesc; } 76 | 77 | // The main pitch/frequency (Hz) getter 78 | float noteToPitch(int note) const; 79 | 80 | protected: 81 | 82 | float parseScaleLine(const QString& line) const; 83 | 84 | void updateBasePitch(); 85 | 86 | private: 87 | 88 | // Instance member variables. 89 | QString m_keyMapFile; 90 | 91 | QString m_scaleFile; 92 | QString m_scaleDesc; 93 | 94 | QVector m_scale; 95 | 96 | float m_refPitch; 97 | int m_refNote; 98 | int m_zeroNote; 99 | int m_mapRepeatInc; 100 | float m_basePitch; 101 | 102 | QVector m_mapping; 103 | }; 104 | 105 | 106 | #endif // __synthv1_tuning_h 107 | 108 | // end of synthv1_tuning.h 109 | -------------------------------------------------------------------------------- /src/synthv1_ui.cpp: -------------------------------------------------------------------------------- 1 | // synthv1_ui.cpp 2 | // 3 | /**************************************************************************** 4 | Copyright (C) 2012-2025, rncbc aka Rui Nuno Capela. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | *****************************************************************************/ 21 | 22 | #include "synthv1_ui.h" 23 | 24 | #include "synthv1_param.h" 25 | 26 | 27 | //------------------------------------------------------------------------- 28 | // synthv1_ui - decl. 29 | // 30 | 31 | synthv1_ui::synthv1_ui ( synthv1 *pSynth, bool bPlugin ) 32 | : m_pSynth(pSynth), m_bPlugin(bPlugin) 33 | { 34 | } 35 | 36 | 37 | synthv1 *synthv1_ui::instance (void) const 38 | { 39 | return m_pSynth; 40 | } 41 | 42 | 43 | bool synthv1_ui::isPlugin (void) const 44 | { 45 | return m_bPlugin; 46 | } 47 | 48 | 49 | bool synthv1_ui::newPreset (void) 50 | { 51 | return synthv1_param::newPreset(m_pSynth); 52 | } 53 | 54 | 55 | bool synthv1_ui::loadPreset ( const QString& sFilename ) 56 | { 57 | return synthv1_param::loadPreset(m_pSynth, sFilename); 58 | } 59 | 60 | bool synthv1_ui::savePreset ( const QString& sFilename ) 61 | { 62 | return synthv1_param::savePreset(m_pSynth, sFilename); 63 | } 64 | 65 | 66 | void synthv1_ui::setParamValue ( synthv1::ParamIndex index, float fValue ) 67 | { 68 | m_pSynth->setParamValue(index, fValue); 69 | } 70 | 71 | float synthv1_ui::paramValue ( synthv1::ParamIndex index ) const 72 | { 73 | return m_pSynth->paramValue(index); 74 | } 75 | 76 | 77 | synthv1_controls *synthv1_ui::controls (void) const 78 | { 79 | return m_pSynth->controls(); 80 | } 81 | 82 | 83 | synthv1_programs *synthv1_ui::programs (void) const 84 | { 85 | return m_pSynth->programs(); 86 | } 87 | 88 | 89 | void synthv1_ui::reset (void) 90 | { 91 | return m_pSynth->reset(); 92 | } 93 | 94 | 95 | void synthv1_ui::updatePreset ( bool bDirty ) 96 | { 97 | m_pSynth->updatePreset(bDirty); 98 | } 99 | 100 | 101 | void synthv1_ui::updateParam ( synthv1::ParamIndex index ) 102 | { 103 | m_pSynth->updateParam(index); 104 | } 105 | 106 | 107 | void synthv1_ui::midiInEnabled ( bool bEnabled ) 108 | { 109 | m_pSynth->midiInEnabled(bEnabled); 110 | } 111 | 112 | 113 | uint32_t synthv1_ui::midiInCount (void) 114 | { 115 | return m_pSynth->midiInCount(); 116 | } 117 | 118 | 119 | void synthv1_ui::directNoteOn ( int note, int vel ) 120 | { 121 | m_pSynth->directNoteOn(note, vel); 122 | } 123 | 124 | 125 | void synthv1_ui::setTuningEnabled ( bool enabled ) 126 | { 127 | m_pSynth->setTuningEnabled(enabled); 128 | } 129 | 130 | bool synthv1_ui::isTuningEnabled (void) const 131 | { 132 | return m_pSynth->isTuningEnabled(); 133 | } 134 | 135 | 136 | void synthv1_ui::setTuningRefPitch ( float refPitch ) 137 | { 138 | m_pSynth->setTuningRefPitch(refPitch); 139 | } 140 | 141 | float synthv1_ui::tuningRefPitch (void) const 142 | { 143 | return m_pSynth->tuningRefPitch(); 144 | } 145 | 146 | 147 | void synthv1_ui::setTuningRefNote ( int refNote ) 148 | { 149 | m_pSynth->setTuningRefNote(refNote); 150 | } 151 | 152 | int synthv1_ui::tuningRefNote (void) const 153 | { 154 | return m_pSynth->tuningRefNote(); 155 | } 156 | 157 | 158 | void synthv1_ui::setTuningScaleFile ( const char *pszScaleFile ) 159 | { 160 | m_pSynth->setTuningScaleFile(pszScaleFile); 161 | } 162 | 163 | const char *synthv1_ui::tuningScaleFile (void) const 164 | { 165 | return m_pSynth->tuningScaleFile(); 166 | } 167 | 168 | 169 | void synthv1_ui::setTuningKeyMapFile ( const char *pszKeyMapFile ) 170 | { 171 | m_pSynth->setTuningKeyMapFile(pszKeyMapFile); 172 | } 173 | 174 | const char *synthv1_ui::tuningKeyMapFile (void) const 175 | { 176 | return m_pSynth->tuningKeyMapFile(); 177 | } 178 | 179 | 180 | void synthv1_ui::resetTuning (void) 181 | { 182 | m_pSynth->resetTuning(); 183 | } 184 | 185 | 186 | // MIDI note/octave name helper (static). 187 | QString synthv1_ui::noteName ( int note ) 188 | { 189 | static const char *s_notes[] = 190 | { 191 | QT_TR_NOOP("C"), 192 | QT_TR_NOOP("C#/Db"), 193 | QT_TR_NOOP("D"), 194 | QT_TR_NOOP("D#/Eb"), 195 | QT_TR_NOOP("E"), 196 | QT_TR_NOOP("F"), 197 | QT_TR_NOOP("F#/Gb"), 198 | QT_TR_NOOP("G"), 199 | QT_TR_NOOP("G#/Ab"), 200 | QT_TR_NOOP("A"), 201 | QT_TR_NOOP("A#/Bb"), 202 | QT_TR_NOOP("B") 203 | }; 204 | 205 | return QString("%1 %2").arg(s_notes[note % 12]).arg((note / 12) - 1); 206 | } 207 | 208 | 209 | // end of synthv1_ui.cpp 210 | -------------------------------------------------------------------------------- /src/synthv1_ui.h: -------------------------------------------------------------------------------- 1 | // synthv1_ui.h 2 | // 3 | /**************************************************************************** 4 | Copyright (C) 2012-2025, rncbc aka Rui Nuno Capela. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | *****************************************************************************/ 21 | 22 | #ifndef __synthv1_ui_h 23 | #define __synthv1_ui_h 24 | 25 | #include "synthv1.h" 26 | 27 | #include 28 | 29 | 30 | //------------------------------------------------------------------------- 31 | // synthv1_ui - decl. 32 | // 33 | 34 | class synthv1_ui 35 | { 36 | public: 37 | 38 | synthv1_ui(synthv1 *pSynth, bool bPlugin); 39 | 40 | synthv1 *instance() const; 41 | 42 | bool isPlugin() const; 43 | 44 | bool newPreset(); 45 | 46 | bool loadPreset(const QString& sFilename); 47 | bool savePreset(const QString& sFilename); 48 | 49 | void setParamValue(synthv1::ParamIndex index, float fValue); 50 | float paramValue(synthv1::ParamIndex index) const; 51 | 52 | synthv1_controls *controls() const; 53 | synthv1_programs *programs() const; 54 | 55 | void reset(); 56 | 57 | void updatePreset(bool bDirty); 58 | 59 | void updateParam(synthv1::ParamIndex index); 60 | 61 | void midiInEnabled(bool bEnabled); 62 | uint32_t midiInCount(); 63 | 64 | void directNoteOn(int note, int vel); 65 | 66 | void setTuningEnabled(bool enabled); 67 | bool isTuningEnabled() const; 68 | 69 | void setTuningRefPitch(float refPitch); 70 | float tuningRefPitch() const; 71 | 72 | void setTuningRefNote(int refNote); 73 | int tuningRefNote() const; 74 | 75 | void setTuningScaleFile(const char *pszScaleFile); 76 | const char *tuningScaleFile() const; 77 | 78 | void setTuningKeyMapFile(const char *pszKeyMapFile); 79 | const char *tuningKeyMapFile() const; 80 | 81 | void resetTuning(); 82 | 83 | // MIDI note/octave name helper. 84 | static QString noteName(int note); 85 | 86 | private: 87 | 88 | synthv1 *m_pSynth; 89 | 90 | bool m_bPlugin; 91 | }; 92 | 93 | 94 | #endif// __synthv1_ui_h 95 | 96 | // end of synthv1_ui.h 97 | -------------------------------------------------------------------------------- /src/synthv1widget.h: -------------------------------------------------------------------------------- 1 | // synthv1widget.h 2 | // 3 | /**************************************************************************** 4 | Copyright (C) 2012-2025, rncbc aka Rui Nuno Capela. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | *****************************************************************************/ 21 | 22 | #ifndef __synthv1widget_h 23 | #define __synthv1widget_h 24 | 25 | #include "synthv1_config.h" 26 | #include "synthv1_sched.h" 27 | 28 | #include "synthv1_ui.h" 29 | 30 | #include 31 | 32 | 33 | // forward decls. 34 | namespace Ui { class synthv1widget; } 35 | 36 | class synthv1widget_param; 37 | class synthv1widget_sched; 38 | 39 | 40 | //------------------------------------------------------------------------- 41 | // synthv1widget - decl. 42 | // 43 | 44 | class synthv1widget : public QWidget 45 | { 46 | Q_OBJECT 47 | 48 | public: 49 | 50 | // Constructor 51 | synthv1widget(QWidget *pParent = nullptr); 52 | 53 | // Destructor. 54 | virtual ~synthv1widget(); 55 | 56 | // Open/close the scheduler/work notifier. 57 | void openSchedNotifier(); 58 | void closeSchedNotifier(); 59 | 60 | // Param port accessors. 61 | void setParamValue(synthv1::ParamIndex index, float fValue); 62 | float paramValue(synthv1::ParamIndex index) const; 63 | 64 | // Param kbob (widget) mapper. 65 | void setParamKnob(synthv1::ParamIndex index, synthv1widget_param *pKnob); 66 | synthv1widget_param *paramKnob(synthv1::ParamIndex index) const; 67 | 68 | // Preset init. 69 | void initPreset(); 70 | // Preset clear. 71 | void clearPreset(); 72 | 73 | // Dirty close prompt, 74 | bool queryClose(); 75 | 76 | // Update visual configuration. 77 | void updateConfig(); 78 | 79 | public slots: 80 | 81 | // Preset file I/O. 82 | bool loadPreset(const QString& sFilename); 83 | bool savePreset(const QString& sFilename); 84 | 85 | // Direct note-on/off slot. 86 | void directNoteOn(int iNote, int iVelocity); 87 | 88 | protected slots: 89 | 90 | // Preset renewal. 91 | void newPreset(); 92 | 93 | // Param knob (widget) slots. 94 | void paramChanged(float fValue); 95 | 96 | // Reset param knobs to default value. 97 | void resetParams(); 98 | 99 | // Randomize params (partial). 100 | void randomParams(); 101 | 102 | // Swap params A/B. 103 | void swapParams(bool bOn); 104 | 105 | // Panic: all-notes/sound-off (reset). 106 | void panic(); 107 | 108 | // Schedule notification updater. 109 | void updateSchedNotify(int stype, int sid); 110 | 111 | // MIDI In LED timeout. 112 | void midiInLedTimeout(); 113 | 114 | // Keyboard note range change. 115 | void noteRangeChanged(); 116 | 117 | // Param knob context menu. 118 | void paramContextMenu(const QPoint& pos); 119 | 120 | // Menu actions. 121 | void helpConfigure(); 122 | 123 | void helpAbout(); 124 | void helpAboutQt(); 125 | 126 | protected: 127 | 128 | // Synth engine accessor. 129 | virtual synthv1_ui *ui_instance() const = 0; 130 | 131 | // Reset swap params A/B group. 132 | void resetSwapParams(); 133 | 134 | // Initialize all param/knob values. 135 | void updateParamValues(); 136 | 137 | // Reset all param/knob default values. 138 | void resetParamValues(); 139 | void resetParamKnobs(); 140 | 141 | // Param port methods. 142 | virtual void updateParam(synthv1::ParamIndex index, float fValue) const = 0; 143 | 144 | // Update local tied widgets. 145 | void updateParamEx(synthv1::ParamIndex index, float fValue); 146 | 147 | // Update scheduled controllers param/knob widgets. 148 | void updateSchedParam(synthv1::ParamIndex index, float fValue); 149 | 150 | // Preset status updater. 151 | void updateLoadPreset(const QString& sPreset); 152 | 153 | // Dirty flag (overridable virtual) methods. 154 | virtual void updateDirtyPreset(bool bDirtyPreset); 155 | 156 | // Show/hide dget handlers. 157 | void showEvent(QShowEvent *pShowEvent); 158 | void hideEvent(QHideEvent *pHideEvent); 159 | 160 | private: 161 | 162 | // Instance variables. 163 | Ui::synthv1widget *p_ui; 164 | Ui::synthv1widget& m_ui; 165 | 166 | synthv1widget_sched *m_sched_notifier; 167 | 168 | QHash m_paramKnobs; 169 | QHash m_knobParams; 170 | 171 | float m_params_ab[synthv1::NUM_PARAMS]; 172 | 173 | int m_iUpdate; 174 | }; 175 | 176 | 177 | //------------------------------------------------------------------------- 178 | // synthv1widget_sched - worker/schedule proxy decl. 179 | // 180 | 181 | class synthv1widget_sched : public QObject 182 | { 183 | Q_OBJECT 184 | 185 | public: 186 | 187 | // ctor. 188 | synthv1widget_sched(synthv1 *pSynth, QObject *pParent = nullptr) 189 | : QObject(pParent), m_notifier(pSynth, this) {} 190 | 191 | signals: 192 | 193 | // Notification signal. 194 | void notify(int stype, int sid); 195 | 196 | protected: 197 | 198 | // Notififier visitor. 199 | class Notifier : public synthv1_sched::Notifier 200 | { 201 | public: 202 | 203 | Notifier(synthv1 *pSynth, synthv1widget_sched *pSched) 204 | : synthv1_sched::Notifier(pSynth), m_pSched(pSched) {} 205 | 206 | void notify(synthv1_sched::Type stype, int sid) const 207 | { m_pSched->emit_notify(stype, sid); } 208 | 209 | private: 210 | 211 | synthv1widget_sched *m_pSched; 212 | }; 213 | 214 | // Notification method. 215 | void emit_notify(synthv1_sched::Type stype, int sid) 216 | { emit notify(int(stype), sid); } 217 | 218 | private: 219 | 220 | // Instance variables. 221 | Notifier m_notifier; 222 | }; 223 | 224 | 225 | #endif // __synthv1widget_h 226 | 227 | // end of synthv1widget.h 228 | -------------------------------------------------------------------------------- /src/synthv1widget_config.h: -------------------------------------------------------------------------------- 1 | // synthv1widget_config.h 2 | // 3 | /**************************************************************************** 4 | Copyright (C) 2012-2024, rncbc aka Rui Nuno Capela. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | *****************************************************************************/ 21 | 22 | #ifndef __synthv1widget_config_h 23 | #define __synthv1widget_config_h 24 | 25 | #include "synthv1_config.h" 26 | 27 | #include 28 | 29 | 30 | // forward decls. 31 | namespace Ui { class synthv1widget_config; } 32 | 33 | class synthv1widget; 34 | class synthv1_ui; 35 | 36 | class QComboBox; 37 | class QFileInfo; 38 | 39 | 40 | //---------------------------------------------------------------------------- 41 | // synthv1widget_config -- UI wrapper form. 42 | 43 | class synthv1widget_config : public QDialog 44 | { 45 | Q_OBJECT 46 | 47 | public: 48 | 49 | // ctor. 50 | synthv1widget_config(synthv1widget *pParent, synthv1_ui *pSynthUi); 51 | 52 | // dtor. 53 | ~synthv1widget_config(); 54 | 55 | // UI instance accessors. 56 | synthv1_ui *ui_instance() const; 57 | 58 | protected slots: 59 | 60 | // command slots. 61 | void editCustomColorThemes(); 62 | 63 | void controlsAddItem(); 64 | void controlsEditItem(); 65 | void controlsDeleteItem(); 66 | 67 | void programsAddBankItem(); 68 | void programsAddItem(); 69 | void programsEditItem(); 70 | void programsDeleteItem(); 71 | 72 | // janitorial slots. 73 | void controlsCurrentChanged(); 74 | void controlsContextMenuRequested(const QPoint&); 75 | 76 | void programsCurrentChanged(); 77 | void programsActivated(); 78 | void programsContextMenuRequested(const QPoint&); 79 | 80 | void controlsEnabled(bool); 81 | void programsEnabled(bool); 82 | 83 | void tuningTabChanged(int); 84 | void tuningRefNoteClicked(); 85 | void tuningScaleFileClicked(); 86 | void tuningKeyMapFileClicked(); 87 | 88 | void tuningChanged(); 89 | void controlsChanged(); 90 | void programsChanged(); 91 | void optionsChanged(); 92 | 93 | // dialog slots. 94 | void accept(); 95 | void reject(); 96 | 97 | protected: 98 | 99 | // Custom color/style themes settlers. 100 | void resetCustomColorThemes(const QString& sCustomColorTheme); 101 | void resetCustomStyleThemes(const QString& sCustomColorTheme); 102 | 103 | // Combo box history persistence helper prototypes. 104 | void loadComboBoxHistory(QComboBox *pComboBox); 105 | void saveComboBoxHistory(QComboBox *pComboBox); 106 | 107 | // Combo box settter/gettter helper prototypes. 108 | bool setComboBoxCurrentItem(QComboBox *pComboBox, const QFileInfo& info); 109 | QString comboBoxCurrentItem(QComboBox *pComboBox); 110 | 111 | // Programs/preset preview stuff... 112 | void loadPreset(const QString& sPreset); 113 | 114 | // stabilizer. 115 | void stabilize(); 116 | 117 | private: 118 | 119 | // UI struct. 120 | Ui::synthv1widget_config *p_ui; 121 | Ui::synthv1widget_config& m_ui; 122 | 123 | // Instance reference. 124 | synthv1_ui *m_pSynthUi; 125 | 126 | // Dialog dirty flag. 127 | int m_iDirtyTuning; 128 | int m_iDirtyControls; 129 | int m_iDirtyPrograms; 130 | int m_iDirtyOptions; 131 | 132 | // Programs/preset related stuff... 133 | bool m_bPresets; 134 | 135 | int m_iLoadPreset; 136 | QString m_sSavePreset; 137 | }; 138 | 139 | 140 | #endif // __synthv1widget_config_h 141 | 142 | // end of synthv1widget_config.h 143 | -------------------------------------------------------------------------------- /src/synthv1widget_control.h: -------------------------------------------------------------------------------- 1 | // synthv1widget_control.h 2 | // 3 | /**************************************************************************** 4 | Copyright (C) 2012-2022, rncbc aka Rui Nuno Capela. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | *****************************************************************************/ 21 | 22 | #ifndef __synthv1widget_control_h 23 | #define __synthv1widget_control_h 24 | 25 | #include "synthv1_controls.h" 26 | #include "synthv1_param.h" 27 | 28 | #include 29 | 30 | 31 | // forward decls. 32 | namespace Ui { class synthv1widget_control; } 33 | 34 | class QAbstractButton; 35 | class QCloseEvent; 36 | 37 | 38 | //---------------------------------------------------------------------------- 39 | // synthv1widget_control -- UI wrapper form. 40 | 41 | class synthv1widget_control : public QDialog 42 | { 43 | Q_OBJECT 44 | 45 | public: 46 | 47 | // Pseudo-singleton instance. 48 | static synthv1widget_control *getInstance(); 49 | 50 | // Pseudo-constructor. 51 | static void showInstance( 52 | synthv1_controls *pControls, synthv1::ParamIndex index, 53 | const QString& sTitle, QWidget *pParent = nullptr); 54 | 55 | // Control accessors. 56 | void setControls(synthv1_controls *pControls, synthv1::ParamIndex index); 57 | synthv1_controls *controls() const; 58 | synthv1::ParamIndex controlIndex() const; 59 | 60 | // Process incoming controller key event. 61 | void setControlKey(const synthv1_controls::Key& key); 62 | synthv1_controls::Key controlKey() const; 63 | 64 | protected slots: 65 | 66 | void changed(); 67 | 68 | void clicked(QAbstractButton *); 69 | void reset(); 70 | 71 | void accept(); 72 | void reject(); 73 | 74 | void activateControlType(int); 75 | void editControlParamFinished(); 76 | 77 | void stabilize(); 78 | 79 | protected: 80 | 81 | // Constructor. 82 | synthv1widget_control(QWidget *pParent = nullptr); 83 | 84 | // Destructor. 85 | ~synthv1widget_control(); 86 | 87 | // Pseudo-destructor. 88 | void cleanup(); 89 | 90 | void closeEvent(QCloseEvent *pCloseEvent); 91 | 92 | // Control type dependency refresh. 93 | void updateControlType(int iControlType); 94 | 95 | void setControlType(synthv1_controls::Type ctype); 96 | synthv1_controls::Type controlType() const; 97 | 98 | void setControlParam(unsigned short param); 99 | unsigned short controlParam() const; 100 | 101 | unsigned short controlChannel() const; 102 | 103 | synthv1_controls::Type controlTypeFromIndex (int iIndex) const; 104 | int indexFromControlType(synthv1_controls::Type ctype) const; 105 | 106 | unsigned short controlParamFromIndex(int iIndex) const; 107 | int indexFromControlParam(unsigned short param) const; 108 | 109 | private: 110 | 111 | // The Qt-designer UI struct... 112 | Ui::synthv1widget_control *p_ui; 113 | Ui::synthv1widget_control& m_ui; 114 | 115 | // Instance variables. 116 | synthv1_controls *m_pControls; 117 | 118 | // Target subject. 119 | synthv1_controls::Key m_key; 120 | synthv1::ParamIndex m_index; 121 | 122 | // Instance variables. 123 | int m_iControlParamUpdate; 124 | 125 | int m_iDirtyCount; 126 | int m_iDirtySetup; 127 | 128 | // Pseudo-singleton instance. 129 | static synthv1widget_control *g_pInstance; 130 | }; 131 | 132 | 133 | #endif // __synthv1widget_control_h 134 | 135 | 136 | // end of synthv1widget_control.h 137 | -------------------------------------------------------------------------------- /src/synthv1widget_control.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | rncbc aka Rui Nuno Capela 4 | synthv1 - an old-school polyphonic synthesizer 5 | 6 | Copyright (C) 2012-2020, rncbc aka Rui Nuno Capela. All rights reserved. 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU General Public License 10 | as published by the Free Software Foundation; either version 2 11 | of the License, or (at your option) 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 along 19 | with this program; if not, write to the Free Software Foundation, Inc., 20 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 21 | 22 | 23 | synthv1widget_control 24 | 25 | 26 | 27 | 0 28 | 0 29 | 320 30 | 120 31 | 32 | 33 | 34 | MIDI Controller 35 | 36 | 37 | :/images/synthv1_control.png 38 | 39 | 40 | 41 | 42 | 43 | &Type: 44 | 45 | 46 | ControlTypeComboBox 47 | 48 | 49 | 50 | 51 | 52 | 53 | MIDI event type 54 | 55 | 56 | 57 | 58 | 59 | 60 | &Channel: 61 | 62 | 63 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 64 | 65 | 66 | ControlChannelSpinBox 67 | 68 | 69 | 70 | 71 | 72 | 73 | MIDI channel 74 | 75 | 76 | Auto 77 | 78 | 79 | false 80 | 81 | 82 | 0 83 | 84 | 85 | 16 86 | 87 | 88 | 89 | 90 | 91 | 92 | &Parameter: 93 | 94 | 95 | ControlParamComboBox 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 220 104 | 0 105 | 106 | 107 | 108 | MIDI parameter 109 | 110 | 111 | 112 | 113 | 114 | 115 | &Logarithmic 116 | 117 | 118 | 119 | 120 | 121 | 122 | &Invert 123 | 124 | 125 | 126 | 127 | 128 | 129 | &Hook 130 | 131 | 132 | 133 | 134 | 135 | 136 | Qt::Vertical 137 | 138 | 139 | 140 | 20 141 | 8 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | Qt::Horizontal 150 | 151 | 152 | QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Reset 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | ControlTypeComboBox 161 | ControlChannelSpinBox 162 | ControlParamComboBox 163 | ControlLogarithmicCheckBox 164 | ControlInvertCheckBox 165 | ControlHookCheckBox 166 | DialogButtonBox 167 | 168 | 169 | 170 | 171 | 172 | 173 | -------------------------------------------------------------------------------- /src/synthv1widget_controls.h: -------------------------------------------------------------------------------- 1 | // synthv1widget_controls.h 2 | // 3 | /**************************************************************************** 4 | Copyright (C) 2012-2023, rncbc aka Rui Nuno Capela. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | *****************************************************************************/ 21 | 22 | #ifndef __synthv1widget_controls_h 23 | #define __synthv1widget_controls_h 24 | 25 | #include 26 | 27 | #include 28 | 29 | 30 | // forward decls. 31 | class synthv1_controls; 32 | 33 | 34 | //---------------------------------------------------------------------------- 35 | // synthv1widget_controls -- Custom (tree) widget. 36 | 37 | class synthv1widget_controls : public QTreeWidget 38 | { 39 | Q_OBJECT 40 | 41 | public: 42 | 43 | // ctor. 44 | synthv1widget_controls(QWidget *pParent = nullptr); 45 | // dtor. 46 | ~synthv1widget_controls(); 47 | 48 | // utilities. 49 | void loadControls(synthv1_controls *pControls); 50 | void saveControls(synthv1_controls *pControls); 51 | 52 | // controller name utilities. 53 | typedef QMap Names; 54 | 55 | static const Names& controllerNames(); 56 | static const Names& rpnNames(); 57 | static const Names& nrpnNames(); 58 | static const Names& control14Names(); 59 | 60 | public slots: 61 | 62 | // slots. 63 | void addControlItem(); 64 | 65 | protected slots: 66 | 67 | // private slots. 68 | void itemChangedSlot(QTreeWidgetItem *, int); 69 | 70 | protected: 71 | 72 | // item delegate decl.. 73 | class ItemDelegate; 74 | 75 | // factory methods. 76 | QTreeWidgetItem *newControlItem(); 77 | }; 78 | 79 | 80 | #endif // __synthv1widget_controls_h 81 | 82 | // end of synthv1widget_controls.h 83 | -------------------------------------------------------------------------------- /src/synthv1widget_env.h: -------------------------------------------------------------------------------- 1 | // synthv1widget_env.h 2 | // 3 | /**************************************************************************** 4 | Copyright (C) 2012-2021, rncbc aka Rui Nuno Capela. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | *****************************************************************************/ 21 | 22 | #ifndef __synthv1widget_env_h 23 | #define __synthv1widget_env_h 24 | 25 | #include 26 | #include 27 | 28 | 29 | //---------------------------------------------------------------------------- 30 | // synthv1widget_env -- Custom widget 31 | 32 | class synthv1widget_env : public QFrame 33 | { 34 | Q_OBJECT 35 | 36 | public: 37 | 38 | // Constructor. 39 | synthv1widget_env(QWidget *pParent = nullptr); 40 | // Destructor. 41 | ~synthv1widget_env(); 42 | 43 | // Parameter getters. 44 | float attack() const; 45 | float decay() const; 46 | float sustain() const; 47 | float release() const; 48 | 49 | public slots: 50 | 51 | // Parameter setters. 52 | void setAttack(float fAttack); 53 | void setDecay(float fDecay); 54 | void setSustain(float fSustain); 55 | void setRelease(float fRelease); 56 | 57 | signals: 58 | 59 | // Parameter change signals. 60 | void attackChanged(float fAttack); 61 | void decayChanged(float fDecay); 62 | void sustainChanged(float fSustain); 63 | void releaseChanged(float fRelease); 64 | 65 | protected: 66 | 67 | // Draw canvas. 68 | void paintEvent(QPaintEvent *); 69 | 70 | // Parameter node indexes. 71 | enum NodeIndex { 72 | Idle = 1, 73 | Attack = 2, 74 | Decay = 3, 75 | Sustain = 4, 76 | Release = 5, 77 | End = 6 78 | }; 79 | 80 | // Draw rectangular point. 81 | QRect nodeRect(int iNode) const; 82 | int nodeIndex(const QPoint& pos) const; 83 | 84 | void dragNode(const QPoint& pos); 85 | 86 | // Mouse interaction. 87 | void mousePressEvent(QMouseEvent *pMouseEvent); 88 | void mouseMoveEvent(QMouseEvent *pMouseEvent); 89 | void mouseReleaseEvent(QMouseEvent *pMouseEvent); 90 | 91 | // Resize canvas. 92 | void resizeEvent(QResizeEvent *); 93 | 94 | // Update the drawing polygon. 95 | void updatePolygon(); 96 | 97 | private: 98 | 99 | // Instance state. 100 | float m_fAttack; 101 | float m_fDecay; 102 | float m_fSustain; 103 | float m_fRelease; 104 | 105 | // Draw state. 106 | QPolygon m_poly; 107 | 108 | // Drag state. 109 | int m_iDragNode; 110 | QPoint m_posDrag; 111 | }; 112 | 113 | #endif // __synthv1widget_env_h 114 | 115 | 116 | // end of synthv1widget_env.h 117 | -------------------------------------------------------------------------------- /src/synthv1widget_filt.h: -------------------------------------------------------------------------------- 1 | // synthv1widget_filt.h 2 | // 3 | /**************************************************************************** 4 | Copyright (C) 2012-2021, rncbc aka Rui Nuno Capela. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | *****************************************************************************/ 21 | 22 | #ifndef __synthv1widget_filt_h 23 | #define __synthv1widget_filt_h 24 | 25 | #include 26 | #include 27 | 28 | 29 | //---------------------------------------------------------------------------- 30 | // synthv1widget_filt -- Custom widget 31 | 32 | class synthv1widget_filt : public QFrame 33 | { 34 | Q_OBJECT 35 | 36 | public: 37 | 38 | // Constructor. 39 | synthv1widget_filt(QWidget *pParent = nullptr); 40 | // Destructor. 41 | ~synthv1widget_filt(); 42 | 43 | // Parameter getters. 44 | float cutoff() const; 45 | float reso() const; 46 | float type() const; 47 | float slope() const; 48 | 49 | public slots: 50 | 51 | // Parameter setters. 52 | void setCutoff(float fCutoff); 53 | void setReso(float fReso); 54 | void setType(float fType); 55 | void setSlope(float fSlope); 56 | 57 | signals: 58 | 59 | // Parameter change signals. 60 | void cutoffChanged(float fCutoff); 61 | void resoChanged(float fReso); 62 | 63 | protected: 64 | 65 | // Draw canvas. 66 | void paintEvent(QPaintEvent *); 67 | 68 | // Filter types/slopes. 69 | enum Types { 70 | LPF = 0, 71 | BPF = 1, 72 | HPF = 2, 73 | BRF = 3, 74 | L2F = 4 75 | }; 76 | 77 | enum Slopes { 78 | S12DB = 0, 79 | S24DB = 1, 80 | SBIQUAD = 2, 81 | SFORMANT = 3 82 | }; 83 | 84 | // Drag/move curve. 85 | void dragCurve(const QPoint& pos); 86 | 87 | // Mouse interaction. 88 | void mousePressEvent(QMouseEvent *pMouseEvent); 89 | void mouseMoveEvent(QMouseEvent *pMouseEvent); 90 | void mouseReleaseEvent(QMouseEvent *pMouseEvent); 91 | void wheelEvent(QWheelEvent *pWheelEvent); 92 | 93 | // Resize canvas. 94 | void resizeEvent(QResizeEvent *); 95 | 96 | // Update the drawing path. 97 | void updatePath(); 98 | 99 | private: 100 | 101 | // Instance state. 102 | float m_fCutoff; 103 | float m_fReso; 104 | int m_iType; 105 | int m_iSlope; 106 | 107 | // Drag state. 108 | bool m_bDragging; 109 | QPoint m_posDrag; 110 | 111 | // Drawable path. 112 | QPainterPath m_path; 113 | }; 114 | 115 | #endif // __synthv1widget_filt_h 116 | 117 | 118 | // end of synthv1widget_filt.h 119 | -------------------------------------------------------------------------------- /src/synthv1widget_jack.cpp: -------------------------------------------------------------------------------- 1 | // synthv1widget_jack.cpp 2 | // 3 | /**************************************************************************** 4 | Copyright (C) 2012-2025, rncbc aka Rui Nuno Capela. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | *****************************************************************************/ 21 | 22 | #include "synthv1widget_jack.h" 23 | 24 | #include "synthv1widget_palette.h" 25 | 26 | #include "synthv1_jack.h" 27 | 28 | #ifdef CONFIG_NSM 29 | #include "synthv1_nsm.h" 30 | #endif 31 | 32 | #include 33 | #include 34 | #include 35 | 36 | #include 37 | 38 | #include 39 | 40 | #ifndef CONFIG_BINDIR 41 | #define CONFIG_BINDIR CONFIG_PREFIX "/bin" 42 | #endif 43 | 44 | #ifndef CONFIG_LIBDIR 45 | #if defined(__x86_64__) 46 | #define CONFIG_LIBDIR CONFIG_PREFIX "/lib64" 47 | #else 48 | #define CONFIG_LIBDIR CONFIG_PREFIX "/lib" 49 | #endif 50 | #endif 51 | 52 | #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) 53 | #define CONFIG_PLUGINSDIR CONFIG_LIBDIR "/qt4/plugins" 54 | #elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 55 | #define CONFIG_PLUGINSDIR CONFIG_LIBDIR "/qt5/plugins" 56 | #else 57 | #define CONFIG_PLUGINSDIR CONFIG_LIBDIR "/qt6/plugins" 58 | #endif 59 | 60 | 61 | //------------------------------------------------------------------------- 62 | // synthv1widget_jack - impl. 63 | // 64 | 65 | // Constructor. 66 | synthv1widget_jack::synthv1widget_jack ( synthv1_jack *pSynth ) 67 | : synthv1widget(), m_pSynth(pSynth) 68 | #ifdef CONFIG_NSM 69 | , m_pNsmClient(nullptr) 70 | #endif 71 | { 72 | // Special style paths... 73 | QString sPluginsPath = QApplication::applicationDirPath(); 74 | sPluginsPath.remove(CONFIG_BINDIR); 75 | sPluginsPath.append(CONFIG_PLUGINSDIR); 76 | if (QDir(sPluginsPath).exists()) 77 | QApplication::addLibraryPath(sPluginsPath); 78 | 79 | // Custom color/style themes... 80 | synthv1_config *pConfig = synthv1_config::getInstance(); 81 | if (pConfig) { 82 | const QChar sep = QDir::separator(); 83 | QString sPalettePath = QApplication::applicationDirPath(); 84 | sPalettePath.remove(CONFIG_BINDIR); 85 | sPalettePath.append(CONFIG_DATADIR); 86 | sPalettePath.append(sep); 87 | sPalettePath.append(PROJECT_NAME); 88 | sPalettePath.append(sep); 89 | sPalettePath.append("palette"); 90 | if (QDir(sPalettePath).exists()) { 91 | QStringList names; 92 | names.append("KXStudio"); 93 | names.append("Wonton Soup"); 94 | QStringListIterator name_iter(names); 95 | while (name_iter.hasNext()) { 96 | const QString& name = name_iter.next(); 97 | const QFileInfo fi(sPalettePath, name + ".conf"); 98 | if (fi.isReadable()) { 99 | synthv1widget_palette::addNamedPaletteConf( 100 | pConfig, name, fi.absoluteFilePath()); 101 | } 102 | } 103 | } 104 | if (!pConfig->sCustomColorTheme.isEmpty()) { 105 | QPalette pal; 106 | if (synthv1widget_palette::namedPalette( 107 | pConfig, pConfig->sCustomColorTheme, pal)) 108 | synthv1widget::setPalette(pal); 109 | } 110 | if (!pConfig->sCustomStyleTheme.isEmpty()) { 111 | QApplication::setStyle( 112 | QStyleFactory::create(pConfig->sCustomStyleTheme)); 113 | } 114 | } 115 | 116 | // Initialize (user) interface stuff... 117 | m_pSynthUi = new synthv1_ui(m_pSynth, false); 118 | 119 | // Initialise preset stuff... 120 | clearPreset(); 121 | 122 | // Initial update, always... 123 | resetParamValues(); 124 | resetParamKnobs(); 125 | 126 | // May initialize the scheduler/work notifier. 127 | openSchedNotifier(); 128 | } 129 | 130 | 131 | // Destructor. 132 | synthv1widget_jack::~synthv1widget_jack (void) 133 | { 134 | delete m_pSynthUi; 135 | } 136 | 137 | 138 | // Synth engine accessor. 139 | synthv1_ui *synthv1widget_jack::ui_instance (void) const 140 | { 141 | return m_pSynthUi; 142 | } 143 | 144 | #ifdef CONFIG_NSM 145 | 146 | // NSM client accessors. 147 | void synthv1widget_jack::setNsmClient ( synthv1_nsm *pNsmClient ) 148 | { 149 | m_pNsmClient = pNsmClient; 150 | } 151 | 152 | synthv1_nsm *synthv1widget_jack::nsmClient (void) const 153 | { 154 | return m_pNsmClient; 155 | } 156 | 157 | #endif // CONFIG_NSM 158 | 159 | 160 | // Param port method. 161 | void synthv1widget_jack::updateParam ( 162 | synthv1::ParamIndex index, float fValue ) const 163 | { 164 | m_pSynthUi->setParamValue(index, fValue); 165 | } 166 | 167 | 168 | // Dirty flag method. 169 | void synthv1widget_jack::updateDirtyPreset ( bool bDirtyPreset ) 170 | { 171 | synthv1widget::updateDirtyPreset(bDirtyPreset); 172 | 173 | #ifdef CONFIG_NSM 174 | if (m_pNsmClient && m_pNsmClient->is_active() && bDirtyPreset) 175 | m_pNsmClient->dirty(true); 176 | #endif 177 | } 178 | 179 | 180 | // Application close. 181 | void synthv1widget_jack::closeEvent ( QCloseEvent *pCloseEvent ) 182 | { 183 | #ifdef CONFIG_NSM 184 | if (m_pNsmClient && m_pNsmClient->is_active()) { 185 | pCloseEvent->ignore(); 186 | synthv1widget::hide(); 187 | } 188 | else 189 | #endif 190 | // Let's be sure about that... 191 | if (queryClose()) { 192 | pCloseEvent->accept(); 193 | #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) 194 | QApplication::exit(0); 195 | #else 196 | QApplication::quit(); 197 | #endif 198 | } else { 199 | pCloseEvent->ignore(); 200 | } 201 | } 202 | 203 | 204 | #ifdef CONFIG_NSM 205 | 206 | // Optional GUI handlers. 207 | void synthv1widget_jack::showEvent ( QShowEvent *pShowEvent ) 208 | { 209 | synthv1widget::showEvent(pShowEvent); 210 | 211 | if (m_pNsmClient) 212 | m_pNsmClient->visible(true); 213 | } 214 | 215 | void synthv1widget_jack::hideEvent ( QHideEvent *pHideEvent ) 216 | { 217 | if (m_pNsmClient) 218 | m_pNsmClient->visible(false); 219 | 220 | synthv1widget::hideEvent(pHideEvent); 221 | } 222 | 223 | #endif // CONFIG_NSM 224 | 225 | 226 | // end of synthv1widget_jack.cpp 227 | -------------------------------------------------------------------------------- /src/synthv1widget_jack.h: -------------------------------------------------------------------------------- 1 | // synthv1widget_jack.h 2 | // 3 | /**************************************************************************** 4 | Copyright (C) 2012-2025, rncbc aka Rui Nuno Capela. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | *****************************************************************************/ 21 | 22 | #ifndef __synthv1widget_jack_h 23 | #define __synthv1widget_jack_h 24 | 25 | #include "synthv1widget.h" 26 | 27 | 28 | // Forward decls. 29 | class synthv1_jack; 30 | 31 | #ifdef CONFIG_NSM 32 | class synthv1_nsm; 33 | #endif 34 | 35 | 36 | //------------------------------------------------------------------------- 37 | // synthv1widget_jack - decl. 38 | // 39 | 40 | class synthv1widget_jack : public synthv1widget 41 | { 42 | public: 43 | 44 | // Constructor. 45 | synthv1widget_jack(synthv1_jack *pSynth); 46 | 47 | // Destructor. 48 | ~synthv1widget_jack(); 49 | 50 | #ifdef CONFIG_NSM 51 | // NSM client accessors. 52 | void setNsmClient(synthv1_nsm *pNsmClient); 53 | synthv1_nsm *nsmClient() const; 54 | #endif // CONFIG_NSM 55 | 56 | // Dirty flag method. 57 | void updateDirtyPreset(bool bDirtyPreset); 58 | 59 | protected: 60 | 61 | // Synth engine accessor. 62 | synthv1_ui *ui_instance() const; 63 | 64 | // Param port method. 65 | void updateParam(synthv1::ParamIndex index, float fValue) const; 66 | 67 | // Application close. 68 | void closeEvent(QCloseEvent *pCloseEvent); 69 | 70 | #ifdef CONFIG_NSM 71 | // Optional GUI handlers. 72 | void showEvent(QShowEvent *pShowEvent); 73 | void hideEvent(QHideEvent *pHideEvent); 74 | #endif // CONFIG_NSM 75 | 76 | private: 77 | 78 | // Instance variables. 79 | synthv1 *m_pSynth; 80 | synthv1_ui *m_pSynthUi; 81 | 82 | #ifdef CONFIG_NSM 83 | synthv1_nsm *m_pNsmClient; 84 | #endif 85 | }; 86 | 87 | 88 | #endif // __synthv1widget_jack_h 89 | 90 | // end of synthv1widget_jack.h 91 | -------------------------------------------------------------------------------- /src/synthv1widget_keybd.h: -------------------------------------------------------------------------------- 1 | // synthv1widget_keybd.h 2 | // 3 | /**************************************************************************** 4 | Copyright (C) 2012-2025, rncbc aka Rui Nuno Capela. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | *****************************************************************************/ 21 | 22 | #ifndef __synthv1widget_keybd_h 23 | #define __synthv1widget_keybd_h 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | 30 | //------------------------------------------------------------------------- 31 | // synthv1widget_keybd - A horizontal piano keyboard widget. 32 | 33 | class synthv1widget_keybd : public QWidget 34 | { 35 | Q_OBJECT 36 | 37 | public: 38 | 39 | // Constructor. 40 | synthv1widget_keybd(QWidget *pParent = 0); 41 | 42 | // Note range predicate. 43 | void setNoteRange(bool bNoteRange); 44 | bool isNoteRange() const; 45 | 46 | // Note enabled predicates. 47 | void setNoteEnabled(int iNote, bool bEnabled); 48 | bool isNoteEnabled(int iNote) const; 49 | 50 | void setAllNotesEnabled(bool bEnabled); 51 | 52 | // Default note-on velocity. 53 | void setVelocity(int iVelocity); 54 | int velocity() const; 55 | 56 | // Keyboard note range getters. 57 | int noteLow() const; 58 | int noteHigh() const; 59 | 60 | // Highlighted note getter. 61 | int noteKey() const; 62 | 63 | public slots: 64 | 65 | // Keyboard note range setters. 66 | void setNoteLow(int iNoteLow); 67 | void setNoteHigh(int iNoteHigh); 68 | 69 | // Keyboard note/key actions. 70 | void noteOn(int iNote); 71 | void noteOff(int iNote); 72 | 73 | void allNotesOff(); 74 | 75 | // Highlighted note setter. 76 | void setNoteKey(int iNoteKey); 77 | 78 | signals: 79 | 80 | // Piano keyboard note-on/off signal. 81 | void noteOnClicked(int iNote, int iVelocity); 82 | 83 | // Keyboard note range changed signal. 84 | void noteRangeChanged(); 85 | 86 | protected slots: 87 | 88 | // Kill dangling notes, if any... 89 | void allNotesTimeout(); 90 | 91 | protected: 92 | 93 | // Keyboard note range sanitizers. 94 | int safeNoteLow(int iNoteLow) const; 95 | int safeNoteHigh(int iNoteHigh) const; 96 | 97 | // Piano key rectangle finder. 98 | QRect noteRect(int iNote, bool bOn = false) const; 99 | QPainterPath notePath(int iNote, bool bOn = false) const; 100 | 101 | // Piano keyboard note-on/off handlers. 102 | void dragNoteOn(const QPoint& pos); 103 | void dragNoteOff(); 104 | 105 | // Piano keyboard note descriminator. 106 | int noteAt(const QPoint& pos) const; 107 | 108 | // (Re)create the complete view pixmap. 109 | void updatePixmap(); 110 | 111 | // Paint event handler. 112 | void paintEvent(QPaintEvent *pPaintEvent); 113 | 114 | // Resize event handler. 115 | void resizeEvent(QResizeEvent *pResizeEvent); 116 | 117 | // Alternate mouse behavior event handlers. 118 | void mousePressEvent(QMouseEvent *pMouseEvent); 119 | void mouseMoveEvent(QMouseEvent *pMouseEvent); 120 | void mouseReleaseEvent(QMouseEvent *pMouseEvent); 121 | 122 | // Keyboard event handler. 123 | void keyPressEvent(QKeyEvent *pKeyEvent); 124 | 125 | // Trap for help/tool-tip events. 126 | bool eventFilter(QObject *pObject, QEvent *pEvent); 127 | 128 | // Present a tooltip for a note. 129 | void noteToolTip(const QPoint& pos) const; 130 | 131 | // Default note name map accessor. 132 | QString noteName(int iNote) const; 133 | 134 | // Reset drag/select state. 135 | void resetDragState(); 136 | 137 | protected: 138 | 139 | // Constants 140 | static const int NUM_NOTES = 128; 141 | 142 | static const int MIN_NOTE = 0; 143 | static const int MAX_NOTE = 127; 144 | 145 | static const int MIN_VELOCITY = 1; 146 | static const int MAX_VELOCITY = 127; 147 | 148 | // Local double-buffering pixmap. 149 | QPixmap m_pixmap; 150 | 151 | // Current notes being keyed on. 152 | struct Note 153 | { 154 | bool enabled; 155 | bool on; 156 | QPainterPath path; 157 | 158 | } m_notes[NUM_NOTES]; 159 | 160 | // Keyboard note range state. 161 | enum DragState { 162 | DragNone = 0, DragStart, 163 | DragNoteRange, DragNoteLow, DragNoteHigh 164 | } m_dragState, m_dragCursor; 165 | 166 | QPoint m_posDrag; 167 | 168 | // Piano keyboard note range. 169 | bool m_bNoteRange; 170 | 171 | int m_iNoteLow; 172 | int m_iNoteLowX; 173 | 174 | int m_iNoteHigh; 175 | int m_iNoteHighX; 176 | 177 | // Current note being keyed on. 178 | int m_iNoteOn; 179 | 180 | // Current note-on timeout. 181 | int m_iTimeout; 182 | 183 | // Default note-on velocity. 184 | int m_iVelocity; 185 | 186 | // Current highlighted note. 187 | int m_iNoteKey; 188 | }; 189 | 190 | 191 | #endif // __synthv1widget_keybd_h 192 | 193 | // end of synthv1widget_keybd.h 194 | -------------------------------------------------------------------------------- /src/synthv1widget_lv2.cpp: -------------------------------------------------------------------------------- 1 | // synthv1widget_lv2.cpp 2 | // 3 | /**************************************************************************** 4 | Copyright (C) 2012-2025, rncbc aka Rui Nuno Capela. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | *****************************************************************************/ 21 | 22 | #include "synthv1widget_lv2.h" 23 | 24 | #include "synthv1_lv2.h" 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include "synthv1widget_palette.h" 31 | 32 | #include 33 | 34 | #include 35 | 36 | #ifndef CONFIG_BINDIR 37 | #define CONFIG_BINDIR CONFIG_PREFIX "/bin" 38 | #endif 39 | 40 | #ifndef CONFIG_LIBDIR 41 | #if defined(__x86_64__) 42 | #define CONFIG_LIBDIR CONFIG_PREFIX "/lib64" 43 | #else 44 | #define CONFIG_LIBDIR CONFIG_PREFIX "/lib" 45 | #endif 46 | #endif 47 | 48 | #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 49 | #define CONFIG_PLUGINSDIR CONFIG_LIBDIR "/qt5/plugins" 50 | #else 51 | #define CONFIG_PLUGINSDIR CONFIG_LIBDIR "/qt6/plugins" 52 | #endif 53 | 54 | 55 | //------------------------------------------------------------------------- 56 | // synthv1widget_lv2 - impl. 57 | // 58 | 59 | synthv1widget_lv2::synthv1widget_lv2 ( synthv1_lv2 *pSynth, 60 | LV2UI_Controller controller, LV2UI_Write_Function write_function ) 61 | : synthv1widget() 62 | { 63 | // Check whether under a dedicated application instance... 64 | QApplication *pApp = synthv1_lv2::qapp_instance(); 65 | if (pApp) { 66 | // Special style paths... 67 | QString sPluginsPath = pApp->applicationDirPath(); 68 | sPluginsPath.remove(CONFIG_BINDIR); 69 | sPluginsPath.append(CONFIG_PLUGINSDIR); 70 | if (QDir(sPluginsPath).exists()) 71 | pApp->addLibraryPath(CONFIG_PLUGINSDIR); 72 | } 73 | 74 | // Custom color/style themes... 75 | synthv1_config *pConfig = synthv1_config::getInstance(); 76 | if (pConfig) { 77 | const QChar sep = QDir::separator(); 78 | QString sPalettePath = QApplication::applicationDirPath(); 79 | sPalettePath.remove(CONFIG_BINDIR); 80 | sPalettePath.append(CONFIG_DATADIR); 81 | sPalettePath.append(sep); 82 | sPalettePath.append(PROJECT_NAME); 83 | sPalettePath.append(sep); 84 | sPalettePath.append("palette"); 85 | if (QDir(sPalettePath).exists()) { 86 | QStringList names; 87 | names.append("KXStudio"); 88 | names.append("Wonton Soup"); 89 | QStringListIterator name_iter(names); 90 | while (name_iter.hasNext()) { 91 | const QString& name = name_iter.next(); 92 | const QFileInfo fi(sPalettePath, name + ".conf"); 93 | if (fi.isReadable()) { 94 | synthv1widget_palette::addNamedPaletteConf( 95 | pConfig, name, fi.absoluteFilePath()); 96 | } 97 | } 98 | } 99 | if (!pConfig->sCustomColorTheme.isEmpty()) { 100 | QPalette pal; 101 | if (synthv1widget_palette::namedPalette( 102 | pConfig, pConfig->sCustomColorTheme, pal)) 103 | synthv1widget::setPalette(pal); 104 | } 105 | #if 0//--Not applicable to plugin forms... 106 | if (!pConfig->sCustomStyleTheme.isEmpty()) { 107 | QApplication::setStyle( 108 | QStyleFactory::create(pConfig->sCustomStyleTheme)); 109 | } 110 | #endif 111 | } 112 | 113 | // Initialize (user) interface stuff... 114 | m_pSynthUi = new synthv1_lv2ui(pSynth, controller, write_function); 115 | 116 | #ifdef CONFIG_LV2_UI_EXTERNAL 117 | m_external_host = nullptr; 118 | #endif 119 | #ifdef CONFIG_LV2_UI_IDLE 120 | m_bIdleClosed = false; 121 | #endif 122 | 123 | // Initialise preset stuff... 124 | clearPreset(); 125 | 126 | // Initial update, always... 127 | //resetParamValues(); 128 | resetParamKnobs(); 129 | 130 | // May initialize the scheduler/work notifier. 131 | openSchedNotifier(); 132 | } 133 | 134 | 135 | // Destructor. 136 | synthv1widget_lv2::~synthv1widget_lv2 (void) 137 | { 138 | delete m_pSynthUi; 139 | } 140 | 141 | 142 | // Synth engine accessor. 143 | synthv1_ui *synthv1widget_lv2::ui_instance (void) const 144 | { 145 | return m_pSynthUi; 146 | } 147 | 148 | 149 | #ifdef CONFIG_LV2_UI_EXTERNAL 150 | 151 | void synthv1widget_lv2::setExternalHost ( LV2_External_UI_Host *external_host ) 152 | { 153 | m_external_host = external_host; 154 | } 155 | 156 | const LV2_External_UI_Host *synthv1widget_lv2::externalHost (void) const 157 | { 158 | return m_external_host; 159 | } 160 | 161 | #endif // CONFIG_LV2_UI_EXTERNAL 162 | 163 | 164 | #ifdef CONFIG_LV2_UI_IDLE 165 | 166 | bool synthv1widget_lv2::isIdleClosed (void) const 167 | { 168 | return m_bIdleClosed; 169 | } 170 | 171 | #endif // CONFIG_LV2_UI_IDLE 172 | 173 | 174 | // Close event handler. 175 | void synthv1widget_lv2::closeEvent ( QCloseEvent *pCloseEvent ) 176 | { 177 | synthv1widget::closeEvent(pCloseEvent); 178 | 179 | #ifdef CONFIG_LV2_UI_IDLE 180 | if (pCloseEvent->isAccepted()) 181 | m_bIdleClosed = true; 182 | #endif 183 | #ifdef CONFIG_LV2_UI_EXTERNAL 184 | if (m_external_host && m_external_host->ui_closed) { 185 | if (pCloseEvent->isAccepted()) 186 | m_external_host->ui_closed(m_pSynthUi->controller()); 187 | } 188 | #endif 189 | } 190 | 191 | 192 | // LV2 port event dispatcher. 193 | void synthv1widget_lv2::port_event ( uint32_t port_index, 194 | uint32_t buffer_size, uint32_t format, const void *buffer ) 195 | { 196 | if (format == 0 && buffer_size == sizeof(float)) { 197 | const synthv1::ParamIndex index 198 | = synthv1::ParamIndex(port_index - synthv1_lv2::ParamBase); 199 | const float fValue = *(float *) buffer; 200 | setParamValue(index, fValue); 201 | } 202 | } 203 | 204 | 205 | // Param method. 206 | void synthv1widget_lv2::updateParam ( 207 | synthv1::ParamIndex index, float fValue ) const 208 | { 209 | m_pSynthUi->write_function(index, fValue); 210 | } 211 | 212 | 213 | // end of synthv1widget_lv2.cpp 214 | -------------------------------------------------------------------------------- /src/synthv1widget_lv2.h: -------------------------------------------------------------------------------- 1 | // synthv1widget_lv2.h 2 | // 3 | /**************************************************************************** 4 | Copyright (C) 2012-2025, rncbc aka Rui Nuno Capela. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | *****************************************************************************/ 21 | 22 | #ifndef __synthv1widget_lv2_h 23 | #define __synthv1widget_lv2_h 24 | 25 | #include "synthv1widget.h" 26 | #include "synthv1_lv2ui.h" 27 | 28 | 29 | //------------------------------------------------------------------------- 30 | // synthv1widget_lv2 - decl. 31 | // 32 | 33 | class synthv1widget_lv2 : public synthv1widget 34 | { 35 | public: 36 | 37 | // Constructor. 38 | synthv1widget_lv2(synthv1_lv2 *pSynth, 39 | LV2UI_Controller controller, LV2UI_Write_Function write_function); 40 | 41 | // Destructor. 42 | ~synthv1widget_lv2(); 43 | 44 | // LV2 port event dispatcher. 45 | void port_event(uint32_t port_index, 46 | uint32_t buffer_size, uint32_t format, const void *buffer); 47 | 48 | #ifdef CONFIG_LV2_UI_EXTERNAL 49 | void setExternalHost(LV2_External_UI_Host *external_host); 50 | const LV2_External_UI_Host *externalHost() const; 51 | #endif 52 | 53 | #ifdef CONFIG_LV2_UI_IDLE 54 | bool isIdleClosed() const; 55 | #endif 56 | 57 | protected: 58 | 59 | // Synth engine accessor. 60 | synthv1_ui *ui_instance() const; 61 | 62 | // Param methods. 63 | void updateParam(synthv1::ParamIndex index, float fValue) const; 64 | 65 | // Close event handler. 66 | void closeEvent(QCloseEvent *pCloseEvent); 67 | 68 | private: 69 | 70 | // Instance variables. 71 | synthv1_lv2ui *m_pSynthUi; 72 | 73 | #ifdef CONFIG_LV2_UI_EXTERNAL 74 | LV2_External_UI_Host *m_external_host; 75 | #endif 76 | #ifdef CONFIG_LV2_UI_IDLE 77 | bool m_bIdleClosed; 78 | #endif 79 | }; 80 | 81 | 82 | #endif // __synthv1widget_lv2_h 83 | 84 | // end of synthv1widget_lv2.h 85 | -------------------------------------------------------------------------------- /src/synthv1widget_preset.h: -------------------------------------------------------------------------------- 1 | // synthv1widget_preset.h 2 | // 3 | /**************************************************************************** 4 | Copyright (C) 2012-2024, rncbc aka Rui Nuno Capela. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | *****************************************************************************/ 21 | 22 | #ifndef __synthv1widget_preset_h 23 | #define __synthv1widget_preset_h 24 | 25 | #include 26 | 27 | // Forward declarations. 28 | class QToolButton; 29 | class QComboBox; 30 | 31 | 32 | //------------------------------------------------------------------------- 33 | // synthv1widget_preset - Custom combo/edit-box widget. 34 | 35 | class synthv1widget_preset : public QWidget 36 | { 37 | Q_OBJECT 38 | 39 | public: 40 | 41 | // Constructor. 42 | synthv1widget_preset(QWidget *pParent = 0); 43 | 44 | void setPreset(const QString& sPreset); 45 | QString preset() const; 46 | 47 | void setDirtyPreset(bool bDirtyPreset); 48 | bool isDirtyPreset() const; 49 | 50 | void clearPreset(); 51 | bool queryPreset(); 52 | 53 | signals: 54 | 55 | void newPresetFile(); 56 | 57 | void loadPresetFile(const QString&); 58 | void savePresetFile(const QString&); 59 | 60 | void resetPresetFile(); 61 | 62 | public slots: 63 | 64 | void initPreset(); 65 | void stabilizePreset(); 66 | 67 | protected slots: 68 | 69 | void newPreset(); 70 | void openPreset(); 71 | void activatePreset(const QString&); 72 | void savePreset(); 73 | void deletePreset(); 74 | void resetPreset(); 75 | 76 | protected: 77 | 78 | void loadPreset(const QString&); 79 | void savePreset(const QString&); 80 | 81 | void refreshPreset(); 82 | 83 | private: 84 | 85 | // Widget members. 86 | QToolButton *m_pNewButton; 87 | QToolButton *m_pOpenButton; 88 | QComboBox *m_pComboBox; 89 | QToolButton *m_pSaveButton; 90 | QToolButton *m_pDeleteButton; 91 | QToolButton *m_pResetButton; 92 | 93 | int m_iInitPreset; 94 | int m_iDirtyPreset; 95 | }; 96 | 97 | 98 | #endif // __synthv1widget_preset_h 99 | 100 | // end of synthv1widget_preset.h 101 | -------------------------------------------------------------------------------- /src/synthv1widget_programs.h: -------------------------------------------------------------------------------- 1 | // synthv1widget_programs.h 2 | // 3 | /**************************************************************************** 4 | Copyright (C) 2012-2023, rncbc aka Rui Nuno Capela. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | *****************************************************************************/ 21 | 22 | #ifndef __synthv1widget_programs_h 23 | #define __synthv1widget_programs_h 24 | 25 | #include 26 | 27 | 28 | // forward decls. 29 | class synthv1_programs; 30 | 31 | 32 | //---------------------------------------------------------------------------- 33 | // synthv1widget_programs -- Custom (tree) widget. 34 | 35 | class synthv1widget_programs : public QTreeWidget 36 | { 37 | Q_OBJECT 38 | 39 | public: 40 | 41 | // ctor. 42 | synthv1widget_programs(QWidget *pParent = nullptr); 43 | // dtor. 44 | ~synthv1widget_programs(); 45 | 46 | // utilities. 47 | void loadPrograms(synthv1_programs *pPrograms); 48 | void savePrograms(synthv1_programs *pPrograms); 49 | 50 | QString currentProgramName() const; 51 | 52 | public slots: 53 | 54 | // slots. 55 | void addBankItem(); 56 | void addProgramItem(); 57 | 58 | protected slots: 59 | 60 | // private slots. 61 | void itemChangedSlot(QTreeWidgetItem *, int); 62 | 63 | void itemExpandedSlot(QTreeWidgetItem *); 64 | void itemCollapsedSlot(QTreeWidgetItem *); 65 | 66 | protected: 67 | 68 | // item delegate decl.. 69 | class ItemDelegate; 70 | 71 | // factory methods. 72 | QTreeWidgetItem *newBankItem(); 73 | QTreeWidgetItem *newProgramItem(); 74 | }; 75 | 76 | 77 | #endif // __synthv1widget_programs_h 78 | 79 | // end of synthv1widget_programs.h 80 | -------------------------------------------------------------------------------- /src/synthv1widget_status.cpp: -------------------------------------------------------------------------------- 1 | // synthv1widget_status.cpp 2 | // 3 | /**************************************************************************** 4 | Copyright (C) 2012-2020, rncbc aka Rui Nuno Capela. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | *****************************************************************************/ 21 | 22 | #include "synthv1widget_status.h" 23 | 24 | #include "synthv1widget_keybd.h" 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #if QT_VERSION < QT_VERSION_CHECK(5, 11, 0) 32 | #define horizontalAdvance width 33 | #endif 34 | 35 | 36 | //------------------------------------------------------------------------- 37 | // synthv1widget_status - Custom status-bar widget. 38 | // 39 | 40 | // Constructor. 41 | synthv1widget_status::synthv1widget_status ( QWidget *pParent ) 42 | : QStatusBar (pParent) 43 | { 44 | QIcon icon; 45 | 46 | icon.addPixmap( 47 | QPixmap(":/images/ledOff.png"), QIcon::Normal, QIcon::Off); 48 | icon.addPixmap( 49 | QPixmap(":/images/ledOn.png"), QIcon::Normal, QIcon::On); 50 | 51 | m_midiInLed[0] = new QPixmap( 52 | icon.pixmap(16, 16, QIcon::Normal, QIcon::Off)); 53 | m_midiInLed[1] = new QPixmap( 54 | icon.pixmap(16, 16, QIcon::Normal, QIcon::On)); 55 | 56 | const QString sMidiIn(tr("MIDI In")); 57 | 58 | QWidget *pMidiInWidget = new QWidget(); 59 | pMidiInWidget->setToolTip(tr("%1 status").arg(sMidiIn)); 60 | 61 | QHBoxLayout *pMidiInLayout = new QHBoxLayout(); 62 | pMidiInLayout->setContentsMargins(0, 0, 0, 0); 63 | pMidiInLayout->setSpacing(0); 64 | 65 | m_pMidiInLedLabel = new QLabel(); 66 | m_pMidiInLedLabel->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); 67 | m_pMidiInLedLabel->setPixmap(*m_midiInLed[0]); 68 | m_pMidiInLedLabel->setFrameStyle(QFrame::NoFrame | QFrame::Plain); 69 | m_pMidiInLedLabel->setAutoFillBackground(true); 70 | pMidiInLayout->addWidget(m_pMidiInLedLabel); 71 | 72 | QLabel *pMidiInTextLabel = new QLabel(sMidiIn); 73 | pMidiInTextLabel->setMargin(2); 74 | pMidiInTextLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); 75 | pMidiInTextLabel->setFrameStyle(QFrame::NoFrame | QFrame::Plain); 76 | pMidiInTextLabel->setAutoFillBackground(true); 77 | pMidiInLayout->addWidget(pMidiInTextLabel); 78 | 79 | pMidiInWidget->setLayout(pMidiInLayout); 80 | QStatusBar::addWidget(pMidiInWidget); 81 | 82 | m_pKeybd = new synthv1widget_keybd(); 83 | m_pKeybd->setMinimumWidth(760); 84 | QStatusBar::addPermanentWidget(m_pKeybd); 85 | 86 | const QFontMetrics fm(QStatusBar::font()); 87 | m_pModifiedLabel = new QLabel(); 88 | m_pModifiedLabel->setAlignment(Qt::AlignHCenter); 89 | m_pModifiedLabel->setMinimumSize(QSize(fm.horizontalAdvance("MOD") + 4, fm.height())); 90 | m_pModifiedLabel->setToolTip(tr("Modification status")); 91 | m_pModifiedLabel->setAutoFillBackground(true); 92 | QStatusBar::addPermanentWidget(m_pModifiedLabel); 93 | } 94 | 95 | 96 | // Destructor. 97 | synthv1widget_status::~synthv1widget_status (void) 98 | { 99 | delete m_midiInLed[1]; 100 | delete m_midiInLed[0]; 101 | } 102 | 103 | 104 | // Permanent widgets accessors. 105 | synthv1widget_keybd *synthv1widget_status::keybd (void) const 106 | { 107 | return m_pKeybd; 108 | } 109 | 110 | 111 | void synthv1widget_status::midiInLed ( bool bMidiInLed ) 112 | { 113 | m_pMidiInLedLabel->setPixmap(*m_midiInLed[bMidiInLed ? 1 : 0]); 114 | } 115 | 116 | 117 | void synthv1widget_status::midiInNote ( int iNote, int iVelocity ) 118 | { 119 | if (iVelocity > 0) 120 | m_pKeybd->noteOn(iNote); 121 | else 122 | m_pKeybd->noteOff(iNote); 123 | } 124 | 125 | 126 | void synthv1widget_status::modified ( bool bModified ) 127 | { 128 | if (bModified) 129 | m_pModifiedLabel->setText(tr("MOD")); 130 | else 131 | m_pModifiedLabel->clear(); 132 | } 133 | 134 | 135 | // end of synthv1widget_status.cpp 136 | -------------------------------------------------------------------------------- /src/synthv1widget_status.h: -------------------------------------------------------------------------------- 1 | // synthv1widget_status.h 2 | // 3 | /**************************************************************************** 4 | Copyright (C) 2012-2020, rncbc aka Rui Nuno Capela. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | *****************************************************************************/ 21 | 22 | #ifndef __synthv1widget_status_h 23 | #define __synthv1widget_status_h 24 | 25 | #include 26 | 27 | 28 | // Forward declarations. 29 | class synthv1widget_keybd; 30 | 31 | class QLabel; 32 | class QPixmap; 33 | 34 | 35 | //------------------------------------------------------------------------- 36 | // synthv1widget_status - Custom status-bar widget. 37 | 38 | class synthv1widget_status : public QStatusBar 39 | { 40 | Q_OBJECT 41 | 42 | public: 43 | 44 | // Constructor. 45 | synthv1widget_status(QWidget *pParent = 0); 46 | 47 | // Destructor. 48 | ~synthv1widget_status(); 49 | 50 | // Permanent widgets accessors. 51 | synthv1widget_keybd *keybd() const; 52 | 53 | void midiInLed(bool bMidiInLed); 54 | void midiInNote(int iNote, int iVelocity); 55 | void modified(bool bModified); 56 | 57 | private: 58 | 59 | // Permanent widgets. 60 | QPixmap *m_midiInLed[2]; 61 | 62 | QLabel *m_pMidiInLedLabel; 63 | QLabel *m_pModifiedLabel; 64 | 65 | synthv1widget_keybd *m_pKeybd; 66 | }; 67 | 68 | 69 | #endif // __synthv1widget_status_h 70 | 71 | // end of synthv1widget_status.h 72 | -------------------------------------------------------------------------------- /src/synthv1widget_wave.cpp: -------------------------------------------------------------------------------- 1 | // synthv1widget_wave.cpp 2 | // 3 | /**************************************************************************** 4 | Copyright (C) 2012-2021, rncbc aka Rui Nuno Capela. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | *****************************************************************************/ 21 | 22 | #include "synthv1widget_wave.h" 23 | 24 | #include "synthv1_wave.h" 25 | 26 | #include 27 | #include 28 | 29 | #include 30 | 31 | #include 32 | #include 33 | 34 | 35 | // Safe value capping. 36 | inline float safe_value ( float x ) 37 | { 38 | return (x < 0.0f ? 0.0f : (x > 1.0f ? 1.0f : x)); 39 | } 40 | 41 | 42 | //---------------------------------------------------------------------------- 43 | // synthv1widget_wave -- Custom widget 44 | 45 | // Constructor. 46 | synthv1widget_wave::synthv1widget_wave ( QWidget *pParent ) 47 | : QFrame(pParent), 48 | m_bDragging(false), m_iDragShape(0) 49 | { 50 | m_pWave = new synthv1_wave_lf(128); 51 | 52 | setFixedSize(QSize(60, 60)); 53 | 54 | QFrame::setFrameShape(QFrame::Panel); 55 | QFrame::setFrameShadow(QFrame::Sunken); 56 | } 57 | 58 | 59 | // Destructor. 60 | synthv1widget_wave::~synthv1widget_wave (void) 61 | { 62 | delete m_pWave; 63 | } 64 | 65 | 66 | // Parameter accessors. 67 | void synthv1widget_wave::setWaveShape ( float fWaveShape ) 68 | { 69 | int iWaveShape = int(fWaveShape); 70 | if (iWaveShape != int(m_pWave->shape())) { 71 | if (iWaveShape < int(synthv1_wave::Pulse)) 72 | iWaveShape = int(synthv1_wave::Noise); 73 | else 74 | if (iWaveShape > int(synthv1_wave::Noise)) 75 | iWaveShape = int(synthv1_wave::Pulse); 76 | m_pWave->reset(synthv1_wave::Shape(iWaveShape), m_pWave->width()); 77 | update(); 78 | emit waveShapeChanged(waveShape()); 79 | } 80 | } 81 | 82 | float synthv1widget_wave::waveShape (void) const 83 | { 84 | return float(m_pWave->shape()); 85 | } 86 | 87 | 88 | void synthv1widget_wave::setWaveWidth ( float fWaveWidth ) 89 | { 90 | if (qAbs(fWaveWidth - m_pWave->width()) > 0.001f) { 91 | m_pWave->reset(m_pWave->shape(), safe_value(fWaveWidth)); 92 | update(); 93 | emit waveWidthChanged(waveWidth()); 94 | } 95 | } 96 | 97 | float synthv1widget_wave::waveWidth (void) const 98 | { 99 | return m_pWave->width(); 100 | } 101 | 102 | 103 | // Draw curve. 104 | void synthv1widget_wave::paintEvent ( QPaintEvent *pPaintEvent ) 105 | { 106 | QPainter painter(this); 107 | 108 | const QRect& rect = QWidget::rect(); 109 | const int h = rect.height(); 110 | const int w = rect.width(); 111 | 112 | const int h2 = (h >> 1); 113 | const int w2 = (w >> 1); 114 | 115 | QPainterPath path; 116 | path.moveTo(0, h2); 117 | for (int x = 1; x < w; ++x) 118 | path.lineTo(x, h2 - int(m_pWave->value(float(x) / float(w)) * float(h2 - 2))); 119 | path.lineTo(w, h2); 120 | 121 | const QPalette& pal = palette(); 122 | const bool bDark = (pal.window().color().value() < 0x7f); 123 | const QColor& rgbLite = (isEnabled() ? Qt::yellow : pal.mid().color()); 124 | const QColor& rgbDark = pal.window().color().darker(); 125 | 126 | painter.fillRect(rect, rgbDark); 127 | 128 | painter.setPen(pal.mid().color()); 129 | painter.drawLine(w2, 0, w2, h); 130 | painter.drawLine(0, h2, w, h2); 131 | 132 | QColor rgbLite1(rgbLite); 133 | QColor rgbDrop1(Qt::black); 134 | rgbLite1.setAlpha(bDark ? 120 : 180); 135 | rgbDrop1.setAlpha(80); 136 | 137 | QLinearGradient grad(0, 0, w << 1, h << 1); 138 | grad.setColorAt(0.0f, rgbLite1.darker(bDark ? 200 : 160)); 139 | grad.setColorAt(1.0f, rgbDrop1); 140 | 141 | painter.setRenderHint(QPainter::Antialiasing, true); 142 | 143 | path.translate(+1, +1); 144 | painter.setPen(QPen(rgbDrop1, 2)); 145 | painter.setBrush(Qt::transparent); 146 | painter.drawPath(path); 147 | path.translate(-1, -1); 148 | painter.setPen(QPen(rgbLite1, 2)); 149 | painter.drawPath(path); 150 | 151 | path.lineTo(1, h2); 152 | painter.setPen(Qt::transparent); 153 | painter.setBrush(grad); 154 | painter.drawPath(path); 155 | 156 | painter.setRenderHint(QPainter::Antialiasing, false); 157 | 158 | painter.end(); 159 | 160 | QFrame::paintEvent(pPaintEvent); 161 | } 162 | 163 | 164 | // Drag/move curve. 165 | void synthv1widget_wave::dragCurve ( const QPoint& pos ) 166 | { 167 | const int h = height(); 168 | const int w = width(); 169 | 170 | const int dx = (pos.x() - m_posDrag.x()); 171 | const int dy = (pos.y() - m_posDrag.y()); 172 | 173 | if (dx || dy) { 174 | const int x = int(waveWidth() * float(w)); 175 | setWaveWidth(float(x + dx) / float(w)); 176 | const int h2 = (h >> 1); 177 | m_iDragShape += dy; 178 | if (m_iDragShape > +h2) { 179 | setWaveShape(waveShape() - 1); 180 | m_iDragShape = 0; 181 | } 182 | else 183 | if (m_iDragShape < -h2) { 184 | setWaveShape(waveShape() + 1); 185 | m_iDragShape = 0; 186 | } 187 | m_posDrag = pos; 188 | } 189 | } 190 | 191 | 192 | // Mouse interaction. 193 | void synthv1widget_wave::mousePressEvent ( QMouseEvent *pMouseEvent ) 194 | { 195 | if (pMouseEvent->button() == Qt::LeftButton) 196 | m_posDrag = pMouseEvent->pos(); 197 | 198 | QFrame::mousePressEvent(pMouseEvent); 199 | } 200 | 201 | 202 | void synthv1widget_wave::mouseMoveEvent ( QMouseEvent *pMouseEvent ) 203 | { 204 | const QPoint& pos = pMouseEvent->pos(); 205 | if (m_bDragging) { 206 | dragCurve(pos); 207 | } else if ((pos - m_posDrag).manhattanLength() > 4) { 208 | setCursor(Qt::SizeAllCursor); 209 | m_bDragging = true; 210 | m_iDragShape = 0; 211 | } 212 | } 213 | 214 | 215 | void synthv1widget_wave::mouseReleaseEvent ( QMouseEvent *pMouseEvent ) 216 | { 217 | QFrame::mouseReleaseEvent(pMouseEvent); 218 | 219 | if (m_bDragging) { 220 | dragCurve(pMouseEvent->pos()); 221 | m_bDragging = false; 222 | unsetCursor(); 223 | } 224 | } 225 | 226 | 227 | void synthv1widget_wave::mouseDoubleClickEvent ( QMouseEvent *pMouseEvent ) 228 | { 229 | QFrame::mouseDoubleClickEvent(pMouseEvent); 230 | 231 | if (!m_bDragging) 232 | setWaveShape(waveShape() + 1); 233 | } 234 | 235 | 236 | void synthv1widget_wave::wheelEvent ( QWheelEvent *pWheelEvent ) 237 | { 238 | const int delta = (pWheelEvent->angleDelta().y() / 60); 239 | 240 | if (pWheelEvent->modifiers() & (Qt::ShiftModifier | Qt::ControlModifier)) { 241 | setWaveShape(waveShape() + (delta < 0 ? -1 : +1)); 242 | } else { 243 | const float w2 = float(width() >> 1); 244 | const int x = int(waveWidth() * w2); 245 | setWaveWidth(float(x + delta) / w2); 246 | } 247 | } 248 | 249 | 250 | // end of synthv1widget_wave.cpp 251 | -------------------------------------------------------------------------------- /src/synthv1widget_wave.h: -------------------------------------------------------------------------------- 1 | // synthv1widget_wave.h 2 | // 3 | /**************************************************************************** 4 | Copyright (C) 2012-2021, rncbc aka Rui Nuno Capela. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | *****************************************************************************/ 21 | 22 | #ifndef __synthv1widget_wave_h 23 | #define __synthv1widget_wave_h 24 | 25 | #include 26 | 27 | 28 | // Forward decl. 29 | class synthv1_wave_lf; 30 | 31 | 32 | //---------------------------------------------------------------------------- 33 | // synthv1widget_wave -- Custom widget 34 | 35 | class synthv1widget_wave : public QFrame 36 | { 37 | Q_OBJECT 38 | 39 | public: 40 | 41 | // Constructor. 42 | synthv1widget_wave(QWidget *pParent = nullptr); 43 | // Destructor. 44 | ~synthv1widget_wave(); 45 | 46 | // Parameter getters. 47 | float waveShape() const; 48 | float waveWidth() const; 49 | 50 | public slots: 51 | 52 | // Parameter setters. 53 | void setWaveShape(float fWaveShape); 54 | void setWaveWidth(float fWaveWidth); 55 | 56 | signals: 57 | 58 | // Parameter change signals. 59 | void waveShapeChanged(float fWaveShape); 60 | void waveWidthChanged(float fWaveWidth); 61 | 62 | protected: 63 | 64 | // Draw canvas. 65 | void paintEvent(QPaintEvent *); 66 | 67 | // Drag/move curve. 68 | void dragCurve(const QPoint& pos); 69 | 70 | // Mouse interaction. 71 | void mousePressEvent(QMouseEvent *pMouseEvent); 72 | void mouseMoveEvent(QMouseEvent *pMouseEvent); 73 | void mouseReleaseEvent(QMouseEvent *pMouseEvent); 74 | void mouseDoubleClickEvent(QMouseEvent *pMouseEvent); 75 | void wheelEvent(QWheelEvent *pWheelEvent); 76 | 77 | private: 78 | 79 | // Instance state. 80 | synthv1_wave_lf *m_pWave; 81 | 82 | // Drag state. 83 | bool m_bDragging; 84 | int m_iDragShape; 85 | QPoint m_posDrag; 86 | }; 87 | 88 | #endif // __synthv1widget_wave_h 89 | 90 | 91 | // end of synthv1widget_wave.h 92 | --------------------------------------------------------------------------------